forked from huawei/openGauss-server
Merge branch 'master' of https://gitee.com/opengauss/openGauss-server
This commit is contained in:
commit
32119f19b0
|
|
@ -398,6 +398,7 @@ function target_file_copy()
|
|||
sed -i '/gs_lcctl/d' binfile
|
||||
sed -i '/gs_wsr/d' binfile
|
||||
sed -i '/gs_gucZenith/d' binfile
|
||||
sed -i '/gs_expansion/d' binfile
|
||||
bin_script=$(cat binfile)
|
||||
rm binfile script_file
|
||||
cd $BUILD_DIR
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@
|
|||
/*
|
||||
* We have to use postgres.h not postgres_fe.h here, because there's so much
|
||||
* backend-only stuff in the XLOG include files we need. But we need a
|
||||
* frontend-ish environment otherwise. Hence this ugly hack.
|
||||
* frontend-ish environment otherwise. Hence this ugly hack.
|
||||
*/
|
||||
#include "postgres.h"
|
||||
#include "knl/knl_variable.h"
|
||||
|
|
@ -31,13 +31,10 @@
|
|||
#include <sys/types.h>
|
||||
#include <sys/wait.h>
|
||||
|
||||
#ifdef HAVE_LIBZ
|
||||
#include "zlib.h"
|
||||
#endif
|
||||
|
||||
#include "getopt_long.h"
|
||||
#include "receivelog.h"
|
||||
#include "streamutil.h"
|
||||
#include "gs_tar_const.h"
|
||||
#include "bin/elog.h"
|
||||
#include "lib/string.h"
|
||||
|
||||
|
|
@ -55,7 +52,6 @@ typedef struct TablespaceList {
|
|||
/* Global options */
|
||||
char* basedir = NULL;
|
||||
static TablespaceList tablespacee_dirs = {NULL, NULL};
|
||||
static const int BLOCK_SIZE = 2560; /* gs_tar block size */
|
||||
char* g_xlogOption = NULL;
|
||||
char format = 'p'; /* p(lain)/t(ar) */
|
||||
char* label = "gs_basebackup base backup";
|
||||
|
|
@ -66,17 +62,6 @@ bool includewal = false;
|
|||
bool streamwal = false;
|
||||
bool fastcheckpoint = false;
|
||||
|
||||
/* fileStream result */
|
||||
static const int READ_ERROR = -2;
|
||||
|
||||
/* gs_tar offset */
|
||||
static const int LEN_LEFT = 1048;
|
||||
static const int FILE_PADDING = 511; /* All files are padded up to 512 bytes */
|
||||
static const int FILE_TYPE = 1080;
|
||||
|
||||
/* file type */
|
||||
static const char TYPE_DICTORY = '5';
|
||||
|
||||
extern char** tblspaceDirectory;
|
||||
extern int tblspaceCount;
|
||||
extern int tblspaceIndex;
|
||||
|
|
@ -122,21 +107,8 @@ static int GsTar(int argc, char** argv);
|
|||
static int GsBaseBackup(int argc, char** argv);
|
||||
|
||||
static const char* get_tablespace_mapping(const char* dir);
|
||||
extern void FetchMotCheckpoint(const char* basedir, PGconn* fetchConn, const char* progname, bool verbose);
|
||||
|
||||
#ifdef HAVE_LIBZ
|
||||
static const char* get_gz_error(gzFile gzf)
|
||||
{
|
||||
int errnum;
|
||||
const char* errmsg = NULL;
|
||||
|
||||
errmsg = gzerror(gzf, &errnum);
|
||||
if (errnum == Z_ERRNO)
|
||||
return strerror(errno);
|
||||
else
|
||||
return errmsg;
|
||||
}
|
||||
#endif
|
||||
extern void FetchMotCheckpoint(const char* basedir, PGconn* fetchConn, const char* progname, bool verbose,
|
||||
const char format = 'p', const int compresslevel = 0);
|
||||
|
||||
/*
|
||||
* Split argument into old_dir and new_dir and append to tablespace mapping
|
||||
|
|
@ -144,7 +116,7 @@ static const char* get_gz_error(gzFile gzf)
|
|||
*/
|
||||
static void tablespace_list_append(const char* arg)
|
||||
{
|
||||
TablespaceListCell* cell = (TablespaceListCell*)malloc(sizeof(TablespaceListCell));
|
||||
TablespaceListCell* cell = (TablespaceListCell*)xmalloc0(sizeof(TablespaceListCell));
|
||||
char* dst = NULL;
|
||||
char* dst_ptr = NULL;
|
||||
const char* arg_ptr = NULL;
|
||||
|
|
@ -601,32 +573,6 @@ static void progress_report(int tablespacenum, const char* filename)
|
|||
fprintf(stderr, "\r");
|
||||
}
|
||||
|
||||
#ifdef HAVE_LIBZ
|
||||
static gzFile openGzFile(const char* filename)
|
||||
{
|
||||
gzFile ztarfile = gzopen(filename, "wb");
|
||||
if (gzsetparams(ztarfile, compresslevel, Z_DEFAULT_STRATEGY) != Z_OK) {
|
||||
fprintf(
|
||||
stderr, _("%s: could not set compression level %d: %s\n"), progname, compresslevel, get_gz_error(ztarfile));
|
||||
disconnect_and_exit(1);
|
||||
}
|
||||
return ztarfile;
|
||||
}
|
||||
|
||||
static void writeGzFile(gzFile ztarfile, char* copybuf, int buf_size, char* filename)
|
||||
{
|
||||
if (gzwrite(ztarfile, copybuf, buf_size) != buf_size) {
|
||||
fprintf(stderr,
|
||||
_("%s: could not write to compressed file \"%s\": %s\n"),
|
||||
progname,
|
||||
filename,
|
||||
get_gz_error(ztarfile));
|
||||
disconnect_and_exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Receive a tar format file from the connection to the server, and write
|
||||
* the data from this file directly into a tar file. If compression is
|
||||
|
|
@ -687,7 +633,15 @@ static void ReceiveTarFile(PGconn* conn, PGresult* res, int rownum)
|
|||
if (compresslevel != 0) {
|
||||
errorno = snprintf_s(filename, sizeof(filename), sizeof(filename) - 1, "%s/base.tar.gz", basedir);
|
||||
securec_check_ss_c(errorno, "", "");
|
||||
ztarfile = openGzFile(filename);
|
||||
ztarfile = openGzFile(filename, compresslevel);
|
||||
if (ztarfile == NULL) {
|
||||
fprintf(stderr,
|
||||
_("%s: could not set compression level %d: %s\n"),
|
||||
progname,
|
||||
compresslevel,
|
||||
get_gz_error(ztarfile));
|
||||
disconnect_and_exit(1);
|
||||
}
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
|
|
@ -706,7 +660,7 @@ static void ReceiveTarFile(PGconn* conn, PGresult* res, int rownum)
|
|||
errorno = snprintf_s(
|
||||
filename, sizeof(filename), sizeof(filename) - 1, "%s/%s.tar.gz", basedir, PQgetvalue(res, rownum, 0));
|
||||
securec_check_ss_c(errorno, "", "");
|
||||
ztarfile = openGzFile(filename);
|
||||
ztarfile = openGzFile(filename, compresslevel);
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
|
|
@ -760,30 +714,6 @@ static void ReceiveTarFile(PGconn* conn, PGresult* res, int rownum)
|
|||
|
||||
int r = PQgetCopyData(conn, ©buf, 0);
|
||||
if (r == -1) {
|
||||
/*
|
||||
* End of chunk. Close file (but not stdout).
|
||||
*
|
||||
* Also, write two completely empty blocks at the end of the tar
|
||||
* file, as required by some tar programs.
|
||||
*/
|
||||
char zerobuf[1024];
|
||||
|
||||
errorno = memset_s(zerobuf, sizeof(zerobuf), 0, sizeof(zerobuf));
|
||||
securec_check_c(errorno, "", "");
|
||||
#ifdef HAVE_LIBZ
|
||||
if (ztarfile != NULL) {
|
||||
writeGzFile(ztarfile, zerobuf, sizeof(zerobuf), filename);
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
if (fwrite(zerobuf, sizeof(zerobuf), 1, tarfile) != 1) {
|
||||
fprintf(stderr, _("%s: could not write to file \"%s\": %s\n"), progname, filename, strerror(errno));
|
||||
fclose(tarfile);
|
||||
tarfile = NULL;
|
||||
disconnect_and_exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef HAVE_LIBZ
|
||||
if (ztarfile != NULL) {
|
||||
if (gzclose(ztarfile) != 0) {
|
||||
|
|
@ -807,7 +737,6 @@ static void ReceiveTarFile(PGconn* conn, PGresult* res, int rownum)
|
|||
tarfile = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
} else if (r == -2) {
|
||||
fprintf(stderr, _("%s: could not read COPY data: %s"), progname, PQerrorMessage(conn));
|
||||
|
|
@ -816,7 +745,14 @@ static void ReceiveTarFile(PGconn* conn, PGresult* res, int rownum)
|
|||
|
||||
#ifdef HAVE_LIBZ
|
||||
if (ztarfile != NULL) {
|
||||
writeGzFile(ztarfile, copybuf, r, filename);
|
||||
if (!writeGzFile(ztarfile, copybuf, r)) {
|
||||
fprintf(stderr,
|
||||
_("%s: could not write to compressed file \"%s\": %s\n"),
|
||||
progname,
|
||||
filename,
|
||||
get_gz_error(ztarfile));
|
||||
disconnect_and_exit(1);
|
||||
}
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
|
|
@ -960,7 +896,7 @@ static void ReceiveAndUnpackTarFile(PGconn* conn, PGresult* res, int rownum)
|
|||
}
|
||||
|
||||
break;
|
||||
} else if (r == READ_ERROR) {
|
||||
} else if (r == TAR_READ_ERROR) {
|
||||
fprintf(stderr, _("%s: could not read COPY data: %s"), progname, PQerrorMessage(conn));
|
||||
disconnect_and_exit(1);
|
||||
}
|
||||
|
|
@ -972,13 +908,13 @@ static void ReceiveAndUnpackTarFile(PGconn* conn, PGresult* res, int rownum)
|
|||
/*
|
||||
* No current file, so this must be the header for a new file
|
||||
*/
|
||||
if (r != BLOCK_SIZE) {
|
||||
if (r != TAR_BLOCK_SIZE) {
|
||||
fprintf(stderr, _("%s: invalid tar block header size: %d\n"), progname, r);
|
||||
disconnect_and_exit(1);
|
||||
}
|
||||
totaldone += BLOCK_SIZE;
|
||||
totaldone += TAR_BLOCK_SIZE;
|
||||
|
||||
if (sscanf_s(copybuf + LEN_LEFT, "%201o", ¤t_len_left) != 1) {
|
||||
if (sscanf_s(copybuf + TAR_LEN_LEFT, "%201o", ¤t_len_left) != 1) {
|
||||
fprintf(stderr, _("%s: could not parse file size\n"), progname);
|
||||
disconnect_and_exit(1);
|
||||
}
|
||||
|
|
@ -992,7 +928,7 @@ static void ReceiveAndUnpackTarFile(PGconn* conn, PGresult* res, int rownum)
|
|||
/*
|
||||
* All files are padded up to 512 bytes
|
||||
*/
|
||||
current_padding = ((current_len_left + FILE_PADDING) & ~FILE_PADDING) - current_len_left;
|
||||
current_padding = ((current_len_left + TAR_FILE_PADDING) & ~TAR_FILE_PADDING) - current_len_left;
|
||||
|
||||
/*
|
||||
* First part of header is zero terminated filename
|
||||
|
|
@ -1010,7 +946,7 @@ static void ReceiveAndUnpackTarFile(PGconn* conn, PGresult* res, int rownum)
|
|||
/*
|
||||
* Ends in a slash means directory or symlink to directory
|
||||
*/
|
||||
if (copybuf[FILE_TYPE] == TYPE_DICTORY) {
|
||||
if (copybuf[TAR_FILE_TYPE] == TAR_TYPE_DICTORY) {
|
||||
/*
|
||||
* Directory
|
||||
*/
|
||||
|
|
@ -1039,12 +975,12 @@ static void ReceiveAndUnpackTarFile(PGconn* conn, PGresult* res, int rownum)
|
|||
filename,
|
||||
strerror(errno));
|
||||
#endif
|
||||
} else if (copybuf[FILE_TYPE] == '2') {
|
||||
} else if (copybuf[TAR_FILE_TYPE] == '2') {
|
||||
/*
|
||||
* Symbolic link
|
||||
*/
|
||||
filename[strlen(filename) - 1] = '\0'; /* Remove trailing slash */
|
||||
mapped_tblspc_path = get_tablespace_mapping(©buf[FILE_TYPE + 1]);
|
||||
mapped_tblspc_path = get_tablespace_mapping(©buf[TAR_FILE_TYPE + 1]);
|
||||
if (symlink(mapped_tblspc_path, filename) != 0) {
|
||||
if (IsXlogDir(filename)) {
|
||||
fprintf(stderr,
|
||||
|
|
@ -1072,7 +1008,7 @@ static void ReceiveAndUnpackTarFile(PGconn* conn, PGresult* res, int rownum)
|
|||
sizeof(absolut_path) - 1,
|
||||
"%s/%s",
|
||||
basedir,
|
||||
©buf[FILE_TYPE + 1]);
|
||||
©buf[TAR_FILE_TYPE + 1]);
|
||||
securec_check_ss_c(errorno, "\0", "\0");
|
||||
|
||||
if (symlink(absolut_path, filename) != 0) {
|
||||
|
|
@ -1517,9 +1453,7 @@ static void BaseBackup(void)
|
|||
exit(1);
|
||||
}
|
||||
ClearAndFreePasswd();
|
||||
if (format == 'p') {
|
||||
FetchMotCheckpoint(basedir, conn, progname, (bool)verbose);
|
||||
}
|
||||
FetchMotCheckpoint(basedir, conn, progname, (bool)verbose, format, compresslevel);
|
||||
PQfinish(conn);
|
||||
conn = NULL;
|
||||
|
||||
|
|
@ -1555,7 +1489,7 @@ static void remove_dw_file(const char* dw_file_name, const char* target_dir, cha
|
|||
/* *
|
||||
* * delete existing double write file if existed, recreate it and write one page of zero
|
||||
* * @param target_dir data base root dir
|
||||
* */
|
||||
* */
|
||||
static void backup_dw_file(const char* target_dir)
|
||||
{
|
||||
int rc;
|
||||
|
|
@ -1708,12 +1642,12 @@ static int GsTar(int argc, char** argv)
|
|||
copybuf = NULL;
|
||||
}
|
||||
|
||||
current_len_left = current_len_left == 0 && current_padding == 0 ? BLOCK_SIZE : current_len_left;
|
||||
current_len_left = current_len_left == 0 && current_padding == 0 ? TAR_BLOCK_SIZE : current_len_left;
|
||||
if (current_len_left == 0 && current_padding != 0) {
|
||||
copybuf = (char*)malloc(current_padding);
|
||||
copybuf = (char*)xmalloc0(current_padding);
|
||||
r = fread(copybuf, 1, current_padding, tarfile);
|
||||
} else {
|
||||
copybuf = (char*)malloc(current_len_left);
|
||||
copybuf = (char*)xmalloc0(current_len_left);
|
||||
r = fread(copybuf, 1, current_len_left, tarfile);
|
||||
// end of file
|
||||
if ((uint64)r < current_len_left) {
|
||||
|
|
@ -1742,12 +1676,12 @@ static int GsTar(int argc, char** argv)
|
|||
int filemode;
|
||||
|
||||
/* No current file, so this must be the header for a new file */
|
||||
if (r != BLOCK_SIZE) {
|
||||
if (r != TAR_BLOCK_SIZE) {
|
||||
fprintf(stderr, "%s: invalid tar block header size: %d\n", progname, r);
|
||||
fclose(tarfile);
|
||||
return -1;
|
||||
}
|
||||
totaldone += BLOCK_SIZE;
|
||||
totaldone += TAR_BLOCK_SIZE;
|
||||
|
||||
if (sscanf_s(copybuf + 1048, "%201o", ¤t_len_left) != 1) {
|
||||
fprintf(stderr, "%s: could not parse file size\n", progname);
|
||||
|
|
@ -1858,7 +1792,7 @@ static int GsTar(int argc, char** argv)
|
|||
}
|
||||
}
|
||||
} else {
|
||||
pg_log(PG_WARNING, "unrecognized link indicator \"%c\"\n", copybuf[FILE_TYPE]);
|
||||
pg_log(PG_WARNING, "unrecognized link indicator \"%c\"\n", copybuf[TAR_FILE_TYPE]);
|
||||
return -1;
|
||||
}
|
||||
continue; /* directory or link handled */
|
||||
|
|
@ -1979,7 +1913,7 @@ static int GsBaseBackup(int argc, char** argv)
|
|||
}
|
||||
}
|
||||
|
||||
while ((c = getopt_long(argc, argv, "D:l:c:h:p:U:s:X:F:T:wWvPxz", long_options, &option_index)) != -1) {
|
||||
while ((c = getopt_long(argc, argv, "D:l:c:h:p:U:s:X:F:T:Z:wWvPxz", long_options, &option_index)) != -1) {
|
||||
switch (c) {
|
||||
case 'D': {
|
||||
GS_FREE(basedir);
|
||||
|
|
|
|||
|
|
@ -127,7 +127,8 @@ static int replace_node_name(char* sSrc, const char* sMatchStr, const char* sRep
|
|||
static void show_full_build_process(const char* errmg);
|
||||
static void backup_dw_file(const char* target_dir);
|
||||
static void get_xlog_location(char (&xlog_location)[MAXPGPATH]);
|
||||
extern void FetchMotCheckpoint(const char* basedir, PGconn* fetchConn, const char* progname, bool verbose);
|
||||
extern void FetchMotCheckpoint(const char* basedir, PGconn* fetchConn, const char* progname, bool verbose,
|
||||
const char format = 'p', const int compresslevel = 0);
|
||||
extern char* GetOptionValueFromFile(const char* fileName, const char* option);
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -27,6 +27,8 @@
|
|||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include "postgres_fe.h"
|
||||
#include "gs_tar_const.h"
|
||||
#include "streamutil.h"
|
||||
#include "libpq/libpq-fe.h"
|
||||
#include "utils/builtins.h"
|
||||
#include "common/fe_memutils.h"
|
||||
|
|
@ -40,6 +42,290 @@
|
|||
|
||||
static uint64 totaldone = 0;
|
||||
|
||||
static void CheckConnResult(PGconn* conn, const char* progname)
|
||||
{
|
||||
PGresult* res = PQgetResult(conn);
|
||||
if (PQresultStatus(res) != PGRES_COPY_OUT) {
|
||||
fprintf(stderr, "%s: could not get COPY data stream: %s", progname, PQerrorMessage(conn));
|
||||
disconnect_and_exit(1);
|
||||
}
|
||||
PQclear(res);
|
||||
}
|
||||
|
||||
static void MotReceiveAndAppendTarFile(
|
||||
const char* basedir, const char* chkptName, PGconn* conn, const char* progname, int compresslevel)
|
||||
{
|
||||
CheckConnResult(conn, progname);
|
||||
|
||||
FILE* tarfile = NULL;
|
||||
char filename[MAXPGPATH];
|
||||
errno_t errorno = EOK;
|
||||
char* copybuf = NULL;
|
||||
FILE* file = NULL;
|
||||
char current_path[MAXPGPATH];
|
||||
int current_len_left = 0;
|
||||
int current_padding = 0;
|
||||
|
||||
errorno = strncpy_s(current_path, sizeof(current_path), basedir, sizeof(current_path) - 1);
|
||||
securec_check_c(errorno, "", "");
|
||||
|
||||
#ifdef HAVE_LIBZ
|
||||
gzFile ztarfile = NULL;
|
||||
int duplicatedfd = -1;
|
||||
#endif
|
||||
if (strcmp(basedir, "-") == 0) {
|
||||
#ifdef HAVE_LIBZ
|
||||
if (compresslevel != 0) {
|
||||
duplicatedfd = dup(fileno(stdout));
|
||||
if (duplicatedfd == -1) {
|
||||
fprintf(stderr, _("%s: could not allocate dup fd by fileno(stdout): %s\n"), progname, strerror(errno));
|
||||
disconnect_and_exit(1);
|
||||
}
|
||||
|
||||
ztarfile = gzdopen(duplicatedfd, "ab");
|
||||
if (gzsetparams(ztarfile, compresslevel, Z_DEFAULT_STRATEGY) != Z_OK) {
|
||||
fprintf(stderr,
|
||||
_("%s: could not set compression level %d: %s\n"),
|
||||
progname,
|
||||
compresslevel,
|
||||
get_gz_error(ztarfile));
|
||||
close(duplicatedfd);
|
||||
duplicatedfd = -1;
|
||||
disconnect_and_exit(1);
|
||||
}
|
||||
close(duplicatedfd);
|
||||
duplicatedfd = -1;
|
||||
} else
|
||||
#endif
|
||||
tarfile = stdout;
|
||||
strcpy_s(filename, 1, "-");
|
||||
} else {
|
||||
#ifdef HAVE_LIBZ
|
||||
if (compresslevel != 0) {
|
||||
errorno = snprintf_s(filename, sizeof(filename), sizeof(filename) - 1, "%s/base.tar.gz", basedir);
|
||||
securec_check_ss_c(errorno, "", "");
|
||||
ztarfile = openGzFile(filename, compresslevel, "ab");
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
errorno = snprintf_s(filename, sizeof(filename), sizeof(filename) - 1, "%s/base.tar", basedir);
|
||||
// basdir has been realpath before
|
||||
securec_check_ss_c(errorno, "", "");
|
||||
tarfile = fopen(filename, "ab");
|
||||
}
|
||||
}
|
||||
|
||||
/* chkptName header */
|
||||
copybuf = (char*)xmalloc0(TAR_BLOCK_SIZE);
|
||||
|
||||
int chkptDirLen = strlen(chkptName);
|
||||
errorno = strcpy_s(copybuf + 2, chkptDirLen + 1, chkptName);
|
||||
securec_check_ss_c(errorno, "", "");
|
||||
|
||||
copybuf[0] = '.';
|
||||
copybuf[1] = '/';
|
||||
copybuf[chkptDirLen + 2] = '/';
|
||||
copybuf[TAR_FILE_TYPE] = TAR_TYPE_DICTORY;
|
||||
|
||||
for (int i = 0; i < 11; i++) {
|
||||
copybuf[TAR_LEN_LEFT + i] = '0';
|
||||
}
|
||||
errorno = sprintf_s(©buf[TAR_FILE_MODE], TAR_BLOCK_SIZE - TAR_FILE_MODE, "%07o ", FILE_PERMISSION);
|
||||
securec_check_ss_c(errorno, "", "");
|
||||
|
||||
#ifdef HAVE_LIBZ
|
||||
if (ztarfile != NULL) {
|
||||
if (!writeGzFile(ztarfile, copybuf, TAR_BLOCK_SIZE)) {
|
||||
fprintf(stderr, _("%s: could not write to file \"%s\": %s\n"), progname, filename, strerror(errno));
|
||||
disconnect_and_exit(1);
|
||||
}
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
if (fwrite(copybuf, TAR_BLOCK_SIZE, 1, tarfile) != 1) {
|
||||
fprintf(stderr, _("%s: could not write to file \"%s\": %s\n"), progname, filename, strerror(errno));
|
||||
disconnect_and_exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
while (1) {
|
||||
int r;
|
||||
|
||||
if (copybuf != NULL) {
|
||||
PQfreemem(copybuf);
|
||||
copybuf = NULL;
|
||||
}
|
||||
|
||||
r = PQgetCopyData(conn, ©buf, 0);
|
||||
if (r == -1) {
|
||||
#ifdef HAVE_LIBZ
|
||||
if (ztarfile != NULL) {
|
||||
if (gzclose(ztarfile) != 0) {
|
||||
fprintf(stderr,
|
||||
_("%s: could not close compressed file \"%s\": %s\n"),
|
||||
progname,
|
||||
filename,
|
||||
get_gz_error(ztarfile));
|
||||
disconnect_and_exit(1);
|
||||
}
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
if (strcmp(basedir, "-") != 0) {
|
||||
if (fclose(tarfile) != 0) {
|
||||
fprintf(
|
||||
stderr, _("%s: could not close file \"%s\": %s\n"), progname, filename, strerror(errno));
|
||||
tarfile = NULL;
|
||||
disconnect_and_exit(1);
|
||||
}
|
||||
tarfile = NULL;
|
||||
}
|
||||
}
|
||||
break;
|
||||
} else if (r == TAR_READ_ERROR) {
|
||||
fprintf(stderr, "%s: could not read COPY data: %s", progname, PQerrorMessage(conn));
|
||||
disconnect_and_exit(1);
|
||||
}
|
||||
if (current_len_left == 0 && current_padding == 0) {
|
||||
/* No current file, so this must be the header for a new file */
|
||||
if (r != TAR_BLOCK_SIZE) {
|
||||
fprintf(stderr, _("%s: invalid tar block header size: %d\n"), progname, r);
|
||||
disconnect_and_exit(1);
|
||||
}
|
||||
|
||||
/* new file */
|
||||
int filemode;
|
||||
totaldone += TAR_BLOCK_SIZE;
|
||||
if (sscanf_s(copybuf + TAR_LEN_LEFT, "%201o", ¤t_len_left) != 1) {
|
||||
fprintf(stderr, "%s: could not parse file size\n", progname);
|
||||
disconnect_and_exit(1);
|
||||
}
|
||||
|
||||
/* Set permissions on the file */
|
||||
if (sscanf_s(©buf[TAR_FILE_MODE], "%07o ", (unsigned int*)&filemode) != 1) {
|
||||
fprintf(stderr, "%s: could not parse file mode\n", progname);
|
||||
disconnect_and_exit(1);
|
||||
}
|
||||
|
||||
/*
|
||||
* All files are padded up to 512 bytes
|
||||
*/
|
||||
current_padding = ((current_len_left + TAR_FILE_PADDING) & ~TAR_FILE_PADDING) - current_len_left;
|
||||
/*
|
||||
* First part of header is zero terminated filename.
|
||||
* when getting a checkpoint, file name can be either
|
||||
* the control file (written to base_dir), or a checkpoint
|
||||
* file (written to base_dir/chkpt_)
|
||||
*/
|
||||
if (strstr(copybuf, "mot.ctrl")) {
|
||||
errorno =
|
||||
snprintf_s(filename, sizeof(filename), sizeof(filename) - 1, "%s/%s", current_path, "mot.ctrl");
|
||||
securec_check_ss_c(errorno, "", "");
|
||||
} else {
|
||||
char* chkptOffset = strstr(copybuf, chkptName);
|
||||
if (chkptOffset) {
|
||||
errorno = snprintf_s(
|
||||
filename, sizeof(filename), sizeof(filename) - 1, "%s/%s", current_path, chkptOffset);
|
||||
securec_check_ss_c(errorno, "", "");
|
||||
} else {
|
||||
errorno =
|
||||
snprintf_s(filename, sizeof(filename), sizeof(filename) - 1, "%s/%s", current_path, copybuf);
|
||||
securec_check_ss_c(errorno, "", "");
|
||||
}
|
||||
}
|
||||
|
||||
if (filename[strlen(filename) - 1] == '/') {
|
||||
filename[strlen(filename) - 1] = '\0'; /* Remove trailing slash */
|
||||
strcpy_s(copybuf, strlen(filename), filename);
|
||||
continue; /* directory or link handled */
|
||||
}
|
||||
#ifdef HAVE_LIBZ
|
||||
if (ztarfile != NULL) {
|
||||
if (!writeGzFile(ztarfile, copybuf, r)) {
|
||||
fprintf(stderr, _("%s: could not write to file \"%s\": %s\n"), progname, filename, strerror(errno));
|
||||
disconnect_and_exit(1);
|
||||
}
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
if (fwrite(copybuf, r, 1, tarfile) != 1) {
|
||||
fprintf(stderr, _("%s: could not write to file \"%s\": %s\n"), progname, filename, strerror(errno));
|
||||
disconnect_and_exit(1);
|
||||
}
|
||||
}
|
||||
if (current_len_left == 0) {
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
* Continuing blocks in existing file
|
||||
*/
|
||||
if (current_len_left == 0 && r == current_padding) {
|
||||
#ifdef HAVE_LIBZ
|
||||
if (ztarfile != NULL) {
|
||||
if (!writeGzFile(ztarfile, copybuf, current_padding)) {
|
||||
fprintf(
|
||||
stderr, _("%s: could not write to file \"%s\": %s\n"), progname, filename, strerror(errno));
|
||||
disconnect_and_exit(1);
|
||||
}
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
if (fwrite(copybuf, current_padding, 1, tarfile) != 1) {
|
||||
fprintf(
|
||||
stderr, _("%s: could not write to file \"%s\": %s\n"), progname, filename, strerror(errno));
|
||||
disconnect_and_exit(1);
|
||||
}
|
||||
}
|
||||
totaldone += r;
|
||||
current_padding -= r;
|
||||
continue;
|
||||
}
|
||||
|
||||
totaldone += r;
|
||||
#ifdef HAVE_LIBZ
|
||||
if (ztarfile != NULL) {
|
||||
if (!writeGzFile(ztarfile, copybuf, r)) {
|
||||
fprintf(stderr, _("%s: could not write to file \"%s\": %s\n"), progname, filename, strerror(errno));
|
||||
disconnect_and_exit(1);
|
||||
}
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
if (fwrite(copybuf, r, 1, tarfile) != 1) {
|
||||
fprintf(stderr, _("%s: could not write to file \"%s\": %s\n"), progname, filename, strerror(errno));
|
||||
disconnect_and_exit(1);
|
||||
}
|
||||
}
|
||||
if (current_len_left == 0) {
|
||||
continue;
|
||||
}
|
||||
current_len_left -= r;
|
||||
if (current_len_left == 0 && current_padding == 0) {
|
||||
/*
|
||||
* Received the last block, and there is no padding to be
|
||||
* expected. Close the file and move on to the next tar
|
||||
* header.
|
||||
*/
|
||||
fclose(file);
|
||||
file = NULL;
|
||||
continue;
|
||||
}
|
||||
} /* continuing data in existing file */
|
||||
} /* loop over all data blocks */
|
||||
if (tarfile != NULL) {
|
||||
fclose(tarfile);
|
||||
tarfile = NULL;
|
||||
}
|
||||
|
||||
if (copybuf != NULL) {
|
||||
PQfreemem(copybuf);
|
||||
copybuf = NULL;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Receive a tar format stream from the connection to the server, and unpack
|
||||
* the contents of it into a directory. Only files, directories and
|
||||
|
|
@ -154,11 +440,8 @@ static void MotReceiveAndUnpackTarFile(const char* basedir, const char* chkptNam
|
|||
*/
|
||||
filename[strlen(filename) - 1] = '\0'; /* Remove trailing slash */
|
||||
if (mkdir(filename, S_IRWXU) != 0) {
|
||||
fprintf(stderr,
|
||||
"%s: could not create directory \"%s\": %s\n",
|
||||
progname,
|
||||
filename,
|
||||
strerror(errno));
|
||||
fprintf(
|
||||
stderr, "%s: could not create directory \"%s\": %s\n", progname, filename, strerror(errno));
|
||||
disconnect_and_exit(1);
|
||||
}
|
||||
#ifndef WIN32
|
||||
|
|
@ -272,7 +555,8 @@ static void MotReceiveAndUnpackTarFile(const char* basedir, const char* chkptNam
|
|||
* @param controls verbose output
|
||||
* @return Boolean value denoting success or failure.
|
||||
*/
|
||||
void FetchMotCheckpoint(const char* basedir, PGconn* fetchConn, const char* progname, bool verbose)
|
||||
void FetchMotCheckpoint(
|
||||
const char* basedir, PGconn* fetchConn, const char* progname, bool verbose, const char format, int compresslevel)
|
||||
{
|
||||
PGresult* res = NULL;
|
||||
const char* fetchQuery = "FETCH_MOT_CHECKPOINT";
|
||||
|
|
@ -333,17 +617,24 @@ void FetchMotCheckpoint(const char* basedir, PGconn* fetchConn, const char* prog
|
|||
fprintf(stderr, "%s: mot checkpoint directory: %s\n", progname, dirName);
|
||||
}
|
||||
|
||||
if (stat(dirName, &fileStat) < 0) {
|
||||
if (pg_mkdir_p(dirName, S_IRWXU) == -1) {
|
||||
fprintf(stderr, "%s: could not create directory \"%s\": %s\n", progname, dirName, strerror(errno));
|
||||
if (format == 'p') {
|
||||
if (stat(dirName, &fileStat) < 0) {
|
||||
if (pg_mkdir_p(dirName, S_IRWXU) == -1) {
|
||||
fprintf(stderr, "%s: could not create directory \"%s\": %s\n", progname, dirName, strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
} else {
|
||||
fprintf(stderr, "%s: directory \"%s\" already exists, please remove it and try again\n", progname,
|
||||
dirName);
|
||||
exit(1);
|
||||
}
|
||||
MotReceiveAndUnpackTarFile(basedir, chkptName, fetchConn, progname);
|
||||
} else if (format == 't') {
|
||||
MotReceiveAndAppendTarFile(basedir, chkptName, fetchConn, progname, compresslevel);
|
||||
} else {
|
||||
fprintf(stderr, "%s: directory \"%s\" already exists, please remove it and try again\n", progname, dirName);
|
||||
fprintf(stderr, "%s: unsupport format type: \"%c\".\n", progname, format);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
MotReceiveAndUnpackTarFile(basedir, chkptName, fetchConn, progname);
|
||||
if (verbose) {
|
||||
fprintf(stderr, "%s: finished fetching mot checkpoint\n", progname);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -290,7 +290,8 @@ static char* get_string_by_sync_mode(bool syncmode);
|
|||
static void free_ctl();
|
||||
extern int GetLengthAndCheckReplConn(const char* ConnInfoList);
|
||||
extern BuildErrorCode gs_increment_build(char* pgdata, const char* connstr, const uint32 term);
|
||||
extern void FetchMotCheckpoint(const char* basedir, PGconn* fetchConn, const char* progname, bool verbose);
|
||||
extern void FetchMotCheckpoint(const char* basedir, PGconn* fetchConn, const char* progname, bool verbose,
|
||||
const char format = 'p', const int compresslevel = 0);
|
||||
extern char* GetOptionValueFromFile(const char* fileName, const char* option);
|
||||
|
||||
void check_input_for_security(char* input_env_value)
|
||||
|
|
@ -2268,7 +2269,7 @@ static void do_query(void)
|
|||
}
|
||||
|
||||
static bool check_pid_exists(pgpid_t pid)
|
||||
{
|
||||
{
|
||||
FILE* fp = NULL;
|
||||
char buf[1024] = {0};
|
||||
char command[128] = {0};
|
||||
|
|
|
|||
|
|
@ -7272,6 +7272,10 @@
|
|||
"pg_terminate_backend", 1,
|
||||
AddBuiltinFunc(_0(2096), _1("pg_terminate_backend"), _2(1), _3(true), _4(false), _5(pg_terminate_backend), _6(16), _7(PG_CATALOG_NAMESPACE), _8(BOOTSTRAP_SUPERUSERID), _9(INTERNALlanguageId), _10(1), _11(0), _12(0), _13(0), _14('f'), _15(false), _16(false), _17('v'), _18(0), _19(1, 20), _20(NULL), _21(NULL), _22(NULL), _23(NULL), _24("pg_terminate_backend"), _25(NULL), _26(NULL), _27(NULL), _28(0), _29(false), _30(NULL), _31(false))
|
||||
),
|
||||
AddFuncGroup(
|
||||
"pg_terminate_session", 1,
|
||||
AddBuiltinFunc(_0(2099), _1("pg_terminate_session"), _2(2), _3(true), _4(false), _5(pg_terminate_session), _6(16), _7(PG_CATALOG_NAMESPACE), _8(BOOTSTRAP_SUPERUSERID), _9(INTERNALlanguageId), _10(1), _11(0), _12(0), _13(0), _14('f'), _15(false), _16(false), _17('v'), _18(0), _19(2, 20, 20), _20(NULL), _21(NULL), _22(NULL), _23(NULL), _24("pg_terminate_session"), _25(NULL), _26(NULL), _27(NULL), _28(0), _29(false), _30(NULL), _31(false))
|
||||
),
|
||||
AddFuncGroup(
|
||||
"pg_test_err_contain_err", 1,
|
||||
AddBuiltinFunc(_0(9999), _1("pg_test_err_contain_err"), _2(1), _3(true), _4(false), _5(pg_test_err_contain_err), _6(2278), _7(PG_CATALOG_NAMESPACE), _8(BOOTSTRAP_SUPERUSERID), _9(INTERNALlanguageId), _10(1), _11(0), _12(0), _13(0), _14('f'), _15(false), _16(false), _17('v'), _18(0), _19(1, 23), _20(NULL), _21(NULL), _22(NULL), _23(NULL), _24("pg_test_err_contain_err"), _25(NULL), _26(NULL), _27(NULL), _28(0), _29(false), _30(NULL), _31(false))
|
||||
|
|
|
|||
|
|
@ -238,15 +238,9 @@ Datum signal_backend(PG_FUNCTION_ARGS)
|
|||
PG_RETURN_BOOL(true);
|
||||
}
|
||||
|
||||
/*
|
||||
* Signal to terminate a backend process. This is allowed if you are superuser
|
||||
* or have the same role as the process being terminated.
|
||||
*/
|
||||
Datum pg_terminate_backend(PG_FUNCTION_ARGS)
|
||||
{
|
||||
ThreadId tid = PG_GETARG_INT64(0);
|
||||
int r = 0;
|
||||
|
||||
static int kill_backend(ThreadId tid)
|
||||
{
|
||||
/*
|
||||
* It is forbidden to kill backend in the online expansion to protect
|
||||
* the lock session from being interrupted by external applications.
|
||||
|
|
@ -256,20 +250,49 @@ Datum pg_terminate_backend(PG_FUNCTION_ARGS)
|
|||
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), (errmsg("kill backend is prohibited during online expansion."))));
|
||||
}
|
||||
|
||||
r = pg_signal_backend(tid, SIGTERM);
|
||||
int r = pg_signal_backend(tid, SIGTERM);
|
||||
if (r == SIGNAL_BACKEND_NOPERMISSION) {
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
|
||||
(errmsg("must be system admin or have the same role to terminate other backend"))));
|
||||
}
|
||||
|
||||
if (t_thrd.proc && t_thrd.proc->workingVersionNum >= 92060) {
|
||||
|
||||
if (t_thrd.proc != NULL) {
|
||||
uint64 query_id = get_query_id_beentry(tid);
|
||||
(void)gs_close_all_stream_by_debug_id(query_id);
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
/*
|
||||
* Signal to terminate a backend process. This is allowed if you are superuser
|
||||
* or have the same role as the process being terminated.
|
||||
*/
|
||||
Datum pg_terminate_backend(PG_FUNCTION_ARGS)
|
||||
{
|
||||
ThreadId tid = PG_GETARG_INT64(0);
|
||||
int r = kill_backend(tid);
|
||||
PG_RETURN_BOOL(r == SIGNAL_BACKEND_SUCCESS);
|
||||
}
|
||||
|
||||
Datum pg_terminate_session(PG_FUNCTION_ARGS)
|
||||
{
|
||||
ThreadId tid = PG_GETARG_INT64(0);
|
||||
uint64 sid = PG_GETARG_INT64(1);
|
||||
int r = 0;
|
||||
|
||||
if (tid == sid) {
|
||||
r = kill_backend(tid);
|
||||
} else {
|
||||
ThreadPoolSessControl *sess_ctrl = g_threadPoolControler->GetSessionCtrl();
|
||||
int ctrl_idx = sess_ctrl->FindCtrlIdxBySessId(sid);
|
||||
r = sess_ctrl->SendSignal((int)ctrl_idx, SIGTERM);
|
||||
}
|
||||
|
||||
PG_RETURN_BOOL(r == 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* function name: pg_wlm_jump_queue
|
||||
* description : wlm jump the queue with thread id.
|
||||
|
|
|
|||
|
|
@ -215,6 +215,10 @@ static void gs_signal_send_mark(GsNode* local_node, GsSignalCheckType check_type
|
|||
}
|
||||
break;
|
||||
}
|
||||
case SIGNAL_CHECK_SESS_KEY: {
|
||||
local_node->sig_data.check.session_id = t_thrd.sig_cxt.session_id;
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
break;
|
||||
}
|
||||
|
|
@ -670,6 +674,14 @@ static bool gs_signal_handle_check(const GsSndSignal* local_node)
|
|||
}
|
||||
break;
|
||||
}
|
||||
case SIGNAL_CHECK_SESS_KEY: {
|
||||
if (u_sess != NULL && local_node->check.session_id == u_sess->session_id) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
break;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2090,7 +2090,8 @@ static void process_owned_by(const Relation seqrel, List* owned_by)
|
|||
|
||||
/* Must be a regular table */
|
||||
if (tablerel->rd_rel->relkind != RELKIND_RELATION &&
|
||||
!(tablerel->rd_rel->relkind == RELKIND_FOREIGN_TABLE && isMOTFromTblOid(RelationGetRelid(tablerel))))
|
||||
!(tablerel->rd_rel->relkind == RELKIND_FOREIGN_TABLE && (isMOTFromTblOid(RelationGetRelid(tablerel)) ||
|
||||
isPostgresFDWFromTblOid(RelationGetRelid(tablerel)))))
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
|
||||
errmsg("referenced relation \"%s\" is not a table", RelationGetRelationName(tablerel))));
|
||||
|
|
|
|||
|
|
@ -9224,13 +9224,13 @@ static void ATAddForeignKeyConstraint(AlteredTableInfo* tab, Relation rel, Const
|
|||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
|
||||
errmsg("permission denied: \"%s\" is a system catalog", RelationGetRelationName(pkrel))));
|
||||
|
||||
#ifdef ENABLE_MULTIPLE_NODES
|
||||
if (RELATION_IS_PARTITIONED(pkrel))
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
|
||||
errmsg("Invalid FOREIGN KEY constraints"),
|
||||
errdetail("Partitioned table cannot be referenced table")));
|
||||
|
||||
#endif
|
||||
/*
|
||||
* References from permanent or unlogged tables to temp tables, and from
|
||||
* permanent tables to unlogged tables, are disallowed because the
|
||||
|
|
|
|||
|
|
@ -83,6 +83,8 @@ static void ConvertTriggerToFK(CreateTrigStmt* stmt, Oid funcoid);
|
|||
static void SetTriggerFlags(TriggerDesc* trigdesc, const Trigger* trigger);
|
||||
static HeapTuple GetTupleForTrigger(EState* estate, EPQState* epqstate, ResultRelInfo* relinfo, Oid targetPartitionOid,
|
||||
int2 bucketid, ItemPointer tid, TupleTableSlot** newSlot);
|
||||
|
||||
static void ReleaseFakeRelation(Relation relation, Partition part, Relation* fakeRelation);
|
||||
static bool TriggerEnabled(EState* estate, ResultRelInfo* relinfo, Trigger* trigger, TriggerEvent event,
|
||||
const Bitmapset* modifiedCols, HeapTuple oldtup, HeapTuple newtup);
|
||||
static HeapTuple ExecCallTriggerFunc(
|
||||
|
|
@ -2624,12 +2626,7 @@ static HeapTuple GetTupleForTrigger(EState* estate, EPQState* epqstate, ResultRe
|
|||
case HeapTupleSelfUpdated:
|
||||
/* treat it as deleted; do not process */
|
||||
ReleaseBuffer(buffer);
|
||||
if (RELATION_IS_PARTITIONED(relation)) {
|
||||
partitionClose(relation, part, NoLock);
|
||||
}
|
||||
if (RELATION_OWN_BUCKET(relation)) {
|
||||
releaseDummyRelation(&fakeRelation);
|
||||
}
|
||||
ReleaseFakeRelation(relation, part, &fakeRelation);
|
||||
return NULL;
|
||||
|
||||
case HeapTupleMayBeUpdated:
|
||||
|
|
@ -2665,12 +2662,7 @@ static HeapTuple GetTupleForTrigger(EState* estate, EPQState* epqstate, ResultRe
|
|||
* if tuple was deleted or PlanQual failed for updated tuple -
|
||||
* we must not process this tuple!
|
||||
*/
|
||||
if (RELATION_IS_PARTITIONED(relation)) {
|
||||
partitionClose(relation, part, NoLock);
|
||||
}
|
||||
if (RELATION_OWN_BUCKET(relation)) {
|
||||
releaseDummyRelation(&fakeRelation);
|
||||
}
|
||||
ReleaseFakeRelation(relation, part, &fakeRelation);
|
||||
return NULL;
|
||||
|
||||
default:
|
||||
|
|
@ -2716,16 +2708,20 @@ static HeapTuple GetTupleForTrigger(EState* estate, EPQState* epqstate, ResultRe
|
|||
result = heapCopyTuple(&tuple, RelationGetDescr(relation), BufferGetPage(buffer));
|
||||
ReleaseBuffer(buffer);
|
||||
|
||||
if (RELATION_IS_PARTITIONED(relation)) {
|
||||
partitionClose(relation, part, NoLock);
|
||||
}
|
||||
if (RELATION_OWN_BUCKET(relation)) {
|
||||
releaseDummyRelation(&fakeRelation);
|
||||
}
|
||||
ReleaseFakeRelation(relation, part, &fakeRelation);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static void ReleaseFakeRelation(Relation relation, Partition part, Relation* fakeRelation){
|
||||
if (RELATION_IS_PARTITIONED(relation)) {
|
||||
partitionClose(relation, part, NoLock);
|
||||
releaseDummyRelation(fakeRelation);
|
||||
} else if (RELATION_OWN_BUCKET(relation)) {
|
||||
releaseDummyRelation(fakeRelation);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Is trigger enabled to fire?
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -216,6 +216,17 @@ int ThreadPoolSessControl::SendSignal(int ctrl_index, int signal)
|
|||
}
|
||||
|
||||
knl_sess_control* ctrl = &m_base[ctrl_index - m_maxReserveSessionCount];
|
||||
knl_session_context* sess = ctrl->sess;
|
||||
|
||||
/* check permission */
|
||||
if (!superuser()) {
|
||||
if (sess->proc_cxt.MyRoleId != GetUserId()) {
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
|
||||
(errmsg("must be system admin or have the same role to terminate other backend"))));
|
||||
}
|
||||
}
|
||||
|
||||
volatile sig_atomic_t* plock = &ctrl->lock;
|
||||
sig_atomic_t val;
|
||||
do {
|
||||
|
|
@ -223,13 +234,18 @@ int ThreadPoolSessControl::SendSignal(int ctrl_index, int signal)
|
|||
/* perform an atomic compare and swap. */
|
||||
val = __sync_val_compare_and_swap(plock, 0, 1);
|
||||
if (val == 0) {
|
||||
if (ctrl->sess != NULL) {
|
||||
if (ctrl->sess->status == KNL_SESS_ATTACH) {
|
||||
status = gs_signal_send(ctrl->sess->attachPid, signal);
|
||||
} else if (ctrl->sess->status == KNL_SESS_DETACH) {
|
||||
if (sess != NULL) {
|
||||
if (sess->status == KNL_SESS_ATTACH) {
|
||||
t_thrd.sig_cxt.gs_sigale_check_type = SIGNAL_CHECK_SESS_KEY;
|
||||
t_thrd.sig_cxt.session_id = sess->session_id;
|
||||
status = gs_signal_send(sess->attachPid, signal);
|
||||
t_thrd.sig_cxt.gs_sigale_check_type = SIGNAL_CHECK_NONE;
|
||||
t_thrd.sig_cxt.session_id = 0;
|
||||
} else if (sess->status == KNL_SESS_DETACH) {
|
||||
switch (signal) {
|
||||
case SIGTERM:
|
||||
ctrl->sess->status = KNL_SESS_CLOSE;
|
||||
sess->status = KNL_SESS_CLOSE;
|
||||
CloseClientSocket(sess, false);
|
||||
status = 0;
|
||||
break;
|
||||
default:
|
||||
|
|
@ -504,3 +520,15 @@ knl_session_context* ThreadPoolSessControl::GetSessionByIdx(int idx)
|
|||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
int ThreadPoolSessControl::FindCtrlIdxBySessId(uint64 id)
|
||||
{
|
||||
int cidx = 0;
|
||||
for (cidx = 0; cidx < m_maxActiveSessionCount; cidx++) {
|
||||
if (m_base[cidx].sess != NULL && m_base[cidx].sess->session_id == id) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return cidx + m_maxReserveSessionCount;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -485,7 +485,7 @@ IndexOnlyScanFusion::IndexOnlyScanFusion(IndexOnlyScan* node, PlannedStmt* plans
|
|||
|
||||
m_keyInit = false;
|
||||
m_keyNum = list_length(node->indexqual);
|
||||
;
|
||||
|
||||
m_scanKeys = (ScanKey)palloc0(m_keyNum * sizeof(ScanKeyData));
|
||||
|
||||
/* init params */
|
||||
|
|
|
|||
|
|
@ -94,7 +94,12 @@ typedef enum {
|
|||
} RecoveryTargetType;
|
||||
|
||||
/* WAL levels */
|
||||
typedef enum WalLevel { WAL_LEVEL_MINIMAL = 0, WAL_LEVEL_ARCHIVE, WAL_LEVEL_HOT_STANDBY, WAL_LEVEL_LOGICAL } WalLevel;
|
||||
typedef enum WalLevel {
|
||||
WAL_LEVEL_MINIMAL = 0,
|
||||
WAL_LEVEL_ARCHIVE,
|
||||
WAL_LEVEL_HOT_STANDBY,
|
||||
WAL_LEVEL_LOGICAL
|
||||
} WalLevel;
|
||||
|
||||
#define XLogArchivingActive() \
|
||||
(u_sess->attr.attr_common.XLogArchiveMode && g_instance.attr.attr_storage.wal_level >= WAL_LEVEL_ARCHIVE)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,76 @@
|
|||
/*
|
||||
* Copyright (c) 2020 Huawei Technologies Co.,Ltd.
|
||||
*
|
||||
* openGauss is licensed under Mulan PSL v2.
|
||||
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||
* You may obtain a copy of Mulan PSL v2 at:
|
||||
*
|
||||
* http://license.coscl.org.cn/MulanPSL2
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
* See the Mulan PSL v2 for more details.
|
||||
* ---------------------------------------------------------------------------------------
|
||||
*
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* src/include/gs_tar_const.h
|
||||
*
|
||||
* ---------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#ifndef GS_TAR_CONST_H_
|
||||
#define GS_TAR_CONST_H_
|
||||
|
||||
#ifdef HAVE_LIBZ
|
||||
#include "zlib.h"
|
||||
#endif
|
||||
|
||||
/* gs_tar offset */
|
||||
static const int TAR_LEN_LEFT = 1048;
|
||||
static const int TAR_FILE_PADDING = 511; /* All files are padded up to 512 bytes */
|
||||
static const int TAR_FILE_TYPE = 1080; /* file type */
|
||||
static const int TAR_BLOCK_SIZE = 2560; /* gs_tar block size */
|
||||
static const int TAR_FILE_MODE = 1024;
|
||||
|
||||
/* fileStream result */
|
||||
static const int TAR_READ_ERROR = -2;
|
||||
|
||||
/* file type */
|
||||
static const char TAR_TYPE_DICTORY = '5';
|
||||
static const int FILE_PERMISSION = 16832;
|
||||
|
||||
#ifdef HAVE_LIBZ
|
||||
static const char* get_gz_error(gzFile gzf)
|
||||
{
|
||||
int errnum;
|
||||
const char* errmsg = NULL;
|
||||
|
||||
errmsg = gzerror(gzf, &errnum);
|
||||
if (errnum == Z_ERRNO)
|
||||
return strerror(errno);
|
||||
else
|
||||
return errmsg;
|
||||
}
|
||||
|
||||
static gzFile openGzFile(const char* filename, int compresslevel, const char* mode = "wb")
|
||||
{
|
||||
gzFile ztarfile = gzopen(filename, mode);
|
||||
if (gzsetparams(ztarfile, compresslevel, Z_DEFAULT_STRATEGY) != Z_OK) {
|
||||
return NULL;
|
||||
}
|
||||
return ztarfile;
|
||||
}
|
||||
|
||||
static bool writeGzFile(gzFile ztarfile, char* copybuf, int buf_size)
|
||||
{
|
||||
if (gzwrite(ztarfile, copybuf, buf_size) != buf_size) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* GS_TAR_CONST_H_ */
|
||||
|
|
@ -38,13 +38,15 @@ typedef void (*gs_sigfunc)(int);
|
|||
typedef enum GsSignalCheckType {
|
||||
SIGNAL_CHECK_NONE,
|
||||
SIGNAL_CHECK_EXECUTOR_STOP,
|
||||
SIGNAL_CHECK_STREAM_STOP
|
||||
SIGNAL_CHECK_STREAM_STOP,
|
||||
SIGNAL_CHECK_SESS_KEY
|
||||
} GsSignalCheckType;
|
||||
|
||||
/* the struct of signal check */
|
||||
typedef struct GsSignalCheck {
|
||||
GsSignalCheckType check_type;
|
||||
uint64 debug_query_id;
|
||||
uint64 session_id;
|
||||
} GsSignalCheck;
|
||||
|
||||
/* the struct of signal to be handled and the signal sender's thread id */
|
||||
|
|
|
|||
|
|
@ -1929,6 +1929,7 @@ typedef struct knl_t_libwalreceiver_context {
|
|||
typedef struct knl_t_sig_context {
|
||||
unsigned long signal_handle_cnt;
|
||||
GsSignalCheckType gs_sigale_check_type;
|
||||
uint64 session_id;
|
||||
} knl_t_sig_context;
|
||||
|
||||
typedef struct knl_t_slot_context {
|
||||
|
|
|
|||
|
|
@ -76,6 +76,7 @@ public:
|
|||
void HandlePoolerReload();
|
||||
SessionMemoryDetail* getSessionMemoryDetail(uint32* num);
|
||||
knl_session_context* GetSessionByIdx(int idx);
|
||||
int FindCtrlIdxBySessId(uint64 id);
|
||||
|
||||
inline int GetActiveSessionCount()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -580,6 +580,7 @@ extern Datum pg_cancel_invalid_query(PG_FUNCTION_ARGS);
|
|||
extern Datum report_fatal(PG_FUNCTION_ARGS);
|
||||
extern Datum signal_backend(PG_FUNCTION_ARGS);
|
||||
extern Datum pg_terminate_backend(PG_FUNCTION_ARGS);
|
||||
extern Datum pg_terminate_session(PG_FUNCTION_ARGS);
|
||||
extern Datum pg_reload_conf(PG_FUNCTION_ARGS);
|
||||
extern Datum pg_tablespace_databases(PG_FUNCTION_ARGS);
|
||||
extern Datum pg_tablespace_location(PG_FUNCTION_ARGS);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,245 @@
|
|||
#!/usr/bin/env python3
|
||||
# -*- coding:utf-8 -*-
|
||||
#############################################################################
|
||||
# Copyright (c) 2020 Huawei Technologies Co.,Ltd.
|
||||
#
|
||||
# openGauss is licensed under Mulan PSL v2.
|
||||
# You can use this software according to the terms
|
||||
# and conditions of the Mulan PSL v2.
|
||||
# You may obtain a copy of Mulan PSL v2 at:
|
||||
#
|
||||
# http://license.coscl.org.cn/MulanPSL2
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OF ANY KIND,
|
||||
# EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
# MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
# See the Mulan PSL v2 for more details.
|
||||
# ----------------------------------------------------------------------------
|
||||
# Description : gs_expansion is a utility to expansion standby node databases
|
||||
#############################################################################
|
||||
|
||||
import os
|
||||
import pwd
|
||||
import sys
|
||||
import threading
|
||||
import uuid
|
||||
import subprocess
|
||||
import weakref
|
||||
|
||||
sys.path.append(sys.path[0])
|
||||
from gspylib.common.DbClusterInfo import dbClusterInfo, \
|
||||
readOneClusterConfigItem, initParserXMLFile, dbNodeInfo, checkPathVaild
|
||||
from gspylib.common.GaussLog import GaussLog
|
||||
from gspylib.common.Common import DefaultValue
|
||||
from gspylib.common.ErrorCode import ErrorCode
|
||||
from gspylib.common.ParallelBaseOM import ParallelBaseOM
|
||||
from gspylib.common.ParameterParsecheck import Parameter
|
||||
from impl.preinstall.OLAP.PreinstallImplOLAP import PreinstallImplOLAP
|
||||
from gspylib.threads.SshTool import SshTool
|
||||
from impl.expansion.ExpansionImpl import ExpansionImpl
|
||||
|
||||
ENV_LIST = ["MPPDB_ENV_SEPARATE_PATH", "GPHOME", "PATH",
|
||||
"LD_LIBRARY_PATH", "PYTHONPATH", "GAUSS_WARNING_TYPE",
|
||||
"GAUSSHOME", "PATH", "LD_LIBRARY_PATH",
|
||||
"S3_CLIENT_CRT_FILE", "GAUSS_VERSION", "PGHOST",
|
||||
"GS_CLUSTER_NAME", "GAUSSLOG", "GAUSS_ENV", "umask"]
|
||||
|
||||
class Expansion(ParallelBaseOM):
|
||||
"""
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
"""
|
||||
"""
|
||||
ParallelBaseOM.__init__(self)
|
||||
# new added standby node backip list
|
||||
self.newHostList = []
|
||||
self.clusterInfoDict = {}
|
||||
self.backIpNameMap = {}
|
||||
self.packagepath = os.path.realpath(
|
||||
os.path.join(os.path.realpath(__file__), "../../"))
|
||||
|
||||
self.standbyLocalMode = False
|
||||
|
||||
def usage(self):
|
||||
"""
|
||||
gs_expansion is a utility to expansion standby node for a cluster.
|
||||
|
||||
Usage:
|
||||
gs_expansion -? | --help
|
||||
gs_expansion -V | --version
|
||||
gs_expansion -U USER -G GROUP -X XMLFILE -h nodeList [-L]
|
||||
General options:
|
||||
-U Cluster user.
|
||||
-G Group of the cluster user.
|
||||
-X Path of the XML configuration file.
|
||||
-h New standby node node backip list.
|
||||
Separate multiple nodes with commas (,).
|
||||
such as '-h 192.168.0.1,192.168.0.2'
|
||||
-L The standby database installed with
|
||||
local mode.
|
||||
-?, --help Show help information for this
|
||||
utility, and exit the command line mode.
|
||||
-V, --version Show version information.
|
||||
"""
|
||||
print(self.usage.__doc__)
|
||||
|
||||
def parseCommandLine(self):
|
||||
"""
|
||||
parse parameter from command line
|
||||
"""
|
||||
ParaObj = Parameter()
|
||||
ParaDict = ParaObj.ParameterCommandLine("expansion")
|
||||
|
||||
# parameter -h or -?
|
||||
if (ParaDict.__contains__("helpFlag")):
|
||||
self.usage()
|
||||
sys.exit(0)
|
||||
# Resolves command line arguments
|
||||
# parameter -U
|
||||
if (ParaDict.__contains__("user")):
|
||||
self.user = ParaDict.get("user")
|
||||
DefaultValue.checkPathVaild(self.user)
|
||||
# parameter -G
|
||||
if (ParaDict.__contains__("group")):
|
||||
self.group = ParaDict.get("group")
|
||||
# parameter -X
|
||||
if (ParaDict.__contains__("confFile")):
|
||||
self.xmlFile = ParaDict.get("confFile")
|
||||
# parameter -L
|
||||
if (ParaDict.__contains__("localMode")):
|
||||
self.localMode = ParaDict.get("localMode")
|
||||
self.standbyLocalMode = ParaDict.get("localMode")
|
||||
# parameter -l
|
||||
if (ParaDict.__contains__("logFile")):
|
||||
self.logFile = ParaDict.get("logFile")
|
||||
#parameter -h
|
||||
if (ParaDict.__contains__("nodename")):
|
||||
self.newHostList = ParaDict.get("nodename")
|
||||
|
||||
|
||||
def checkParameters(self):
|
||||
"""
|
||||
function: Check parameter from command line
|
||||
input: NA
|
||||
output: NA
|
||||
"""
|
||||
|
||||
# check user | group | xmlfile | node
|
||||
if len(self.user) == 0:
|
||||
GaussLog.exitWithError(ErrorCode.GAUSS_357["GAUSS_35701"] % "-U")
|
||||
if len(self.group) == 0:
|
||||
GaussLog.exitWithError(ErrorCode.GAUSS_357["GAUSS_35701"] % "-G")
|
||||
if len(self.xmlFile) == 0:
|
||||
GaussLog.exitWithError(ErrorCode.GAUSS_357["GAUSS_35701"] % "-X")
|
||||
if len(self.newHostList) == 0:
|
||||
GaussLog.exitWithError(ErrorCode.GAUSS_357["GAUSS_35701"] % "-h")
|
||||
|
||||
clusterInfo = ExpansipnClusterInfo()
|
||||
hostNameIpDict = clusterInfo.initFromXml(self.xmlFile)
|
||||
clusterDict = clusterInfo.getClusterDirectorys()
|
||||
backIpList = clusterInfo.getClusterBackIps()
|
||||
nodeNameList = clusterInfo.getClusterNodeNames()
|
||||
|
||||
self.nodeNameList = nodeNameList
|
||||
self.backIpNameMap = {}
|
||||
for backip in backIpList:
|
||||
self.backIpNameMap[backip] = clusterInfo.getNodeNameByBackIp(backip)
|
||||
|
||||
# check parameter node must in xml config file
|
||||
for nodeid in self.newHostList:
|
||||
if nodeid not in backIpList:
|
||||
GaussLog.exitWithError(ErrorCode.GAUSS_357["GAUSS_35702"] % \
|
||||
nodeid)
|
||||
|
||||
# get corepath and toolpath from xml file
|
||||
corePath = clusterInfo.readClustercorePath(self.xmlFile)
|
||||
toolPath = clusterInfo.getToolPath(self.xmlFile)
|
||||
# parse xml file and cache node info
|
||||
clusterInfoDict = {}
|
||||
clusterInfoDict["appPath"] = clusterDict["appPath"][0]
|
||||
clusterInfoDict["logPath"] = clusterDict["logPath"][0]
|
||||
clusterInfoDict["corePath"] = corePath
|
||||
clusterInfoDict["toolPath"] = toolPath
|
||||
for nodeName in nodeNameList:
|
||||
hostInfo = hostNameIpDict[nodeName]
|
||||
ipList = hostInfo[0]
|
||||
portList = hostInfo[1]
|
||||
backIp = ""
|
||||
sshIp = ""
|
||||
if len(ipList) == 1:
|
||||
backIp = sshIp = ipList[0]
|
||||
elif len(ipList) == 2:
|
||||
backIp = ipList[0]
|
||||
sshIp = ipList[1]
|
||||
port = portList[0]
|
||||
cluster = clusterDict[nodeName]
|
||||
dataNode = cluster[2]
|
||||
clusterInfoDict[nodeName] = {
|
||||
"backIp": backIp,
|
||||
"sshIp": sshIp,
|
||||
"port": port,
|
||||
"localport": int(port) + 1,
|
||||
"localservice": int(port) + 4,
|
||||
"heartBeatPort": int(port) + 3,
|
||||
"dataNode": dataNode,
|
||||
"instanceType": -1
|
||||
}
|
||||
|
||||
nodeIdList = clusterInfo.getClusterNodeIds()
|
||||
for id in nodeIdList:
|
||||
insType = clusterInfo.getdataNodeInstanceType(id)
|
||||
hostName = clusterInfo.getHostNameByNodeId(id)
|
||||
clusterInfoDict[hostName]["instanceType"] = insType
|
||||
self.clusterInfoDict = clusterInfoDict
|
||||
|
||||
|
||||
def initLogs(self):
|
||||
"""
|
||||
init log file
|
||||
"""
|
||||
# if no log file
|
||||
if (self.logFile == ""):
|
||||
self.logFile = DefaultValue.getOMLogPath(
|
||||
DefaultValue.EXPANSION_LOG_FILE, self.user, "",
|
||||
self.xmlFile)
|
||||
# if not absolute path
|
||||
if (not os.path.isabs(self.logFile)):
|
||||
GaussLog.exitWithError(ErrorCode.GAUSS_502["GAUSS_50213"] % "log")
|
||||
|
||||
self.initLogger("gs_expansion")
|
||||
self.logger.ignoreErr = True
|
||||
|
||||
class ExpansipnClusterInfo(dbClusterInfo):
|
||||
|
||||
def __init__(self):
|
||||
dbClusterInfo.__init__(self)
|
||||
|
||||
def getToolPath(self, xmlFile):
|
||||
"""
|
||||
function : Read tool path from default xml file
|
||||
input : String
|
||||
output : String
|
||||
"""
|
||||
self.setDefaultXmlFile(xmlFile)
|
||||
# read gaussdb tool path from xml file
|
||||
(retStatus, retValue) = readOneClusterConfigItem(
|
||||
initParserXMLFile(xmlFile), "gaussdbToolPath", "cluster")
|
||||
if retStatus != 0:
|
||||
raise Exception(ErrorCode.GAUSS_512["GAUSS_51200"]
|
||||
% "gaussdbToolPath" + " Error: \n%s" % retValue)
|
||||
toolPath = os.path.normpath(retValue)
|
||||
checkPathVaild(toolPath)
|
||||
return toolPath
|
||||
|
||||
if __name__ == "__main__":
|
||||
"""
|
||||
"""
|
||||
expansion = Expansion()
|
||||
expansion.parseCommandLine()
|
||||
expansion.checkParameters()
|
||||
expansion.initLogs()
|
||||
expImpl = ExpansionImpl(expansion)
|
||||
expImpl.run()
|
||||
|
||||
|
|
@ -309,6 +309,7 @@ class DefaultValue():
|
|||
LCCTL_LOG_FILE = "gs_lcctl.log"
|
||||
RESIZE_LOG_FILE = "gs_resize.log"
|
||||
HOTPATCH_LOG_FILE = "gs_hotpatch.log"
|
||||
EXPANSION_LOG_FILE = "gs_expansion.log"
|
||||
# hotpatch action
|
||||
HOTPATCH_ACTION_LIST = ["load", "unload", "active", "deactive",
|
||||
"info", "list"]
|
||||
|
|
|
|||
|
|
@ -1092,6 +1092,24 @@ class ErrorCode():
|
|||
'GAUSS_53612': "[GAUSS-53612]: Can not find any catalog in database %s"
|
||||
}
|
||||
|
||||
##########################################################################
|
||||
# gs_expansion
|
||||
# [GAUSS-537] : gs_expansion failed
|
||||
##########################################################################
|
||||
GAUSS_357 = {
|
||||
"GAUSS_35700": "[GAUSS-35700] Expansion standby node failed.",
|
||||
"GAUSS_35701": "[GAUSS-35701] Empty parameter. The %s parameter is"
|
||||
"missing in the command.",
|
||||
"GAUSS_35702": "[GAUSS-35702] Unrecognized parameter, standby host "
|
||||
"backip %s is not in the "
|
||||
"XML configuration file",
|
||||
"GAUSS_35703": "[GAUSS-35703] Check standby database Failed. The "
|
||||
"database on node is abnormal. \n"
|
||||
"node [%s], user [%s], dataNode [%s]. \n"
|
||||
"You can use command \"gs_ctl query -D %s\" for more "
|
||||
"detail."
|
||||
}
|
||||
|
||||
|
||||
class OmError(BaseException):
|
||||
"""
|
||||
|
|
|
|||
|
|
@ -93,6 +93,8 @@ gs_ssh = ["-?", "--help", "-V", "--version", "-c:"]
|
|||
gs_checkos = ["-?", "--help", "-V", "--version", "-h:", "-f:", "-o:",
|
||||
"-i:", "--detail",
|
||||
"-l:", "-X:"]
|
||||
gs_expansion = ["-?", "--help", "-V", "--version", "-U:", "-G:", "-L",
|
||||
"-X:", "-h:", "--sep-env-file="]
|
||||
|
||||
# gs_om child branch
|
||||
gs_om_start = ["-t:", "-?", "--help", "-V", "--version", "-h:", "-I:",
|
||||
|
|
@ -153,7 +155,8 @@ ParameterDict = {"preinstall": gs_preinstall,
|
|||
"postuninstall": gs_postuninstall,
|
||||
"view": gs_om_view,
|
||||
"query": gs_om_query,
|
||||
"refreshconf": gs_om_refreshconf
|
||||
"refreshconf": gs_om_refreshconf,
|
||||
"expansion": gs_expansion
|
||||
}
|
||||
|
||||
# List of scripts with the -t parameter
|
||||
|
|
|
|||
|
|
@ -0,0 +1,829 @@
|
|||
# -*- coding:utf-8 -*-
|
||||
#############################################################################
|
||||
# Copyright (c) 2020 Huawei Technologies Co.,Ltd.
|
||||
#
|
||||
# openGauss is licensed under Mulan PSL v2.
|
||||
# You can use this software according to the terms
|
||||
# and conditions of the Mulan PSL v2.
|
||||
# You may obtain a copy of Mulan PSL v2 at:
|
||||
#
|
||||
# http://license.coscl.org.cn/MulanPSL2
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OF ANY KIND,
|
||||
# EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
# MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
# See the Mulan PSL v2 for more details.
|
||||
# ----------------------------------------------------------------------------
|
||||
# Description : ExpansionImpl.py
|
||||
#############################################################################
|
||||
|
||||
import subprocess
|
||||
import sys
|
||||
import re
|
||||
import os
|
||||
import getpass
|
||||
import pwd
|
||||
import datetime
|
||||
from random import sample
|
||||
import time
|
||||
from multiprocessing import Process, Value
|
||||
|
||||
sys.path.append(sys.path[0] + "/../../../../")
|
||||
from gspylib.common.DbClusterInfo import dbClusterInfo, queryCmd
|
||||
from gspylib.threads.SshTool import SshTool
|
||||
from gspylib.common.DbClusterStatus import DbClusterStatus
|
||||
from gspylib.common.ErrorCode import ErrorCode
|
||||
from gspylib.common.Common import DefaultValue
|
||||
from gspylib.common.GaussLog import GaussLog
|
||||
|
||||
sys.path.append(sys.path[0] + "/../../../lib/")
|
||||
DefaultValue.doConfigForParamiko()
|
||||
import paramiko
|
||||
|
||||
|
||||
#mode
|
||||
MODE_PRIMARY = "primary"
|
||||
MODE_STANDBY = "standby"
|
||||
MODE_NORMAL = "normal"
|
||||
|
||||
#db state
|
||||
STAT_NORMAL = "normal"
|
||||
|
||||
# master
|
||||
MASTER_INSTANCE = 0
|
||||
# standby
|
||||
STANDBY_INSTANCE = 1
|
||||
|
||||
# statu failed
|
||||
STATUS_FAIL = "Failure"
|
||||
|
||||
class ExpansionImpl():
|
||||
"""
|
||||
class for expansion standby node.
|
||||
step:
|
||||
1. preinstall database on new standby node
|
||||
2. install as single-node database
|
||||
3. establish primary-standby relationship of all node
|
||||
"""
|
||||
|
||||
def __init__(self, expansion):
|
||||
"""
|
||||
"""
|
||||
self.context = expansion
|
||||
|
||||
self.user = self.context.user
|
||||
self.group = self.context.group
|
||||
|
||||
self.logger = self.context.logger
|
||||
|
||||
self.envFile = DefaultValue.getEnv("MPPDB_ENV_SEPARATE_PATH")
|
||||
|
||||
currentTime = str(datetime.datetime.now()).replace(" ", "_").replace(
|
||||
".", "_")
|
||||
|
||||
self.commonGsCtl = GsCtlCommon(expansion)
|
||||
self.tempFileDir = "/tmp/gs_expansion_%s" % (currentTime)
|
||||
self.logger.debug("tmp expansion dir is %s ." % self.tempFileDir)
|
||||
|
||||
|
||||
def sendSoftToHosts(self):
|
||||
"""
|
||||
create software dir and send it on each nodes
|
||||
"""
|
||||
self.logger.debug("Start to send software to each standby nodes.\n")
|
||||
hostNames = self.context.newHostList
|
||||
hostList = hostNames
|
||||
|
||||
sshTool = SshTool(hostNames)
|
||||
|
||||
srcFile = self.context.packagepath
|
||||
targetDir = os.path.realpath(
|
||||
os.path.join(srcFile, "../"))
|
||||
|
||||
## mkdir package dir and send package to remote nodes.
|
||||
sshTool.executeCommand("mkdir -p %s" % srcFile , "", DefaultValue.SUCCESS,
|
||||
hostList)
|
||||
sshTool.scpFiles(srcFile, targetDir, hostList)
|
||||
|
||||
## change mode of package dir to set privileges for users
|
||||
tPathList = os.path.split(targetDir)
|
||||
path2ChangeMode = targetDir
|
||||
if len(tPathList) > 2:
|
||||
path2ChangeMode = os.path.join(tPathList[0],tPathList[1])
|
||||
changeModCmd = "chmod -R a+x {srcFile}".format(user=self.user,
|
||||
group=self.group,srcFile=path2ChangeMode)
|
||||
sshTool.executeCommand(changeModCmd, "", DefaultValue.SUCCESS,
|
||||
hostList)
|
||||
self.logger.debug("End to send software to each standby nodes.\n")
|
||||
|
||||
def generateAndSendXmlFile(self):
|
||||
"""
|
||||
"""
|
||||
self.logger.debug("Start to generateAndSend XML file.\n")
|
||||
|
||||
tempXmlFile = "%s/clusterconfig.xml" % self.tempFileDir
|
||||
cmd = "mkdir -p %s; touch %s; cat /dev/null > %s" % \
|
||||
(self.tempFileDir, tempXmlFile, tempXmlFile)
|
||||
(status, output) = subprocess.getstatusoutput(cmd)
|
||||
|
||||
cmd = "chown -R %s:%s %s" % (self.user, self.group, self.tempFileDir)
|
||||
(status, output) = subprocess.getstatusoutput(cmd)
|
||||
|
||||
newHosts = self.context.newHostList
|
||||
for host in newHosts:
|
||||
# create single deploy xml file for each standby node
|
||||
xmlContent = self.__generateXml(host)
|
||||
fo = open("%s" % tempXmlFile, "w")
|
||||
fo.write( xmlContent )
|
||||
fo.close()
|
||||
# send single deploy xml file to each standby node
|
||||
sshTool = SshTool(host)
|
||||
retmap, output = sshTool.getSshStatusOutput("mkdir -p %s" %
|
||||
self.tempFileDir , [host], self.envFile)
|
||||
retmap, output = sshTool.getSshStatusOutput("chown %s:%s %s" %
|
||||
(self.user, self.group, self.tempFileDir), [host], self.envFile)
|
||||
sshTool.scpFiles("%s" % tempXmlFile, "%s" %
|
||||
tempXmlFile, [host], self.envFile)
|
||||
|
||||
self.logger.debug("End to generateAndSend XML file.\n")
|
||||
|
||||
def __generateXml(self, backIp):
|
||||
"""
|
||||
"""
|
||||
nodeName = self.context.backIpNameMap[backIp]
|
||||
nodeInfo = self.context.clusterInfoDict[nodeName]
|
||||
|
||||
backIp = nodeInfo["backIp"]
|
||||
sshIp = nodeInfo["sshIp"]
|
||||
port = nodeInfo["port"]
|
||||
dataNode = nodeInfo["dataNode"]
|
||||
|
||||
appPath = self.context.clusterInfoDict["appPath"]
|
||||
logPath = self.context.clusterInfoDict["logPath"]
|
||||
corePath = self.context.clusterInfoDict["corePath"]
|
||||
toolPath = self.context.clusterInfoDict["toolPath"]
|
||||
|
||||
xmlConfig = """\
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ROOT>
|
||||
<CLUSTER>
|
||||
<PARAM name="clusterName" value="dbCluster" />
|
||||
<PARAM name="nodeNames" value="{nodeName}" />
|
||||
<PARAM name="backIp1s" value="{backIp}"/>
|
||||
<PARAM name="gaussdbAppPath" value="{appPath}" />
|
||||
<PARAM name="gaussdbLogPath" value="{logPath}" />
|
||||
<PARAM name="gaussdbToolPath" value="{toolPath}" />
|
||||
<PARAM name="corePath" value="{corePath}"/>
|
||||
<PARAM name="clusterType" value="single-inst"/>
|
||||
</CLUSTER>
|
||||
<DEVICELIST>
|
||||
<DEVICE sn="1000001">
|
||||
<PARAM name="name" value="{nodeName}"/>
|
||||
<PARAM name="azName" value="AZ1"/>
|
||||
<PARAM name="azPriority" value="1"/>
|
||||
<PARAM name="backIp1" value="{backIp}"/>
|
||||
<PARAM name="sshIp1" value="{sshIp}"/>
|
||||
<!--dbnode-->
|
||||
<PARAM name="dataNum" value="1"/>
|
||||
<PARAM name="dataPortBase" value="{port}"/>
|
||||
<PARAM name="dataNode1" value="{dataNode}"/>
|
||||
</DEVICE>
|
||||
</DEVICELIST>
|
||||
</ROOT>
|
||||
""".format(nodeName=nodeName,backIp=backIp,appPath=appPath,
|
||||
logPath=logPath,toolPath=toolPath,corePath=corePath,
|
||||
sshIp=sshIp,port=port,dataNode=dataNode)
|
||||
return xmlConfig
|
||||
|
||||
def changeUser(self):
|
||||
user = self.user
|
||||
try:
|
||||
pw_record = pwd.getpwnam(user)
|
||||
except Exception:
|
||||
GaussLog.exitWithError(ErrorCode.GAUSS_503["GAUSS_50300"] % user)
|
||||
|
||||
user_name = pw_record.pw_name
|
||||
user_uid = pw_record.pw_uid
|
||||
user_gid = pw_record.pw_gid
|
||||
env = os.environ.copy()
|
||||
os.setgid(user_gid)
|
||||
os.setuid(user_uid)
|
||||
|
||||
def initSshConnect(self, host, user='root'):
|
||||
|
||||
try:
|
||||
getPwdStr = "Please enter the password of user [%s] on node [%s]: " \
|
||||
% (user, host)
|
||||
passwd = getpass.getpass(getPwdStr)
|
||||
self.sshClient = paramiko.SSHClient()
|
||||
self.sshClient.set_missing_host_key_policy(paramiko.AutoAddPolicy())
|
||||
self.sshClient.connect(host, 22, user, passwd)
|
||||
except paramiko.ssh_exception.AuthenticationException as e :
|
||||
self.logger.log("Authentication failed.")
|
||||
self.initSshConnect(host, user)
|
||||
|
||||
def installDatabaseOnHosts(self):
|
||||
"""
|
||||
install database on each standby node
|
||||
"""
|
||||
hostList = self.context.newHostList
|
||||
envfile = DefaultValue.getEnv(DefaultValue.MPPRC_FILE_ENV)
|
||||
tempXmlFile = "%s/clusterconfig.xml" % self.tempFileDir
|
||||
installCmd = "source {envfile} ; gs_install -X {xmlfile} \
|
||||
2>&1".format(envfile=envfile,xmlfile=tempXmlFile)
|
||||
|
||||
statusArr = []
|
||||
|
||||
for newHost in hostList:
|
||||
|
||||
self.logger.log("\ninstalling database on node %s:" % newHost)
|
||||
self.logger.debug(installCmd)
|
||||
|
||||
hostName = self.context.backIpNameMap[newHost]
|
||||
sshIp = self.context.clusterInfoDict[hostName]["sshIp"]
|
||||
self.initSshConnect(sshIp, self.user)
|
||||
|
||||
stdin, stdout, stderr = self.sshClient.exec_command(installCmd,
|
||||
get_pty=True)
|
||||
channel = stdout.channel
|
||||
echannel = stderr.channel
|
||||
|
||||
while not channel.exit_status_ready():
|
||||
try:
|
||||
recvOut = channel.recv(1024)
|
||||
outDecode = recvOut.decode("utf-8");
|
||||
outStr = outDecode.strip()
|
||||
if(len(outStr) == 0):
|
||||
continue
|
||||
if(outDecode.endswith("\r\n")):
|
||||
self.logger.log(outStr)
|
||||
else:
|
||||
value = ""
|
||||
if re.match(r".*yes.*no.*", outStr):
|
||||
value = input(outStr)
|
||||
while True:
|
||||
# check the input
|
||||
if (
|
||||
value.upper() != "YES"
|
||||
and value.upper() != "NO"
|
||||
and value.upper() != "Y"
|
||||
and value.upper() != "N"):
|
||||
value = input("Please type 'yes' or 'no': ")
|
||||
continue
|
||||
break
|
||||
else:
|
||||
value = getpass.getpass(outStr)
|
||||
stdin.channel.send("%s\r\n" %value)
|
||||
stdin.flush()
|
||||
stdout.flush()
|
||||
except Exception as e:
|
||||
sys.exit(1)
|
||||
pass
|
||||
if channel.exit_status_ready() and \
|
||||
not channel.recv_stderr_ready() and \
|
||||
not channel.recv_ready():
|
||||
channel.close()
|
||||
break
|
||||
|
||||
stdout.close()
|
||||
stderr.close()
|
||||
status = channel.recv_exit_status()
|
||||
statusArr.append(status)
|
||||
|
||||
isBothSuccess = True
|
||||
for status in statusArr:
|
||||
if status != 0:
|
||||
isBothSuccess = False
|
||||
break
|
||||
if isBothSuccess:
|
||||
self.logger.log("\nSuccessfully install database on node %s" %
|
||||
hostList)
|
||||
else:
|
||||
sys.exit(1)
|
||||
|
||||
def preInstallOnHosts(self):
|
||||
"""
|
||||
execute preinstall step
|
||||
"""
|
||||
self.logger.debug("Start to preinstall database step.\n")
|
||||
newBackIps = self.context.newHostList
|
||||
newHostNames = []
|
||||
for host in newBackIps:
|
||||
newHostNames.append(self.context.backIpNameMap[host])
|
||||
envfile = self.envFile
|
||||
tempXmlFile = "%s/clusterconfig.xml" % self.tempFileDir
|
||||
|
||||
preinstallCmd = "{softpath}/script/gs_preinstall -U {user} -G {group} \
|
||||
-X {xmlfile} --sep-env-file={envfile} \
|
||||
--non-interactive 2>&1\
|
||||
".format(softpath=self.context.packagepath,user=self.user,
|
||||
group=self.group,xmlfile=tempXmlFile,envfile=envfile)
|
||||
|
||||
sshTool = SshTool(newHostNames)
|
||||
|
||||
status, output = sshTool.getSshStatusOutput(preinstallCmd , [], envfile)
|
||||
statusValues = status.values()
|
||||
if STATUS_FAIL in statusValues:
|
||||
GaussLog.exitWithError(output)
|
||||
|
||||
self.logger.debug("End to preinstall database step.\n")
|
||||
|
||||
|
||||
def buildStandbyRelation(self):
|
||||
"""
|
||||
func: after install single database on standby nodes.
|
||||
build the relation with primary and standby nodes.
|
||||
step:
|
||||
1. restart primary node with Primary Mode
|
||||
(only used to Single-Node instance)
|
||||
2. set guc config to primary node
|
||||
3. restart standby node with Standby Mode
|
||||
4. set guc config to standby node
|
||||
5. generate cluster static file and send to each node.
|
||||
"""
|
||||
self.queryPrimaryClusterDetail()
|
||||
self.setPrimaryGUCConfig()
|
||||
self.setStandbyGUCConfig()
|
||||
self.buildStandbyHosts()
|
||||
self.generateClusterStaticFile()
|
||||
|
||||
def queryPrimaryClusterDetail(self):
|
||||
"""
|
||||
get current cluster type.
|
||||
single-node or primary-standby
|
||||
"""
|
||||
self.logger.debug("Query primary database instance mode.\n")
|
||||
self.isSingleNodeInstance = True
|
||||
primaryHost = self.getPrimaryHostName()
|
||||
result = self.commonGsCtl.queryOmCluster(primaryHost, self.envFile)
|
||||
instance = re.findall(r"node\s+node_ip\s+instance\s+state", result)
|
||||
if len(instance) > 1:
|
||||
self.isSingleNodeInstance = False
|
||||
self.logger.debug("Original instance mode is %s" %
|
||||
self.isSingleNodeInstance)
|
||||
|
||||
def setPrimaryGUCConfig(self):
|
||||
"""
|
||||
"""
|
||||
self.logger.debug("Start to set primary node GUC config.\n")
|
||||
primaryHost = self.getPrimaryHostName()
|
||||
dataNode = self.context.clusterInfoDict[primaryHost]["dataNode"]
|
||||
|
||||
self.setGUCOnClusterHosts([primaryHost])
|
||||
self.addStandbyIpInPrimaryConf()
|
||||
insType, dbStat = self.commonGsCtl.queryInstanceStatus(primaryHost,
|
||||
dataNode,self.envFile)
|
||||
if insType != MODE_PRIMARY:
|
||||
self.commonGsCtl.stopInstance(primaryHost, dataNode, self.envFile)
|
||||
self.commonGsCtl.startInstanceWithMode(primaryHost, dataNode,
|
||||
MODE_PRIMARY,self.envFile)
|
||||
|
||||
# start db to primary state for three times max
|
||||
start_retry_num = 1
|
||||
while start_retry_num <= 3:
|
||||
insType, dbStat = self.commonGsCtl.queryInstanceStatus(primaryHost,
|
||||
dataNode, self.envFile)
|
||||
if insType == MODE_PRIMARY:
|
||||
break
|
||||
self.logger.debug("Start database as Primary mode failed, \
|
||||
retry for %s times" % start_retry_num)
|
||||
self.commonGsCtl.startInstanceWithMode(primaryHost, dataNode,
|
||||
MODE_PRIMARY, self.envFile)
|
||||
start_retry_num = start_retry_num + 1
|
||||
|
||||
def setStandbyGUCConfig(self):
|
||||
"""
|
||||
"""
|
||||
self.logger.debug("Start to set standby node GUC config.\n")
|
||||
standbyHosts = self.context.newHostList
|
||||
standbyHostNames = []
|
||||
for host in standbyHosts:
|
||||
hostName = self.context.backIpNameMap[host]
|
||||
standbyHostNames.append(hostName)
|
||||
self.setGUCOnClusterHosts(standbyHostNames)
|
||||
|
||||
def addStandbyIpInPrimaryConf(self):
|
||||
"""
|
||||
add standby hosts ip in primary node pg_hba.conf
|
||||
"""
|
||||
|
||||
standbyHosts = self.context.newHostList
|
||||
primaryHost = self.getPrimaryHostName()
|
||||
command = ''
|
||||
for host in standbyHosts:
|
||||
hostName = self.context.backIpNameMap[host]
|
||||
dataNode = self.context.clusterInfoDict[hostName]["dataNode"]
|
||||
command += "gs_guc set -D %s -h 'host all all %s/32 \
|
||||
trust';" % (dataNode, host)
|
||||
self.logger.debug(command)
|
||||
sshTool = SshTool([primaryHost])
|
||||
resultMap, outputCollect = sshTool.getSshStatusOutput(command,
|
||||
[primaryHost], self.envFile)
|
||||
self.logger.debug(outputCollect)
|
||||
|
||||
def reloadPrimaryConf(self):
|
||||
"""
|
||||
"""
|
||||
primaryHost = self.getPrimaryHostName()
|
||||
dataNode = self.context.clusterInfoDict[primaryHost]["dataNode"]
|
||||
command = "gs_ctl reload -D %s " % dataNode
|
||||
sshTool = SshTool([primaryHost])
|
||||
self.logger.debug(command)
|
||||
resultMap, outputCollect = sshTool.getSshStatusOutput(command,
|
||||
[primaryHost], self.envFile)
|
||||
self.logger.debug(outputCollect)
|
||||
|
||||
def getPrimaryHostName(self):
|
||||
"""
|
||||
"""
|
||||
primaryHost = ""
|
||||
for nodeName in self.context.nodeNameList:
|
||||
if self.context.clusterInfoDict[nodeName]["instanceType"] \
|
||||
== MASTER_INSTANCE:
|
||||
primaryHost = nodeName
|
||||
break
|
||||
return primaryHost
|
||||
|
||||
|
||||
def buildStandbyHosts(self):
|
||||
"""
|
||||
stop the new standby host`s database and build it as standby mode
|
||||
"""
|
||||
self.logger.debug("start to build standby node...\n")
|
||||
|
||||
standbyHosts = self.context.newHostList
|
||||
|
||||
for host in standbyHosts:
|
||||
hostName = self.context.backIpNameMap[host]
|
||||
dataNode = self.context.clusterInfoDict[hostName]["dataNode"]
|
||||
self.commonGsCtl.stopInstance(hostName, dataNode, self.envFile)
|
||||
self.commonGsCtl.startInstanceWithMode(hostName, dataNode,
|
||||
MODE_STANDBY, self.envFile)
|
||||
|
||||
# start standby as standby mode for three times max.
|
||||
start_retry_num = 1
|
||||
while start_retry_num <= 3:
|
||||
insType, dbStat = self.commonGsCtl.queryInstanceStatus(hostName,
|
||||
dataNode, self.envFile)
|
||||
if insType != MODE_STANDBY:
|
||||
self.logger.debug("Start databasse as Standby mode failed, \
|
||||
retry for %s times" % start_retry_num)
|
||||
self.setGUCOnClusterHosts([])
|
||||
self.addStandbyIpInPrimaryConf()
|
||||
self.reloadPrimaryConf()
|
||||
self.commonGsCtl.startInstanceWithMode(hostName, dataNode,
|
||||
MODE_STANDBY, self.envFile)
|
||||
start_retry_num = start_retry_num + 1
|
||||
else:
|
||||
break
|
||||
|
||||
# build standby node
|
||||
self.addStandbyIpInPrimaryConf()
|
||||
self.reloadPrimaryConf()
|
||||
self.commonGsCtl.buildInstance(hostName, dataNode, MODE_STANDBY,
|
||||
self.envFile)
|
||||
|
||||
# if build failed first time. retry for three times.
|
||||
start_retry_num = 1
|
||||
while start_retry_num <= 3:
|
||||
insType, dbStat = self.commonGsCtl.queryInstanceStatus(hostName,
|
||||
dataNode, self.envFile)
|
||||
if dbStat != STAT_NORMAL:
|
||||
self.logger.debug("Build standby instance failed, \
|
||||
retry for %s times" % start_retry_num)
|
||||
self.addStandbyIpInPrimaryConf()
|
||||
self.reloadPrimaryConf()
|
||||
self.commonGsCtl.buildInstance(hostName, dataNode,
|
||||
MODE_STANDBY, self.envFile)
|
||||
start_retry_num = start_retry_num + 1
|
||||
else:
|
||||
break
|
||||
|
||||
|
||||
def generateClusterStaticFile(self):
|
||||
"""
|
||||
generate static_config_files and send to all hosts
|
||||
"""
|
||||
self.logger.debug("Start to generate and send cluster static file.\n")
|
||||
|
||||
primaryHosts = self.getPrimaryHostName()
|
||||
command = "gs_om -t generateconf -X %s" % self.context.xmlFile
|
||||
sshTool = SshTool([primaryHosts])
|
||||
resultMap, outputCollect = sshTool.getSshStatusOutput(command,
|
||||
[primaryHosts], self.envFile)
|
||||
self.logger.debug(outputCollect)
|
||||
|
||||
nodeNameList = self.context.nodeNameList
|
||||
|
||||
for hostName in nodeNameList:
|
||||
hostSsh = SshTool([hostName])
|
||||
toolPath = self.context.clusterInfoDict["toolPath"]
|
||||
appPath = self.context.clusterInfoDict["appPath"]
|
||||
srcFile = "%s/script/static_config_files/cluster_static_config_%s" \
|
||||
% (toolPath, hostName)
|
||||
targetFile = "%s/bin/cluster_static_config" % appPath
|
||||
hostSsh.scpFiles(srcFile, targetFile, [hostName], self.envFile)
|
||||
|
||||
self.logger.debug("End to generate and send cluster static file.\n")
|
||||
time.sleep(10)
|
||||
|
||||
# Single-node database need start cluster after expansion
|
||||
if self.isSingleNodeInstance:
|
||||
self.logger.debug("Single-Node instance need restart.\n")
|
||||
self.commonGsCtl.queryOmCluster(primaryHosts, self.envFile)
|
||||
|
||||
# if primary database not normal, restart it
|
||||
primaryHost = self.getPrimaryHostName()
|
||||
dataNode = self.context.clusterInfoDict[primaryHost]["dataNode"]
|
||||
insType, dbStat = self.commonGsCtl.queryInstanceStatus(primaryHost,
|
||||
dataNode, self.envFile)
|
||||
if insType != MODE_PRIMARY:
|
||||
self.commonGsCtl.startInstanceWithMode(primaryHost, dataNode,
|
||||
MODE_PRIMARY, self.envFile)
|
||||
# if stat if not normal,rebuild standby database
|
||||
standbyHosts = self.context.newHostList
|
||||
for host in standbyHosts:
|
||||
hostName = self.context.backIpNameMap[host]
|
||||
dataNode = self.context.clusterInfoDict[hostName]["dataNode"]
|
||||
insType, dbStat = self.commonGsCtl.queryInstanceStatus(hostName,
|
||||
dataNode, self.envFile)
|
||||
if dbStat != STAT_NORMAL:
|
||||
self.commonGsCtl.buildInstance(hostName, dataNode,
|
||||
MODE_STANDBY, self.envFile)
|
||||
|
||||
self.commonGsCtl.startOmCluster(primaryHosts, self.envFile)
|
||||
|
||||
def setGUCOnClusterHosts(self, hostNames=[]):
|
||||
"""
|
||||
guc config on all hosts
|
||||
"""
|
||||
|
||||
gucDict = self.getGUCConfig()
|
||||
|
||||
tempShFile = "%s/guc.sh" % self.tempFileDir
|
||||
|
||||
if len(hostNames) == 0:
|
||||
hostNames = self.context.nodeNameList
|
||||
|
||||
for host in hostNames:
|
||||
|
||||
command = "source %s ; " % self.envFile + gucDict[host]
|
||||
|
||||
self.logger.debug(command)
|
||||
|
||||
sshTool = SshTool([host])
|
||||
|
||||
# create temporary dir to save guc command bashfile.
|
||||
mkdirCmd = "mkdir -m a+x -p %s; chown %s:%s %s" % \
|
||||
(self.tempFileDir,self.user,self.group,self.tempFileDir)
|
||||
retmap, output = sshTool.getSshStatusOutput(mkdirCmd, [host], self.envFile)
|
||||
|
||||
subprocess.getstatusoutput("mkdir -m a+x -p %s; touch %s; \
|
||||
cat /dev/null > %s" % \
|
||||
(self.tempFileDir, tempShFile, tempShFile))
|
||||
fo = open("%s" % tempShFile, "w")
|
||||
fo.write("#bash\n")
|
||||
fo.write( command )
|
||||
fo.close()
|
||||
|
||||
# send guc command bashfile to each host and execute it.
|
||||
sshTool.scpFiles("%s" % tempShFile, "%s" % tempShFile, [host],
|
||||
self.envFile)
|
||||
|
||||
resultMap, outputCollect = sshTool.getSshStatusOutput("sh %s" % \
|
||||
tempShFile, [host], self.envFile)
|
||||
|
||||
self.logger.debug(outputCollect)
|
||||
|
||||
def getGUCConfig(self):
|
||||
"""
|
||||
get guc config of each node:
|
||||
replconninfo[index]
|
||||
remote_read_mode
|
||||
replication_type
|
||||
"""
|
||||
nodeDict = self.context.clusterInfoDict
|
||||
hostNames = self.context.nodeNameList
|
||||
|
||||
gucDict = {}
|
||||
|
||||
for hostName in hostNames:
|
||||
|
||||
localeHostInfo = nodeDict[hostName]
|
||||
index = 1
|
||||
guc_tempate_str = ""
|
||||
for remoteHost in hostNames:
|
||||
if(remoteHost == hostName):
|
||||
continue
|
||||
remoteHostInfo = nodeDict[remoteHost]
|
||||
|
||||
guc_repl_template = """\
|
||||
gs_guc set -D {dn} -c "replconninfo{index}=\
|
||||
'localhost={localhost} localport={localport} \
|
||||
localheartbeatport={localeHeartPort} \
|
||||
localservice={localservice} \
|
||||
remotehost={remoteNode} \
|
||||
remoteport={remotePort} \
|
||||
remoteheartbeatport={remoteHeartPort} \
|
||||
remoteservice={remoteservice}'"
|
||||
""".format(dn=localeHostInfo["dataNode"],
|
||||
index=index,
|
||||
localhost=localeHostInfo["sshIp"],
|
||||
localport=localeHostInfo["localport"],
|
||||
localeHeartPort=localeHostInfo["heartBeatPort"],
|
||||
localservice=localeHostInfo["localservice"],
|
||||
remoteNode=remoteHostInfo["sshIp"],
|
||||
remotePort=remoteHostInfo["localport"],
|
||||
remoteHeartPort=remoteHostInfo["heartBeatPort"],
|
||||
remoteservice=remoteHostInfo["localservice"])
|
||||
|
||||
guc_tempate_str += guc_repl_template
|
||||
|
||||
index += 1
|
||||
|
||||
guc_mode_type = """
|
||||
gs_guc set -D {dn} -c 'remote_read_mode=off';
|
||||
gs_guc set -D {dn} -c 'replication_type=1';
|
||||
""".format(dn=localeHostInfo["dataNode"])
|
||||
guc_tempate_str += guc_mode_type
|
||||
|
||||
gucDict[hostName] = guc_tempate_str
|
||||
return gucDict
|
||||
|
||||
def checkLocalModeOnStandbyHosts(self):
|
||||
"""
|
||||
"""
|
||||
standbyHosts = self.context.newHostList
|
||||
self.logger.log("Checking the database with locale mode.")
|
||||
for host in standbyHosts:
|
||||
hostName = self.context.backIpNameMap[host]
|
||||
dataNode = self.context.clusterInfoDict[hostName]["dataNode"]
|
||||
insType, dbStat = self.commonGsCtl.queryInstanceStatus(hostName,
|
||||
dataNode, self.envFile)
|
||||
if insType not in (MODE_PRIMARY, MODE_STANDBY, MODE_NORMAL):
|
||||
GaussLog.exitWithError(ErrorCode.GAUSS_357["GAUSS_35703"] %
|
||||
(hostName, self.user, dataNode, dataNode))
|
||||
|
||||
self.logger.log("Successfully checked the database with locale mode.")
|
||||
|
||||
def preInstall(self):
|
||||
"""
|
||||
preinstall on new hosts.
|
||||
"""
|
||||
self.logger.log("Start to preinstall database on the new \
|
||||
standby nodes.")
|
||||
self.sendSoftToHosts()
|
||||
self.generateAndSendXmlFile()
|
||||
self.preInstallOnHosts()
|
||||
self.logger.log("Successfully preinstall database on the new \
|
||||
standby nodes.")
|
||||
|
||||
|
||||
def clearTmpFile(self):
|
||||
"""
|
||||
clear temporary file after expansion success
|
||||
"""
|
||||
self.logger.debug("start to delete temporary file")
|
||||
hostNames = self.context.nodeNameList
|
||||
sshTool = SshTool(hostNames)
|
||||
clearCmd = "source %s ; rm -rf %s" % (self.envFile, self.tempFileDir)
|
||||
result, output = sshTool.getSshStatusOutput(clearCmd,
|
||||
hostNames, self.envFile)
|
||||
self.logger.debug(output)
|
||||
|
||||
def installAndExpansion(self):
|
||||
"""
|
||||
install database and expansion standby node with db om user
|
||||
"""
|
||||
pvalue = Value('i', 0)
|
||||
proc = Process(target=self.installProcess, args=(pvalue,))
|
||||
proc.start()
|
||||
proc.join()
|
||||
if not pvalue.value:
|
||||
sys.exit(1)
|
||||
else:
|
||||
proc.terminate()
|
||||
|
||||
def installProcess(self, pvalue):
|
||||
# change to db manager user. the below steps run with db manager user.
|
||||
self.changeUser()
|
||||
|
||||
if not self.context.standbyLocalMode:
|
||||
self.logger.log("\nStart to install database on the new \
|
||||
standby nodes.")
|
||||
self.installDatabaseOnHosts()
|
||||
else:
|
||||
self.logger.log("\nStandby nodes is installed with locale mode.")
|
||||
self.checkLocalModeOnStandbyHosts()
|
||||
|
||||
self.logger.log("\nDatabase on standby nodes installed finished. \
|
||||
Start to establish the primary-standby relationship.")
|
||||
self.buildStandbyRelation()
|
||||
# process success
|
||||
pvalue.value = 1
|
||||
|
||||
def run(self):
|
||||
"""
|
||||
start expansion
|
||||
"""
|
||||
# preinstall on standby nodes with root user.
|
||||
if not self.context.standbyLocalMode:
|
||||
self.preInstall()
|
||||
|
||||
self.installAndExpansion()
|
||||
|
||||
self.clearTmpFile()
|
||||
|
||||
self.logger.log("\nSuccess to expansion standby nodes.")
|
||||
|
||||
|
||||
class GsCtlCommon:
|
||||
|
||||
def __init__(self, expansion):
|
||||
"""
|
||||
"""
|
||||
self.logger = expansion.logger
|
||||
|
||||
def queryInstanceStatus(self, host, datanode, env):
|
||||
"""
|
||||
"""
|
||||
command = "source %s ; gs_ctl query -D %s" % (env, datanode)
|
||||
sshTool = SshTool([datanode])
|
||||
resultMap, outputCollect = sshTool.getSshStatusOutput(command,
|
||||
[host], env)
|
||||
self.logger.debug(outputCollect)
|
||||
localRole = re.findall(r"local_role.*: (.*?)\n", outputCollect)
|
||||
db_state = re.findall(r"db_state.*: (.*?)\n", outputCollect)
|
||||
|
||||
insType = ""
|
||||
|
||||
if(len(localRole)) == 0:
|
||||
insType = ""
|
||||
else:
|
||||
insType = localRole[0]
|
||||
|
||||
dbStatus = ""
|
||||
if(len(db_state)) == 0:
|
||||
dbStatus = ""
|
||||
else:
|
||||
dbStatus = db_state[0]
|
||||
|
||||
return insType.strip().lower(), dbStatus.strip().lower()
|
||||
|
||||
def stopInstance(self, host, datanode, env):
|
||||
"""
|
||||
"""
|
||||
command = "source %s ; gs_ctl stop -D %s" % (env, datanode)
|
||||
sshTool = SshTool([host])
|
||||
resultMap, outputCollect = sshTool.getSshStatusOutput(command,
|
||||
[host], env)
|
||||
self.logger.debug(host)
|
||||
self.logger.debug(outputCollect)
|
||||
|
||||
def startInstanceWithMode(self, host, datanode, mode, env):
|
||||
"""
|
||||
"""
|
||||
command = "source %s ; gs_ctl start -D %s -M %s" % (env, datanode, mode)
|
||||
self.logger.debug(command)
|
||||
sshTool = SshTool([host])
|
||||
resultMap, outputCollect = sshTool.getSshStatusOutput(command,
|
||||
[host], env)
|
||||
self.logger.debug(host)
|
||||
self.logger.debug(outputCollect)
|
||||
|
||||
def buildInstance(self, host, datanode, mode, env):
|
||||
command = "source %s ; gs_ctl build -D %s -M %s" % (env, datanode, mode)
|
||||
self.logger.debug(command)
|
||||
sshTool = SshTool([host])
|
||||
resultMap, outputCollect = sshTool.getSshStatusOutput(command,
|
||||
[host], env)
|
||||
self.logger.debug(host)
|
||||
self.logger.debug(outputCollect)
|
||||
|
||||
def startOmCluster(self, host, env):
|
||||
"""
|
||||
om tool start cluster
|
||||
"""
|
||||
command = "source %s ; gs_om -t start" % env
|
||||
self.logger.debug(command)
|
||||
sshTool = SshTool([host])
|
||||
resultMap, outputCollect = sshTool.getSshStatusOutput(command,
|
||||
[host], env)
|
||||
self.logger.debug(host)
|
||||
self.logger.debug(outputCollect)
|
||||
|
||||
def queryOmCluster(self, host, env):
|
||||
"""
|
||||
query om cluster detail with command:
|
||||
gs_om -t status --detail
|
||||
"""
|
||||
command = "source %s ; gs_om -t status --detail" % env
|
||||
sshTool = SshTool([host])
|
||||
resultMap, outputCollect = sshTool.getSshStatusOutput(command,
|
||||
[host], env)
|
||||
self.logger.debug(host)
|
||||
self.logger.debug(outputCollect)
|
||||
return outputCollect
|
||||
|
||||
|
||||
|
|
@ -1146,6 +1146,7 @@ WHERE d.classoid IS NULL AND p1.oid <= 9999 order by 1;
|
|||
2096 | pg_terminate_backend
|
||||
2097 | pg_get_variable_info
|
||||
2098 | pg_get_functiondef
|
||||
2099 | pg_terminate_session
|
||||
2100 | avg
|
||||
2101 | avg
|
||||
2102 | avg
|
||||
|
|
@ -2637,7 +2638,7 @@ WHERE d.classoid IS NULL AND p1.oid <= 9999 order by 1;
|
|||
9016 | pg_advisory_lock
|
||||
9017 | pgxc_unlock_for_sp_database
|
||||
9999 | pg_test_err_contain_err
|
||||
(2275 rows)
|
||||
(2276 rows)
|
||||
|
||||
-- **************** pg_cast ****************
|
||||
-- Catch bogus values in pg_cast columns (other than cases detected by
|
||||
|
|
|
|||
|
|
@ -0,0 +1,751 @@
|
|||
DROP TABLE IF EXISTS pt2;
|
||||
NOTICE: table "pt2" does not exist, skipping
|
||||
DROP TABLE IF EXISTS pt1;
|
||||
NOTICE: table "pt1" does not exist, skipping
|
||||
CREATE TABLE pt1(
|
||||
d_date date UNIQUE
|
||||
)partition BY RANGE (d_date) INTERVAL('1 day')
|
||||
(PARTITION part1 VALUES LESS THAN ('1900-01-01'));
|
||||
NOTICE: CREATE TABLE / UNIQUE will create implicit index "pt1_d_date_key" for table "pt1"
|
||||
|
||||
CREATE TABLE pt2(
|
||||
d_date date
|
||||
)partition BY RANGE (d_date) INTERVAL('1 day')
|
||||
(PARTITION part1 VALUES LESS THAN ('1900-01-01'));
|
||||
|
||||
ALTER TABLE pt2 ADD CONSTRAINT test_foreign FOREIGN KEY(d_date)
|
||||
REFERENCES pt1(d_date) on UPDATE CASCADE ON DELETE CASCADE;
|
||||
|
||||
INSERT into pt1 VALUES('1999-01-01'),('1999-01-02'),('1999-01-03'),('1999-01-04');
|
||||
|
||||
INSERT into pt2 VALUES('1999-01-01');
|
||||
|
||||
INSERT into pt2 VALUES('2000-01-01');
|
||||
ERROR: insert or update on table "pt2" violates foreign key constraint "test_foreign"
|
||||
DETAIL: Key (d_date)=(Sat Jan 01 00:00:00 2000) is not present in table "pt1".
|
||||
|
||||
update pt2 set pt2.d_date = '2000-01-01' where pt2.d_date = '1999-01-01';
|
||||
ERROR: insert or update on table "pt2" violates foreign key constraint "test_foreign"
|
||||
DETAIL: Key (d_date)=(Sat Jan 01 00:00:00 2000) is not present in table "pt1".
|
||||
|
||||
update pt2 set pt2.d_date = '1999-01-02' where pt2.d_date = '1999-01-01';
|
||||
|
||||
SELECT * FROM pt2;
|
||||
d_date
|
||||
--------------------------
|
||||
Sat Jan 02 00:00:00 1999
|
||||
(1 row)
|
||||
|
||||
|
||||
SELECT * FROM pt2 PARTITION(sys_p2);
|
||||
d_date
|
||||
--------------------------
|
||||
Sat Jan 02 00:00:00 1999
|
||||
(1 row)
|
||||
|
||||
|
||||
delete from pt2;
|
||||
INSERT into pt2 VALUES('1999-01-01'), ('1999-01-03'),('1999-01-04');
|
||||
|
||||
INSERT into pt1 VALUES('1999-01-08');
|
||||
|
||||
INSERT into pt2 VALUES('1999-01-08');
|
||||
|
||||
update pt1 set pt1.d_date = '2000-01-01' where pt1.d_date = '1999-01-08';
|
||||
|
||||
delete from pt1 where pt1.d_date = '2000-01-01';
|
||||
|
||||
DROP TABLE pt2;
|
||||
DROP TABLE pt1;
|
||||
|
||||
CREATE TABLE pt1(
|
||||
d_date date UNIQUE
|
||||
)partition BY RANGE (d_date) INTERVAL('1 month')
|
||||
(PARTITION part1 VALUES LESS THAN ('1900-01-01'));
|
||||
NOTICE: CREATE TABLE / UNIQUE will create implicit index "pt1_d_date_key" for table "pt1"
|
||||
|
||||
CREATE TABLE pt2(
|
||||
d_date date
|
||||
)partition BY RANGE (d_date) INTERVAL('1 month')
|
||||
(PARTITION part1 VALUES LESS THAN ('1900-01-01'));
|
||||
|
||||
ALTER TABLE pt2 ADD CONSTRAINT test_foreign FOREIGN KEY(d_date)
|
||||
REFERENCES pt1(d_date) on UPDATE CASCADE ON DELETE CASCADE;
|
||||
|
||||
INSERT INTO pt1 VALUES
|
||||
('1999-01-01'),('1999-01-02'),('1999-01-019'),('1999-01-20'),
|
||||
('1999-02-01'),('1999-02-02'),('1999-02-19'),('1999-02-20'),
|
||||
('1999-03-01'),('1999-03-02'),('1999-03-19'),('1999-03-20'),
|
||||
('1999-04-01'),('1999-04-02'),('1999-04-19'),('1999-04-20'),
|
||||
('1999-05-01'),('1999-05-02'),('1999-05-19'),('1999-05-20'),
|
||||
('1999-06-01'),('1999-06-02'),('1999-06-19'),('1999-06-20'),
|
||||
('1999-07-01'),('1999-07-02'),('1999-07-19'),('1999-07-20'),
|
||||
('1999-08-01'),('1999-08-02'),('1999-08-19'),('1999-08-20'),
|
||||
('1999-09-01'),('1999-09-02'),('1999-09-19'),('1999-09-20'),
|
||||
('1999-10-01'),('1999-10-02'),('1999-10-19'),('1999-10-20'),
|
||||
('1999-11-01'),('1999-11-02'),('1999-11-19'),('1999-11-20'),
|
||||
('1999-12-01'),('1999-12-02'),('1999-12-19'),('1999-12-20');
|
||||
|
||||
INSERT INTO pt2 VALUES
|
||||
('1999-01-01'),('1999-01-02'),('1999-01-019'),('1999-01-20'),
|
||||
('1999-02-01'),('1999-02-02'),('1999-02-19'),('1999-02-20'),
|
||||
('1999-03-01'),('1999-03-02'),('1999-03-19'),('1999-03-20'),
|
||||
('1999-04-01'),('1999-04-02'),('1999-04-19'),('1999-04-20'),
|
||||
('1999-05-01'),('1999-05-02'),('1999-05-19'),('1999-05-20'),
|
||||
('1999-06-01'),('1999-06-02'),('1999-06-19'),('1999-06-20'),
|
||||
('1999-07-01'),('1999-07-02'),('1999-07-19'),('1999-07-20'),
|
||||
('1999-08-01'),('1999-08-02'),('1999-08-19'),('1999-08-20'),
|
||||
('1999-09-01'),('1999-09-02'),('1999-09-19'),('1999-09-20'),
|
||||
('1999-10-01'),('1999-10-02'),('1999-10-19'),('1999-10-20'),
|
||||
('1999-11-01'),('1999-11-02'),('1999-11-19'),('1999-11-20'),
|
||||
('1999-12-01'),('1999-12-02'),('1999-12-19'),('1999-12-20');
|
||||
|
||||
delete from pt2 where pt2.d_date<'1999-03-01';
|
||||
|
||||
select * from pt2 where pt2.d_date<'1999-06-01';
|
||||
d_date
|
||||
--------------------------
|
||||
Mon Mar 01 00:00:00 1999
|
||||
Tue Mar 02 00:00:00 1999
|
||||
Fri Mar 19 00:00:00 1999
|
||||
Sat Mar 20 00:00:00 1999
|
||||
Thu Apr 01 00:00:00 1999
|
||||
Fri Apr 02 00:00:00 1999
|
||||
Mon Apr 19 00:00:00 1999
|
||||
Tue Apr 20 00:00:00 1999
|
||||
Sat May 01 00:00:00 1999
|
||||
Sun May 02 00:00:00 1999
|
||||
Wed May 19 00:00:00 1999
|
||||
Thu May 20 00:00:00 1999
|
||||
(12 rows)
|
||||
|
||||
|
||||
delete from pt1 where pt1.d_date<'1999-05-01';
|
||||
|
||||
delete from pt2 where pt2.d_date>'1999-11-15' and pt2.d_date<'1999-12-15';
|
||||
SELECT * FROM pt2 WHERE pt2.d_date>='1999-10-01';
|
||||
d_date
|
||||
--------------------------
|
||||
Fri Oct 01 00:00:00 1999
|
||||
Sat Oct 02 00:00:00 1999
|
||||
Tue Oct 19 00:00:00 1999
|
||||
Wed Oct 20 00:00:00 1999
|
||||
Mon Nov 01 00:00:00 1999
|
||||
Tue Nov 02 00:00:00 1999
|
||||
Sun Dec 19 00:00:00 1999
|
||||
Mon Dec 20 00:00:00 1999
|
||||
(8 rows)
|
||||
|
||||
|
||||
delete from pt1 where pt1.d_date>'1999-10-15' and pt1.d_date<'1999-11-15';
|
||||
SELECT * FROM pt1 WHERE pt1.d_date>='1999-10-01';
|
||||
d_date
|
||||
--------------------------
|
||||
Fri Oct 01 00:00:00 1999
|
||||
Sat Oct 02 00:00:00 1999
|
||||
Fri Nov 19 00:00:00 1999
|
||||
Sat Nov 20 00:00:00 1999
|
||||
Wed Dec 01 00:00:00 1999
|
||||
Thu Dec 02 00:00:00 1999
|
||||
Sun Dec 19 00:00:00 1999
|
||||
Mon Dec 20 00:00:00 1999
|
||||
(8 rows)
|
||||
|
||||
|
||||
SELECT * FROM pt2 WHERE pt2.d_date>='1999-10-01';
|
||||
d_date
|
||||
--------------------------
|
||||
Fri Oct 01 00:00:00 1999
|
||||
Sat Oct 02 00:00:00 1999
|
||||
Sun Dec 19 00:00:00 1999
|
||||
Mon Dec 20 00:00:00 1999
|
||||
(4 rows)
|
||||
|
||||
|
||||
UPDATE pt2 set d_date = d_date - INTERVAL '4' month where d_date>='1999-05-01' and d_date<'1999-06-01';
|
||||
ERROR: insert or update on table "pt2" violates foreign key constraint "test_foreign"
|
||||
DETAIL: Key (d_date)=(Fri Jan 01 00:00:00 1999) is not present in table "pt1".
|
||||
|
||||
UPDATE pt1 set d_date = d_date - INTERVAL '4' month where d_date>='1999-05-01' and d_date<'1999-06-01';
|
||||
SELECT * FROM pt1 WHERE d_date<'1999-07-01';
|
||||
d_date
|
||||
--------------------------
|
||||
Fri Jan 01 00:00:00 1999
|
||||
Sat Jan 02 00:00:00 1999
|
||||
Tue Jan 19 00:00:00 1999
|
||||
Wed Jan 20 00:00:00 1999
|
||||
Tue Jun 01 00:00:00 1999
|
||||
Wed Jun 02 00:00:00 1999
|
||||
Sat Jun 19 00:00:00 1999
|
||||
Sun Jun 20 00:00:00 1999
|
||||
(8 rows)
|
||||
|
||||
|
||||
SELECT * FROM pt1 WHERE d_date<'1999-07-01';
|
||||
d_date
|
||||
--------------------------
|
||||
Fri Jan 01 00:00:00 1999
|
||||
Sat Jan 02 00:00:00 1999
|
||||
Tue Jan 19 00:00:00 1999
|
||||
Wed Jan 20 00:00:00 1999
|
||||
Tue Jun 01 00:00:00 1999
|
||||
Wed Jun 02 00:00:00 1999
|
||||
Sat Jun 19 00:00:00 1999
|
||||
Sun Jun 20 00:00:00 1999
|
||||
(8 rows)
|
||||
|
||||
|
||||
UPDATE pt2 set d_date = d_date - INTERVAL '1' month where d_date>='1999-06-01' and d_date<='1999-07-15';
|
||||
ERROR: insert or update on table "pt2" violates foreign key constraint "test_foreign"
|
||||
DETAIL: Key (d_date)=(Sat May 01 00:00:00 1999) is not present in table "pt1".
|
||||
|
||||
UPDATE pt1 set d_date = d_date - INTERVAL '1' month where d_date>='1999-06-01' and d_date<='1999-07-15';
|
||||
SELECT * FROM pt1 WHERE d_date<'1999-08-01';
|
||||
d_date
|
||||
--------------------------
|
||||
Fri Jan 01 00:00:00 1999
|
||||
Sat Jan 02 00:00:00 1999
|
||||
Tue Jan 19 00:00:00 1999
|
||||
Wed Jan 20 00:00:00 1999
|
||||
Sat May 01 00:00:00 1999
|
||||
Sun May 02 00:00:00 1999
|
||||
Wed May 19 00:00:00 1999
|
||||
Thu May 20 00:00:00 1999
|
||||
Tue Jun 01 00:00:00 1999
|
||||
Wed Jun 02 00:00:00 1999
|
||||
Mon Jul 19 00:00:00 1999
|
||||
Tue Jul 20 00:00:00 1999
|
||||
(12 rows)
|
||||
|
||||
|
||||
SELECT * FROM pt2 WHERE d_date<'1999-08-01';
|
||||
d_date
|
||||
--------------------------
|
||||
Fri Jan 01 00:00:00 1999
|
||||
Sat Jan 02 00:00:00 1999
|
||||
Tue Jan 19 00:00:00 1999
|
||||
Wed Jan 20 00:00:00 1999
|
||||
Sat May 01 00:00:00 1999
|
||||
Sun May 02 00:00:00 1999
|
||||
Wed May 19 00:00:00 1999
|
||||
Thu May 20 00:00:00 1999
|
||||
Tue Jun 01 00:00:00 1999
|
||||
Wed Jun 02 00:00:00 1999
|
||||
Mon Jul 19 00:00:00 1999
|
||||
Tue Jul 20 00:00:00 1999
|
||||
(12 rows)
|
||||
|
||||
|
||||
DROP TABLE IF EXISTS pt2;
|
||||
DROP TABLE IF EXISTS pt1;
|
||||
|
||||
CREATE TABLE pt1(
|
||||
d_date date UNIQUE
|
||||
)partition BY RANGE (d_date) INTERVAL('1 month')
|
||||
(PARTITION part1 VALUES LESS THAN ('1900-01-01'))
|
||||
;
|
||||
NOTICE: CREATE TABLE / UNIQUE will create implicit index "pt1_d_date_key" for table "pt1"
|
||||
|
||||
CREATE TABLE pt2(
|
||||
d_date date,
|
||||
d_date_backup date
|
||||
)partition BY RANGE (d_date_backup) INTERVAL('1 month')
|
||||
(PARTITION part1 VALUES LESS THAN ('1900-01-01'));
|
||||
|
||||
|
||||
ALTER TABLE pt2 ADD CONSTRAINT test_foreign FOREIGN KEY(d_date)
|
||||
REFERENCES pt1(d_date) on UPDATE SET NULL ON DELETE SET NULL;
|
||||
|
||||
INSERT INTO pt1 VALUES
|
||||
('1999-01-01'),('1999-01-02'),('1999-01-019'),('1999-01-20'),
|
||||
('1999-02-01'),('1999-02-02'),('1999-02-19'),('1999-02-20'),
|
||||
('1999-03-01'),('1999-03-02'),('1999-03-19'),('1999-03-20'),
|
||||
('1999-04-01'),('1999-04-02'),('1999-04-19'),('1999-04-20'),
|
||||
('1999-05-01'),('1999-05-02'),('1999-05-19'),('1999-05-20'),
|
||||
('1999-06-01'),('1999-06-02'),('1999-06-19'),('1999-06-20'),
|
||||
('1999-07-01'),('1999-07-02'),('1999-07-19'),('1999-07-20'),
|
||||
('1999-08-01'),('1999-08-02'),('1999-08-19'),('1999-08-20'),
|
||||
('1999-09-01'),('1999-09-02'),('1999-09-19'),('1999-09-20'),
|
||||
('1999-10-01'),('1999-10-02'),('1999-10-19'),('1999-10-20'),
|
||||
('1999-11-01'),('1999-11-02'),('1999-11-19'),('1999-11-20'),
|
||||
('1999-12-01'),('1999-12-02'),('1999-12-19'),('1999-12-20');
|
||||
|
||||
INSERT INTO pt2 VALUES
|
||||
('1999-01-01','1999-01-01'),('1999-01-02','1999-01-02'),
|
||||
('1999-01-19','1999-01-19'),('1999-01-20','1999-01-20'),
|
||||
('1999-02-01','1999-02-01'),('1999-02-02','1999-02-02'),
|
||||
('1999-02-19','1999-02-19'),('1999-02-20','1999-02-20'),
|
||||
('1999-03-01','1999-03-01'),('1999-03-02','1999-03-02'),
|
||||
('1999-03-19','1999-03-19'),('1999-03-20','1999-03-20'),
|
||||
('1999-04-01','1999-04-01'),('1999-04-02','1999-04-02'),
|
||||
('1999-04-19','1999-04-19'),('1999-04-20','1999-04-20'),
|
||||
('1999-05-01','1999-05-01'),('1999-05-02','1999-05-02'),
|
||||
('1999-05-19','1999-05-19'),('1999-05-20','1999-05-20'),
|
||||
('1999-06-01','1999-06-01'),('1999-06-02','1999-06-02'),
|
||||
('1999-06-19','1999-06-19'),('1999-06-20','1999-06-20'),
|
||||
('1999-07-01','1999-07-01'),('1999-07-02','1999-07-02'),
|
||||
('1999-07-19','1999-07-19'),('1999-07-20','1999-07-20'),
|
||||
('1999-08-01','1999-08-01'),('1999-08-02','1999-08-02'),
|
||||
('1999-08-19','1999-08-19'),('1999-08-20','1999-08-20'),
|
||||
('1999-09-01','1999-09-01'),('1999-09-02','1999-09-02'),
|
||||
('1999-09-19','1999-09-19'),('1999-09-20','1999-09-20'),
|
||||
('1999-10-01','1999-10-01'),('1999-10-02','1999-10-02'),
|
||||
('1999-10-19','1999-10-19'),('1999-10-20','1999-10-20'),
|
||||
('1999-11-01','1999-11-01'),('1999-11-02','1999-11-02'),
|
||||
('1999-11-19','1999-11-19'),('1999-11-20','1999-11-20'),
|
||||
('1999-12-01','1999-12-01'),('1999-12-02','1999-12-02'),
|
||||
('1999-12-19','1999-12-19'),('1999-12-20','1999-12-20');
|
||||
|
||||
insert into pt1 VALUES('2000-01-01'),('2000-01-02'),
|
||||
('2000-01-19'),('2000-01-20'),
|
||||
('2000-02-01'),('2000-02-02'),
|
||||
('2000-02-19'),('2000-02-20');
|
||||
SELECT * FROM pt1 WHERE d_date>='2000-01-01';
|
||||
d_date
|
||||
--------------------------
|
||||
Sat Jan 01 00:00:00 2000
|
||||
Sun Jan 02 00:00:00 2000
|
||||
Wed Jan 19 00:00:00 2000
|
||||
Thu Jan 20 00:00:00 2000
|
||||
Tue Feb 01 00:00:00 2000
|
||||
Wed Feb 02 00:00:00 2000
|
||||
Sat Feb 19 00:00:00 2000
|
||||
Sun Feb 20 00:00:00 2000
|
||||
(8 rows)
|
||||
|
||||
|
||||
update pt1 set d_date = '2000-02-21' WHERE d_date = '2000-02-20';
|
||||
SELECT * FROM pt1 WHERE d_date>='2000-02-01';
|
||||
d_date
|
||||
--------------------------
|
||||
Tue Feb 01 00:00:00 2000
|
||||
Wed Feb 02 00:00:00 2000
|
||||
Sat Feb 19 00:00:00 2000
|
||||
Mon Feb 21 00:00:00 2000
|
||||
(4 rows)
|
||||
|
||||
|
||||
DELETE FROM pt1 WHERE d_date = '2000-02-21';
|
||||
SELECT * FROM pt1 WHERE d_date>='2000-02-01';
|
||||
d_date
|
||||
--------------------------
|
||||
Tue Feb 01 00:00:00 2000
|
||||
Wed Feb 02 00:00:00 2000
|
||||
Sat Feb 19 00:00:00 2000
|
||||
(3 rows)
|
||||
|
||||
|
||||
SELECT * FROM pt1 PARTITION FOR('1999-06-16');
|
||||
d_date
|
||||
--------------------------
|
||||
Tue Jun 01 00:00:00 1999
|
||||
Wed Jun 02 00:00:00 1999
|
||||
Sat Jun 19 00:00:00 1999
|
||||
Sun Jun 20 00:00:00 1999
|
||||
(4 rows)
|
||||
|
||||
|
||||
INSERT into pt2 VALUES('2020-08-19','2020-08-19');
|
||||
ERROR: insert or update on table "pt2" violates foreign key constraint "test_foreign"
|
||||
DETAIL: Key (d_date)=(Wed Aug 19 00:00:00 2020) is not present in table "pt1".
|
||||
|
||||
INSERT into pt2 VALUES('2000-01-01','2000-01-01');
|
||||
|
||||
update pt2 set pt2.d_date = '2020-08-13'
|
||||
where pt2.d_date = '1999-01-01';
|
||||
ERROR: insert or update on table "pt2" violates foreign key constraint "test_foreign"
|
||||
DETAIL: Key (d_date)=(Thu Aug 13 00:00:00 2020) is not present in table "pt1".
|
||||
|
||||
update pt2 set pt2.d_date = '2000-02-01',pt2.d_date_backup = '2000-02-01'
|
||||
where pt2.d_date = '2000-01-01';
|
||||
|
||||
SELECT * FROM pt2;
|
||||
d_date | d_date_backup
|
||||
--------------------------+--------------------------
|
||||
Fri Jan 01 00:00:00 1999 | Fri Jan 01 00:00:00 1999
|
||||
Sat Jan 02 00:00:00 1999 | Sat Jan 02 00:00:00 1999
|
||||
Tue Jan 19 00:00:00 1999 | Tue Jan 19 00:00:00 1999
|
||||
Wed Jan 20 00:00:00 1999 | Wed Jan 20 00:00:00 1999
|
||||
Mon Feb 01 00:00:00 1999 | Mon Feb 01 00:00:00 1999
|
||||
Tue Feb 02 00:00:00 1999 | Tue Feb 02 00:00:00 1999
|
||||
Fri Feb 19 00:00:00 1999 | Fri Feb 19 00:00:00 1999
|
||||
Sat Feb 20 00:00:00 1999 | Sat Feb 20 00:00:00 1999
|
||||
Mon Mar 01 00:00:00 1999 | Mon Mar 01 00:00:00 1999
|
||||
Tue Mar 02 00:00:00 1999 | Tue Mar 02 00:00:00 1999
|
||||
Fri Mar 19 00:00:00 1999 | Fri Mar 19 00:00:00 1999
|
||||
Sat Mar 20 00:00:00 1999 | Sat Mar 20 00:00:00 1999
|
||||
Thu Apr 01 00:00:00 1999 | Thu Apr 01 00:00:00 1999
|
||||
Fri Apr 02 00:00:00 1999 | Fri Apr 02 00:00:00 1999
|
||||
Mon Apr 19 00:00:00 1999 | Mon Apr 19 00:00:00 1999
|
||||
Tue Apr 20 00:00:00 1999 | Tue Apr 20 00:00:00 1999
|
||||
Sat May 01 00:00:00 1999 | Sat May 01 00:00:00 1999
|
||||
Sun May 02 00:00:00 1999 | Sun May 02 00:00:00 1999
|
||||
Wed May 19 00:00:00 1999 | Wed May 19 00:00:00 1999
|
||||
Thu May 20 00:00:00 1999 | Thu May 20 00:00:00 1999
|
||||
Tue Jun 01 00:00:00 1999 | Tue Jun 01 00:00:00 1999
|
||||
Wed Jun 02 00:00:00 1999 | Wed Jun 02 00:00:00 1999
|
||||
Sat Jun 19 00:00:00 1999 | Sat Jun 19 00:00:00 1999
|
||||
Sun Jun 20 00:00:00 1999 | Sun Jun 20 00:00:00 1999
|
||||
Thu Jul 01 00:00:00 1999 | Thu Jul 01 00:00:00 1999
|
||||
Fri Jul 02 00:00:00 1999 | Fri Jul 02 00:00:00 1999
|
||||
Mon Jul 19 00:00:00 1999 | Mon Jul 19 00:00:00 1999
|
||||
Tue Jul 20 00:00:00 1999 | Tue Jul 20 00:00:00 1999
|
||||
Sun Aug 01 00:00:00 1999 | Sun Aug 01 00:00:00 1999
|
||||
Mon Aug 02 00:00:00 1999 | Mon Aug 02 00:00:00 1999
|
||||
Thu Aug 19 00:00:00 1999 | Thu Aug 19 00:00:00 1999
|
||||
Fri Aug 20 00:00:00 1999 | Fri Aug 20 00:00:00 1999
|
||||
Wed Sep 01 00:00:00 1999 | Wed Sep 01 00:00:00 1999
|
||||
Thu Sep 02 00:00:00 1999 | Thu Sep 02 00:00:00 1999
|
||||
Sun Sep 19 00:00:00 1999 | Sun Sep 19 00:00:00 1999
|
||||
Mon Sep 20 00:00:00 1999 | Mon Sep 20 00:00:00 1999
|
||||
Fri Oct 01 00:00:00 1999 | Fri Oct 01 00:00:00 1999
|
||||
Sat Oct 02 00:00:00 1999 | Sat Oct 02 00:00:00 1999
|
||||
Tue Oct 19 00:00:00 1999 | Tue Oct 19 00:00:00 1999
|
||||
Wed Oct 20 00:00:00 1999 | Wed Oct 20 00:00:00 1999
|
||||
Mon Nov 01 00:00:00 1999 | Mon Nov 01 00:00:00 1999
|
||||
Tue Nov 02 00:00:00 1999 | Tue Nov 02 00:00:00 1999
|
||||
Fri Nov 19 00:00:00 1999 | Fri Nov 19 00:00:00 1999
|
||||
Sat Nov 20 00:00:00 1999 | Sat Nov 20 00:00:00 1999
|
||||
Wed Dec 01 00:00:00 1999 | Wed Dec 01 00:00:00 1999
|
||||
Thu Dec 02 00:00:00 1999 | Thu Dec 02 00:00:00 1999
|
||||
Sun Dec 19 00:00:00 1999 | Sun Dec 19 00:00:00 1999
|
||||
Mon Dec 20 00:00:00 1999 | Mon Dec 20 00:00:00 1999
|
||||
Tue Feb 01 00:00:00 2000 | Tue Feb 01 00:00:00 2000
|
||||
(49 rows)
|
||||
|
||||
|
||||
SELECT * FROM pt2 PARTITION(sys_p2);
|
||||
d_date | d_date_backup
|
||||
--------------------------+--------------------------
|
||||
Mon Feb 01 00:00:00 1999 | Mon Feb 01 00:00:00 1999
|
||||
Tue Feb 02 00:00:00 1999 | Tue Feb 02 00:00:00 1999
|
||||
Fri Feb 19 00:00:00 1999 | Fri Feb 19 00:00:00 1999
|
||||
Sat Feb 20 00:00:00 1999 | Sat Feb 20 00:00:00 1999
|
||||
(4 rows)
|
||||
|
||||
|
||||
delete from pt2 where pt2.d_date<'1999-03-01';
|
||||
select * from pt2 where pt2.d_date<'1999-06-01';
|
||||
d_date | d_date_backup
|
||||
--------------------------+--------------------------
|
||||
Mon Mar 01 00:00:00 1999 | Mon Mar 01 00:00:00 1999
|
||||
Tue Mar 02 00:00:00 1999 | Tue Mar 02 00:00:00 1999
|
||||
Fri Mar 19 00:00:00 1999 | Fri Mar 19 00:00:00 1999
|
||||
Sat Mar 20 00:00:00 1999 | Sat Mar 20 00:00:00 1999
|
||||
Thu Apr 01 00:00:00 1999 | Thu Apr 01 00:00:00 1999
|
||||
Fri Apr 02 00:00:00 1999 | Fri Apr 02 00:00:00 1999
|
||||
Mon Apr 19 00:00:00 1999 | Mon Apr 19 00:00:00 1999
|
||||
Tue Apr 20 00:00:00 1999 | Tue Apr 20 00:00:00 1999
|
||||
Sat May 01 00:00:00 1999 | Sat May 01 00:00:00 1999
|
||||
Sun May 02 00:00:00 1999 | Sun May 02 00:00:00 1999
|
||||
Wed May 19 00:00:00 1999 | Wed May 19 00:00:00 1999
|
||||
Thu May 20 00:00:00 1999 | Thu May 20 00:00:00 1999
|
||||
(12 rows)
|
||||
|
||||
|
||||
delete from pt1 where d_date<'1999-05-01';
|
||||
select * from pt1 where d_date<'1999-06-01';
|
||||
d_date
|
||||
--------------------------
|
||||
Sat May 01 00:00:00 1999
|
||||
Sun May 02 00:00:00 1999
|
||||
Wed May 19 00:00:00 1999
|
||||
Thu May 20 00:00:00 1999
|
||||
(4 rows)
|
||||
|
||||
|
||||
select * from pt2 where d_date_backup<'1999-06-01';
|
||||
d_date | d_date_backup
|
||||
--------------------------+--------------------------
|
||||
| Mon Mar 01 00:00:00 1999
|
||||
| Tue Mar 02 00:00:00 1999
|
||||
| Fri Mar 19 00:00:00 1999
|
||||
| Sat Mar 20 00:00:00 1999
|
||||
| Thu Apr 01 00:00:00 1999
|
||||
| Fri Apr 02 00:00:00 1999
|
||||
| Mon Apr 19 00:00:00 1999
|
||||
| Tue Apr 20 00:00:00 1999
|
||||
Sat May 01 00:00:00 1999 | Sat May 01 00:00:00 1999
|
||||
Sun May 02 00:00:00 1999 | Sun May 02 00:00:00 1999
|
||||
Wed May 19 00:00:00 1999 | Wed May 19 00:00:00 1999
|
||||
Thu May 20 00:00:00 1999 | Thu May 20 00:00:00 1999
|
||||
(12 rows)
|
||||
|
||||
|
||||
delete from pt2 where pt2.d_date>'1999-11-15' and pt2.d_date<'1999-12-15';
|
||||
SELECT * FROM pt2 WHERE pt2.d_date>='1999-10-01';
|
||||
d_date | d_date_backup
|
||||
--------------------------+--------------------------
|
||||
Fri Oct 01 00:00:00 1999 | Fri Oct 01 00:00:00 1999
|
||||
Sat Oct 02 00:00:00 1999 | Sat Oct 02 00:00:00 1999
|
||||
Tue Oct 19 00:00:00 1999 | Tue Oct 19 00:00:00 1999
|
||||
Wed Oct 20 00:00:00 1999 | Wed Oct 20 00:00:00 1999
|
||||
Mon Nov 01 00:00:00 1999 | Mon Nov 01 00:00:00 1999
|
||||
Tue Nov 02 00:00:00 1999 | Tue Nov 02 00:00:00 1999
|
||||
Sun Dec 19 00:00:00 1999 | Sun Dec 19 00:00:00 1999
|
||||
Mon Dec 20 00:00:00 1999 | Mon Dec 20 00:00:00 1999
|
||||
Tue Feb 01 00:00:00 2000 | Tue Feb 01 00:00:00 2000
|
||||
(9 rows)
|
||||
|
||||
|
||||
delete from pt1 where pt1.d_date>'1999-10-15' and pt1.d_date<'1999-11-15';
|
||||
SELECT * FROM pt1 WHERE pt1.d_date>='1999-10-01';
|
||||
d_date
|
||||
--------------------------
|
||||
Fri Oct 01 00:00:00 1999
|
||||
Sat Oct 02 00:00:00 1999
|
||||
Fri Nov 19 00:00:00 1999
|
||||
Sat Nov 20 00:00:00 1999
|
||||
Wed Dec 01 00:00:00 1999
|
||||
Thu Dec 02 00:00:00 1999
|
||||
Sun Dec 19 00:00:00 1999
|
||||
Mon Dec 20 00:00:00 1999
|
||||
Sat Jan 01 00:00:00 2000
|
||||
Sun Jan 02 00:00:00 2000
|
||||
Wed Jan 19 00:00:00 2000
|
||||
Thu Jan 20 00:00:00 2000
|
||||
Tue Feb 01 00:00:00 2000
|
||||
Wed Feb 02 00:00:00 2000
|
||||
Sat Feb 19 00:00:00 2000
|
||||
(15 rows)
|
||||
|
||||
|
||||
SELECT * FROM pt2 WHERE pt2.d_date_backup>='1999-10-01';
|
||||
d_date | d_date_backup
|
||||
--------------------------+--------------------------
|
||||
Fri Oct 01 00:00:00 1999 | Fri Oct 01 00:00:00 1999
|
||||
Sat Oct 02 00:00:00 1999 | Sat Oct 02 00:00:00 1999
|
||||
| Tue Oct 19 00:00:00 1999
|
||||
| Wed Oct 20 00:00:00 1999
|
||||
| Mon Nov 01 00:00:00 1999
|
||||
| Tue Nov 02 00:00:00 1999
|
||||
Sun Dec 19 00:00:00 1999 | Sun Dec 19 00:00:00 1999
|
||||
Mon Dec 20 00:00:00 1999 | Mon Dec 20 00:00:00 1999
|
||||
Tue Feb 01 00:00:00 2000 | Tue Feb 01 00:00:00 2000
|
||||
(9 rows)
|
||||
|
||||
|
||||
UPDATE pt2 set d_date = d_date - INTERVAL '4' month where d_date>='1999-05-01' and d_date<'1999-06-01';
|
||||
ERROR: insert or update on table "pt2" violates foreign key constraint "test_foreign"
|
||||
DETAIL: Key (d_date)=(Fri Jan 01 00:00:00 1999) is not present in table "pt1".
|
||||
|
||||
UPDATE pt1 set d_date = d_date - INTERVAL '4' month where d_date>='1999-05-01' and d_date<'1999-06-01';
|
||||
SELECT * FROM pt1 WHERE d_date<'1999-07-01';
|
||||
d_date
|
||||
--------------------------
|
||||
Fri Jan 01 00:00:00 1999
|
||||
Sat Jan 02 00:00:00 1999
|
||||
Tue Jan 19 00:00:00 1999
|
||||
Wed Jan 20 00:00:00 1999
|
||||
Tue Jun 01 00:00:00 1999
|
||||
Wed Jun 02 00:00:00 1999
|
||||
Sat Jun 19 00:00:00 1999
|
||||
Sun Jun 20 00:00:00 1999
|
||||
(8 rows)
|
||||
|
||||
|
||||
SELECT * FROM pt2 WHERE d_date_backup<'1999-07-01';
|
||||
d_date | d_date_backup
|
||||
--------------------------+--------------------------
|
||||
| Mon Mar 01 00:00:00 1999
|
||||
| Tue Mar 02 00:00:00 1999
|
||||
| Fri Mar 19 00:00:00 1999
|
||||
| Sat Mar 20 00:00:00 1999
|
||||
| Thu Apr 01 00:00:00 1999
|
||||
| Fri Apr 02 00:00:00 1999
|
||||
| Mon Apr 19 00:00:00 1999
|
||||
| Tue Apr 20 00:00:00 1999
|
||||
| Sat May 01 00:00:00 1999
|
||||
| Sun May 02 00:00:00 1999
|
||||
| Wed May 19 00:00:00 1999
|
||||
| Thu May 20 00:00:00 1999
|
||||
Tue Jun 01 00:00:00 1999 | Tue Jun 01 00:00:00 1999
|
||||
Wed Jun 02 00:00:00 1999 | Wed Jun 02 00:00:00 1999
|
||||
Sat Jun 19 00:00:00 1999 | Sat Jun 19 00:00:00 1999
|
||||
Sun Jun 20 00:00:00 1999 | Sun Jun 20 00:00:00 1999
|
||||
(16 rows)
|
||||
|
||||
|
||||
UPDATE pt2 set d_date = d_date - INTERVAL '1' month where d_date>='1999-06-01' and d_date<='1999-07-15';
|
||||
ERROR: insert or update on table "pt2" violates foreign key constraint "test_foreign"
|
||||
DETAIL: Key (d_date)=(Sat May 01 00:00:00 1999) is not present in table "pt1".
|
||||
|
||||
UPDATE pt1 set d_date = d_date - INTERVAL '1' month where d_date>='1999-06-01' and d_date<='1999-07-15';
|
||||
SELECT * FROM pt1 WHERE d_date<'1999-08-01';
|
||||
d_date
|
||||
--------------------------
|
||||
Fri Jan 01 00:00:00 1999
|
||||
Sat Jan 02 00:00:00 1999
|
||||
Tue Jan 19 00:00:00 1999
|
||||
Wed Jan 20 00:00:00 1999
|
||||
Sat May 01 00:00:00 1999
|
||||
Sun May 02 00:00:00 1999
|
||||
Wed May 19 00:00:00 1999
|
||||
Thu May 20 00:00:00 1999
|
||||
Tue Jun 01 00:00:00 1999
|
||||
Wed Jun 02 00:00:00 1999
|
||||
Mon Jul 19 00:00:00 1999
|
||||
Tue Jul 20 00:00:00 1999
|
||||
(12 rows)
|
||||
|
||||
|
||||
SELECT * FROM pt2 WHERE d_date_backup<'1999-08-01';
|
||||
d_date | d_date_backup
|
||||
--------------------------+--------------------------
|
||||
| Mon Mar 01 00:00:00 1999
|
||||
| Tue Mar 02 00:00:00 1999
|
||||
| Fri Mar 19 00:00:00 1999
|
||||
| Sat Mar 20 00:00:00 1999
|
||||
| Thu Apr 01 00:00:00 1999
|
||||
| Fri Apr 02 00:00:00 1999
|
||||
| Mon Apr 19 00:00:00 1999
|
||||
| Tue Apr 20 00:00:00 1999
|
||||
| Sat May 01 00:00:00 1999
|
||||
| Sun May 02 00:00:00 1999
|
||||
| Wed May 19 00:00:00 1999
|
||||
| Thu May 20 00:00:00 1999
|
||||
| Tue Jun 01 00:00:00 1999
|
||||
| Wed Jun 02 00:00:00 1999
|
||||
| Sat Jun 19 00:00:00 1999
|
||||
| Sun Jun 20 00:00:00 1999
|
||||
Mon Jul 19 00:00:00 1999 | Mon Jul 19 00:00:00 1999
|
||||
Tue Jul 20 00:00:00 1999 | Tue Jul 20 00:00:00 1999
|
||||
| Thu Jul 01 00:00:00 1999
|
||||
| Fri Jul 02 00:00:00 1999
|
||||
(20 rows)
|
||||
|
||||
|
||||
DROP TABLE IF EXISTS pt2;
|
||||
DROP TABLE IF EXISTS pt1;
|
||||
|
||||
CREATE TABLE pt1(
|
||||
d_date date UNIQUE
|
||||
)partition BY RANGE (d_date) INTERVAL('1 month')
|
||||
(PARTITION part1 VALUES LESS THAN ('1900-01-01'));
|
||||
NOTICE: CREATE TABLE / UNIQUE will create implicit index "pt1_d_date_key" for table "pt1"
|
||||
|
||||
CREATE TABLE pt2(
|
||||
d_date date,
|
||||
d_date_backup date
|
||||
)partition BY RANGE (d_date_backup) INTERVAL('1 month')
|
||||
(PARTITION part1 VALUES LESS THAN ('1900-01-01'));
|
||||
|
||||
|
||||
ALTER TABLE pt2 ADD CONSTRAINT test_foreign FOREIGN KEY(d_date)
|
||||
REFERENCES pt1(d_date) on UPDATE RESTRICT ON DELETE RESTRICT;
|
||||
|
||||
INSERT INTO pt1 VALUES
|
||||
('1999-01-01'),('1999-01-02'),('1999-01-019'),('1999-01-20'),
|
||||
('1999-02-01'),('1999-02-02'),('1999-02-19'),('1999-02-20'),
|
||||
('1999-03-01'),('1999-03-02'),('1999-03-19'),('1999-03-20'),
|
||||
('1999-04-01'),('1999-04-02'),('1999-04-19'),('1999-04-20'),
|
||||
('1999-05-01'),('1999-05-02'),('1999-05-19'),('1999-05-20'),
|
||||
('1999-06-01'),('1999-06-02'),('1999-06-19'),('1999-06-20'),
|
||||
('1999-07-01'),('1999-07-02'),('1999-07-19'),('1999-07-20'),
|
||||
('1999-08-01'),('1999-08-02'),('1999-08-19'),('1999-08-20'),
|
||||
('1999-09-01'),('1999-09-02'),('1999-09-19'),('1999-09-20'),
|
||||
('1999-10-01'),('1999-10-02'),('1999-10-19'),('1999-10-20'),
|
||||
('1999-11-01'),('1999-11-02'),('1999-11-19'),('1999-11-20'),
|
||||
('1999-12-01'),('1999-12-02'),('1999-12-19'),('1999-12-20');
|
||||
|
||||
INSERT INTO pt2 VALUES
|
||||
('1999-01-01','1999-01-01'),('1999-01-02','1999-01-02'),
|
||||
('1999-01-19','1999-01-19'),('1999-01-20','1999-01-20'),
|
||||
('1999-02-01','1999-02-01'),('1999-02-02','1999-02-02'),
|
||||
('1999-02-19','1999-02-19'),('1999-02-20','1999-02-20'),
|
||||
('1999-03-01','1999-03-01'),('1999-03-02','1999-03-02'),
|
||||
('1999-03-19','1999-03-19'),('1999-03-20','1999-03-20'),
|
||||
('1999-04-01','1999-04-01'),('1999-04-02','1999-04-02'),
|
||||
('1999-04-19','1999-04-19'),('1999-04-20','1999-04-20'),
|
||||
('1999-05-01','1999-05-01'),('1999-05-02','1999-05-02'),
|
||||
('1999-05-19','1999-05-19'),('1999-05-20','1999-05-20'),
|
||||
('1999-06-01','1999-06-01'),('1999-06-02','1999-06-02'),
|
||||
('1999-06-19','1999-06-19'),('1999-06-20','1999-06-20'),
|
||||
('1999-07-01','1999-07-01'),('1999-07-02','1999-07-02'),
|
||||
('1999-07-19','1999-07-19'),('1999-07-20','1999-07-20'),
|
||||
('1999-08-01','1999-08-01'),('1999-08-02','1999-08-02'),
|
||||
('1999-08-19','1999-08-19'),('1999-08-20','1999-08-20'),
|
||||
('1999-09-01','1999-09-01'),('1999-09-02','1999-09-02'),
|
||||
('1999-09-19','1999-09-19'),('1999-09-20','1999-09-20'),
|
||||
('1999-10-01','1999-10-01'),('1999-10-02','1999-10-02'),
|
||||
('1999-10-19','1999-10-19'),('1999-10-20','1999-10-20'),
|
||||
('1999-11-01','1999-11-01'),('1999-11-02','1999-11-02'),
|
||||
('1999-11-19','1999-11-19'),('1999-11-20','1999-11-20'),
|
||||
('1999-12-01','1999-12-01'),('1999-12-02','1999-12-02'),
|
||||
('1999-12-19','1999-12-19'),('1999-12-20','1999-12-20');
|
||||
|
||||
delete from pt2 where pt2.d_date<'1999-03-01';
|
||||
select * from pt2 where pt2.d_date<'1999-06-01';
|
||||
d_date | d_date_backup
|
||||
--------------------------+--------------------------
|
||||
Mon Mar 01 00:00:00 1999 | Mon Mar 01 00:00:00 1999
|
||||
Tue Mar 02 00:00:00 1999 | Tue Mar 02 00:00:00 1999
|
||||
Fri Mar 19 00:00:00 1999 | Fri Mar 19 00:00:00 1999
|
||||
Sat Mar 20 00:00:00 1999 | Sat Mar 20 00:00:00 1999
|
||||
Thu Apr 01 00:00:00 1999 | Thu Apr 01 00:00:00 1999
|
||||
Fri Apr 02 00:00:00 1999 | Fri Apr 02 00:00:00 1999
|
||||
Mon Apr 19 00:00:00 1999 | Mon Apr 19 00:00:00 1999
|
||||
Tue Apr 20 00:00:00 1999 | Tue Apr 20 00:00:00 1999
|
||||
Sat May 01 00:00:00 1999 | Sat May 01 00:00:00 1999
|
||||
Sun May 02 00:00:00 1999 | Sun May 02 00:00:00 1999
|
||||
Wed May 19 00:00:00 1999 | Wed May 19 00:00:00 1999
|
||||
Thu May 20 00:00:00 1999 | Thu May 20 00:00:00 1999
|
||||
(12 rows)
|
||||
|
||||
|
||||
delete from pt1 where d_date<'1999-05-01';
|
||||
ERROR: update or delete on table "pt1" violates foreign key constraint "test_foreign" on table "pt2"
|
||||
DETAIL: Key (d_date)=(Mon Mar 01 00:00:00 1999) is still referenced from table "pt2".
|
||||
|
||||
delete from pt2 where pt2.d_date>'1999-11-15' and pt2.d_date<'1999-12-15';
|
||||
SELECT * FROM pt2 WHERE pt2.d_date>='1999-10-01';
|
||||
d_date | d_date_backup
|
||||
--------------------------+--------------------------
|
||||
Fri Oct 01 00:00:00 1999 | Fri Oct 01 00:00:00 1999
|
||||
Sat Oct 02 00:00:00 1999 | Sat Oct 02 00:00:00 1999
|
||||
Tue Oct 19 00:00:00 1999 | Tue Oct 19 00:00:00 1999
|
||||
Wed Oct 20 00:00:00 1999 | Wed Oct 20 00:00:00 1999
|
||||
Mon Nov 01 00:00:00 1999 | Mon Nov 01 00:00:00 1999
|
||||
Tue Nov 02 00:00:00 1999 | Tue Nov 02 00:00:00 1999
|
||||
Sun Dec 19 00:00:00 1999 | Sun Dec 19 00:00:00 1999
|
||||
Mon Dec 20 00:00:00 1999 | Mon Dec 20 00:00:00 1999
|
||||
(8 rows)
|
||||
|
||||
|
||||
delete from pt1 where pt1.d_date>'1999-10-15' and pt1.d_date<'1999-11-15';
|
||||
ERROR: update or delete on table "pt1" violates foreign key constraint "test_foreign" on table "pt2"
|
||||
DETAIL: Key (d_date)=(Tue Oct 19 00:00:00 1999) is still referenced from table "pt2".
|
||||
|
||||
delete from pt2 where pt2.d_date>='1999-01-01' and pt2.d_date<'1999-05-01';
|
||||
delete from pt1 where pt1.d_date>='1999-01-01' and pt1.d_date<'1999-05-01';
|
||||
|
||||
UPDATE pt2 set d_date = d_date - INTERVAL '4' month where d_date>='1999-05-01' and d_date<'1999-06-01';
|
||||
ERROR: insert or update on table "pt2" violates foreign key constraint "test_foreign"
|
||||
DETAIL: Key (d_date)=(Fri Jan 01 00:00:00 1999) is not present in table "pt1".
|
||||
|
||||
UPDATE pt1 set d_date = d_date - INTERVAL '4' month where d_date>='1999-05-01' and d_date<'1999-06-01';
|
||||
ERROR: update or delete on table "pt1" violates foreign key constraint "test_foreign" on table "pt2"
|
||||
DETAIL: Key (d_date)=(Sat May 01 00:00:00 1999) is still referenced from table "pt2".
|
||||
SELECT * FROM pt1 WHERE d_date<'1999-07-01';
|
||||
d_date
|
||||
--------------------------
|
||||
Sat May 01 00:00:00 1999
|
||||
Sun May 02 00:00:00 1999
|
||||
Wed May 19 00:00:00 1999
|
||||
Thu May 20 00:00:00 1999
|
||||
Tue Jun 01 00:00:00 1999
|
||||
Wed Jun 02 00:00:00 1999
|
||||
Sat Jun 19 00:00:00 1999
|
||||
Sun Jun 20 00:00:00 1999
|
||||
(8 rows)
|
||||
|
||||
|
||||
UPDATE pt2 set d_date = d_date - INTERVAL '1' month where d_date>='1999-06-01' and d_date<='1999-07-15';
|
||||
|
||||
UPDATE pt1 set d_date = d_date - INTERVAL '5' month where d_date>='1999-06-01' and d_date<='1999-07-15';
|
||||
ERROR: update or delete on table "pt1" violates foreign key constraint "test_foreign" on table "pt2"
|
||||
DETAIL: Key (d_date)=(Tue Jun 01 00:00:00 1999) is still referenced from table "pt2".
|
||||
|
||||
delete from pt2 where d_date>='1999-06-01' and d_date<='1999-07-15';
|
||||
UPDATE pt1 set d_date = d_date - INTERVAL '5' month where d_date>='1999-06-01' and d_date<='1999-07-15';
|
||||
|
||||
|
|
@ -0,0 +1,294 @@
|
|||
DROP TABLE IF EXISTS pt2;
|
||||
DROP TABLE IF EXISTS pt1;
|
||||
DROP FUNCTION IF EXISTS test_function();
|
||||
NOTICE: function test_function() does not exist, skipping
|
||||
|
||||
CREATE TABLE pt1(
|
||||
d_date date UNIQUE
|
||||
)partition BY RANGE (d_date) INTERVAL('1 month')
|
||||
(PARTITION part1 VALUES LESS THAN ('1900-01-01'));
|
||||
NOTICE: CREATE TABLE / UNIQUE will create implicit index "pt1_d_date_key" for table "pt1"
|
||||
|
||||
CREATE TABLE pt2(
|
||||
d_date date
|
||||
)partition BY RANGE (d_date) INTERVAL('1 month')
|
||||
(PARTITION part1 VALUES LESS THAN ('1900-01-01'));
|
||||
|
||||
|
||||
INSERT INTO pt1 VALUES
|
||||
('1999-01-01'),('1999-01-02'),('1999-01-019'),('1999-01-20'),
|
||||
('1999-02-01'),('1999-02-02'),('1999-02-19'),('1999-02-20'),
|
||||
('1999-03-01'),('1999-03-02'),('1999-03-19'),('1999-03-20'),
|
||||
('1999-04-01'),('1999-04-02'),('1999-04-19'),('1999-04-20'),
|
||||
('1999-05-01'),('1999-05-02'),('1999-05-19'),('1999-05-20'),
|
||||
('1999-06-01'),('1999-06-02'),('1999-06-19'),('1999-06-20'),
|
||||
('1999-07-01'),('1999-07-02'),('1999-07-19'),('1999-07-20'),
|
||||
('1999-08-01'),('1999-08-02'),('1999-08-19'),('1999-08-20'),
|
||||
('1999-09-01'),('1999-09-02'),('1999-09-19'),('1999-09-20'),
|
||||
('1999-10-01'),('1999-10-02'),('1999-10-19'),('1999-10-20'),
|
||||
('1999-11-01'),('1999-11-02'),('1999-11-19'),('1999-11-20'),
|
||||
('1999-12-01'),('1999-12-02'),('1999-12-19'),('1999-12-20');
|
||||
|
||||
INSERT INTO pt2 VALUES
|
||||
('1999-01-01'),('1999-01-02'),('1999-01-019'),('1999-01-20'),
|
||||
('1999-02-01'),('1999-02-02'),('1999-02-19'),('1999-02-20'),
|
||||
('1999-03-01'),('1999-03-02'),('1999-03-19'),('1999-03-20'),
|
||||
('1999-04-01'),('1999-04-02'),('1999-04-19'),('1999-04-20'),
|
||||
('1999-05-01'),('1999-05-02'),('1999-05-19'),('1999-05-20'),
|
||||
('1999-06-01'),('1999-06-02'),('1999-06-19'),('1999-06-20'),
|
||||
('1999-07-01'),('1999-07-02'),('1999-07-19'),('1999-07-20'),
|
||||
('1999-08-01'),('1999-08-02'),('1999-08-19'),('1999-08-20'),
|
||||
('1999-09-01'),('1999-09-02'),('1999-09-19'),('1999-09-20'),
|
||||
('1999-10-01'),('1999-10-02'),('1999-10-19'),('1999-10-20'),
|
||||
('1999-11-01'),('1999-11-02'),('1999-11-19'),('1999-11-20'),
|
||||
('1999-12-01'),('1999-12-02'),('1999-12-19'),('1999-12-20');
|
||||
|
||||
|
||||
CREATE FUNCTION test_function()
|
||||
RETURNS TRIGGER AS $$
|
||||
BEGIN
|
||||
IF(TG_OP = 'DELETE') THEN
|
||||
DELETE FROM pt2 WHERE d_date=OLD.d_date;
|
||||
RETURN OLD;
|
||||
ELSEIF(TG_OP = 'UPDATE') THEN
|
||||
UPDATE pt2 set d_date=NEW.d_date where d_date=OLD.d_date;
|
||||
RETURN NEW;
|
||||
ELSEIF(TG_OP = 'INSERT') THEN
|
||||
INSERT INTO pt2 VALUES(NEW.d_date);
|
||||
RETURN NEW;
|
||||
END IF;
|
||||
RETURN NULL;
|
||||
END;
|
||||
$$ LANGUAGE plpgsql;
|
||||
|
||||
|
||||
CREATE TRIGGER test_trigger
|
||||
AFTER INSERT OR UPDATE OR DELETE on pt1
|
||||
FOR EACH ROW EXECUTE PROCEDURE test_function();
|
||||
|
||||
INSERT INTO pt1 VALUES('2016-01-01');
|
||||
UPDATE pt2 set d_date = d_date + INTERVAL '4' month where d_date>='1999-05-01';
|
||||
DELETE FROM pt1 WHERE d_date<'1999-05-01';
|
||||
SELECT * FROM pt1;
|
||||
d_date
|
||||
--------------------------
|
||||
Sat May 01 00:00:00 1999
|
||||
Sun May 02 00:00:00 1999
|
||||
Wed May 19 00:00:00 1999
|
||||
Thu May 20 00:00:00 1999
|
||||
Tue Jun 01 00:00:00 1999
|
||||
Wed Jun 02 00:00:00 1999
|
||||
Sat Jun 19 00:00:00 1999
|
||||
Sun Jun 20 00:00:00 1999
|
||||
Thu Jul 01 00:00:00 1999
|
||||
Fri Jul 02 00:00:00 1999
|
||||
Mon Jul 19 00:00:00 1999
|
||||
Tue Jul 20 00:00:00 1999
|
||||
Sun Aug 01 00:00:00 1999
|
||||
Mon Aug 02 00:00:00 1999
|
||||
Thu Aug 19 00:00:00 1999
|
||||
Fri Aug 20 00:00:00 1999
|
||||
Wed Sep 01 00:00:00 1999
|
||||
Thu Sep 02 00:00:00 1999
|
||||
Sun Sep 19 00:00:00 1999
|
||||
Mon Sep 20 00:00:00 1999
|
||||
Fri Oct 01 00:00:00 1999
|
||||
Sat Oct 02 00:00:00 1999
|
||||
Tue Oct 19 00:00:00 1999
|
||||
Wed Oct 20 00:00:00 1999
|
||||
Mon Nov 01 00:00:00 1999
|
||||
Tue Nov 02 00:00:00 1999
|
||||
Fri Nov 19 00:00:00 1999
|
||||
Sat Nov 20 00:00:00 1999
|
||||
Wed Dec 01 00:00:00 1999
|
||||
Thu Dec 02 00:00:00 1999
|
||||
Sun Dec 19 00:00:00 1999
|
||||
Mon Dec 20 00:00:00 1999
|
||||
Fri Jan 01 00:00:00 2016
|
||||
(33 rows)
|
||||
|
||||
SELECT * FROM pt2;
|
||||
d_date
|
||||
--------------------------
|
||||
Wed Sep 01 00:00:00 1999
|
||||
Thu Sep 02 00:00:00 1999
|
||||
Sun Sep 19 00:00:00 1999
|
||||
Mon Sep 20 00:00:00 1999
|
||||
Fri Oct 01 00:00:00 1999
|
||||
Sat Oct 02 00:00:00 1999
|
||||
Tue Oct 19 00:00:00 1999
|
||||
Wed Oct 20 00:00:00 1999
|
||||
Mon Nov 01 00:00:00 1999
|
||||
Tue Nov 02 00:00:00 1999
|
||||
Fri Nov 19 00:00:00 1999
|
||||
Sat Nov 20 00:00:00 1999
|
||||
Wed Dec 01 00:00:00 1999
|
||||
Thu Dec 02 00:00:00 1999
|
||||
Sun Dec 19 00:00:00 1999
|
||||
Mon Dec 20 00:00:00 1999
|
||||
Sat Jan 01 00:00:00 2000
|
||||
Sun Jan 02 00:00:00 2000
|
||||
Wed Jan 19 00:00:00 2000
|
||||
Thu Jan 20 00:00:00 2000
|
||||
Tue Feb 01 00:00:00 2000
|
||||
Wed Feb 02 00:00:00 2000
|
||||
Sat Feb 19 00:00:00 2000
|
||||
Sun Feb 20 00:00:00 2000
|
||||
Wed Mar 01 00:00:00 2000
|
||||
Thu Mar 02 00:00:00 2000
|
||||
Sun Mar 19 00:00:00 2000
|
||||
Mon Mar 20 00:00:00 2000
|
||||
Sat Apr 01 00:00:00 2000
|
||||
Sun Apr 02 00:00:00 2000
|
||||
Wed Apr 19 00:00:00 2000
|
||||
Thu Apr 20 00:00:00 2000
|
||||
Sun May 01 00:00:00 2016
|
||||
(33 rows)
|
||||
|
||||
|
||||
DROP TABLE IF EXISTS pt2;
|
||||
DROP TABLE IF EXISTS pt1;
|
||||
DROP FUNCTION IF EXISTS test_function();
|
||||
|
||||
CREATE TABLE pt1(
|
||||
d_date date UNIQUE
|
||||
)partition BY RANGE (d_date) INTERVAL('1 month')
|
||||
(PARTITION part1 VALUES LESS THAN ('1900-01-01'));
|
||||
NOTICE: CREATE TABLE / UNIQUE will create implicit index "pt1_d_date_key" for table "pt1"
|
||||
|
||||
CREATE TABLE pt2(
|
||||
d_date date
|
||||
)partition BY RANGE (d_date) INTERVAL('1 month')
|
||||
(PARTITION part1 VALUES LESS THAN ('1900-01-01'));
|
||||
|
||||
|
||||
INSERT INTO pt1 VALUES
|
||||
('1999-01-01'),('1999-01-02'),('1999-01-019'),('1999-01-20'),
|
||||
('1999-02-01'),('1999-02-02'),('1999-02-19'),('1999-02-20'),
|
||||
('1999-03-01'),('1999-03-02'),('1999-03-19'),('1999-03-20'),
|
||||
('1999-04-01'),('1999-04-02'),('1999-04-19'),('1999-04-20'),
|
||||
('1999-05-01'),('1999-05-02'),('1999-05-19'),('1999-05-20'),
|
||||
('1999-06-01'),('1999-06-02'),('1999-06-19'),('1999-06-20'),
|
||||
('1999-07-01'),('1999-07-02'),('1999-07-19'),('1999-07-20'),
|
||||
('1999-08-01'),('1999-08-02'),('1999-08-19'),('1999-08-20'),
|
||||
('1999-09-01'),('1999-09-02'),('1999-09-19'),('1999-09-20'),
|
||||
('1999-10-01'),('1999-10-02'),('1999-10-19'),('1999-10-20'),
|
||||
('1999-11-01'),('1999-11-02'),('1999-11-19'),('1999-11-20'),
|
||||
('1999-12-01'),('1999-12-02'),('1999-12-19'),('1999-12-20');
|
||||
|
||||
INSERT INTO pt2 VALUES
|
||||
('1999-01-01'),('1999-01-02'),('1999-01-019'),('1999-01-20'),
|
||||
('1999-02-01'),('1999-02-02'),('1999-02-19'),('1999-02-20'),
|
||||
('1999-03-01'),('1999-03-02'),('1999-03-19'),('1999-03-20'),
|
||||
('1999-04-01'),('1999-04-02'),('1999-04-19'),('1999-04-20'),
|
||||
('1999-05-01'),('1999-05-02'),('1999-05-19'),('1999-05-20'),
|
||||
('1999-06-01'),('1999-06-02'),('1999-06-19'),('1999-06-20'),
|
||||
('1999-07-01'),('1999-07-02'),('1999-07-19'),('1999-07-20'),
|
||||
('1999-08-01'),('1999-08-02'),('1999-08-19'),('1999-08-20'),
|
||||
('1999-09-01'),('1999-09-02'),('1999-09-19'),('1999-09-20'),
|
||||
('1999-10-01'),('1999-10-02'),('1999-10-19'),('1999-10-20'),
|
||||
('1999-11-01'),('1999-11-02'),('1999-11-19'),('1999-11-20'),
|
||||
('1999-12-01'),('1999-12-02'),('1999-12-19'),('1999-12-20');
|
||||
|
||||
|
||||
CREATE FUNCTION test_function()
|
||||
RETURNS TRIGGER AS $$
|
||||
BEGIN
|
||||
IF(TG_OP = 'DELETE') THEN
|
||||
DELETE FROM pt2 WHERE d_date=OLD.d_date;
|
||||
RETURN OLD;
|
||||
ELSEIF(TG_OP = 'UPDATE') THEN
|
||||
UPDATE pt2 set d_date=NEW.d_date where d_date=OLD.d_date;
|
||||
RETURN NEW;
|
||||
ELSEIF(TG_OP = 'INSERT') THEN
|
||||
INSERT INTO pt2 VALUES(NEW.d_date);
|
||||
RETURN NEW;
|
||||
END IF;
|
||||
RETURN NULL;
|
||||
END;
|
||||
$$ LANGUAGE plpgsql;
|
||||
|
||||
|
||||
CREATE TRIGGER test_trigger
|
||||
BEFORE INSERT OR UPDATE OR DELETE on pt1
|
||||
FOR EACH ROW EXECUTE PROCEDURE test_function();
|
||||
|
||||
INSERT INTO pt1 VALUES('2016-01-01');
|
||||
UPDATE pt2 set d_date = d_date + INTERVAL '4' month where d_date>='1999-05-01';
|
||||
DELETE FROM pt1 WHERE d_date<'1999-05-01';
|
||||
SELECT * FROM pt1;
|
||||
d_date
|
||||
--------------------------
|
||||
Sat May 01 00:00:00 1999
|
||||
Sun May 02 00:00:00 1999
|
||||
Wed May 19 00:00:00 1999
|
||||
Thu May 20 00:00:00 1999
|
||||
Tue Jun 01 00:00:00 1999
|
||||
Wed Jun 02 00:00:00 1999
|
||||
Sat Jun 19 00:00:00 1999
|
||||
Sun Jun 20 00:00:00 1999
|
||||
Thu Jul 01 00:00:00 1999
|
||||
Fri Jul 02 00:00:00 1999
|
||||
Mon Jul 19 00:00:00 1999
|
||||
Tue Jul 20 00:00:00 1999
|
||||
Sun Aug 01 00:00:00 1999
|
||||
Mon Aug 02 00:00:00 1999
|
||||
Thu Aug 19 00:00:00 1999
|
||||
Fri Aug 20 00:00:00 1999
|
||||
Wed Sep 01 00:00:00 1999
|
||||
Thu Sep 02 00:00:00 1999
|
||||
Sun Sep 19 00:00:00 1999
|
||||
Mon Sep 20 00:00:00 1999
|
||||
Fri Oct 01 00:00:00 1999
|
||||
Sat Oct 02 00:00:00 1999
|
||||
Tue Oct 19 00:00:00 1999
|
||||
Wed Oct 20 00:00:00 1999
|
||||
Mon Nov 01 00:00:00 1999
|
||||
Tue Nov 02 00:00:00 1999
|
||||
Fri Nov 19 00:00:00 1999
|
||||
Sat Nov 20 00:00:00 1999
|
||||
Wed Dec 01 00:00:00 1999
|
||||
Thu Dec 02 00:00:00 1999
|
||||
Sun Dec 19 00:00:00 1999
|
||||
Mon Dec 20 00:00:00 1999
|
||||
Fri Jan 01 00:00:00 2016
|
||||
(33 rows)
|
||||
|
||||
SELECT * FROM pt2;
|
||||
d_date
|
||||
--------------------------
|
||||
Wed Sep 01 00:00:00 1999
|
||||
Thu Sep 02 00:00:00 1999
|
||||
Sun Sep 19 00:00:00 1999
|
||||
Mon Sep 20 00:00:00 1999
|
||||
Fri Oct 01 00:00:00 1999
|
||||
Sat Oct 02 00:00:00 1999
|
||||
Tue Oct 19 00:00:00 1999
|
||||
Wed Oct 20 00:00:00 1999
|
||||
Mon Nov 01 00:00:00 1999
|
||||
Tue Nov 02 00:00:00 1999
|
||||
Fri Nov 19 00:00:00 1999
|
||||
Sat Nov 20 00:00:00 1999
|
||||
Wed Dec 01 00:00:00 1999
|
||||
Thu Dec 02 00:00:00 1999
|
||||
Sun Dec 19 00:00:00 1999
|
||||
Mon Dec 20 00:00:00 1999
|
||||
Sat Jan 01 00:00:00 2000
|
||||
Sun Jan 02 00:00:00 2000
|
||||
Wed Jan 19 00:00:00 2000
|
||||
Thu Jan 20 00:00:00 2000
|
||||
Tue Feb 01 00:00:00 2000
|
||||
Wed Feb 02 00:00:00 2000
|
||||
Sat Feb 19 00:00:00 2000
|
||||
Sun Feb 20 00:00:00 2000
|
||||
Wed Mar 01 00:00:00 2000
|
||||
Thu Mar 02 00:00:00 2000
|
||||
Sun Mar 19 00:00:00 2000
|
||||
Mon Mar 20 00:00:00 2000
|
||||
Sat Apr 01 00:00:00 2000
|
||||
Sun Apr 02 00:00:00 2000
|
||||
Wed Apr 19 00:00:00 2000
|
||||
Thu Apr 20 00:00:00 2000
|
||||
Sun May 01 00:00:00 2016
|
||||
(33 rows)
|
||||
|
||||
|
|
@ -1185,6 +1185,7 @@ WHERE d.classoid IS NULL AND p1.oid <= 9999 order by 1;
|
|||
2096 | pg_terminate_backend
|
||||
2097 | pg_get_variable_info
|
||||
2098 | pg_get_functiondef
|
||||
2099 | pg_terminate_session
|
||||
2100 | avg
|
||||
2101 | avg
|
||||
2102 | avg
|
||||
|
|
@ -2676,7 +2677,7 @@ WHERE d.classoid IS NULL AND p1.oid <= 9999 order by 1;
|
|||
9016 | pg_advisory_lock
|
||||
9017 | pgxc_unlock_for_sp_database
|
||||
9999 | pg_test_err_contain_err
|
||||
(2275 rows)
|
||||
(2276 rows)
|
||||
|
||||
-- Check prokind
|
||||
select count(*) from pg_proc where prokind = 'a';
|
||||
|
|
@ -2694,7 +2695,7 @@ select count(*) from pg_proc where prokind = 'w';
|
|||
select count(*) from pg_proc where prokind = 'f';
|
||||
count
|
||||
-------
|
||||
3149
|
||||
3150
|
||||
(1 row)
|
||||
|
||||
select count(*) from pg_proc where prokind = 'p';
|
||||
|
|
|
|||
|
|
@ -2868,33 +2868,34 @@ NOTICE: CREATE TABLE will create implicit sequence "loc1_f1_seq" for serial col
|
|||
create foreign table rem1 (f1 serial, f2 text)
|
||||
server loopback options(table_name 'loc1');
|
||||
NOTICE: CREATE FOREIGN TABLE will create implicit sequence "rem1_f1_seq" for serial column "rem1.f1"
|
||||
ERROR: referenced relation "rem1" is not a table
|
||||
select pg_catalog.setval('rem1_f1_seq', 10, false);
|
||||
ERROR: relation "rem1_f1_seq" does not exist
|
||||
LINE 1: select pg_catalog.setval('rem1_f1_seq', 10, false);
|
||||
^
|
||||
CONTEXT: referenced column: setval
|
||||
setval
|
||||
--------
|
||||
10
|
||||
(1 row)
|
||||
|
||||
insert into loc1(f2) values('hi');
|
||||
insert into rem1(f2) values('hi remote');
|
||||
ERROR: relation "rem1" does not exist on datanode1
|
||||
LINE 1: insert into rem1(f2) values('hi remote');
|
||||
^
|
||||
insert into loc1(f2) values('bye');
|
||||
insert into rem1(f2) values('bye remote');
|
||||
ERROR: relation "rem1" does not exist on datanode1
|
||||
LINE 1: insert into rem1(f2) values('bye remote');
|
||||
^
|
||||
select * from loc1;
|
||||
f1 | f2
|
||||
----+-----
|
||||
f1 | f2
|
||||
----+------------
|
||||
1 | hi
|
||||
10 | hi remote
|
||||
2 | bye
|
||||
(2 rows)
|
||||
11 | bye remote
|
||||
(4 rows)
|
||||
|
||||
select * from rem1;
|
||||
ERROR: relation "rem1" does not exist on datanode1
|
||||
LINE 1: select * from rem1;
|
||||
^
|
||||
f1 | f2
|
||||
----+------------
|
||||
1 | hi
|
||||
10 | hi remote
|
||||
2 | bye
|
||||
11 | bye remote
|
||||
(4 rows)
|
||||
|
||||
-- ===================================================================
|
||||
-- test local triggers
|
||||
-- ===================================================================
|
||||
|
|
@ -2907,10 +2908,10 @@ BEGIN
|
|||
END;$$;
|
||||
CREATE TRIGGER trig_stmt_before BEFORE DELETE OR INSERT OR UPDATE ON rem1
|
||||
FOR EACH STATEMENT EXECUTE PROCEDURE trigger_func();
|
||||
ERROR: relation "rem1" does not exist
|
||||
ERROR: "rem1" is not a table or view
|
||||
CREATE TRIGGER trig_stmt_after AFTER DELETE OR INSERT OR UPDATE ON rem1
|
||||
FOR EACH STATEMENT EXECUTE PROCEDURE trigger_func();
|
||||
ERROR: relation "rem1" does not exist
|
||||
ERROR: "rem1" is not a table or view
|
||||
CREATE OR REPLACE FUNCTION trigger_data() RETURNS trigger
|
||||
LANGUAGE plpgsql AS $$
|
||||
|
||||
|
|
@ -2953,97 +2954,67 @@ $$;
|
|||
CREATE TRIGGER trig_row_before
|
||||
BEFORE INSERT OR UPDATE OR DELETE ON rem1
|
||||
FOR EACH ROW EXECUTE PROCEDURE trigger_data(23,'skidoo');
|
||||
ERROR: relation "rem1" does not exist
|
||||
ERROR: "rem1" is not a table or view
|
||||
CREATE TRIGGER trig_row_after
|
||||
AFTER INSERT OR UPDATE OR DELETE ON rem1
|
||||
FOR EACH ROW EXECUTE PROCEDURE trigger_data(23,'skidoo');
|
||||
ERROR: relation "rem1" does not exist
|
||||
ERROR: "rem1" is not a table or view
|
||||
delete from rem1;
|
||||
ERROR: relation "rem1" does not exist on datanode1
|
||||
LINE 1: delete from rem1;
|
||||
^
|
||||
insert into rem1 values(1,'insert');
|
||||
ERROR: relation "rem1" does not exist on datanode1
|
||||
LINE 1: insert into rem1 values(1,'insert');
|
||||
^
|
||||
update rem1 set f2 = 'update' where f1 = 1;
|
||||
ERROR: relation "rem1" does not exist on datanode1
|
||||
LINE 1: update rem1 set f2 = 'update' where f1 = 1;
|
||||
^
|
||||
update rem1 set f2 = f2 || f2;
|
||||
ERROR: relation "rem1" does not exist on datanode1
|
||||
LINE 1: update rem1 set f2 = f2 || f2;
|
||||
^
|
||||
-- cleanup
|
||||
DROP TRIGGER trig_row_before ON rem1;
|
||||
ERROR: relation "rem1" does not exist
|
||||
ERROR: trigger "trig_row_before" for table "rem1" does not exist
|
||||
DROP TRIGGER trig_row_after ON rem1;
|
||||
ERROR: relation "rem1" does not exist
|
||||
ERROR: trigger "trig_row_after" for table "rem1" does not exist
|
||||
DROP TRIGGER trig_stmt_before ON rem1;
|
||||
ERROR: relation "rem1" does not exist
|
||||
ERROR: trigger "trig_stmt_before" for table "rem1" does not exist
|
||||
DROP TRIGGER trig_stmt_after ON rem1;
|
||||
ERROR: relation "rem1" does not exist
|
||||
ERROR: trigger "trig_stmt_after" for table "rem1" does not exist
|
||||
DELETE from rem1;
|
||||
ERROR: relation "rem1" does not exist on datanode1
|
||||
LINE 1: DELETE from rem1;
|
||||
^
|
||||
-- Test WHEN conditions
|
||||
CREATE TRIGGER trig_row_before_insupd
|
||||
BEFORE INSERT OR UPDATE ON rem1
|
||||
FOR EACH ROW
|
||||
WHEN (NEW.f2 like '%update%')
|
||||
EXECUTE PROCEDURE trigger_data(23,'skidoo');
|
||||
ERROR: relation "rem1" does not exist
|
||||
ERROR: "rem1" is not a table or view
|
||||
CREATE TRIGGER trig_row_after_insupd
|
||||
AFTER INSERT OR UPDATE ON rem1
|
||||
FOR EACH ROW
|
||||
WHEN (NEW.f2 like '%update%')
|
||||
EXECUTE PROCEDURE trigger_data(23,'skidoo');
|
||||
ERROR: relation "rem1" does not exist
|
||||
ERROR: "rem1" is not a table or view
|
||||
-- Insert or update not matching: nothing happens
|
||||
INSERT INTO rem1 values(1, 'insert');
|
||||
ERROR: relation "rem1" does not exist on datanode1
|
||||
LINE 1: INSERT INTO rem1 values(1, 'insert');
|
||||
^
|
||||
UPDATE rem1 set f2 = 'test';
|
||||
ERROR: relation "rem1" does not exist on datanode1
|
||||
LINE 1: UPDATE rem1 set f2 = 'test';
|
||||
^
|
||||
-- Insert or update matching: triggers are fired
|
||||
INSERT INTO rem1 values(2, 'update');
|
||||
ERROR: relation "rem1" does not exist on datanode1
|
||||
LINE 1: INSERT INTO rem1 values(2, 'update');
|
||||
^
|
||||
UPDATE rem1 set f2 = 'update update' where f1 = '2';
|
||||
ERROR: relation "rem1" does not exist on datanode1
|
||||
LINE 1: UPDATE rem1 set f2 = 'update update' where f1 = '2';
|
||||
^
|
||||
CREATE TRIGGER trig_row_before_delete
|
||||
BEFORE DELETE ON rem1
|
||||
FOR EACH ROW
|
||||
WHEN (OLD.f2 like '%update%')
|
||||
EXECUTE PROCEDURE trigger_data(23,'skidoo');
|
||||
ERROR: relation "rem1" does not exist
|
||||
ERROR: "rem1" is not a table or view
|
||||
CREATE TRIGGER trig_row_after_delete
|
||||
AFTER DELETE ON rem1
|
||||
FOR EACH ROW
|
||||
WHEN (OLD.f2 like '%update%')
|
||||
EXECUTE PROCEDURE trigger_data(23,'skidoo');
|
||||
ERROR: relation "rem1" does not exist
|
||||
ERROR: "rem1" is not a table or view
|
||||
-- Trigger is fired for f1=2, not for f1=1
|
||||
DELETE FROM rem1;
|
||||
ERROR: relation "rem1" does not exist on datanode1
|
||||
LINE 1: DELETE FROM rem1;
|
||||
^
|
||||
-- cleanup
|
||||
DROP TRIGGER trig_row_before_insupd ON rem1;
|
||||
ERROR: relation "rem1" does not exist
|
||||
ERROR: trigger "trig_row_before_insupd" for table "rem1" does not exist
|
||||
DROP TRIGGER trig_row_after_insupd ON rem1;
|
||||
ERROR: relation "rem1" does not exist
|
||||
ERROR: trigger "trig_row_after_insupd" for table "rem1" does not exist
|
||||
DROP TRIGGER trig_row_before_delete ON rem1;
|
||||
ERROR: relation "rem1" does not exist
|
||||
ERROR: trigger "trig_row_before_delete" for table "rem1" does not exist
|
||||
DROP TRIGGER trig_row_after_delete ON rem1;
|
||||
ERROR: relation "rem1" does not exist
|
||||
ERROR: trigger "trig_row_after_delete" for table "rem1" does not exist
|
||||
-- Test various RETURN statements in BEFORE triggers.
|
||||
CREATE FUNCTION trig_row_before_insupdate() RETURNS TRIGGER AS $$
|
||||
BEGIN
|
||||
|
|
@ -3054,134 +3025,123 @@ $$ language plpgsql;
|
|||
CREATE TRIGGER trig_row_before_insupd
|
||||
BEFORE INSERT OR UPDATE ON rem1
|
||||
FOR EACH ROW EXECUTE PROCEDURE trig_row_before_insupdate();
|
||||
ERROR: relation "rem1" does not exist
|
||||
ERROR: "rem1" is not a table or view
|
||||
-- The new values should have 'triggered' appended
|
||||
INSERT INTO rem1 values(1, 'insert');
|
||||
ERROR: relation "rem1" does not exist on datanode1
|
||||
LINE 1: INSERT INTO rem1 values(1, 'insert');
|
||||
^
|
||||
SELECT * from loc1;
|
||||
f1 | f2
|
||||
----+-----
|
||||
1 | hi
|
||||
2 | bye
|
||||
(2 rows)
|
||||
f1 | f2
|
||||
----+--------
|
||||
1 | insert
|
||||
(1 row)
|
||||
|
||||
INSERT INTO rem1 values(2, 'insert') RETURNING f2;
|
||||
ERROR: relation "rem1" does not exist on datanode1
|
||||
LINE 1: INSERT INTO rem1 values(2, 'insert') RETURNING f2;
|
||||
^
|
||||
f2
|
||||
--------
|
||||
insert
|
||||
(1 row)
|
||||
|
||||
SELECT * from loc1;
|
||||
f1 | f2
|
||||
----+-----
|
||||
1 | hi
|
||||
2 | bye
|
||||
f1 | f2
|
||||
----+--------
|
||||
1 | insert
|
||||
2 | insert
|
||||
(2 rows)
|
||||
|
||||
UPDATE rem1 set f2 = '';
|
||||
ERROR: relation "rem1" does not exist on datanode1
|
||||
LINE 1: UPDATE rem1 set f2 = '';
|
||||
^
|
||||
SELECT * from loc1;
|
||||
f1 | f2
|
||||
----+-----
|
||||
1 | hi
|
||||
2 | bye
|
||||
f1 | f2
|
||||
----+----
|
||||
1 |
|
||||
2 |
|
||||
(2 rows)
|
||||
|
||||
UPDATE rem1 set f2 = 'skidoo' RETURNING f2;
|
||||
ERROR: relation "rem1" does not exist on datanode1
|
||||
LINE 1: UPDATE rem1 set f2 = 'skidoo' RETURNING f2;
|
||||
^
|
||||
f2
|
||||
--------
|
||||
skidoo
|
||||
skidoo
|
||||
(2 rows)
|
||||
|
||||
SELECT * from loc1;
|
||||
f1 | f2
|
||||
----+-----
|
||||
1 | hi
|
||||
2 | bye
|
||||
f1 | f2
|
||||
----+--------
|
||||
1 | skidoo
|
||||
2 | skidoo
|
||||
(2 rows)
|
||||
|
||||
EXPLAIN (verbose, costs off)
|
||||
UPDATE rem1 set f1 = 10; -- all columns should be transmitted
|
||||
ERROR: relation "rem1" does not exist on datanode1
|
||||
LINE 2: UPDATE rem1 set f1 = 10;
|
||||
^
|
||||
QUERY PLAN
|
||||
-----------------------------------------------------------------
|
||||
Update on public.rem1
|
||||
-> Foreign Scan on public.rem1
|
||||
Output: 10, f2, ctid
|
||||
Remote SQL: SELECT f2, ctid FROM public.loc1 FOR UPDATE
|
||||
(4 rows)
|
||||
|
||||
UPDATE rem1 set f1 = 10;
|
||||
ERROR: relation "rem1" does not exist on datanode1
|
||||
LINE 1: UPDATE rem1 set f1 = 10;
|
||||
^
|
||||
SELECT * from loc1;
|
||||
f1 | f2
|
||||
----+-----
|
||||
1 | hi
|
||||
2 | bye
|
||||
f1 | f2
|
||||
----+--------
|
||||
10 | skidoo
|
||||
10 | skidoo
|
||||
(2 rows)
|
||||
|
||||
DELETE FROM rem1;
|
||||
ERROR: relation "rem1" does not exist on datanode1
|
||||
LINE 1: DELETE FROM rem1;
|
||||
^
|
||||
-- Add a second trigger, to check that the changes are propagated correctly
|
||||
-- from trigger to trigger
|
||||
CREATE TRIGGER trig_row_before_insupd2
|
||||
BEFORE INSERT OR UPDATE ON rem1
|
||||
FOR EACH ROW EXECUTE PROCEDURE trig_row_before_insupdate();
|
||||
ERROR: relation "rem1" does not exist
|
||||
ERROR: "rem1" is not a table or view
|
||||
INSERT INTO rem1 values(1, 'insert');
|
||||
ERROR: relation "rem1" does not exist on datanode1
|
||||
LINE 1: INSERT INTO rem1 values(1, 'insert');
|
||||
^
|
||||
SELECT * from loc1;
|
||||
f1 | f2
|
||||
----+-----
|
||||
1 | hi
|
||||
2 | bye
|
||||
(2 rows)
|
||||
f1 | f2
|
||||
----+--------
|
||||
1 | insert
|
||||
(1 row)
|
||||
|
||||
INSERT INTO rem1 values(2, 'insert') RETURNING f2;
|
||||
ERROR: relation "rem1" does not exist on datanode1
|
||||
LINE 1: INSERT INTO rem1 values(2, 'insert') RETURNING f2;
|
||||
^
|
||||
f2
|
||||
--------
|
||||
insert
|
||||
(1 row)
|
||||
|
||||
SELECT * from loc1;
|
||||
f1 | f2
|
||||
----+-----
|
||||
1 | hi
|
||||
2 | bye
|
||||
f1 | f2
|
||||
----+--------
|
||||
1 | insert
|
||||
2 | insert
|
||||
(2 rows)
|
||||
|
||||
UPDATE rem1 set f2 = '';
|
||||
ERROR: relation "rem1" does not exist on datanode1
|
||||
LINE 1: UPDATE rem1 set f2 = '';
|
||||
^
|
||||
SELECT * from loc1;
|
||||
f1 | f2
|
||||
----+-----
|
||||
1 | hi
|
||||
2 | bye
|
||||
f1 | f2
|
||||
----+----
|
||||
1 |
|
||||
2 |
|
||||
(2 rows)
|
||||
|
||||
UPDATE rem1 set f2 = 'skidoo' RETURNING f2;
|
||||
ERROR: relation "rem1" does not exist on datanode1
|
||||
LINE 1: UPDATE rem1 set f2 = 'skidoo' RETURNING f2;
|
||||
^
|
||||
f2
|
||||
--------
|
||||
skidoo
|
||||
skidoo
|
||||
(2 rows)
|
||||
|
||||
SELECT * from loc1;
|
||||
f1 | f2
|
||||
----+-----
|
||||
1 | hi
|
||||
2 | bye
|
||||
f1 | f2
|
||||
----+--------
|
||||
1 | skidoo
|
||||
2 | skidoo
|
||||
(2 rows)
|
||||
|
||||
DROP TRIGGER trig_row_before_insupd ON rem1;
|
||||
ERROR: relation "rem1" does not exist
|
||||
ERROR: trigger "trig_row_before_insupd" for table "rem1" does not exist
|
||||
DROP TRIGGER trig_row_before_insupd2 ON rem1;
|
||||
ERROR: relation "rem1" does not exist
|
||||
ERROR: trigger "trig_row_before_insupd2" for table "rem1" does not exist
|
||||
DELETE from rem1;
|
||||
ERROR: relation "rem1" does not exist on datanode1
|
||||
LINE 1: DELETE from rem1;
|
||||
^
|
||||
INSERT INTO rem1 VALUES (1, 'test');
|
||||
ERROR: relation "rem1" does not exist on datanode1
|
||||
LINE 1: INSERT INTO rem1 VALUES (1, 'test');
|
||||
^
|
||||
-- Test with a trigger returning NULL
|
||||
CREATE FUNCTION trig_null() RETURNS TRIGGER AS $$
|
||||
BEGIN
|
||||
|
|
@ -3191,68 +3151,49 @@ $$ language plpgsql;
|
|||
CREATE TRIGGER trig_null
|
||||
BEFORE INSERT OR UPDATE OR DELETE ON rem1
|
||||
FOR EACH ROW EXECUTE PROCEDURE trig_null();
|
||||
ERROR: relation "rem1" does not exist
|
||||
ERROR: "rem1" is not a table or view
|
||||
-- Nothing should have changed.
|
||||
INSERT INTO rem1 VALUES (2, 'test2');
|
||||
ERROR: relation "rem1" does not exist on datanode1
|
||||
LINE 1: INSERT INTO rem1 VALUES (2, 'test2');
|
||||
^
|
||||
SELECT * from loc1;
|
||||
f1 | f2
|
||||
----+-----
|
||||
1 | hi
|
||||
2 | bye
|
||||
f1 | f2
|
||||
----+-------
|
||||
1 | test
|
||||
2 | test2
|
||||
(2 rows)
|
||||
|
||||
UPDATE rem1 SET f2 = 'test2';
|
||||
ERROR: relation "rem1" does not exist on datanode1
|
||||
LINE 1: UPDATE rem1 SET f2 = 'test2';
|
||||
^
|
||||
SELECT * from loc1;
|
||||
f1 | f2
|
||||
----+-----
|
||||
1 | hi
|
||||
2 | bye
|
||||
f1 | f2
|
||||
----+-------
|
||||
1 | test2
|
||||
2 | test2
|
||||
(2 rows)
|
||||
|
||||
DELETE from rem1;
|
||||
ERROR: relation "rem1" does not exist on datanode1
|
||||
LINE 1: DELETE from rem1;
|
||||
^
|
||||
SELECT * from loc1;
|
||||
f1 | f2
|
||||
----+-----
|
||||
1 | hi
|
||||
2 | bye
|
||||
(2 rows)
|
||||
f1 | f2
|
||||
----+----
|
||||
(0 rows)
|
||||
|
||||
DROP TRIGGER trig_null ON rem1;
|
||||
ERROR: relation "rem1" does not exist
|
||||
ERROR: trigger "trig_null" for table "rem1" does not exist
|
||||
DELETE from rem1;
|
||||
ERROR: relation "rem1" does not exist on datanode1
|
||||
LINE 1: DELETE from rem1;
|
||||
^
|
||||
-- Test a combination of local and remote triggers
|
||||
CREATE TRIGGER trig_row_before
|
||||
BEFORE INSERT OR UPDATE OR DELETE ON rem1
|
||||
FOR EACH ROW EXECUTE PROCEDURE trigger_data(23,'skidoo');
|
||||
ERROR: relation "rem1" does not exist
|
||||
ERROR: "rem1" is not a table or view
|
||||
CREATE TRIGGER trig_row_after
|
||||
AFTER INSERT OR UPDATE OR DELETE ON rem1
|
||||
FOR EACH ROW EXECUTE PROCEDURE trigger_data(23,'skidoo');
|
||||
ERROR: relation "rem1" does not exist
|
||||
ERROR: "rem1" is not a table or view
|
||||
CREATE TRIGGER trig_local_before BEFORE INSERT OR UPDATE ON loc1
|
||||
FOR EACH ROW EXECUTE PROCEDURE trig_row_before_insupdate();
|
||||
INSERT INTO rem1(f2) VALUES ('test');
|
||||
ERROR: relation "rem1" does not exist on datanode1
|
||||
LINE 1: INSERT INTO rem1(f2) VALUES ('test');
|
||||
^
|
||||
UPDATE rem1 SET f2 = 'testo';
|
||||
ERROR: relation "rem1" does not exist on datanode1
|
||||
LINE 1: UPDATE rem1 SET f2 = 'testo';
|
||||
^
|
||||
-- Test returning a system attribute
|
||||
INSERT INTO rem1(f2) VALUES ('test') RETURNING ctid;
|
||||
ERROR: relation "rem1" does not exist on datanode1
|
||||
ERROR: column "ctid" does not exist
|
||||
LINE 1: INSERT INTO rem1(f2) VALUES ('test') RETURNING ctid;
|
||||
^
|
||||
^
|
||||
CONTEXT: referenced column: ctid
|
||||
|
|
@ -74,3 +74,5 @@ test: with
|
|||
|
||||
# run alter object to test pg_object
|
||||
#test: pg_object_test
|
||||
test: partition_foreign_key
|
||||
test: partition_trigger
|
||||
|
|
@ -0,0 +1,312 @@
|
|||
DROP TABLE IF EXISTS pt2;
|
||||
DROP TABLE IF EXISTS pt1;
|
||||
CREATE TABLE pt1(
|
||||
d_date date UNIQUE
|
||||
)partition BY RANGE (d_date) INTERVAL('1 day')
|
||||
(PARTITION part1 VALUES LESS THAN ('1900-01-01'));
|
||||
|
||||
CREATE TABLE pt2(
|
||||
d_date date
|
||||
)partition BY RANGE (d_date) INTERVAL('1 day')
|
||||
(PARTITION part1 VALUES LESS THAN ('1900-01-01'));
|
||||
|
||||
ALTER TABLE pt2 ADD CONSTRAINT test_foreign FOREIGN KEY(d_date)
|
||||
REFERENCES pt1(d_date) on UPDATE CASCADE ON DELETE CASCADE;
|
||||
|
||||
INSERT into pt1 VALUES('1999-01-01'),('1999-01-02'),('1999-01-03'),('1999-01-04');
|
||||
|
||||
INSERT into pt2 VALUES('1999-01-01');
|
||||
|
||||
INSERT into pt2 VALUES('2000-01-01');
|
||||
|
||||
update pt2 set pt2.d_date = '2000-01-01' where pt2.d_date = '1999-01-01';
|
||||
|
||||
update pt2 set pt2.d_date = '1999-01-02' where pt2.d_date = '1999-01-01';
|
||||
|
||||
SELECT * FROM pt2;
|
||||
|
||||
SELECT * FROM pt2 PARTITION(sys_p2);
|
||||
|
||||
delete from pt2;
|
||||
INSERT into pt2 VALUES('1999-01-01'), ('1999-01-03'),('1999-01-04');
|
||||
|
||||
INSERT into pt1 VALUES('1999-01-08');
|
||||
|
||||
INSERT into pt2 VALUES('1999-01-08');
|
||||
|
||||
update pt1 set pt1.d_date = '2000-01-01' where pt1.d_date = '1999-01-08';
|
||||
|
||||
delete from pt1 where pt1.d_date = '2000-01-01';
|
||||
|
||||
DROP TABLE pt2;
|
||||
DROP TABLE pt1;
|
||||
|
||||
CREATE TABLE pt1(
|
||||
d_date date UNIQUE
|
||||
)partition BY RANGE (d_date) INTERVAL('1 month')
|
||||
(PARTITION part1 VALUES LESS THAN ('1900-01-01'));
|
||||
|
||||
CREATE TABLE pt2(
|
||||
d_date date
|
||||
)partition BY RANGE (d_date) INTERVAL('1 month')
|
||||
(PARTITION part1 VALUES LESS THAN ('1900-01-01'));
|
||||
|
||||
ALTER TABLE pt2 ADD CONSTRAINT test_foreign FOREIGN KEY(d_date)
|
||||
REFERENCES pt1(d_date) on UPDATE CASCADE ON DELETE CASCADE;
|
||||
|
||||
INSERT INTO pt1 VALUES
|
||||
('1999-01-01'),('1999-01-02'),('1999-01-019'),('1999-01-20'),
|
||||
('1999-02-01'),('1999-02-02'),('1999-02-19'),('1999-02-20'),
|
||||
('1999-03-01'),('1999-03-02'),('1999-03-19'),('1999-03-20'),
|
||||
('1999-04-01'),('1999-04-02'),('1999-04-19'),('1999-04-20'),
|
||||
('1999-05-01'),('1999-05-02'),('1999-05-19'),('1999-05-20'),
|
||||
('1999-06-01'),('1999-06-02'),('1999-06-19'),('1999-06-20'),
|
||||
('1999-07-01'),('1999-07-02'),('1999-07-19'),('1999-07-20'),
|
||||
('1999-08-01'),('1999-08-02'),('1999-08-19'),('1999-08-20'),
|
||||
('1999-09-01'),('1999-09-02'),('1999-09-19'),('1999-09-20'),
|
||||
('1999-10-01'),('1999-10-02'),('1999-10-19'),('1999-10-20'),
|
||||
('1999-11-01'),('1999-11-02'),('1999-11-19'),('1999-11-20'),
|
||||
('1999-12-01'),('1999-12-02'),('1999-12-19'),('1999-12-20');
|
||||
|
||||
INSERT INTO pt2 VALUES
|
||||
('1999-01-01'),('1999-01-02'),('1999-01-019'),('1999-01-20'),
|
||||
('1999-02-01'),('1999-02-02'),('1999-02-19'),('1999-02-20'),
|
||||
('1999-03-01'),('1999-03-02'),('1999-03-19'),('1999-03-20'),
|
||||
('1999-04-01'),('1999-04-02'),('1999-04-19'),('1999-04-20'),
|
||||
('1999-05-01'),('1999-05-02'),('1999-05-19'),('1999-05-20'),
|
||||
('1999-06-01'),('1999-06-02'),('1999-06-19'),('1999-06-20'),
|
||||
('1999-07-01'),('1999-07-02'),('1999-07-19'),('1999-07-20'),
|
||||
('1999-08-01'),('1999-08-02'),('1999-08-19'),('1999-08-20'),
|
||||
('1999-09-01'),('1999-09-02'),('1999-09-19'),('1999-09-20'),
|
||||
('1999-10-01'),('1999-10-02'),('1999-10-19'),('1999-10-20'),
|
||||
('1999-11-01'),('1999-11-02'),('1999-11-19'),('1999-11-20'),
|
||||
('1999-12-01'),('1999-12-02'),('1999-12-19'),('1999-12-20');
|
||||
|
||||
delete from pt2 where pt2.d_date<'1999-03-01';
|
||||
|
||||
select * from pt2 where pt2.d_date<'1999-06-01';
|
||||
|
||||
delete from pt1 where pt1.d_date<'1999-05-01';
|
||||
|
||||
delete from pt2 where pt2.d_date>'1999-11-15' and pt2.d_date<'1999-12-15';
|
||||
SELECT * FROM pt2 WHERE pt2.d_date>='1999-10-01';
|
||||
|
||||
delete from pt1 where pt1.d_date>'1999-10-15' and pt1.d_date<'1999-11-15';
|
||||
SELECT * FROM pt1 WHERE pt1.d_date>='1999-10-01';
|
||||
|
||||
SELECT * FROM pt2 WHERE pt2.d_date>='1999-10-01';
|
||||
|
||||
UPDATE pt2 set d_date = d_date - INTERVAL '4' month where d_date>='1999-05-01' and d_date<'1999-06-01';
|
||||
|
||||
UPDATE pt1 set d_date = d_date - INTERVAL '4' month where d_date>='1999-05-01' and d_date<'1999-06-01';
|
||||
SELECT * FROM pt1 WHERE d_date<'1999-07-01';
|
||||
|
||||
SELECT * FROM pt1 WHERE d_date<'1999-07-01';
|
||||
|
||||
UPDATE pt2 set d_date = d_date - INTERVAL '1' month where d_date>='1999-06-01' and d_date<='1999-07-15';
|
||||
|
||||
UPDATE pt1 set d_date = d_date - INTERVAL '1' month where d_date>='1999-06-01' and d_date<='1999-07-15';
|
||||
SELECT * FROM pt1 WHERE d_date<'1999-08-01';
|
||||
|
||||
SELECT * FROM pt2 WHERE d_date<'1999-08-01';
|
||||
|
||||
DROP TABLE IF EXISTS pt2;
|
||||
DROP TABLE IF EXISTS pt1;
|
||||
|
||||
CREATE TABLE pt1(
|
||||
d_date date UNIQUE
|
||||
)partition BY RANGE (d_date) INTERVAL('1 month')
|
||||
(PARTITION part1 VALUES LESS THAN ('1900-01-01'))
|
||||
;
|
||||
|
||||
CREATE TABLE pt2(
|
||||
d_date date,
|
||||
d_date_backup date
|
||||
)partition BY RANGE (d_date_backup) INTERVAL('1 month')
|
||||
(PARTITION part1 VALUES LESS THAN ('1900-01-01'));
|
||||
|
||||
|
||||
ALTER TABLE pt2 ADD CONSTRAINT test_foreign FOREIGN KEY(d_date)
|
||||
REFERENCES pt1(d_date) on UPDATE SET NULL ON DELETE SET NULL;
|
||||
|
||||
INSERT INTO pt1 VALUES
|
||||
('1999-01-01'),('1999-01-02'),('1999-01-019'),('1999-01-20'),
|
||||
('1999-02-01'),('1999-02-02'),('1999-02-19'),('1999-02-20'),
|
||||
('1999-03-01'),('1999-03-02'),('1999-03-19'),('1999-03-20'),
|
||||
('1999-04-01'),('1999-04-02'),('1999-04-19'),('1999-04-20'),
|
||||
('1999-05-01'),('1999-05-02'),('1999-05-19'),('1999-05-20'),
|
||||
('1999-06-01'),('1999-06-02'),('1999-06-19'),('1999-06-20'),
|
||||
('1999-07-01'),('1999-07-02'),('1999-07-19'),('1999-07-20'),
|
||||
('1999-08-01'),('1999-08-02'),('1999-08-19'),('1999-08-20'),
|
||||
('1999-09-01'),('1999-09-02'),('1999-09-19'),('1999-09-20'),
|
||||
('1999-10-01'),('1999-10-02'),('1999-10-19'),('1999-10-20'),
|
||||
('1999-11-01'),('1999-11-02'),('1999-11-19'),('1999-11-20'),
|
||||
('1999-12-01'),('1999-12-02'),('1999-12-19'),('1999-12-20');
|
||||
|
||||
INSERT INTO pt2 VALUES
|
||||
('1999-01-01','1999-01-01'),('1999-01-02','1999-01-02'),
|
||||
('1999-01-19','1999-01-19'),('1999-01-20','1999-01-20'),
|
||||
('1999-02-01','1999-02-01'),('1999-02-02','1999-02-02'),
|
||||
('1999-02-19','1999-02-19'),('1999-02-20','1999-02-20'),
|
||||
('1999-03-01','1999-03-01'),('1999-03-02','1999-03-02'),
|
||||
('1999-03-19','1999-03-19'),('1999-03-20','1999-03-20'),
|
||||
('1999-04-01','1999-04-01'),('1999-04-02','1999-04-02'),
|
||||
('1999-04-19','1999-04-19'),('1999-04-20','1999-04-20'),
|
||||
('1999-05-01','1999-05-01'),('1999-05-02','1999-05-02'),
|
||||
('1999-05-19','1999-05-19'),('1999-05-20','1999-05-20'),
|
||||
('1999-06-01','1999-06-01'),('1999-06-02','1999-06-02'),
|
||||
('1999-06-19','1999-06-19'),('1999-06-20','1999-06-20'),
|
||||
('1999-07-01','1999-07-01'),('1999-07-02','1999-07-02'),
|
||||
('1999-07-19','1999-07-19'),('1999-07-20','1999-07-20'),
|
||||
('1999-08-01','1999-08-01'),('1999-08-02','1999-08-02'),
|
||||
('1999-08-19','1999-08-19'),('1999-08-20','1999-08-20'),
|
||||
('1999-09-01','1999-09-01'),('1999-09-02','1999-09-02'),
|
||||
('1999-09-19','1999-09-19'),('1999-09-20','1999-09-20'),
|
||||
('1999-10-01','1999-10-01'),('1999-10-02','1999-10-02'),
|
||||
('1999-10-19','1999-10-19'),('1999-10-20','1999-10-20'),
|
||||
('1999-11-01','1999-11-01'),('1999-11-02','1999-11-02'),
|
||||
('1999-11-19','1999-11-19'),('1999-11-20','1999-11-20'),
|
||||
('1999-12-01','1999-12-01'),('1999-12-02','1999-12-02'),
|
||||
('1999-12-19','1999-12-19'),('1999-12-20','1999-12-20');
|
||||
|
||||
insert into pt1 VALUES('2000-01-01'),('2000-01-02'),
|
||||
('2000-01-19'),('2000-01-20'),
|
||||
('2000-02-01'),('2000-02-02'),
|
||||
('2000-02-19'),('2000-02-20');
|
||||
SELECT * FROM pt1 WHERE d_date>='2000-01-01';
|
||||
|
||||
update pt1 set d_date = '2000-02-21' WHERE d_date = '2000-02-20';
|
||||
SELECT * FROM pt1 WHERE d_date>='2000-02-01';
|
||||
|
||||
DELETE FROM pt1 WHERE d_date = '2000-02-21';
|
||||
SELECT * FROM pt1 WHERE d_date>='2000-02-01';
|
||||
|
||||
SELECT * FROM pt1 PARTITION FOR('1999-06-16');
|
||||
|
||||
INSERT into pt2 VALUES('2020-08-19','2020-08-19');
|
||||
|
||||
INSERT into pt2 VALUES('2000-01-01','2000-01-01');
|
||||
|
||||
update pt2 set pt2.d_date = '2020-08-13'
|
||||
where pt2.d_date = '1999-01-01';
|
||||
|
||||
update pt2 set pt2.d_date = '2000-02-01',pt2.d_date_backup = '2000-02-01'
|
||||
where pt2.d_date = '2000-01-01';
|
||||
|
||||
SELECT * FROM pt2;
|
||||
|
||||
SELECT * FROM pt2 PARTITION(sys_p2);
|
||||
|
||||
delete from pt2 where pt2.d_date<'1999-03-01';
|
||||
select * from pt2 where pt2.d_date<'1999-06-01';
|
||||
|
||||
delete from pt1 where d_date<'1999-05-01';
|
||||
select * from pt1 where d_date<'1999-06-01';
|
||||
|
||||
select * from pt2 where d_date_backup<'1999-06-01';
|
||||
|
||||
delete from pt2 where pt2.d_date>'1999-11-15' and pt2.d_date<'1999-12-15';
|
||||
SELECT * FROM pt2 WHERE pt2.d_date>='1999-10-01';
|
||||
|
||||
delete from pt1 where pt1.d_date>'1999-10-15' and pt1.d_date<'1999-11-15';
|
||||
SELECT * FROM pt1 WHERE pt1.d_date>='1999-10-01';
|
||||
|
||||
SELECT * FROM pt2 WHERE pt2.d_date_backup>='1999-10-01';
|
||||
|
||||
UPDATE pt2 set d_date = d_date - INTERVAL '4' month where d_date>='1999-05-01' and d_date<'1999-06-01';
|
||||
|
||||
UPDATE pt1 set d_date = d_date - INTERVAL '4' month where d_date>='1999-05-01' and d_date<'1999-06-01';
|
||||
SELECT * FROM pt1 WHERE d_date<'1999-07-01';
|
||||
|
||||
SELECT * FROM pt2 WHERE d_date_backup<'1999-07-01';
|
||||
|
||||
UPDATE pt2 set d_date = d_date - INTERVAL '1' month where d_date>='1999-06-01' and d_date<='1999-07-15';
|
||||
|
||||
UPDATE pt1 set d_date = d_date - INTERVAL '1' month where d_date>='1999-06-01' and d_date<='1999-07-15';
|
||||
SELECT * FROM pt1 WHERE d_date<'1999-08-01';
|
||||
|
||||
SELECT * FROM pt2 WHERE d_date_backup<'1999-08-01';
|
||||
|
||||
DROP TABLE IF EXISTS pt2;
|
||||
DROP TABLE IF EXISTS pt1;
|
||||
|
||||
CREATE TABLE pt1(
|
||||
d_date date UNIQUE
|
||||
)partition BY RANGE (d_date) INTERVAL('1 month')
|
||||
(PARTITION part1 VALUES LESS THAN ('1900-01-01'));
|
||||
|
||||
CREATE TABLE pt2(
|
||||
d_date date,
|
||||
d_date_backup date
|
||||
)partition BY RANGE (d_date_backup) INTERVAL('1 month')
|
||||
(PARTITION part1 VALUES LESS THAN ('1900-01-01'));
|
||||
|
||||
|
||||
ALTER TABLE pt2 ADD CONSTRAINT test_foreign FOREIGN KEY(d_date)
|
||||
REFERENCES pt1(d_date) on UPDATE RESTRICT ON DELETE RESTRICT;
|
||||
|
||||
INSERT INTO pt1 VALUES
|
||||
('1999-01-01'),('1999-01-02'),('1999-01-019'),('1999-01-20'),
|
||||
('1999-02-01'),('1999-02-02'),('1999-02-19'),('1999-02-20'),
|
||||
('1999-03-01'),('1999-03-02'),('1999-03-19'),('1999-03-20'),
|
||||
('1999-04-01'),('1999-04-02'),('1999-04-19'),('1999-04-20'),
|
||||
('1999-05-01'),('1999-05-02'),('1999-05-19'),('1999-05-20'),
|
||||
('1999-06-01'),('1999-06-02'),('1999-06-19'),('1999-06-20'),
|
||||
('1999-07-01'),('1999-07-02'),('1999-07-19'),('1999-07-20'),
|
||||
('1999-08-01'),('1999-08-02'),('1999-08-19'),('1999-08-20'),
|
||||
('1999-09-01'),('1999-09-02'),('1999-09-19'),('1999-09-20'),
|
||||
('1999-10-01'),('1999-10-02'),('1999-10-19'),('1999-10-20'),
|
||||
('1999-11-01'),('1999-11-02'),('1999-11-19'),('1999-11-20'),
|
||||
('1999-12-01'),('1999-12-02'),('1999-12-19'),('1999-12-20');
|
||||
|
||||
INSERT INTO pt2 VALUES
|
||||
('1999-01-01','1999-01-01'),('1999-01-02','1999-01-02'),
|
||||
('1999-01-19','1999-01-19'),('1999-01-20','1999-01-20'),
|
||||
('1999-02-01','1999-02-01'),('1999-02-02','1999-02-02'),
|
||||
('1999-02-19','1999-02-19'),('1999-02-20','1999-02-20'),
|
||||
('1999-03-01','1999-03-01'),('1999-03-02','1999-03-02'),
|
||||
('1999-03-19','1999-03-19'),('1999-03-20','1999-03-20'),
|
||||
('1999-04-01','1999-04-01'),('1999-04-02','1999-04-02'),
|
||||
('1999-04-19','1999-04-19'),('1999-04-20','1999-04-20'),
|
||||
('1999-05-01','1999-05-01'),('1999-05-02','1999-05-02'),
|
||||
('1999-05-19','1999-05-19'),('1999-05-20','1999-05-20'),
|
||||
('1999-06-01','1999-06-01'),('1999-06-02','1999-06-02'),
|
||||
('1999-06-19','1999-06-19'),('1999-06-20','1999-06-20'),
|
||||
('1999-07-01','1999-07-01'),('1999-07-02','1999-07-02'),
|
||||
('1999-07-19','1999-07-19'),('1999-07-20','1999-07-20'),
|
||||
('1999-08-01','1999-08-01'),('1999-08-02','1999-08-02'),
|
||||
('1999-08-19','1999-08-19'),('1999-08-20','1999-08-20'),
|
||||
('1999-09-01','1999-09-01'),('1999-09-02','1999-09-02'),
|
||||
('1999-09-19','1999-09-19'),('1999-09-20','1999-09-20'),
|
||||
('1999-10-01','1999-10-01'),('1999-10-02','1999-10-02'),
|
||||
('1999-10-19','1999-10-19'),('1999-10-20','1999-10-20'),
|
||||
('1999-11-01','1999-11-01'),('1999-11-02','1999-11-02'),
|
||||
('1999-11-19','1999-11-19'),('1999-11-20','1999-11-20'),
|
||||
('1999-12-01','1999-12-01'),('1999-12-02','1999-12-02'),
|
||||
('1999-12-19','1999-12-19'),('1999-12-20','1999-12-20');
|
||||
|
||||
delete from pt2 where pt2.d_date<'1999-03-01';
|
||||
select * from pt2 where pt2.d_date<'1999-06-01';
|
||||
|
||||
delete from pt1 where d_date<'1999-05-01';
|
||||
|
||||
delete from pt2 where pt2.d_date>'1999-11-15' and pt2.d_date<'1999-12-15';
|
||||
SELECT * FROM pt2 WHERE pt2.d_date>='1999-10-01';
|
||||
|
||||
delete from pt1 where pt1.d_date>'1999-10-15' and pt1.d_date<'1999-11-15';
|
||||
|
||||
delete from pt2 where pt2.d_date>='1999-01-01' and pt2.d_date<'1999-05-01';
|
||||
delete from pt1 where pt1.d_date>='1999-01-01' and pt1.d_date<'1999-05-01';
|
||||
|
||||
UPDATE pt2 set d_date = d_date - INTERVAL '4' month where d_date>='1999-05-01' and d_date<'1999-06-01';
|
||||
|
||||
UPDATE pt1 set d_date = d_date - INTERVAL '4' month where d_date>='1999-05-01' and d_date<'1999-06-01';
|
||||
SELECT * FROM pt1 WHERE d_date<'1999-07-01';
|
||||
|
||||
UPDATE pt2 set d_date = d_date - INTERVAL '1' month where d_date>='1999-06-01' and d_date<='1999-07-15';
|
||||
|
||||
UPDATE pt1 set d_date = d_date - INTERVAL '5' month where d_date>='1999-06-01' and d_date<='1999-07-15';
|
||||
|
||||
delete from pt2 where d_date>='1999-06-01' and d_date<='1999-07-15';
|
||||
UPDATE pt1 set d_date = d_date - INTERVAL '5' month where d_date>='1999-06-01' and d_date<='1999-07-15';
|
||||
|
||||
|
|
@ -0,0 +1,143 @@
|
|||
DROP TABLE IF EXISTS pt2;
|
||||
DROP TABLE IF EXISTS pt1;
|
||||
DROP FUNCTION IF EXISTS test_function();
|
||||
|
||||
CREATE TABLE pt1(
|
||||
d_date date UNIQUE
|
||||
)partition BY RANGE (d_date) INTERVAL('1 month')
|
||||
(PARTITION part1 VALUES LESS THAN ('1900-01-01'));
|
||||
|
||||
CREATE TABLE pt2(
|
||||
d_date date
|
||||
)partition BY RANGE (d_date) INTERVAL('1 month')
|
||||
(PARTITION part1 VALUES LESS THAN ('1900-01-01'));
|
||||
|
||||
|
||||
INSERT INTO pt1 VALUES
|
||||
('1999-01-01'),('1999-01-02'),('1999-01-019'),('1999-01-20'),
|
||||
('1999-02-01'),('1999-02-02'),('1999-02-19'),('1999-02-20'),
|
||||
('1999-03-01'),('1999-03-02'),('1999-03-19'),('1999-03-20'),
|
||||
('1999-04-01'),('1999-04-02'),('1999-04-19'),('1999-04-20'),
|
||||
('1999-05-01'),('1999-05-02'),('1999-05-19'),('1999-05-20'),
|
||||
('1999-06-01'),('1999-06-02'),('1999-06-19'),('1999-06-20'),
|
||||
('1999-07-01'),('1999-07-02'),('1999-07-19'),('1999-07-20'),
|
||||
('1999-08-01'),('1999-08-02'),('1999-08-19'),('1999-08-20'),
|
||||
('1999-09-01'),('1999-09-02'),('1999-09-19'),('1999-09-20'),
|
||||
('1999-10-01'),('1999-10-02'),('1999-10-19'),('1999-10-20'),
|
||||
('1999-11-01'),('1999-11-02'),('1999-11-19'),('1999-11-20'),
|
||||
('1999-12-01'),('1999-12-02'),('1999-12-19'),('1999-12-20');
|
||||
|
||||
INSERT INTO pt2 VALUES
|
||||
('1999-01-01'),('1999-01-02'),('1999-01-019'),('1999-01-20'),
|
||||
('1999-02-01'),('1999-02-02'),('1999-02-19'),('1999-02-20'),
|
||||
('1999-03-01'),('1999-03-02'),('1999-03-19'),('1999-03-20'),
|
||||
('1999-04-01'),('1999-04-02'),('1999-04-19'),('1999-04-20'),
|
||||
('1999-05-01'),('1999-05-02'),('1999-05-19'),('1999-05-20'),
|
||||
('1999-06-01'),('1999-06-02'),('1999-06-19'),('1999-06-20'),
|
||||
('1999-07-01'),('1999-07-02'),('1999-07-19'),('1999-07-20'),
|
||||
('1999-08-01'),('1999-08-02'),('1999-08-19'),('1999-08-20'),
|
||||
('1999-09-01'),('1999-09-02'),('1999-09-19'),('1999-09-20'),
|
||||
('1999-10-01'),('1999-10-02'),('1999-10-19'),('1999-10-20'),
|
||||
('1999-11-01'),('1999-11-02'),('1999-11-19'),('1999-11-20'),
|
||||
('1999-12-01'),('1999-12-02'),('1999-12-19'),('1999-12-20');
|
||||
|
||||
|
||||
CREATE FUNCTION test_function()
|
||||
RETURNS TRIGGER AS $$
|
||||
BEGIN
|
||||
IF(TG_OP = 'DELETE') THEN
|
||||
DELETE FROM pt2 WHERE d_date=OLD.d_date;
|
||||
RETURN OLD;
|
||||
ELSEIF(TG_OP = 'UPDATE') THEN
|
||||
UPDATE pt2 set d_date=NEW.d_date where d_date=OLD.d_date;
|
||||
RETURN NEW;
|
||||
ELSEIF(TG_OP = 'INSERT') THEN
|
||||
INSERT INTO pt2 VALUES(NEW.d_date);
|
||||
RETURN NEW;
|
||||
END IF;
|
||||
RETURN NULL;
|
||||
END;
|
||||
$$ LANGUAGE plpgsql;
|
||||
|
||||
|
||||
CREATE TRIGGER test_trigger
|
||||
AFTER INSERT OR UPDATE OR DELETE on pt1
|
||||
FOR EACH ROW EXECUTE PROCEDURE test_function();
|
||||
|
||||
INSERT INTO pt1 VALUES('2016-01-01');
|
||||
UPDATE pt2 set d_date = d_date + INTERVAL '4' month where d_date>='1999-05-01';
|
||||
DELETE FROM pt1 WHERE d_date<'1999-05-01';
|
||||
SELECT * FROM pt1;
|
||||
SELECT * FROM pt2;
|
||||
|
||||
DROP TABLE IF EXISTS pt2;
|
||||
DROP TABLE IF EXISTS pt1;
|
||||
DROP FUNCTION IF EXISTS test_function();
|
||||
|
||||
CREATE TABLE pt1(
|
||||
d_date date UNIQUE
|
||||
)partition BY RANGE (d_date) INTERVAL('1 month')
|
||||
(PARTITION part1 VALUES LESS THAN ('1900-01-01'));
|
||||
|
||||
CREATE TABLE pt2(
|
||||
d_date date
|
||||
)partition BY RANGE (d_date) INTERVAL('1 month')
|
||||
(PARTITION part1 VALUES LESS THAN ('1900-01-01'));
|
||||
|
||||
|
||||
INSERT INTO pt1 VALUES
|
||||
('1999-01-01'),('1999-01-02'),('1999-01-019'),('1999-01-20'),
|
||||
('1999-02-01'),('1999-02-02'),('1999-02-19'),('1999-02-20'),
|
||||
('1999-03-01'),('1999-03-02'),('1999-03-19'),('1999-03-20'),
|
||||
('1999-04-01'),('1999-04-02'),('1999-04-19'),('1999-04-20'),
|
||||
('1999-05-01'),('1999-05-02'),('1999-05-19'),('1999-05-20'),
|
||||
('1999-06-01'),('1999-06-02'),('1999-06-19'),('1999-06-20'),
|
||||
('1999-07-01'),('1999-07-02'),('1999-07-19'),('1999-07-20'),
|
||||
('1999-08-01'),('1999-08-02'),('1999-08-19'),('1999-08-20'),
|
||||
('1999-09-01'),('1999-09-02'),('1999-09-19'),('1999-09-20'),
|
||||
('1999-10-01'),('1999-10-02'),('1999-10-19'),('1999-10-20'),
|
||||
('1999-11-01'),('1999-11-02'),('1999-11-19'),('1999-11-20'),
|
||||
('1999-12-01'),('1999-12-02'),('1999-12-19'),('1999-12-20');
|
||||
|
||||
INSERT INTO pt2 VALUES
|
||||
('1999-01-01'),('1999-01-02'),('1999-01-019'),('1999-01-20'),
|
||||
('1999-02-01'),('1999-02-02'),('1999-02-19'),('1999-02-20'),
|
||||
('1999-03-01'),('1999-03-02'),('1999-03-19'),('1999-03-20'),
|
||||
('1999-04-01'),('1999-04-02'),('1999-04-19'),('1999-04-20'),
|
||||
('1999-05-01'),('1999-05-02'),('1999-05-19'),('1999-05-20'),
|
||||
('1999-06-01'),('1999-06-02'),('1999-06-19'),('1999-06-20'),
|
||||
('1999-07-01'),('1999-07-02'),('1999-07-19'),('1999-07-20'),
|
||||
('1999-08-01'),('1999-08-02'),('1999-08-19'),('1999-08-20'),
|
||||
('1999-09-01'),('1999-09-02'),('1999-09-19'),('1999-09-20'),
|
||||
('1999-10-01'),('1999-10-02'),('1999-10-19'),('1999-10-20'),
|
||||
('1999-11-01'),('1999-11-02'),('1999-11-19'),('1999-11-20'),
|
||||
('1999-12-01'),('1999-12-02'),('1999-12-19'),('1999-12-20');
|
||||
|
||||
|
||||
CREATE FUNCTION test_function()
|
||||
RETURNS TRIGGER AS $$
|
||||
BEGIN
|
||||
IF(TG_OP = 'DELETE') THEN
|
||||
DELETE FROM pt2 WHERE d_date=OLD.d_date;
|
||||
RETURN OLD;
|
||||
ELSEIF(TG_OP = 'UPDATE') THEN
|
||||
UPDATE pt2 set d_date=NEW.d_date where d_date=OLD.d_date;
|
||||
RETURN NEW;
|
||||
ELSEIF(TG_OP = 'INSERT') THEN
|
||||
INSERT INTO pt2 VALUES(NEW.d_date);
|
||||
RETURN NEW;
|
||||
END IF;
|
||||
RETURN NULL;
|
||||
END;
|
||||
$$ LANGUAGE plpgsql;
|
||||
|
||||
|
||||
CREATE TRIGGER test_trigger
|
||||
BEFORE INSERT OR UPDATE OR DELETE on pt1
|
||||
FOR EACH ROW EXECUTE PROCEDURE test_function();
|
||||
|
||||
INSERT INTO pt1 VALUES('2016-01-01');
|
||||
UPDATE pt2 set d_date = d_date + INTERVAL '4' month where d_date>='1999-05-01';
|
||||
DELETE FROM pt1 WHERE d_date<'1999-05-01';
|
||||
SELECT * FROM pt1;
|
||||
SELECT * FROM pt2;
|
||||
Loading…
Reference in New Issue