forked from huawei/openGauss-server
Compare commits
1 Commits
master
...
undorecycl
| Author | SHA1 | Date |
|---|---|---|
|
|
0c4cf14576 |
|
|
@ -1,5 +1,4 @@
|
|||
#!/usr/bin/perl
|
||||
#Again
|
||||
|
||||
use warnings;
|
||||
use strict;
|
||||
|
|
|
|||
|
|
@ -72,7 +72,7 @@ select_package_command
|
|||
export PLAT_FORM_STR=$(sh "${ROOT_DIR}/src/get_PlatForm_str.sh")
|
||||
if [ "${PLAT_FORM_STR}"x == "Failed"x -o "${PLAT_FORM_STR}"x == ""x ]
|
||||
then
|
||||
echo "We only support openEuler(aarch64), EulerOS(aarch64), CentOS, Kylin(aarch64), Asianux platform."
|
||||
echo "We only support openEuler(aarch64), EulerOS(aarch64), CentOS, Kylin(aarch64) platform."
|
||||
exit 1;
|
||||
fi
|
||||
|
||||
|
|
@ -96,21 +96,16 @@ elif [[ "$PLAT_FORM_STR" =~ "kylin" ]]; then
|
|||
if [ "$PLATFORM_ARCH"X == "aarch64"X ];then
|
||||
GAUSSDB_EXTRA_FLAGS=" -D__USE_NUMA"
|
||||
fi
|
||||
elif [[ "$PLAT_FORM_STR" =~ "asianux" ]]; then
|
||||
dist_version="Asianux"
|
||||
if [ "$PLATFORM_ARCH"X == "aarch64"X ];then
|
||||
GAUSSDB_EXTRA_FLAGS=" -D__USE_NUMA"
|
||||
fi
|
||||
else
|
||||
echo "We only support openEuler(aarch64), EulerOS(aarch64), CentOS, Kylin(aarch64), Asianux platform."
|
||||
echo "We only support openEuler(aarch64), EulerOS(aarch64), CentOS, Kylin(aarch64) platform."
|
||||
echo "Kernel is $kernel"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
##add platform architecture information
|
||||
if [ "$PLATFORM_ARCH"X == "aarch64"X ] ; then
|
||||
if [ "$dist_version" != "openEuler" ] && [ "$dist_version" != "EulerOS" ] && [ "$dist_version" != "Kylin" ] && [ "$dist_version" != "Asianux" ]; then
|
||||
echo "We only support NUMA on openEuler(aarch64), EulerOS(aarch64), Kylin(aarch64), Asianux platform."
|
||||
if [ "$dist_version" != "openEuler" ] && [ "$dist_version" != "EulerOS" ] && [ "$dist_version" != "Kylin" ] ; then
|
||||
echo "We only support NUMA on openEuler(aarch64), EulerOS(aarch64), Kylin(aarch64) platform."
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
|
|
|||
|
|
@ -26,7 +26,6 @@ Complete list of usable sgml source files in this directory.
|
|||
<!ENTITY alterOperator SYSTEM "alter_operator.sgml">
|
||||
<!ENTITY alterOperatorClass SYSTEM "alter_opclass.sgml">
|
||||
<!ENTITY alterOperatorFamily SYSTEM "alter_opfamily.sgml">
|
||||
<!ENTITY alterProcedure SYSTEM "alter_procedure.sgml">
|
||||
<!ENTITY alterRole SYSTEM "alter_role.sgml">
|
||||
<!ENTITY alterSchema SYSTEM "alter_schema.sgml">
|
||||
<!ENTITY alterServer SYSTEM "alter_server.sgml">
|
||||
|
|
|
|||
|
|
@ -1,37 +0,0 @@
|
|||
<refentry id="sql-alterprocedure">
|
||||
<indexterm zone="sql-alterprocedure">
|
||||
<primary>ALTER PROCEDURE</primary>
|
||||
</indexterm>
|
||||
|
||||
<refmeta>
|
||||
<refentrytitle>ALTER PROCEDURE</refentrytitle>
|
||||
<manvolnum>7</manvolnum>
|
||||
<refmiscinfo>SQL - Language Statements</refmiscinfo>
|
||||
</refmeta>
|
||||
|
||||
<refnamediv>
|
||||
<refname>ALTER PROCEDURE</refname>
|
||||
<refpurpose>change the definition of a procedure</refpurpose>
|
||||
</refnamediv>
|
||||
|
||||
<refsynopsisdiv>
|
||||
<synopsis>
|
||||
ALTER PROCEDURE <replaceable>name</replaceable> [ ( [ [ <replaceable class="parameter">argmode</replaceable> ] [ <replaceable class="parameter">argname</replaceable> ] <replaceable class="parameter">argtype</replaceable> [, ...] ] ) ]
|
||||
<replaceable class="parameter">action</replaceable> [ ... ] [ RESTRICT ]
|
||||
ALTER PROCEDURE <replaceable>name</replaceable> [ ( [ [ <replaceable class="parameter">argmode</replaceable> ] [ <replaceable class="parameter">argname</replaceable> ] <replaceable class="parameter">argtype</replaceable> [, ...] ] ) ]
|
||||
RENAME TO <replaceable>new_name</replaceable>
|
||||
ALTER PROCEDURE <replaceable>name</replaceable> [ ( [ [ <replaceable class="parameter">argmode</replaceable> ] [ <replaceable class="parameter">argname</replaceable> ] <replaceable class="parameter">argtype</replaceable> [, ...] ] ) ]
|
||||
OWNER TO { <replaceable>new_owner</replaceable> | CURRENT_ROLE | CURRENT_USER | SESSION_USER }
|
||||
ALTER PROCEDURE <replaceable>name</replaceable> [ ( [ [ <replaceable class="parameter">argmode</replaceable> ] [ <replaceable class="parameter">argname</replaceable> ] <replaceable class="parameter">argtype</replaceable> [, ...] ] ) ]
|
||||
SET SCHEMA <replaceable>new_schema</replaceable>
|
||||
|
||||
<phrase>where <replaceable class="parameter">action</replaceable> is one of:</phrase>
|
||||
|
||||
[ EXTERNAL ] SECURITY INVOKER | [ EXTERNAL ] SECURITY DEFINER
|
||||
SET <replaceable class="parameter">configuration_parameter</replaceable> { TO | = } { <replaceable class="parameter">value</replaceable> | DEFAULT }
|
||||
SET <replaceable class="parameter">configuration_parameter</replaceable> FROM CURRENT
|
||||
RESET <replaceable class="parameter">configuration_parameter</replaceable>
|
||||
RESET ALL
|
||||
</synopsis>
|
||||
</refsynopsisdiv>
|
||||
</refentry>
|
||||
|
|
@ -11,7 +11,7 @@
|
|||
<refsynopsisdiv>
|
||||
<synopsis>
|
||||
DROP TABLE [ IF EXISTS ]
|
||||
{[schema.]table_name} [, ...] [ CASCADE | RESTRICT ] [ PURGE ];
|
||||
{[schema.]table_name} [, ...] [ CASCADE | RESTRICT ] [ PURGE ]};
|
||||
</synopsis>
|
||||
</refsynopsisdiv>
|
||||
</refentry>
|
||||
|
|
@ -27,14 +27,7 @@
|
|||
#include "securec_check.h"
|
||||
#include "cipher.h"
|
||||
#include "crypt.h"
|
||||
/*
|
||||
function name: crypt_malloc_zero
|
||||
description: Distribute internal memory
|
||||
arguments: An integer that designates the size of internal memory distributed
|
||||
return value: A pointer of type void*
|
||||
Note:If the size of internal memory distributed is zero, it's unreasonable. The size should be greater than zero.
|
||||
At the same time, if malloc fails, program would exit.
|
||||
*/
|
||||
|
||||
void* crypt_malloc_zero(size_t size)
|
||||
{
|
||||
void* ret = NULL;
|
||||
|
|
|
|||
|
|
@ -34,14 +34,6 @@
|
|||
static int check_key_num(const char* password);
|
||||
static void create_child_dir(const char* pathdir);
|
||||
|
||||
|
||||
/*
|
||||
function name: check_path
|
||||
description: Check if the string delivered has the character that should not be included
|
||||
arguments: A pointer to string that its type is const char
|
||||
return value: void
|
||||
Note:none
|
||||
*/
|
||||
void check_path(const char *path_name)
|
||||
{
|
||||
const char* danger_character_list[] = {"|",
|
||||
|
|
@ -77,14 +69,6 @@ void check_path(const char *path_name)
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
function name: check_key_num
|
||||
description: Check if the password is a null string, if so, then the password is invalid.
|
||||
At the same time, the function check if the length of password exceeds MAX_CRYPT_LEN, if so, print the error.
|
||||
arguments: A pointer to string that its type is const char
|
||||
return value: An integer that its type is static int
|
||||
Note:The length of password should not be zero, and never exceeds MAX_CRYPT_LEN
|
||||
*/
|
||||
static int check_key_num(const char* password)
|
||||
{
|
||||
int key_len = 0;
|
||||
|
|
@ -100,13 +84,6 @@ static int check_key_num(const char* password)
|
|||
return key_len;
|
||||
}
|
||||
|
||||
/*
|
||||
function name: create_child_dir
|
||||
description: 函数作用
|
||||
arguments: A pointer to string that its type is const char
|
||||
return value: static void
|
||||
Note:函数中提醒阅读者需要注意的东西
|
||||
*/
|
||||
static void create_child_dir(const char* pathdir)
|
||||
{
|
||||
if (pathdir == NULL) {
|
||||
|
|
|
|||
|
|
@ -1229,12 +1229,6 @@ parse_next_sync_groups(char **pgroup, char *result)
|
|||
static int
|
||||
transform_az_name(char *config_value, char *allAZString, int allAZStringBufLen, const char *data_dir)
|
||||
{
|
||||
if (strcmp(config_value, "''") == 0) {
|
||||
errno_t rc = strncpy_s(allAZString, allAZStringBufLen, config_value, strlen(config_value));
|
||||
securec_check_c(rc, "\0", "\0");
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
char *azString = NULL;
|
||||
char *buf = allAZString;
|
||||
int buflen = allAZStringBufLen;
|
||||
|
|
|
|||
|
|
@ -5923,7 +5923,7 @@ int main(int argc, char** argv)
|
|||
&option_index)) != -1)
|
||||
#endif
|
||||
#else
|
||||
while ((c = getopt_long(argc, argv, "b:cD:e:fi:G:l:m:M:N:o:O:p:P:r:R:v:x:sS:t:u:U:wWZ:C:dqL:T:Q:", long_options,
|
||||
while ((c = getopt_long(argc, argv, "b:cD:e:fi:G:l:m:M:N:o:O:p:P:r:R:v:x:sS:t:u:U:wWZ:dqL:T:Q:", long_options,
|
||||
&option_index)) != -1)
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -233,7 +233,7 @@ char* all_data_nodename_list = NULL;
|
|||
const uint32 USTORE_UPGRADE_VERSION = 92368;
|
||||
const uint32 PACKAGE_ENHANCEMENT = 92444;
|
||||
const uint32 SUBSCRIPTION_VERSION = 92580;
|
||||
const uint32 SUBSCRIPTION_BINARY_VERSION_NUM = 92606;
|
||||
const uint32 SUBSCRIPTION_BINARY_VERSION_NUM = 92607;
|
||||
|
||||
#ifdef DUMPSYSLOG
|
||||
char* syslogpath = NULL;
|
||||
|
|
@ -4454,7 +4454,16 @@ void getSubscriptions(Archive *fout)
|
|||
}
|
||||
|
||||
if (!isExecUserSuperRole(fout)) {
|
||||
write_msg(NULL, "WARNING: subscriptions not dumped because current user is not a superuser\n");
|
||||
res = ExecuteSqlQuery(fout,
|
||||
"SELECT count(*) FROM pg_subscription "
|
||||
"WHERE subdbid = (SELECT oid FROM pg_catalog.pg_database"
|
||||
" WHERE datname = current_database())",
|
||||
PGRES_TUPLES_OK);
|
||||
uint64 n = (res != NULL) ? strtoul(PQgetvalue(res, 0, 0), NULL, 10) : 0;
|
||||
if (n > 0) {
|
||||
write_msg(NULL, "WARNING: subscriptions not dumped because current user is not a superuser\n");
|
||||
}
|
||||
PQclear(res);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -10786,11 +10795,6 @@ static void dumpDirectory(Archive* fout)
|
|||
char* dirpath = NULL;
|
||||
char* diracl = NULL;
|
||||
|
||||
if (!isExecUserSuperRole(fout)) {
|
||||
write_msg(NULL, "WARNING: directory not dumped because current user is not a superuser\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Make sure we are in proper schema */
|
||||
selectSourceSchema(fout, "pg_catalog");
|
||||
|
||||
|
|
@ -21400,11 +21404,6 @@ static void dumpSynonym(Archive* fout)
|
|||
PQExpBuffer q;
|
||||
PQExpBuffer delq;
|
||||
|
||||
if (!isExecUserSuperRole(fout)) {
|
||||
write_msg(NULL, "WARNING: synonym not dumped because current user is not a superuser\n");
|
||||
return;
|
||||
}
|
||||
|
||||
selectSourceSchema(fout, "pg_catalog");
|
||||
query = createPQExpBuffer();
|
||||
printfPQExpBuffer(query,
|
||||
|
|
|
|||
|
|
@ -31,9 +31,6 @@
|
|||
it will be backuped up in external dirs */
|
||||
parray *pgdata_nobackup_dir = NULL;
|
||||
|
||||
/* list of logical replication slots */
|
||||
parray *logical_replslot = NULL;
|
||||
|
||||
static int standby_message_timeout_local = 10 ; /* 10 sec = default */
|
||||
static XLogRecPtr stop_backup_lsn = InvalidXLogRecPtr;
|
||||
static XLogRecPtr stop_stream_lsn = InvalidXLogRecPtr;
|
||||
|
|
@ -92,11 +89,10 @@ static void backup_cleanup(bool fatal, void *userdata);
|
|||
|
||||
static void *backup_files(void *arg);
|
||||
|
||||
static void do_backup_instance(PGconn *backup_conn, PGNodeInfo *nodeInfo, bool no_sync, bool backup_logs,
|
||||
bool backup_replslots);
|
||||
static void do_backup_instance(PGconn *backup_conn, PGNodeInfo *nodeInfo, bool no_sync, bool backup_logs);
|
||||
|
||||
static void pg_start_backup(const char *label, bool smooth, pgBackup *backup,
|
||||
PGNodeInfo *nodeInfo, PGconn *conn, bool backup_replslots);
|
||||
PGNodeInfo *nodeInfo, PGconn *conn);
|
||||
static void pg_stop_backup(pgBackup *backup, PGconn *pg_startbackup_conn, PGNodeInfo *nodeInfo);
|
||||
static int checkpoint_timeout(PGconn *backup_conn);
|
||||
|
||||
|
|
@ -562,7 +558,7 @@ static void sync_files(parray *database_map, const char *database_path, parray *
|
|||
* Move files from 'pgdata' to a subdirectory in 'backup_path'.
|
||||
*/
|
||||
static void
|
||||
do_backup_instance(PGconn *backup_conn, PGNodeInfo *nodeInfo, bool no_sync, bool backup_logs, bool backup_replslots)
|
||||
do_backup_instance(PGconn *backup_conn, PGNodeInfo *nodeInfo, bool no_sync, bool backup_logs)
|
||||
{
|
||||
int i;
|
||||
char database_path[MAXPGPATH];
|
||||
|
|
@ -595,7 +591,7 @@ do_backup_instance(PGconn *backup_conn, PGNodeInfo *nodeInfo, bool no_sync, bool
|
|||
securec_check_c(rc, "\0", "\0");
|
||||
|
||||
/* Call pg_start_backup function in openGauss connect */
|
||||
pg_start_backup(label, smooth_checkpoint, ¤t, nodeInfo, backup_conn, backup_replslots);
|
||||
pg_start_backup(label, smooth_checkpoint, ¤t, nodeInfo, backup_conn);
|
||||
|
||||
/* Obtain current timeline */
|
||||
#if PG_VERSION_NUM >= 90600
|
||||
|
|
@ -628,10 +624,10 @@ do_backup_instance(PGconn *backup_conn, PGNodeInfo *nodeInfo, bool no_sync, bool
|
|||
/* list files with the logical path. omit $PGDATA */
|
||||
if (fio_is_remote(FIO_DB_HOST))
|
||||
fio_list_dir(backup_files_list, instance_config.pgdata,
|
||||
true, true, false, backup_logs, true, 0, backup_replslots);
|
||||
true, true, false, backup_logs, true, 0);
|
||||
else
|
||||
dir_list_file(backup_files_list, instance_config.pgdata,
|
||||
true, true, false, backup_logs, true, 0, FIO_LOCAL_HOST, backup_replslots);
|
||||
true, true, false, backup_logs, true, 0, FIO_LOCAL_HOST);
|
||||
|
||||
/*
|
||||
* Get database_map (name to oid) for use in partial restore feature.
|
||||
|
|
@ -753,11 +749,6 @@ do_backup_instance(PGconn *backup_conn, PGNodeInfo *nodeInfo, bool no_sync, bool
|
|||
}
|
||||
pgdata_nobackup_dir = NULL;
|
||||
|
||||
if (logical_replslot) {
|
||||
free_dir_list(logical_replslot);
|
||||
}
|
||||
logical_replslot = NULL;
|
||||
|
||||
/* Cleanup */
|
||||
if (backup_list)
|
||||
{
|
||||
|
|
@ -858,7 +849,7 @@ static void do_after_backup()
|
|||
*/
|
||||
int
|
||||
do_backup(time_t start_time, pgSetBackupParams *set_backup_params,
|
||||
bool no_validate, bool no_sync, bool backup_logs, bool backup_replslots)
|
||||
bool no_validate, bool no_sync, bool backup_logs)
|
||||
{
|
||||
PGconn *backup_conn = NULL;
|
||||
PGNodeInfo nodeInfo;
|
||||
|
|
@ -934,7 +925,7 @@ do_backup(time_t start_time, pgSetBackupParams *set_backup_params,
|
|||
add_note(¤t, set_backup_params->note);
|
||||
|
||||
/* backup data */
|
||||
do_backup_instance(backup_conn, &nodeInfo, no_sync, backup_logs, backup_replslots);
|
||||
do_backup_instance(backup_conn, &nodeInfo, no_sync, backup_logs);
|
||||
pgut_atexit_pop(backup_cleanup, NULL);
|
||||
|
||||
/* compute size of wal files of this backup stored in the archive */
|
||||
|
|
@ -1043,15 +1034,13 @@ confirm_block_size(PGconn *conn, const char *name, int blcksz)
|
|||
*/
|
||||
static void
|
||||
pg_start_backup(const char *label, bool smooth, pgBackup *backup,
|
||||
PGNodeInfo *nodeInfo, PGconn *conn, bool backup_replslots)
|
||||
PGNodeInfo *nodeInfo, PGconn *conn)
|
||||
{
|
||||
PGresult *res;
|
||||
const char *params[2];
|
||||
uint32 lsn_hi;
|
||||
uint32 lsn_lo;
|
||||
int ret;
|
||||
int i;
|
||||
XLogRecPtr startLsn;
|
||||
|
||||
params[0] = label;
|
||||
|
||||
|
|
@ -1079,33 +1068,7 @@ pg_start_backup(const char *label, bool smooth, pgBackup *backup,
|
|||
XLogDataFromLSN(ret, PQgetvalue(res, 0, 0), &lsn_hi, &lsn_lo);
|
||||
securec_check_for_sscanf_s(ret, 2, "\0", "\0");
|
||||
/* Calculate LSN */
|
||||
startLsn = ((uint64) lsn_hi )<< 32 | lsn_lo;
|
||||
|
||||
if (backup_replslots) {
|
||||
logical_replslot = parray_new();
|
||||
/* query for logical replication slots of subscriptions */
|
||||
res = pgut_execute(conn,
|
||||
"SELECT slot_name, restart_lsn FROM pg_catalog.pg_get_replication_slots()"
|
||||
"WHERE slot_type = 'logical' AND plugin = 'pgoutput'", 0, NULL);
|
||||
if (PQntuples(res) == 0) {
|
||||
elog(LOG, "logical replication slots for subscriptions not found");
|
||||
} else {
|
||||
XLogRecPtr repslotLsn;
|
||||
|
||||
for (i = 0; i < PQntuples(res); i++) {
|
||||
XLogDataFromLSN(ret, PQgetvalue(res, i, 1), &lsn_hi, &lsn_lo);
|
||||
securec_check_for_sscanf_s(ret, 2, "\0", "\0");
|
||||
repslotLsn = ((uint64) lsn_hi )<< 32 | lsn_lo;
|
||||
startLsn = Min(startLsn, repslotLsn);
|
||||
|
||||
char* slotname = pg_strdup(PQgetvalue(res, i, 0));
|
||||
parray_append(logical_replslot, slotname);
|
||||
}
|
||||
elog(WARNING, "logical replication slots for subscriptions will be backed up. "
|
||||
"If don't use them after restoring, please drop them to avoid affecting xlog recycling.");
|
||||
}
|
||||
}
|
||||
backup->start_lsn = startLsn;
|
||||
backup->start_lsn = ((uint64) lsn_hi )<< 32 | lsn_lo;
|
||||
|
||||
PQclear(res);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -42,6 +42,13 @@ const char *pgdata_exclude_dir[] =
|
|||
(const char *)"pg_stat_tmp",
|
||||
(const char *)"pgsql_tmp",
|
||||
|
||||
/*
|
||||
* It is generally not useful to backup the contents of this directory even
|
||||
* if the intention is to restore to another master. See backup.sgml for a
|
||||
* more detailed description.
|
||||
*/
|
||||
(const char *)"pg_replslot",
|
||||
|
||||
/* Contents removed on startup, see dsm_cleanup_for_mmap(). */
|
||||
(const char *)"pg_dynshmem",
|
||||
|
||||
|
|
@ -61,7 +68,7 @@ const char *pgdata_exclude_dir[] =
|
|||
(const char *)"pg_subtrans",
|
||||
|
||||
/* end of list */
|
||||
NULL, /* pg_log and pg_replslot will be set later */
|
||||
NULL, /* pg_log will be set later */
|
||||
NULL
|
||||
};
|
||||
|
||||
|
|
@ -121,20 +128,17 @@ may be removed int the future */
|
|||
|
||||
static int pgCompareString(const void *str1, const void *str2);
|
||||
|
||||
static char dir_check_file(pgFile *file, bool backup_logs, bool backup_replslots);
|
||||
static char dir_check_file(pgFile *file, bool backup_logs);
|
||||
static char check_in_tablespace(pgFile *file, bool in_tablespace);
|
||||
static char check_db_dir(pgFile *file);
|
||||
static char check_digit_file(pgFile *file);
|
||||
static char check_nobackup_dir(pgFile *file);
|
||||
static void dir_list_file_internal(parray *files, pgFile *parent, const char *parent_dir,
|
||||
bool exclude, bool follow_symlink, bool backup_logs,
|
||||
bool skip_hidden, int external_dir_num, fio_location location,
|
||||
bool backup_replslots);
|
||||
bool skip_hidden, int external_dir_num, fio_location location);
|
||||
static void opt_path_map(ConfigOption *opt, const char *arg,
|
||||
TablespaceList *list, const char *type);
|
||||
|
||||
char check_logical_replslot_dir(const char *rel_path);
|
||||
|
||||
/* Tablespace mapping */
|
||||
static TablespaceList tablespace_dirs = {NULL, NULL};
|
||||
/* Extra directories mapping */
|
||||
|
|
@ -534,7 +538,7 @@ db_map_entry_free(void *entry)
|
|||
void
|
||||
dir_list_file(parray *files, const char *root, bool exclude, bool follow_symlink,
|
||||
bool add_root, bool backup_logs, bool skip_hidden, int external_dir_num,
|
||||
fio_location location, bool backup_replslots)
|
||||
fio_location location)
|
||||
{
|
||||
pgFile *file;
|
||||
|
||||
|
|
@ -561,7 +565,7 @@ dir_list_file(parray *files, const char *root, bool exclude, bool follow_symlink
|
|||
parray_append(files, file);
|
||||
|
||||
dir_list_file_internal(files, file, root, exclude, follow_symlink,
|
||||
backup_logs, skip_hidden, external_dir_num, location, backup_replslots);
|
||||
backup_logs, skip_hidden, external_dir_num, location);
|
||||
|
||||
if (!add_root)
|
||||
pgFileFree(file);
|
||||
|
|
@ -585,7 +589,7 @@ dir_list_file(parray *files, const char *root, bool exclude, bool follow_symlink
|
|||
* - datafiles
|
||||
*/
|
||||
static char
|
||||
dir_check_file(pgFile *file, bool backup_logs, bool backup_replslots)
|
||||
dir_check_file(pgFile *file, bool backup_logs)
|
||||
{
|
||||
int i;
|
||||
int sscanf_res;
|
||||
|
|
@ -648,29 +652,6 @@ dir_check_file(pgFile *file, bool backup_logs, bool backup_replslots)
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Backup pg_replslot if it is specified.
|
||||
* It is generally not useful to backup the contents of this directory even
|
||||
* if the intention is to restore to another master. See backup.sgml for a
|
||||
* more detailed description.
|
||||
*/
|
||||
if (!backup_replslots) {
|
||||
if (strcmp(file->rel_path, PG_REPLSLOT_DIR) == 0) {
|
||||
/* Skip */
|
||||
elog(VERBOSE, "Excluding directory content: %s", file->rel_path);
|
||||
return CHECK_EXCLUDE_FALSE;
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
* Check file that under pg_replslot and judge whether it
|
||||
* belonged to logical replication slots for subscriptions.
|
||||
*/
|
||||
if (strcmp(file->rel_path, PG_REPLSLOT_DIR) != 0 &&
|
||||
path_is_prefix_of_path(PG_REPLSLOT_DIR, file->rel_path)) {
|
||||
return check_logical_replslot_dir(file->rel_path);
|
||||
}
|
||||
}
|
||||
|
||||
ret = check_nobackup_dir(file);
|
||||
if (ret != -1) { /* -1 means need backup */
|
||||
return ret;
|
||||
|
|
@ -768,35 +749,6 @@ static char check_nobackup_dir(pgFile *file)
|
|||
return ret;
|
||||
}
|
||||
|
||||
char check_logical_replslot_dir(const char *rel_path)
|
||||
{
|
||||
char ret = CHECK_FALSE;
|
||||
int i = 0;
|
||||
char *tmp = pg_strdup(rel_path);
|
||||
char *p;
|
||||
#define DIRECTORY_DELIMITER "/"
|
||||
|
||||
if (logical_replslot) {
|
||||
/* extract slot name from rel_path, such as sub1 from pg_replslot/sub1/snap */
|
||||
p = strtok(tmp, DIRECTORY_DELIMITER);
|
||||
if (p != NULL) {
|
||||
p = strtok(NULL, DIRECTORY_DELIMITER);
|
||||
}
|
||||
|
||||
for (i = 0; p != NULL && i < (int)parray_num(logical_replslot); i++) {
|
||||
char *slotName = (char *)parray_get(logical_replslot, i);
|
||||
if (strcmp(p, slotName) == 0) {
|
||||
pfree(tmp);
|
||||
return CHECK_TRUE;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
ret = CHECK_TRUE;
|
||||
}
|
||||
pfree(tmp);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static char check_db_dir(pgFile *file)
|
||||
{
|
||||
char ret = -1;
|
||||
|
|
@ -937,8 +889,7 @@ bool SkipSomeDirFile(pgFile *file, struct dirent *dent, bool skipHidden)
|
|||
static void
|
||||
dir_list_file_internal(parray *files, pgFile *parent, const char *parent_dir,
|
||||
bool exclude, bool follow_symlink, bool backup_logs,
|
||||
bool skip_hidden, int external_dir_num, fio_location location,
|
||||
bool backup_replslots)
|
||||
bool skip_hidden, int external_dir_num, fio_location location)
|
||||
{
|
||||
DIR *dir;
|
||||
struct dirent *dent;
|
||||
|
|
@ -986,7 +937,7 @@ dir_list_file_internal(parray *files, pgFile *parent, const char *parent_dir,
|
|||
|
||||
if (exclude)
|
||||
{
|
||||
check_res = dir_check_file(file, backup_logs, backup_replslots);
|
||||
check_res = dir_check_file(file, backup_logs);
|
||||
if (check_res == CHECK_FALSE)
|
||||
{
|
||||
/* Skip */
|
||||
|
|
@ -1012,7 +963,7 @@ dir_list_file_internal(parray *files, pgFile *parent, const char *parent_dir,
|
|||
*/
|
||||
if (S_ISDIR(file->mode))
|
||||
dir_list_file_internal(files, file, child, exclude, follow_symlink,
|
||||
backup_logs, skip_hidden, external_dir_num, location, backup_replslots);
|
||||
backup_logs, skip_hidden, external_dir_num, location);
|
||||
}
|
||||
|
||||
if (errno && errno != ENOENT)
|
||||
|
|
|
|||
|
|
@ -51,7 +51,6 @@ typedef struct
|
|||
bool exclusive_backup;
|
||||
bool skip_hidden;
|
||||
int external_dir_num;
|
||||
bool backup_replslots;
|
||||
} fio_list_dir_request;
|
||||
|
||||
typedef struct
|
||||
|
|
@ -1795,7 +1794,7 @@ cleanup:
|
|||
/* Compile the array of files located on remote machine in directory root */
|
||||
void fio_list_dir(parray *files, const char *root, bool exclude,
|
||||
bool follow_symlink, bool add_root, bool backup_logs,
|
||||
bool skip_hidden, int external_dir_num, bool backup_replslots)
|
||||
bool skip_hidden, int external_dir_num)
|
||||
{
|
||||
fio_header hdr;
|
||||
fio_list_dir_request req;
|
||||
|
|
@ -1812,7 +1811,6 @@ void fio_list_dir(parray *files, const char *root, bool exclude,
|
|||
req.exclusive_backup = exclusive_backup;
|
||||
req.skip_hidden = skip_hidden;
|
||||
req.external_dir_num = external_dir_num;
|
||||
req.backup_replslots = backup_replslots;
|
||||
|
||||
hdr.cop = FIO_LIST_DIR;
|
||||
hdr.size = sizeof(req);
|
||||
|
|
@ -1872,14 +1870,7 @@ void fio_list_dir(parray *files, const char *root, bool exclude,
|
|||
securec_check_ss_c(nRet, "\0", "\0");
|
||||
}
|
||||
|
||||
/*
|
||||
* Check file that under pg_replslot and judge whether it
|
||||
* belonged to logical replication slots for subscriptions.
|
||||
*/
|
||||
if (backup_replslots && strcmp(buf, PG_REPLSLOT_DIR) != 0 &&
|
||||
path_is_prefix_of_path(PG_REPLSLOT_DIR, buf) && check_logical_replslot_dir(file->rel_path) != 1) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
parray_append(files, file);
|
||||
}
|
||||
|
|
@ -1923,7 +1914,7 @@ static void fio_list_dir_impl(int out, char* buf)
|
|||
|
||||
dir_list_file(file_files, req->path, req->exclude, req->follow_symlink,
|
||||
req->add_root, req->backup_logs, req->skip_hidden,
|
||||
req->external_dir_num, FIO_LOCAL_HOST, req->backup_replslots);
|
||||
req->external_dir_num, FIO_LOCAL_HOST);
|
||||
|
||||
/* send information about files to the main process */
|
||||
for (i = 0; i < (int)parray_num(file_files); i++)
|
||||
|
|
|
|||
|
|
@ -163,7 +163,5 @@ extern z_off_t fio_gzseek(gzFile f, z_off_t offset, int whence);
|
|||
extern const char* fio_gzerror(gzFile file, int *errnum);
|
||||
#endif
|
||||
|
||||
extern char check_logical_replslot_dir(const char *rel_path);
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
|||
|
|
@ -154,7 +154,6 @@ void help_pg_probackup(void)
|
|||
printf(_(" [--remote-port=port] [--ssh-options=ssh_options]\n"));
|
||||
printf(_(" [--remote-libpath=libpath]\n"));
|
||||
printf(_(" [--ttl=interval] [--expire-time=time]\n"));
|
||||
printf(_(" [--backup-pg-replslot]\n"));
|
||||
printf(_(" [--help]\n"));
|
||||
|
||||
printf(_("\n %s restore -B backup-path --instance=instance_name\n"), PROGRAM_NAME);
|
||||
|
|
@ -421,7 +420,6 @@ static void help_backup(void)
|
|||
printf(_(" [--remote-port=port] [--ssh-options=ssh_options]\n"));
|
||||
printf(_(" [--remote-libpath=libpath]\n"));
|
||||
printf(_(" [--ttl=interval] [--expire-time=time]\n\n"));
|
||||
printf(_(" [--backup-pg-replslot]\n"));
|
||||
|
||||
printf(_(" -B, --backup-path=backup-path location of the backup storage area\n"));
|
||||
printf(_(" --instance=instance_name name of the instance\n"));
|
||||
|
|
@ -443,7 +441,6 @@ static void help_backup(void)
|
|||
printf(_(" --note=text add note to backup\n"));
|
||||
printf(_(" (example: --note='backup before app update to v13.1')\n"));
|
||||
printf(_(" --archive-timeout=timeout wait timeout for WAL segment archiving (default: 5min)\n"));
|
||||
printf(_(" --backup-pg-replslot] backup of '%s' directory\n"), PG_REPLSLOT_DIR);
|
||||
|
||||
printf(_("\n Logging options:\n"));
|
||||
printf(_(" --log-level-console=log-level-console\n"));
|
||||
|
|
|
|||
|
|
@ -77,7 +77,6 @@ int rw_timeout = 0;
|
|||
|
||||
/* backup options */
|
||||
bool backup_logs = false;
|
||||
bool backup_replslots = false;
|
||||
bool smooth_checkpoint;
|
||||
char *remote_agent;
|
||||
static char *backup_note = NULL;
|
||||
|
|
@ -187,7 +186,6 @@ static ConfigOption cmd_options[] =
|
|||
{ 'b', 145, "wal", &delete_wal, SOURCE_CMD_STRICT },
|
||||
{ 'b', 146, "expired", &delete_expired, SOURCE_CMD_STRICT },
|
||||
{ 's', 172, "status", &delete_status, SOURCE_CMD_STRICT },
|
||||
{ 'b', 186, "backup-pg-replslot", &backup_replslots, SOURCE_CMD_STRICT},
|
||||
|
||||
{ 'b', 147, "force", &force, SOURCE_CMD_STRICT },
|
||||
{ 'b', 148, "compress", &compress_shortcut, SOURCE_CMD_STRICT },
|
||||
|
|
@ -552,7 +550,7 @@ static int do_actual_operate()
|
|||
elog(ERROR, "required parameter not specified: BACKUP_MODE "
|
||||
"(-b, --backup-mode)");
|
||||
|
||||
return do_backup(start_time, set_backup_params, no_validate, no_sync, backup_logs, backup_replslots);
|
||||
return do_backup(start_time, set_backup_params, no_validate, no_sync, backup_logs);
|
||||
}
|
||||
case RESTORE_CMD:
|
||||
return do_restore_or_validate(current.backup_id,
|
||||
|
|
|
|||
|
|
@ -69,7 +69,6 @@ extern const char *PROGRAM_FULL_PATH;
|
|||
#define HEADER_MAP "page_header_map"
|
||||
#define HEADER_MAP_TMP "page_header_map_tmp"
|
||||
#define PG_RELATIVE_TBLSPC_DIR "pg_location"
|
||||
#define PG_REPLSLOT_DIR "pg_replslot"
|
||||
|
||||
/* Timeout defaults */
|
||||
#define ARCHIVE_TIMEOUT_DEFAULT 300
|
||||
|
|
|
|||
|
|
@ -54,9 +54,6 @@ extern bool smooth_checkpoint;
|
|||
it will be backuped up in external dirs */
|
||||
extern parray *pgdata_nobackup_dir;
|
||||
|
||||
/* list of logical replication slots */
|
||||
extern parray *logical_replslot;
|
||||
|
||||
/* remote probackup options */
|
||||
extern char* remote_agent;
|
||||
|
||||
|
|
@ -92,7 +89,7 @@ extern const char *pgdata_exclude_dir[];
|
|||
|
||||
/* in backup.c */
|
||||
extern int do_backup(time_t start_time, pgSetBackupParams *set_backup_params,
|
||||
bool no_validate, bool no_sync, bool backup_logs, bool backup_replslots);
|
||||
bool no_validate, bool no_sync, bool backup_logs);
|
||||
extern BackupMode parse_backup_mode(const char *value);
|
||||
extern const char *deparse_backup_mode(BackupMode mode);
|
||||
extern void process_block_change(ForkNumber forknum, const RelFileNode rnode,
|
||||
|
|
@ -242,8 +239,7 @@ extern const char* deparse_compress_alg(int alg);
|
|||
/* in dir.c */
|
||||
extern void dir_list_file(parray *files, const char *root, bool exclude,
|
||||
bool follow_symlink, bool add_root, bool backup_logs,
|
||||
bool skip_hidden, int external_dir_num, fio_location location,
|
||||
bool backup_replslots = false);
|
||||
bool skip_hidden, int external_dir_num, fio_location location);
|
||||
|
||||
extern void create_data_directories(parray *dest_files,
|
||||
const char *data_dir,
|
||||
|
|
@ -436,8 +432,7 @@ extern int fio_send_file(const char *from_fullpath, const char *to_fullpath, FIL
|
|||
pgFile *file, char **errormsg);
|
||||
|
||||
extern void fio_list_dir(parray *files, const char *root, bool exclude, bool follow_symlink,
|
||||
bool add_root, bool backup_logs, bool skip_hidden, int external_dir_num,
|
||||
bool backup_replslots = false);
|
||||
bool add_root, bool backup_logs, bool skip_hidden, int external_dir_num);
|
||||
|
||||
extern bool pgut_rmtree(const char *path, bool rmtopdir, bool strict);
|
||||
|
||||
|
|
|
|||
|
|
@ -8641,7 +8641,7 @@
|
|||
),
|
||||
AddFuncGroup(
|
||||
"pg_stat_get_wal_senders", 1,
|
||||
AddBuiltinFunc(_0(3099), _1("pg_stat_get_wal_senders"), _2(0), _3(false), _4(true), _5(pg_stat_get_wal_senders), _6(2249), _7(PG_CATALOG_NAMESPACE), _8(BOOTSTRAP_SUPERUSERID), _9(INTERNALlanguageId), _10(1), _11(10), _12(0), _13(0), _14(false), _15(false), _16(false), _17(false), _18('s'), _19(0), _20(0), _21(21, 20, 23, 25, 25, 25, 25, 1184, 1184, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 23, 25, 25), _22(21, 'o', 'o', 'o', 'o', 'o', 'o', 'o', 'o', 'o', 'o', 'o', 'o', 'o', 'o', 'o', 'o', 'o', 'o', 'o', 'o', 'o'), _23(21, "pid", "sender_pid", "local_role", "peer_role", "peer_state", "state", "catchup_start", "catchup_end", "sender_sent_location", "sender_write_location", "sender_flush_location", "sender_replay_location", "receiver_received_location", "receiver_write_location", "receiver_flush_location", "receiver_replay_location", "sync_percent", "sync_state", "sync_priority", "sync_most_available", "channel"), _24(NULL), _25("pg_stat_get_wal_senders"), _26(NULL), _27(NULL), _28(NULL), _29(0), _30(false), _31(NULL), _32(false), _33("statistics: information about currently active replication"), _34('f'), _35(NULL), _36(0), _37(false), _38(NULL), _39(NULL), _40(0))
|
||||
AddBuiltinFunc(_0(3099), _1("pg_stat_get_wal_senders"), _2(0), _3(false), _4(true), _5(pg_stat_get_wal_senders), _6(2249), _7(PG_CATALOG_NAMESPACE), _8(BOOTSTRAP_SUPERUSERID), _9(INTERNALlanguageId), _10(1), _11(10), _12(0), _13(0), _14(false), _15(false), _16(false), _17(false), _18('s'), _19(0), _20(0), _21(22, 20, 23, 25, 25, 25, 25, 1184, 1184, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 23, 23, 25, 25), _22(22, 'o', 'o', 'o', 'o', 'o', 'o', 'o', 'o', 'o', 'o', 'o', 'o', 'o', 'o', 'o', 'o', 'o', 'o', 'o', 'o', 'o', 'o'), _23(22, "pid", "sender_pid", "local_role", "peer_role", "peer_state", "state", "catchup_start", "catchup_end", "sender_sent_location", "sender_write_location", "sender_flush_location", "sender_replay_location", "receiver_received_location", "receiver_write_location", "receiver_flush_location", "receiver_replay_location", "sync_percent", "sync_state", "sync_group", "sync_priority", "sync_most_available", "channel"), _24(NULL), _25("pg_stat_get_wal_senders"), _26(NULL), _27(NULL), _28(NULL), _29(0), _30(false), _31(NULL), _32(false), _33("statistics: information about currently active replication"), _34('f'), _35(NULL), _36(0), _37(false), _38(NULL), _39(NULL), _40(0))
|
||||
),
|
||||
AddFuncGroup(
|
||||
"pg_stat_get_wlm_ec_operator_info", 1,
|
||||
|
|
|
|||
|
|
@ -6230,7 +6230,7 @@ Datum GetPartBoundaryByTuple(Relation rel, HeapTuple tuple)
|
|||
return Timestamp2Boundarys(rel, Align2UpBoundary(value, partMap->intervalValue, boundaryTs));
|
||||
}
|
||||
|
||||
Oid AddNewIntervalPartition(Relation rel, void* insertTuple, bool isDDL)
|
||||
Oid AddNewIntervalPartition(Relation rel, void* insertTuple)
|
||||
{
|
||||
Relation pgPartRel = NULL;
|
||||
Oid newPartOid = InvalidOid;
|
||||
|
|
@ -6327,13 +6327,7 @@ Oid AddNewIntervalPartition(Relation rel, void* insertTuple, bool isDDL)
|
|||
*/
|
||||
CommandCounterIncrement();
|
||||
|
||||
/*
|
||||
* If add interval partition in the DDL, do not need to change the csn
|
||||
* because the scn has been changed in the DDL.
|
||||
*/
|
||||
if (!isDDL) {
|
||||
UpdatePgObjectChangecsn(RelationGetRelid(rel), rel->rd_rel->relkind);
|
||||
}
|
||||
UpdatePgObjectChangecsn(RelationGetRelid(rel), rel->rd_rel->relkind);
|
||||
|
||||
return newPartOid;
|
||||
}
|
||||
|
|
@ -7119,7 +7113,7 @@ int lookupHBucketid(oidvector *buckets, int low, int2 bktId)
|
|||
* Description :
|
||||
* Notes :
|
||||
*/
|
||||
Oid heapTupleGetPartitionId(Relation rel, void *tuple, bool isDDL)
|
||||
Oid heapTupleGetPartitionId(Relation rel, void *tuple)
|
||||
{
|
||||
Oid partitionid = InvalidOid;
|
||||
|
||||
|
|
@ -7146,7 +7140,7 @@ Oid heapTupleGetPartitionId(Relation rel, void *tuple, bool isDDL)
|
|||
(errcode(ERRCODE_NO_DATA_FOUND), errmsg("inserted partition key does not map to any table partition")));
|
||||
} break;
|
||||
case PART_AREA_INTERVAL: {
|
||||
return AddNewIntervalPartition(rel, tuple, isDDL);
|
||||
return AddNewIntervalPartition(rel, tuple);
|
||||
} break;
|
||||
case PART_AREA_LIST: {
|
||||
ereport(ERROR,
|
||||
|
|
|
|||
|
|
@ -47,8 +47,7 @@ static void InternalAggIsSupported(const char *aggName)
|
|||
"json_agg",
|
||||
"json_object_agg",
|
||||
"st_summarystatsagg",
|
||||
"st_union",
|
||||
"wm_concat"
|
||||
"st_union"
|
||||
};
|
||||
|
||||
uint len = lengthof(supportList);
|
||||
|
|
|
|||
|
|
@ -52,7 +52,7 @@ static_assert(sizeof(false) == sizeof(char), "illegal bool size");
|
|||
static struct HTAB* nameHash = NULL;
|
||||
static struct HTAB* oidHash = NULL;
|
||||
|
||||
/* for dolphin */
|
||||
/* for b_sql_plugin */
|
||||
struct HTAB* b_nameHash = NULL;
|
||||
struct HTAB* b_oidHash = NULL;
|
||||
|
||||
|
|
@ -118,7 +118,7 @@ static const FuncGroup* NameHashTableAccess(HASHACTION action, const char* name,
|
|||
|
||||
Assert(name != NULL);
|
||||
|
||||
if (DB_IS_CMPT(B_FORMAT) && b_nameHash != NULL && u_sess->attr.attr_sql.dolphin) {
|
||||
if (DB_IS_CMPT(B_FORMAT) && b_nameHash != NULL && u_sess->attr.attr_sql.b_sql_plugin) {
|
||||
result = (HashEntryNameToFuncGroup *)hash_search(b_nameHash, &temp_name, action, &found);
|
||||
} else {
|
||||
result = (HashEntryNameToFuncGroup *)hash_search(nameHash, &temp_name, action, &found);
|
||||
|
|
@ -144,7 +144,7 @@ static const Builtin_func* OidHashTableAccess(HASHACTION action, Oid oid, const
|
|||
bool found = false;
|
||||
Assert(oid > 0);
|
||||
|
||||
if (DB_IS_CMPT(B_FORMAT) && b_oidHash != NULL && u_sess->attr.attr_sql.dolphin) {
|
||||
if (DB_IS_CMPT(B_FORMAT) && b_oidHash != NULL && u_sess->attr.attr_sql.b_sql_plugin) {
|
||||
result = (HashEntryOidToBuiltinFunc *)hash_search(b_oidHash, &oid, action, &found);
|
||||
} else {
|
||||
result = (HashEntryOidToBuiltinFunc *)hash_search(oidHash, &oid, action, &found);
|
||||
|
|
|
|||
|
|
@ -68,7 +68,7 @@ Subscription *GetSubscription(Oid subid, bool missing_ok)
|
|||
|
||||
/* Get slotname */
|
||||
datum = SysCacheGetAttr(SUBSCRIPTIONOID, tup, Anum_pg_subscription_subslotname, &isnull);
|
||||
if (!isnull) {
|
||||
if (unlikely(isnull)) {
|
||||
sub->slotname = pstrdup(NameStr(*DatumGetName(datum)));
|
||||
} else {
|
||||
sub->slotname = NULL;
|
||||
|
|
@ -92,10 +92,10 @@ Subscription *GetSubscription(Oid subid, bool missing_ok)
|
|||
|
||||
datum = SysCacheGetAttr(SUBSCRIPTIONOID, tup, Anum_pg_subscription_subbinary, &isnull);
|
||||
if (unlikely(isnull)) {
|
||||
sub->binary = false;
|
||||
} else {
|
||||
sub->binary = DatumGetBool(datum);
|
||||
ereport(ERROR, (errcode(ERRCODE_UNEXPECTED_NULL_VALUE),
|
||||
errmsg("null binary for subscription %u", subid)));
|
||||
}
|
||||
sub->binary = DatumGetBool(datum);
|
||||
|
||||
ReleaseSysCache(tup);
|
||||
|
||||
|
|
|
|||
|
|
@ -70,7 +70,6 @@
|
|||
|
||||
THR_LOCAL bool skip_read_extern_fields = false;
|
||||
|
||||
#define IS_DATANODE_BUT_NOT_SINGLENODE (IS_PGXC_DATANODE && !IS_SINGLE_NODE)
|
||||
/*
|
||||
* Macros to simplify reading of different kinds of fields. Use these
|
||||
* wherever possible to reduce the chance for silly typos. Note that these
|
||||
|
|
@ -402,27 +401,24 @@ THR_LOCAL bool skip_read_extern_fields = false;
|
|||
token = pg_strtok(&length); /* skip :fldname */ \
|
||||
local_node->fldname = _readBitmapset()
|
||||
|
||||
#define READ_TYPEINFO_FIELD(fldname) \
|
||||
do { \
|
||||
if (local_node->fldname >= FirstBootstrapObjectId) { \
|
||||
IF_EXIST(exprtypename) \
|
||||
{ \
|
||||
char* exprtypename = NULL; \
|
||||
char* exprtypenamespace = NULL; \
|
||||
token = pg_strtok(&length); \
|
||||
token = pg_strtok(&length); \
|
||||
exprtypename = nullable_string(token, length); \
|
||||
token = pg_strtok(&length); \
|
||||
token = pg_strtok(&length); \
|
||||
exprtypenamespace = nullable_string(token, length); \
|
||||
/* No need to reset field on CN or singlenode, keep pg_strtok() for forward compatibility */ \
|
||||
if (IS_DATANODE_BUT_NOT_SINGLENODE) { \
|
||||
local_node->fldname = get_typeoid(get_namespace_oid(exprtypenamespace, false), exprtypename); \
|
||||
} \
|
||||
pfree_ext(exprtypename); \
|
||||
pfree_ext(exprtypenamespace); \
|
||||
} \
|
||||
} \
|
||||
#define READ_TYPEINFO_FIELD(fldname) \
|
||||
do { \
|
||||
if (local_node->fldname >= FirstBootstrapObjectId) { \
|
||||
IF_EXIST(exprtypename) \
|
||||
{ \
|
||||
char* exprtypename = NULL; \
|
||||
char* exprtypenamespace = NULL; \
|
||||
token = pg_strtok(&length); \
|
||||
token = pg_strtok(&length); \
|
||||
exprtypename = nullable_string(token, length); \
|
||||
token = pg_strtok(&length); \
|
||||
token = pg_strtok(&length); \
|
||||
exprtypenamespace = nullable_string(token, length); \
|
||||
local_node->fldname = get_typeoid(get_namespace_oid(exprtypenamespace, false), exprtypename); \
|
||||
pfree_ext(exprtypename); \
|
||||
pfree_ext(exprtypenamespace); \
|
||||
} \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define READ_TYPEINFO(typePtr) \
|
||||
|
|
@ -497,30 +493,9 @@ THR_LOCAL bool skip_read_extern_fields = false;
|
|||
token = pg_strtok(&length); \
|
||||
token = pg_strtok(&length); \
|
||||
funcnamespace = nullable_string(token, length); \
|
||||
bool notfound = false; \
|
||||
if (IS_DATANODE_BUT_NOT_SINGLENODE && !skip_read_extern_fields) { \
|
||||
Oid funcoid = InvalidOid; \
|
||||
do { \
|
||||
Oid nspid = get_namespace_oid(funcnamespace, true); \
|
||||
if (!OidIsValid(nspid)) { \
|
||||
notfound = true; \
|
||||
break; \
|
||||
} \
|
||||
funcoid = get_func_oid(funcname, nspid, (Expr*)local_node); \
|
||||
} while (0); \
|
||||
if (notfound || !OidIsValid(funcoid)) { \
|
||||
ereport(ERROR, \
|
||||
(errmodule(MOD_OPT), errcode(ERRCODE_UNDEFINED_OBJECT), \
|
||||
errmsg("Cannot identify function %s.%s while deserializing field.", \
|
||||
funcname, funcnamespace), \
|
||||
errdetail("Function with oid %u or its namespace may be renamed", \
|
||||
local_node->fldname), \
|
||||
errhint("Please rebuild column defalt expression, views etc. that are" \
|
||||
" related to this renamed object."), \
|
||||
errcause("Object renamed after recorded as nodetree."), \
|
||||
erraction("Rebuild relevant object."))); \
|
||||
} \
|
||||
local_node->fldname = funcoid; \
|
||||
if (IS_PGXC_DATANODE && !skip_read_extern_fields) { \
|
||||
local_node->fldname = \
|
||||
get_func_oid(funcname, get_namespace_oid(funcnamespace, false), (Expr*)local_node); \
|
||||
} \
|
||||
pfree_ext(funcname); \
|
||||
pfree_ext(funcnamespace); \
|
||||
|
|
@ -550,7 +525,7 @@ THR_LOCAL bool skip_read_extern_fields = false;
|
|||
token = pg_strtok(&length); \
|
||||
token = pg_strtok(&length); \
|
||||
oprrightname = nullable_string(token, length); \
|
||||
if (IS_DATANODE_BUT_NOT_SINGLENODE) { \
|
||||
if (IS_PGXC_DATANODE) { \
|
||||
namespaceId = get_namespace_oid(opnamespace, false); \
|
||||
oprleft = get_typeoid(namespaceId, oprleftname); \
|
||||
oprright = oprleft; \
|
||||
|
|
@ -593,7 +568,7 @@ THR_LOCAL bool skip_read_extern_fields = false;
|
|||
token = pg_strtok(&length); \
|
||||
token = pg_strtok(&length); \
|
||||
oprrightname = nullable_string(token, length); \
|
||||
if (IS_DATANODE_BUT_NOT_SINGLENODE) { \
|
||||
if (IS_PGXC_DATANODE) { \
|
||||
namespaceId = get_namespace_oid(opnamespace, false); \
|
||||
oprleft = get_typeoid(namespaceId, oprleftname); \
|
||||
oprright = oprleft; \
|
||||
|
|
@ -2151,21 +2126,14 @@ static FuncExpr* _readFuncExpr(void)
|
|||
ereport(ERROR, (errcode(ERRCODE_UNEXPECTED_NULL_VALUE), errmsg("NULL seqNamespace for nextval()")));
|
||||
}
|
||||
|
||||
if (IS_DATANODE_BUT_NOT_SINGLENODE && !skip_read_extern_fields) {
|
||||
if (!IS_PGXC_COORDINATOR && !skip_read_extern_fields) {
|
||||
Oid seqid = get_valid_relname_relid(seqNamespace, seqName);
|
||||
|
||||
Oid seqid = get_valid_relname_relid(seqNamespace, seqName, true);
|
||||
Const* firstArg = (Const*)linitial(local_node->args);
|
||||
if (OidIsValid(seqid)) {
|
||||
Const* firstArg = (Const*)linitial(local_node->args);
|
||||
if (firstArg != NULL) {
|
||||
firstArg->constvalue = ObjectIdGetDatum(seqid);
|
||||
}
|
||||
} else {
|
||||
ereport(ERROR, (errmodule(MOD_OPT), errcode(ERRCODE_UNDEFINED_OBJECT),
|
||||
errmsg("Cannot identify sequence %s.%s while deserializing field.", seqNamespace, seqName),
|
||||
errdetail("Sequence with oid %u or its namespace may be renamed",
|
||||
DatumGetObjectId(firstArg->constvalue)),
|
||||
errhint("Please rebuild column defalt expression, views etc. that are related to this sequence"),
|
||||
errcause("Object renamed after recorded as nodetree."), erraction("Rebuild relevant object.")));
|
||||
}
|
||||
}
|
||||
pfree_ext(seqName);
|
||||
|
|
|
|||
|
|
@ -1454,14 +1454,7 @@ FuncCandidateList sort_candidate_func_list(FuncCandidateList oldCandidates)
|
|||
}
|
||||
candidates[smallestIndex] = NULL;
|
||||
}
|
||||
|
||||
for (int i = 0; i < size; i++) {
|
||||
if (candidates[i] != NULL) {
|
||||
lastCandidate->next = candidates[i];
|
||||
lastCandidate = lastCandidate->next;
|
||||
}
|
||||
}
|
||||
lastCandidate->next = NULL;
|
||||
|
||||
pfree(candidates);
|
||||
return sortedCandidates;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -61,7 +61,7 @@ void GlobalBaseDefCache::RemoveElemFromBucket(GlobalBaseEntry *base)
|
|||
if (is_relation) {
|
||||
GlobalRelationEntry *entry = (GlobalRelationEntry *)base;
|
||||
uint64 rel_size = GetRelEstimateSize(entry);
|
||||
pg_atomic_fetch_sub_u64(&m_base_space, AllocSetContextUsedSpace(((AllocSet)entry->rel_mem_manager)));
|
||||
pg_atomic_fetch_sub_u64(&m_base_space, rel_size);
|
||||
m_db_entry->MemoryEstimateSub(rel_size);
|
||||
} else {
|
||||
GlobalPartitionEntry *entry = (GlobalPartitionEntry *)base;
|
||||
|
|
@ -77,7 +77,7 @@ void GlobalBaseDefCache::AddHeadToBucket(Index hash_index, GlobalBaseEntry *base
|
|||
if (is_relation) {
|
||||
GlobalRelationEntry *entry = (GlobalRelationEntry *)base;
|
||||
uint64 rel_size = GetRelEstimateSize(entry);
|
||||
pg_atomic_fetch_add_u64(&m_base_space, AllocSetContextUsedSpace(((AllocSet)entry->rel_mem_manager)));
|
||||
pg_atomic_fetch_add_u64(&m_base_space, rel_size);
|
||||
m_db_entry->MemoryEstimateAdd(rel_size);
|
||||
} else {
|
||||
GlobalPartitionEntry *entry = (GlobalPartitionEntry *)base;
|
||||
|
|
@ -400,4 +400,4 @@ GlobalBaseDefCache::GlobalBaseDefCache(Oid db_oid, bool is_shared, GlobalSysDBCa
|
|||
m_base_space = 0;
|
||||
m_obj_locks = NULL;
|
||||
m_db_entry = entry;
|
||||
}
|
||||
}
|
||||
|
|
@ -659,27 +659,7 @@ void GlobalSysDBCache::InitSysCacheRelIds()
|
|||
*/
|
||||
void GlobalSysDBCache::RefreshHotStandby()
|
||||
{
|
||||
if (!EnableGlobalSysCache()) {
|
||||
return;
|
||||
}
|
||||
hot_standby = (t_thrd.postmaster_cxt.HaShmData->current_mode != STANDBY_MODE || XLogStandbyInfoActive());
|
||||
if (hot_standby || !m_is_inited) {
|
||||
return;
|
||||
}
|
||||
/* clean all */
|
||||
for (int hash_index = 0; hash_index < m_nbuckets; hash_index ++) {
|
||||
PthreadRWlockRdlock(LOCAL_SYSDB_RESOWNER, &m_db_locks[hash_index]);
|
||||
for (Dlelem * elt = DLGetTail(m_bucket_list.GetBucket(hash_index)); elt != NULL;) {
|
||||
GlobalSysDBCacheEntry *entry = (GlobalSysDBCacheEntry *)DLE_VAL(elt);
|
||||
elt = DLGetPred(elt);
|
||||
entry->ResetDBCache<true>();
|
||||
}
|
||||
PthreadRWlockUnlock(LOCAL_SYSDB_RESOWNER, &m_db_locks[hash_index]);
|
||||
}
|
||||
if (m_global_shared_db_entry != NULL) {
|
||||
m_global_shared_db_entry->ResetDBCache<true>();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void GlobalSysDBCache::Init(MemoryContext parent)
|
||||
|
|
@ -1292,18 +1272,9 @@ int ResizeHashBucket(int origin_nbucket, DynamicHashBucketStrategy strategy)
|
|||
return cc_nbuckets;
|
||||
}
|
||||
|
||||
void NotifyGscRecoveryStarted()
|
||||
{
|
||||
if (!EnableGlobalSysCache()) {
|
||||
return;
|
||||
}
|
||||
g_instance.global_sysdbcache.recovery_finished = false;
|
||||
|
||||
}
|
||||
|
||||
void NotifyGscRecoveryFinished()
|
||||
{
|
||||
if (EnableGlobalSysCache()) {
|
||||
g_instance.global_sysdbcache.recovery_finished = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -183,7 +183,7 @@ void GlobalSysTabCache::InvalidTuples(int cache_id, uint32 hash_value, bool rese
|
|||
|
||||
/* maybe upgrade from version before v5r2c00, the cacheid is out of order
|
||||
* whatever, we cache nothing except relmap, so just ignore the catcache invalmsg */
|
||||
if (unlikely(!g_instance.global_sysdbcache.recovery_finished && m_global_systupcaches[cache_id] == NULL)) {
|
||||
if (unlikely(!g_instance.global_sysdbcache.recovery_finished) && m_global_systupcaches[cache_id] == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -74,7 +74,7 @@ Partition LocalPartDefCache::SearchPartitionFromGlobalCopy(Oid part_oid)
|
|||
if (!g_instance.global_sysdbcache.hot_standby) {
|
||||
return NULL;
|
||||
}
|
||||
if (unlikely(!IsPrimaryRecoveryFinished())) {
|
||||
if (unlikely(!g_instance.global_sysdbcache.recovery_finished)) {
|
||||
return NULL;
|
||||
}
|
||||
uint32 hash_value = oid_hash((void *)&(part_oid), sizeof(Oid));
|
||||
|
|
@ -165,7 +165,7 @@ static bool IsPartOidStoreInGlobal(Oid part_oid)
|
|||
if (!g_instance.global_sysdbcache.hot_standby) {
|
||||
return false;
|
||||
}
|
||||
if (unlikely(!IsPrimaryRecoveryFinished())) {
|
||||
if (unlikely(!g_instance.global_sysdbcache.recovery_finished)) {
|
||||
return false;
|
||||
}
|
||||
if (g_instance.global_sysdbcache.StopInsertGSC()) {
|
||||
|
|
@ -456,4 +456,4 @@ Partition LocalPartDefCache::PartitionIdGetPartition(Oid part_oid, StorageType s
|
|||
}
|
||||
|
||||
return pd;
|
||||
}
|
||||
}
|
||||
|
|
@ -433,7 +433,7 @@ LocalCatCTup *LocalSysTupCache::SearchTupleFromGlobal(Datum *arguments, uint32 h
|
|||
bool bypass_gsc = HistoricSnapshotActive() ||
|
||||
m_global_systupcache->enable_rls ||
|
||||
!g_instance.global_sysdbcache.hot_standby ||
|
||||
unlikely(!IsPrimaryRecoveryFinished());
|
||||
unlikely(!g_instance.global_sysdbcache.recovery_finished);
|
||||
if (invalid_entries.ExistTuple(hash_value) || bypass_gsc) {
|
||||
global_ct = m_global_systupcache->SearchTupleFromFile(hash_value, arguments, true);
|
||||
} else {
|
||||
|
|
@ -585,7 +585,7 @@ LocalCatCList *LocalSysTupCache::SearchListFromGlobal(int nkeys, Datum *argument
|
|||
bool bypass_gsc = HistoricSnapshotActive() ||
|
||||
m_global_systupcache->enable_rls ||
|
||||
!g_instance.global_sysdbcache.hot_standby ||
|
||||
unlikely(!IsPrimaryRecoveryFinished());
|
||||
unlikely(!g_instance.global_sysdbcache.recovery_finished);
|
||||
GlobalCatCList *global_cl;
|
||||
if (invalid_entries.ExistList() || bypass_gsc) {
|
||||
global_cl = m_global_systupcache->SearchListFromFile(hash_value, nkeys, arguments, true);
|
||||
|
|
@ -703,7 +703,7 @@ LocalCatCTup *LocalSysTupCache::SearchTupleFromGlobalForProcAllArgs(
|
|||
bool bypass_gsc = HistoricSnapshotActive() ||
|
||||
m_global_systupcache->enable_rls ||
|
||||
!g_instance.global_sysdbcache.hot_standby ||
|
||||
unlikely(!IsPrimaryRecoveryFinished());
|
||||
unlikely(!g_instance.global_sysdbcache.recovery_finished);
|
||||
if (invalid_entries.ExistTuple(hash_value) || bypass_gsc) {
|
||||
global_ct = m_global_systupcache->SearchTupleFromFileWithArgModes(hash_value, arguments, argModes, true);
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -93,7 +93,7 @@ Relation LocalTabDefCache::SearchRelationFromGlobalCopy(Oid rel_oid)
|
|||
if (!g_instance.global_sysdbcache.hot_standby) {
|
||||
return NULL;
|
||||
}
|
||||
if (unlikely(!IsPrimaryRecoveryFinished())) {
|
||||
if (unlikely(!g_instance.global_sysdbcache.recovery_finished)) {
|
||||
return NULL;
|
||||
}
|
||||
uint32 hash_value = oid_hash((void *)&(rel_oid), sizeof(Oid));
|
||||
|
|
@ -190,7 +190,7 @@ static bool IsRelOidStoreInGlobal(Oid rel_oid)
|
|||
if (!g_instance.global_sysdbcache.hot_standby) {
|
||||
return false;
|
||||
}
|
||||
if (unlikely(!IsPrimaryRecoveryFinished())) {
|
||||
if (unlikely(!g_instance.global_sysdbcache.recovery_finished)) {
|
||||
return false;
|
||||
}
|
||||
if (g_instance.global_sysdbcache.StopInsertGSC()) {
|
||||
|
|
@ -1137,4 +1137,4 @@ void LocalTabDefCache::ResetInitFlag()
|
|||
m_is_inited_phase3 = false;
|
||||
|
||||
m_db_id = InvalidOid;
|
||||
}
|
||||
}
|
||||
|
|
@ -1723,7 +1723,7 @@ char* get_relname_relid_extend(
|
|||
extern bool StreamTopConsumerAmI();
|
||||
|
||||
/* same as get_relname_relid except we check for cache invalidation here */
|
||||
Oid get_valid_relname_relid(const char* relnamespace, const char* relname, bool nsp_missing_ok)
|
||||
Oid get_valid_relname_relid(const char* relnamespace, const char* relname)
|
||||
{
|
||||
Oid nspid = InvalidOid;
|
||||
Oid oldnspid = InvalidOid;
|
||||
|
|
@ -1747,10 +1747,7 @@ Oid get_valid_relname_relid(const char* relnamespace, const char* relname, bool
|
|||
if (EnableLocalSysCache()) {
|
||||
thrd_inval_count = t_thrd.lsc_cxt.lsc->inval_cxt.SIMCounter;
|
||||
}
|
||||
nspid = get_namespace_oid(relnamespace, nsp_missing_ok);
|
||||
if (!OidIsValid(nspid)) {
|
||||
return InvalidOid;
|
||||
}
|
||||
nspid = get_namespace_oid(relnamespace, false);
|
||||
relid = get_relname_relid(relname, nspid);
|
||||
/*
|
||||
* In bootstrap processing mode, we don't bother with locking
|
||||
|
|
|
|||
|
|
@ -59,7 +59,7 @@ bool open_join_children = true;
|
|||
bool will_shutdown = false;
|
||||
|
||||
/* hard-wired binary version number */
|
||||
const uint32 GRAND_VERSION_NUM = 92606;
|
||||
const uint32 GRAND_VERSION_NUM = 92607;
|
||||
|
||||
const uint32 PREDPUSH_SAME_LEVEL_VERSION_NUM = 92522;
|
||||
const uint32 UPSERT_WHERE_VERSION_NUM = 92514;
|
||||
|
|
@ -101,7 +101,7 @@ const uint32 PRIVS_DIRECTORY_VERSION_NUM = 92460;
|
|||
const uint32 COMMENT_RECORD_PARAM_VERSION_NUM = 92484;
|
||||
const uint32 SCAN_BATCH_MODE_VERSION_NUM = 92568;
|
||||
const uint32 PUBLICATION_VERSION_NUM = 92580;
|
||||
const uint32 SUBSCRIPTION_BINARY_VERSION_NUM = 92606;
|
||||
const uint32 SUBSCRIPTION_BINARY_VERSION_NUM = 92607;
|
||||
|
||||
/* Version number of the guc parameter backend_version added in V500R001C20 */
|
||||
const uint32 V5R1C20_BACKEND_VERSION_NUM = 92305;
|
||||
|
|
|
|||
|
|
@ -2712,8 +2712,8 @@ void PostgresInitializer::InitExtensionVariable()
|
|||
}
|
||||
|
||||
/* check whether the extension has been created */
|
||||
const char* dolphin = "dolphin";
|
||||
u_sess->attr.attr_sql.dolphin = CheckIfExtensionExists(dolphin);
|
||||
const char* b_sql_plugin = "b_sql_plugin";
|
||||
u_sess->attr.attr_sql.b_sql_plugin = CheckIfExtensionExists(b_sql_plugin);
|
||||
}
|
||||
|
||||
void PostgresInitializer::FinishInit()
|
||||
|
|
|
|||
|
|
@ -10340,16 +10340,7 @@ check_sql_expr(const char *stmt, int location, int leaderlen)
|
|||
|
||||
oldCxt = MemoryContextSwitchTo(u_sess->plsql_cxt.curr_compile_context->compile_tmp_cxt);
|
||||
u_sess->plsql_cxt.plpgsql_yylloc = plpgsql_yylloc;
|
||||
RawParserHook parser_hook= raw_parser;
|
||||
#ifndef ENABLE_MULTIPLE_NODES
|
||||
if (u_sess->attr.attr_sql.dolphin) {
|
||||
int id = GetCustomParserId();
|
||||
if (id >= 0 && g_instance.raw_parser_hook[id] != NULL) {
|
||||
parser_hook = (RawParserHook)g_instance.raw_parser_hook[id];
|
||||
}
|
||||
}
|
||||
#endif
|
||||
(void)parser_hook(stmt, NULL);
|
||||
(void) raw_parser(stmt);
|
||||
MemoryContextSwitchTo(oldCxt);
|
||||
|
||||
/* Restore former ereport callback */
|
||||
|
|
|
|||
|
|
@ -44,22 +44,11 @@ static int g_iPosBlackList = 0;
|
|||
/* array store for black list */
|
||||
static BBOX_BLACKLIST_STRU g_stBlackList[BBOX_BLACK_LIST_COUNT_MAX];
|
||||
|
||||
/*
|
||||
function name: BBOX_DetermineMsb
|
||||
description: The function should judge the mode that PC uses to store data is Big-endian/Little-endian.
|
||||
arguments: void
|
||||
return value: An integer that indicates the mode is Big-endian/Little-endian,
|
||||
if it is ELFDATA2LSB, the mode is Little-endian,
|
||||
if it is ELFDATA2MSB, the mode is Big-endian.
|
||||
note:The way that this function judge the mode that PC uses to store data is through a union variable unProbe,
|
||||
at first we give its first member variable sShortInt a value BBOX_MSB_LSB_INT of type short, then its second
|
||||
member variable cSplit[sizeof(short)] equaling to cSplit[2] would have the equal value of the first. Finally we
|
||||
just need to compare BBOX_LITTER_BITS and BBOX_HIGH_BITS, namely the low byte and high byte of
|
||||
BBOX_MSB_LSB_INT, with unProbe.cSplit[0] and unProbe.cSplit[1], if they are correspondingly equal, the mode is
|
||||
Little-endian, else is the Big-endian.
|
||||
date: 2022/8/2
|
||||
contact tel: 18720816902
|
||||
*/
|
||||
/*
|
||||
* Determines whether the byte order of the local machine is large or small
|
||||
* return : ELFDATA2LSB - large
|
||||
* : ELFDATA2MSB - small
|
||||
*/
|
||||
int BBOX_DetermineMsb(void)
|
||||
{
|
||||
union INT_PROBE {
|
||||
|
|
|
|||
|
|
@ -51,19 +51,8 @@ struct PIPE_IDS {
|
|||
static struct PIPE_IDS astPipeIds[BBOX_MAX_PIDS];
|
||||
|
||||
/*
|
||||
function name: bbox_strncmp
|
||||
description: To compare two substrings, the pointers pszSrc and pszTarget store their host strings'addresses.
|
||||
arguments: Two pointers of type const char*, pointing to two strings needed to be compared.
|
||||
An integer indicates the number of characters at the former of two strings that
|
||||
will be compared.
|
||||
return value: Type s32, an interger.
|
||||
If it's zero, then the former substrings of string pszSrc and pszTarget are same,
|
||||
else it indicates the difference between the first two characters that these two
|
||||
strings can't match.
|
||||
note:The two pointers shouldn't be null. The last argument shouldn't less than zero.
|
||||
date: 2022/8/2
|
||||
contact tel: 18720816902
|
||||
*/
|
||||
* compare string pszSrc and pszTarget
|
||||
*/
|
||||
s32 bbox_strncmp(const char* pszSrc, const char* pszTarget, s32 count)
|
||||
{
|
||||
signed char cRes = 0;
|
||||
|
|
@ -79,20 +68,8 @@ s32 bbox_strncmp(const char* pszSrc, const char* pszTarget, s32 count)
|
|||
}
|
||||
|
||||
/*
|
||||
function name: bbox_strcmp
|
||||
description: compare two strings, the pointer pszSrc and pszTarget store their addresses.
|
||||
arguments: Two pointers of type const char*, pointing to two strings needed to be compared.
|
||||
An integer indicates the number of characters at the former of two strings that
|
||||
will be compared.
|
||||
return value: Type s32, an interger.
|
||||
If it's zero, then the former substrings of string pszSrc and pszTarget are same,
|
||||
else if it's 1, then it indicates between first two characters that these two
|
||||
strings can't match, the character of first string that pszSrc points is greater,
|
||||
else if it's -1, the character of second string that pszTarget points is greater.
|
||||
note:The two pointers shouldn't be null. The last argument shouldn't less than zero.
|
||||
date: 2022/8/2
|
||||
contact tel:same
|
||||
*/
|
||||
* compare string pszSrc and pszTarget
|
||||
*/
|
||||
s32 bbox_strcmp(const char* pszSrc, const char* pszTarget)
|
||||
{
|
||||
unsigned char c1, c2;
|
||||
|
|
@ -113,15 +90,8 @@ s32 bbox_strcmp(const char* pszSrc, const char* pszTarget)
|
|||
}
|
||||
|
||||
/*
|
||||
function name: bbox_strlen
|
||||
description: Calculate the length of string.
|
||||
arguments: An pointer that indicates the address of a string.
|
||||
return value: Type s32, an integer indicating the length of string.
|
||||
note: the length of string=(address of the last character not '\0'-address of the first character)/sizeof(char), and sizeof(char)
|
||||
equals to 1, so the length of string=(address of the last character not '\0'-address of the first character).
|
||||
date: 2022/8/2
|
||||
contact tel:same
|
||||
*/
|
||||
* get the length of string pszString
|
||||
*/
|
||||
s32 bbox_strlen(const char* pszString)
|
||||
{
|
||||
const char* pszTemp = NULL;
|
||||
|
|
@ -135,16 +105,8 @@ s32 bbox_strlen(const char* pszString)
|
|||
}
|
||||
|
||||
/*
|
||||
function name: bbox_strnlen
|
||||
description: Calculate the length of string, but having some restrictive conditions.
|
||||
arguments: An pointer that indicates the address of a string.
|
||||
And an integer that indicates the maxlenth.
|
||||
return value: Type s32, an integer indicating the length of string.
|
||||
note: If the length of string exceed the argument count, then return the length of string,
|
||||
else return the argument count.
|
||||
date: 2022/8/2
|
||||
contact tel:same
|
||||
*/
|
||||
* get the length of string pszString
|
||||
*/
|
||||
s32 bbox_strnlen(const char* pszString, s32 count)
|
||||
{
|
||||
const char* pszTemp = NULL;
|
||||
|
|
@ -157,16 +119,8 @@ s32 bbox_strnlen(const char* pszString, s32 count)
|
|||
}
|
||||
|
||||
/*
|
||||
function name: bbox_atoi
|
||||
description: Convert a string that includes continuous digital characters to an integer,
|
||||
if the first character of the string is '-', then we will return a negative result.
|
||||
arguments: An pointer that indicates the address of a string.
|
||||
return value: Type s32, an integer indicating the result of string converted.
|
||||
note: I think the function isn't perfect, though it's not a core function. For example, what about
|
||||
the condition that the first character of the string is '+'?
|
||||
date: 2022/8/2
|
||||
contact tel:same
|
||||
*/
|
||||
* convert a string to interger
|
||||
*/
|
||||
s32 bbox_atoi(const char* pszString)
|
||||
{
|
||||
s32 n = 0;
|
||||
|
|
@ -186,18 +140,10 @@ s32 bbox_atoi(const char* pszString)
|
|||
|
||||
return iNeg ? -n : n;
|
||||
}
|
||||
|
||||
/*
|
||||
function name: bbox_memcmp
|
||||
description: Compare former count bytes in ASCII of data stored in two areas that pointers cs and ct direct.
|
||||
arguments: Two pointers to areas of memory, and an integer indicating the max counts compared.
|
||||
return value: Type s32, an integer.
|
||||
If the value returned is 0, then the data stored in two areas destined are same,
|
||||
else if is 1, then between two first data in ASCII of byte different, cs's is greater,
|
||||
else if is -1, then ct's is greater.
|
||||
note: The two pointers should not be null, it's dangerous.
|
||||
date: 2022/8/2
|
||||
contact tel: same
|
||||
*/
|
||||
* compare memory
|
||||
*/
|
||||
s32 bbox_memcmp(const void* cs, const void* ct, s32 count)
|
||||
{
|
||||
const unsigned char *su1 = NULL;
|
||||
|
|
@ -213,18 +159,8 @@ s32 bbox_memcmp(const void* cs, const void* ct, s32 count)
|
|||
}
|
||||
|
||||
/*
|
||||
function name: bbox_strstr
|
||||
description: Judge if the string s2 directs is substring of string s1 directs.
|
||||
arguments: Two pointers of type const char*, pointing to two strings.
|
||||
return value: Type char*, a pointer. Actually it's a address, if s2 directs a
|
||||
null string, then return the address of the first character of s1,
|
||||
if the string s2 directs isn't substring of string s1 directs, return
|
||||
null, if the string s2 directs is substring of string s1 directs, then return
|
||||
the address of first character matched.
|
||||
note: The two pointers should not be null, it's dangerous.
|
||||
date: 2022/8/2
|
||||
contact tel: same
|
||||
*/
|
||||
* search string l2 in l1
|
||||
*/
|
||||
char* bbox_strstr(const char* s1, const char* s2)
|
||||
{
|
||||
int l1, l2;
|
||||
|
|
@ -246,17 +182,8 @@ char* bbox_strstr(const char* s1, const char* s2)
|
|||
}
|
||||
|
||||
/*
|
||||
function name: bbox_mkdir
|
||||
description: We distinguish parent directory and child directory through character '/',
|
||||
normally through a for loop, we can make sure all directories above the directory
|
||||
we want to creat exist, finally we will creat the flag directory after its parent.
|
||||
arguments: A pointers of type const char*, pointing to one strings, which indicates the filename and its full path.
|
||||
return value: An integer of type s32, if it's RET_ERR, then we fail to make a directory, else if it's RET_OK then we succeed.
|
||||
note: Take care the last non-null character of the string needed to be '/', and once if flag directory's
|
||||
ancestors aren't exist, the function return RET_ERR.
|
||||
date: 2022/8/2
|
||||
contact tel: same
|
||||
*/
|
||||
* make a directory
|
||||
*/
|
||||
s32 bbox_mkdir(const char* pszDir)
|
||||
{
|
||||
char szDirName[BBOX_TMP_LEN_32 * 16];
|
||||
|
|
@ -301,16 +228,8 @@ s32 bbox_mkdir(const char* pszDir)
|
|||
}
|
||||
|
||||
/*
|
||||
function name: bbox_GetFreePid
|
||||
description: Through a for loop, we search a free pipe in a structure array, to an array element if its
|
||||
member variable isUsed's value is 0, we return the array element's another member variable
|
||||
stPid's address.
|
||||
arguments: void
|
||||
return value: An pointer of type struct PIPE_ID* or NULL.
|
||||
note: none
|
||||
date: 2022/8/2
|
||||
contact tel: same
|
||||
*/
|
||||
* search free pipe id
|
||||
*/
|
||||
struct PIPE_ID* bbox_GetFreePid(void)
|
||||
{
|
||||
u32 i;
|
||||
|
|
@ -326,14 +245,8 @@ struct PIPE_ID* bbox_GetFreePid(void)
|
|||
}
|
||||
|
||||
/*
|
||||
function name: bbox_PutPid
|
||||
description: Release the occupied pipe.
|
||||
arguments: A pointer of type struct PIPE_ID*.
|
||||
return value: void
|
||||
note: If the argument pointer is null, then there is no need to free the storage, the function ends.
|
||||
date: 2022/8/2
|
||||
contact tel: same
|
||||
*/
|
||||
* Release the occupied pipeid
|
||||
*/
|
||||
void bbox_PutPid(struct PIPE_ID* pstPid)
|
||||
{
|
||||
struct PIPE_IDS* pstPids = NULL;
|
||||
|
|
@ -348,16 +261,8 @@ void bbox_PutPid(struct PIPE_ID* pstPid)
|
|||
}
|
||||
|
||||
/*
|
||||
function name: bbox_FindPid
|
||||
description: In all occupied pipes, the function search the flag pipe through compare all structure
|
||||
array elements's member variable stPid's member variable iFd with the function
|
||||
argument iFd, if they are equal, then return the addres of this array elements.
|
||||
arguments: An integer that indicates a file's file handle.
|
||||
return value: A pointer of type struct PIPE_ID* or NULL.
|
||||
note: none
|
||||
date: 2022/8/2
|
||||
contact tel: same
|
||||
*/
|
||||
* find available pipe id by file handle
|
||||
*/
|
||||
struct PIPE_ID* bbox_FindPid(int iFd)
|
||||
{
|
||||
u32 i;
|
||||
|
|
@ -376,17 +281,8 @@ struct PIPE_ID* bbox_FindPid(int iFd)
|
|||
}
|
||||
|
||||
/*
|
||||
function name: sys_popen
|
||||
description: The function gets a free pipe by function bbox_GetFreePid, if normally, then creat a pipe
|
||||
through sys_pipe, andcreat a child process through function sys_fork, execute a shell command
|
||||
to run a process.
|
||||
arguments: One pointer to a string that represents command line, another pointer of type const char*
|
||||
indicates that the file file handle directs is used in the this mode.
|
||||
return value: A pointer of type struct PIPE_ID* or NULL.
|
||||
note: The string that indicates pszMode should only be "r" or "w",
|
||||
date: 2022/8/2
|
||||
contact tel: same
|
||||
*/
|
||||
* run popen
|
||||
*/
|
||||
s32 sys_popen(char* pszCmd, const char* pszMode)
|
||||
{
|
||||
struct PIPE_ID* volatile stCurPid = NULL;
|
||||
|
|
@ -491,15 +387,8 @@ s32 sys_popen(char* pszCmd, const char* pszMode)
|
|||
}
|
||||
|
||||
/*
|
||||
function name: sys_pclose
|
||||
description: The function has an contrary action to function sys_popen, it close the pipe
|
||||
that sys_popen open.
|
||||
arguments: iFd, an integer that indicates a file handle.
|
||||
return value: An integer that indicates the final status of the process working before.
|
||||
note: none
|
||||
date: 2022/8/2
|
||||
contact tel: same
|
||||
*/
|
||||
* close file handle
|
||||
*/
|
||||
int sys_pclose(s32 iFd)
|
||||
{
|
||||
struct PIPE_ID* pstCur = NULL;
|
||||
|
|
@ -522,17 +411,8 @@ int sys_pclose(s32 iFd)
|
|||
}
|
||||
|
||||
/*
|
||||
function name: bbox_listdir
|
||||
description: The function list all files below this path in directory.
|
||||
arguments: The first argument is a pointer to a string representing a file path, all files below
|
||||
this path will be listed in directory. The second argument is a pointer to a callback
|
||||
function. The last is a pointer of type void*, it indicates a command line.
|
||||
return value: An integer that indicates the result of function, if normal, it's RET_OK, else
|
||||
it's RET_ERR.
|
||||
note: The path that the first argument represents should be absolute path, take care.
|
||||
date: 2022/8/2
|
||||
contact tel: same
|
||||
*/
|
||||
* list file in directory
|
||||
*/
|
||||
s32 bbox_listdir(const char* pstPath, BBOX_LIST_DIR_CALLBACK callback, void* pArgs)
|
||||
{
|
||||
struct linux_dirent* pstEntry = NULL;
|
||||
|
|
|
|||
|
|
@ -57,37 +57,23 @@ void bbox_initlog(int iLogScreen)
|
|||
}
|
||||
|
||||
/*
|
||||
function name: bbox_itoc
|
||||
description: Convert an integer to a character.
|
||||
arguments: An integer needed to be converted.
|
||||
return value: An character that corresponds to the function's integer argument.
|
||||
note: The integer argument can be converted in radices more than decimalism.
|
||||
date: 2022/8/2
|
||||
contact tel: 18720816902
|
||||
*/
|
||||
* convert int to string
|
||||
*/
|
||||
inline char bbox_itoc(u8 sNum)
|
||||
{
|
||||
return (char)((sNum < 10) ? (sNum + 48) : (sNum + 87));
|
||||
}
|
||||
|
||||
/*
|
||||
function name: bbox_put_dox
|
||||
description: Conversion of number systems.
|
||||
arguments: The first argument pCallback is a pointer to a callback function, we
|
||||
use it to reverse the final result. The second argument is a pointer of
|
||||
type void* used as a argument of function pCallback. The third argument
|
||||
piCount is a pointer of type int, an offset pointer, also be used as a argument
|
||||
of pCallback. The fourth argument is an integer of 32 bits, it indicates the buffer
|
||||
size pCallback uses.The fifth argument uNum is a decimal integer that will
|
||||
be converted to an integer in another radix. The sixth argument is used as
|
||||
base to conversion of number systems. The last argument indicates the integer
|
||||
after converted is a negative integer or not.
|
||||
return value: An integer, indicating if the function pCallback work successfully.
|
||||
note: The argument uNum should be a positive integer, after conversion of number systems
|
||||
the sign will be appended to string's tail.
|
||||
date: 2022/8/2
|
||||
contact tel: 18720816902
|
||||
*/
|
||||
* convert int to string
|
||||
* in : pCallback - call back function
|
||||
* ptr - private data to call this function
|
||||
* piCount - offset pointer
|
||||
* iSize - buffer size
|
||||
* uNum - the variable to convert
|
||||
* sSys - type of variable
|
||||
* isNeg - is negative
|
||||
* return : need call back
|
||||
*/
|
||||
s32 bbox_put_dox(BBOX_vnprintCallBack pCallback, void* ptr, s32* piCount, u32 iSize, u64 uNum, s32 sSys, s32 isNeg)
|
||||
{
|
||||
s64 i = 0;
|
||||
|
|
@ -128,7 +114,7 @@ s32 bbox_put_dox(BBOX_vnprintCallBack pCallback, void* ptr, s32* piCount, u32 iS
|
|||
* ptr - private data to call this function
|
||||
* iSize - buffer size
|
||||
* pFmt - format type
|
||||
* ap - parameter list pointer<EFBFBD><EFBFBD>ʽ
|
||||
* ap - parameter list pointer¸ñʽ
|
||||
* return : length of string
|
||||
*/
|
||||
s32 bbox_vsnprintf(BBOX_vnprintCallBack pCallback, void* ptr, s32 iSize, const char* pFmt, va_list ap)
|
||||
|
|
|
|||
|
|
@ -222,7 +222,6 @@ NON_EXEC_STATIC void PercentileMain()
|
|||
g_instance.stat_cxt.force_process = false;
|
||||
sleep(SLEEP_INTERVAL);
|
||||
}
|
||||
elog(LOG, "instrumention percentile ended");
|
||||
gs_thread_exit(0);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -14,23 +14,11 @@ import os
|
|||
|
||||
from . import feature_mapping
|
||||
from . import features
|
||||
# To import file feature_mapping and features from parent folder
|
||||
|
||||
#function name: load_feature_lib
|
||||
#description: Print the variable FEATURE_LIB in the file-- features
|
||||
#return value: The value of FEATURE_LIB
|
||||
#date: 2022/8/2
|
||||
#contact: 1865997821
|
||||
|
||||
def load_feature_lib():
|
||||
return features.FEATURE_LIB
|
||||
|
||||
#function name: get_feature_mapper
|
||||
#description: Get the item and value of a dictionary type in the file-- feature_mapping and output it as a generator.
|
||||
#return value: The item and value in _dict_ variable
|
||||
#note:Dictionary key-value pairs must start with C then the item and value will be return.
|
||||
#date: 2022/8/2
|
||||
#contact: 1865997821
|
||||
|
||||
def get_feature_mapper():
|
||||
return {
|
||||
|
|
|
|||
|
|
@ -11,27 +11,22 @@
|
|||
# MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
# See the Mulan PSL v2 for more details.
|
||||
import csv
|
||||
#import csv packet
|
||||
from collections import defaultdict
|
||||
from typing import List
|
||||
# To import defaultdict in the parent floder collections and List in the parent floder typing
|
||||
|
||||
import numpy as np
|
||||
# import numpy packet as the name np
|
||||
|
||||
from ..analyzer import _euclid_distance as euclid_distance
|
||||
from dbmind.common.utils import ExceptionCatch
|
||||
#To import private function-- _euclid_distance as euclid_distance
|
||||
|
||||
#function name: calculate_weight
|
||||
#description: This function will output feature_weight (= residual_vector / the sum of residual_vector)
|
||||
#The data used for the calculation is from the features_labels_dict, and the key value pairs of the features_labels_dict are filtered
|
||||
#arguments: np.ndarray and np.ndarray
|
||||
#return value: weight_matrix
|
||||
#date: 2022/8/2
|
||||
#contact: 1865997821
|
||||
|
||||
def calculate_weight(features: np.ndarray, labels: np.ndarray) -> List:
|
||||
"""
|
||||
Calculate weight matrix based on feature set
|
||||
:param features: feature set
|
||||
:param labels: label set
|
||||
:return: weight_matrix
|
||||
"""
|
||||
normalize_features, normalize_labels = [], []
|
||||
features_labels_dict = defaultdict(list)
|
||||
for i in range(len(labels)):
|
||||
|
|
@ -61,16 +56,6 @@ def calculate_weight(features: np.ndarray, labels: np.ndarray) -> List:
|
|||
return weight_matrix
|
||||
|
||||
|
||||
# function name: build_model
|
||||
# description: Create two variables-- features and labels.There are refer to two numpy array(all elements are zero)
|
||||
# The features array's size is feature_number and dimension is feature_dimension
|
||||
# This function will read the two arrays and write it as a matrix in a csv file(the save path is './features_new.npz')
|
||||
# And then it will call the function calculate_weight to calculate the matrix
|
||||
# arguments: feature_path, feature_number, feature_dimension
|
||||
# return value: None
|
||||
# note:A ExceptionCatch function modifier is used
|
||||
# date: 2022/8/2
|
||||
#contact: 1865997821
|
||||
@ExceptionCatch(strategy='exit', name='FEATURE')
|
||||
def build_model(feature_path: str, feature_number: int, feature_dimension: int,
|
||||
save_path: str = './features_new.npz') -> None:
|
||||
|
|
|
|||
|
|
@ -11,13 +11,6 @@
|
|||
# MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
# See the Mulan PSL v2 for more details.
|
||||
|
||||
#function name: detect
|
||||
#description: if the method is "bool" type, then call the functions sum_detect、avg_detect、ks_detect to diagnose errors
|
||||
#These functions are in the parent slow_sql/significance_detection
|
||||
#arguments: data1(array), data2(array), method
|
||||
#return value: bool type
|
||||
#date: 2022/8/2
|
||||
#contact: 1865997821
|
||||
|
||||
def detect(data1, data2, method='bool', threshold=0.01, p_value=0.5):
|
||||
if method == 'bool':
|
||||
|
|
|
|||
|
|
@ -12,16 +12,17 @@
|
|||
# See the Mulan PSL v2 for more details.
|
||||
|
||||
alpha = 1e-10
|
||||
#Define a minimum number of errors
|
||||
|
||||
#function name: detect
|
||||
#description: Calculate whether the data has abrupt changes based on the average value
|
||||
#arguments: data1, data2, threshold,method
|
||||
#return value: bool
|
||||
#date: 2022/8/
|
||||
#contact: 1865997821
|
||||
|
||||
def detect(data1, data2, threshold=0.5, method='bool'):
|
||||
"""
|
||||
Calculate whether the data has abrupt changes based on the average value
|
||||
:param data1: input data array
|
||||
:param data2: input data array
|
||||
:param threshold: Mutation rate
|
||||
:param method: The way to calculate the mutation
|
||||
:return: bool
|
||||
"""
|
||||
if not isinstance(data1, list) or not isinstance(data2, list):
|
||||
raise TypeError("The format of the input data is wrong.")
|
||||
avg1 = sum(data1) / len(data1) if data1 else 0
|
||||
|
|
|
|||
|
|
@ -26,11 +26,9 @@ import logging
|
|||
try:
|
||||
from .dao.gsql_execute import GSqlExecute
|
||||
from .dao.execute_factory import ExecuteFactory
|
||||
from .mcts import MCTS
|
||||
except ImportError:
|
||||
from dao.gsql_execute import GSqlExecute
|
||||
from dao.execute_factory import ExecuteFactory
|
||||
from mcts import MCTS
|
||||
|
||||
ENABLE_MULTI_NODE = False
|
||||
SAMPLE_NUM = 5
|
||||
|
|
@ -194,12 +192,9 @@ class IndexAdvisor:
|
|||
self.workload_used_index))
|
||||
if DRIVER:
|
||||
self.db.close_conn()
|
||||
if MAX_INDEX_STORAGE:
|
||||
opt_config = MCTS(self.workload_info[0], atomic_config_total, candidate_indexes,
|
||||
MAX_INDEX_STORAGE, MAX_INDEX_NUM)
|
||||
else:
|
||||
opt_config = greedy_determine_opt_config(self.workload_info[0], atomic_config_total,
|
||||
candidate_indexes, self.index_cost_total[0])
|
||||
|
||||
opt_config = greedy_determine_opt_config(self.workload_info[0], atomic_config_total,
|
||||
candidate_indexes, self.index_cost_total[0])
|
||||
self.retain_lower_cost_index(candidate_indexes)
|
||||
if len(opt_config) == 0:
|
||||
print("No optimal indexes generated!")
|
||||
|
|
@ -948,7 +943,7 @@ def check_parameter(args):
|
|||
raise argparse.ArgumentTypeError("%s is an invalid positive int value" %
|
||||
args.max_index_num)
|
||||
if args.max_index_storage is not None and args.max_index_storage <= 0:
|
||||
raise argparse.ArgumentTypeError("%s is an invalid positive float value" %
|
||||
raise argparse.ArgumentTypeError("%s is an invalid positive int value" %
|
||||
args.max_index_storage)
|
||||
JSON_TYPE = args.json
|
||||
MAX_INDEX_NUM = args.max_index_num
|
||||
|
|
@ -976,7 +971,7 @@ def main(argv):
|
|||
arg_parser.add_argument(
|
||||
"--max_index_num", help="Maximum number of suggested indexes", type=int)
|
||||
arg_parser.add_argument("--max_index_storage",
|
||||
help="Maximum storage of suggested indexes/MB", type=float)
|
||||
help="Maximum storage of suggested indexes/MB", type=int)
|
||||
arg_parser.add_argument("--multi_iter_mode", action='store_true',
|
||||
help="Whether to use multi-iteration algorithm", default=False)
|
||||
arg_parser.add_argument("--multi_node", action='store_true',
|
||||
|
|
|
|||
|
|
@ -1,397 +0,0 @@
|
|||
import sys
|
||||
import math
|
||||
import random
|
||||
import copy
|
||||
|
||||
STORAGE_THRESHOLD = 0
|
||||
AVAILABLE_CHOICES = None
|
||||
ATOMIC_CHOICES = None
|
||||
WORKLOAD_INFO = None
|
||||
MAX_INDEX_NUM = 0
|
||||
|
||||
|
||||
def is_same_index(index, compared_index):
|
||||
return index.table == compared_index.table and \
|
||||
index.columns == compared_index.columns and \
|
||||
index.index_type == compared_index.index_type
|
||||
|
||||
|
||||
def atomic_config_is_valid(atomic_config, config):
|
||||
# if candidate indexes contains all atomic index of current config1, then record it
|
||||
for atomic_index in atomic_config:
|
||||
is_exist = False
|
||||
for index in config:
|
||||
if is_same_index(index, atomic_index):
|
||||
index.storage = atomic_index.storage
|
||||
is_exist = True
|
||||
break
|
||||
if not is_exist:
|
||||
return False
|
||||
return True
|
||||
|
||||
|
||||
def find_subsets_num(choice):
|
||||
atomic_subsets_num = []
|
||||
for pos, atomic in enumerate(ATOMIC_CHOICES):
|
||||
if not atomic or len(atomic) > len(choice):
|
||||
continue
|
||||
# find valid atomic index
|
||||
if atomic_config_is_valid(atomic, choice):
|
||||
atomic_subsets_num.append(pos)
|
||||
# find the same atomic index as the candidate index
|
||||
if len(atomic) == 1 and (is_same_index(choice[-1], atomic[0])):
|
||||
choice[-1].atomic_pos = pos
|
||||
return atomic_subsets_num
|
||||
|
||||
|
||||
def find_best_benefit(choice):
|
||||
atomic_subsets_num = find_subsets_num(choice)
|
||||
total_benefit = 0
|
||||
for ind, obj in enumerate(WORKLOAD_INFO):
|
||||
# calculate the best benefit for the current sql
|
||||
max_benefit = 0
|
||||
for pos in atomic_subsets_num:
|
||||
if (obj.cost_list[0] - obj.cost_list[pos]) > max_benefit:
|
||||
max_benefit = obj.cost_list[0] - obj.cost_list[pos]
|
||||
total_benefit += max_benefit
|
||||
return total_benefit
|
||||
|
||||
|
||||
def get_diff(available_choices, choices):
|
||||
except_choices = copy.copy(available_choices)
|
||||
for i in available_choices:
|
||||
for j in choices:
|
||||
if is_same_index(i, j):
|
||||
except_choices.remove(i)
|
||||
return except_choices
|
||||
|
||||
|
||||
class State(object):
|
||||
"""
|
||||
The game state of the Monte Carlo tree search,
|
||||
the state data recorded under a certain Node node,
|
||||
including the current game score, the current number of game rounds,
|
||||
and the execution record from the beginning to the current.
|
||||
|
||||
It is necessary to realize whether the current state has reached the end of the game state,
|
||||
and support the operation of randomly fetching from the Action collection.
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
self.current_storage = 0.0
|
||||
self.current_benefit = 0.0
|
||||
# record the sum of choices up to the current state
|
||||
self.accumulation_choices = []
|
||||
# record available choices of current state
|
||||
self.available_choices = []
|
||||
self.displayable_choices = []
|
||||
|
||||
def get_available_choices(self):
|
||||
return self.available_choices
|
||||
|
||||
def set_available_choices(self, choices):
|
||||
self.available_choices = choices
|
||||
|
||||
def get_current_storage(self):
|
||||
return self.current_storage
|
||||
|
||||
def set_current_storage(self, value):
|
||||
self.current_storage = value
|
||||
|
||||
def get_current_benefit(self):
|
||||
return self.current_benefit
|
||||
|
||||
def set_current_benefit(self, value):
|
||||
self.current_benefit = value
|
||||
|
||||
def get_accumulation_choices(self):
|
||||
return self.accumulation_choices
|
||||
|
||||
def set_accumulation_choices(self, choices):
|
||||
self.accumulation_choices = choices
|
||||
|
||||
def is_terminal(self):
|
||||
# the current node is a leaf node
|
||||
return len(self.accumulation_choices) == MAX_INDEX_NUM
|
||||
|
||||
def compute_benefit(self):
|
||||
return self.current_benefit
|
||||
|
||||
def get_next_state_with_random_choice(self):
|
||||
# ensure that the choices taken are not repeated
|
||||
if not self.available_choices:
|
||||
return None
|
||||
random_choice = random.choice([choice for choice in self.available_choices])
|
||||
self.available_choices.remove(random_choice)
|
||||
choice = copy.copy(self.accumulation_choices)
|
||||
choice.append(random_choice)
|
||||
benefit = find_best_benefit(choice)
|
||||
# if current choice not satisfy restrictions, then continue get next choice
|
||||
if benefit <= self.current_benefit or \
|
||||
self.current_storage + random_choice.storage > STORAGE_THRESHOLD:
|
||||
return self.get_next_state_with_random_choice()
|
||||
|
||||
next_state = State()
|
||||
# initialize the properties of the new state
|
||||
next_state.set_accumulation_choices(choice)
|
||||
next_state.set_current_benefit(benefit)
|
||||
next_state.set_current_storage(self.current_storage + random_choice.storage)
|
||||
next_state.set_available_choices(get_diff(AVAILABLE_CHOICES, choice))
|
||||
return next_state
|
||||
|
||||
def __repr__(self):
|
||||
self.displayable_choices = ['{}: {}'.format(choice.table, choice.columns)
|
||||
for choice in self.accumulation_choices]
|
||||
return "reward: {}, storage :{}, choices: {}".format(
|
||||
self.current_benefit, self.current_storage, self.displayable_choices)
|
||||
|
||||
|
||||
class Node(object):
|
||||
"""
|
||||
The Node of the Monte Carlo tree search tree contains the parent node and
|
||||
current point information,
|
||||
which is used to calculate the traversal times and quality value of the UCB,
|
||||
and the State of the Node selected by the game.
|
||||
"""
|
||||
def __init__(self):
|
||||
self.visit_number = 0
|
||||
self.quality = 0.0
|
||||
|
||||
self.parent = None
|
||||
self.children = []
|
||||
self.state = None
|
||||
|
||||
def get_parent(self):
|
||||
return self.parent
|
||||
|
||||
def set_parent(self, parent):
|
||||
self.parent = parent
|
||||
|
||||
def get_children(self):
|
||||
return self.children
|
||||
|
||||
def expand_child(self, node):
|
||||
node.set_parent(self)
|
||||
self.children.append(node)
|
||||
|
||||
def set_state(self, state):
|
||||
self.state = state
|
||||
|
||||
def get_state(self):
|
||||
return self.state
|
||||
|
||||
def get_visit_number(self):
|
||||
return self.visit_number
|
||||
|
||||
def set_visit_number(self, number):
|
||||
self.visit_number = number
|
||||
|
||||
def update_visit_number(self):
|
||||
self.visit_number += 1
|
||||
|
||||
def get_quality_value(self):
|
||||
return self.quality
|
||||
|
||||
def set_quality_value(self, value):
|
||||
self.quality = value
|
||||
|
||||
def update_quality_value(self, reward):
|
||||
self.quality += reward
|
||||
|
||||
def is_all_expand(self):
|
||||
return len(self.children) == \
|
||||
len(AVAILABLE_CHOICES) - len(self.get_state().get_accumulation_choices())
|
||||
|
||||
def __repr__(self):
|
||||
return "Node: {}, Q/N: {}/{}, State: {}".format(
|
||||
hash(self), self.quality, self.visit_number, self.state)
|
||||
|
||||
|
||||
def tree_policy(node):
|
||||
"""
|
||||
In the Selection and Expansion stages of Monte Carlo tree search,
|
||||
the node that needs to be searched (such as the root node) is passed in,
|
||||
and the best node that needs to be expanded is returned
|
||||
according to the exploration/exploitation algorithm.
|
||||
Note that if the node is a leaf node, it will be returned directly.
|
||||
|
||||
The basic strategy is to first find the child nodes that have not been selected at present,
|
||||
and select them randomly if there are more than one. If both are selected,
|
||||
find the one with the largest UCB value that has weighed exploration/exploitation,
|
||||
and randomly select if the UCB values are equal.
|
||||
"""
|
||||
|
||||
# check if the current node is leaf node
|
||||
while node and not node.get_state().is_terminal():
|
||||
|
||||
if node.is_all_expand():
|
||||
node = best_child(node, True)
|
||||
else:
|
||||
# return the new sub node
|
||||
sub_node = expand(node)
|
||||
# when there is no node that satisfies the condition in the remaining nodes,
|
||||
# this state is empty
|
||||
if sub_node.get_state():
|
||||
return sub_node
|
||||
|
||||
# return the leaf node
|
||||
return node
|
||||
|
||||
|
||||
def default_policy(node):
|
||||
"""
|
||||
In the Simulation stage of Monte Carlo tree search, input a node that needs to be expanded,
|
||||
create a new node after random operation, and return the reward of the new node.
|
||||
Note that the input node should not be a child node,
|
||||
and there are unexecuted Actions that can be expendable.
|
||||
|
||||
The basic strategy is to choose the Action at random.
|
||||
"""
|
||||
|
||||
# get the state of the game
|
||||
current_state = copy.deepcopy(node.get_state())
|
||||
|
||||
# run until the game over
|
||||
while not current_state.is_terminal():
|
||||
# pick one random action to play and get next state
|
||||
next_state = current_state.get_next_state_with_random_choice()
|
||||
if not next_state:
|
||||
break
|
||||
current_state = next_state
|
||||
|
||||
final_state_reward = current_state.compute_benefit()
|
||||
return final_state_reward
|
||||
|
||||
|
||||
def expand(node):
|
||||
"""
|
||||
Enter a node, expand a new node on the node, use the random method to execute the Action,
|
||||
and return the new node. Note that it is necessary to ensure that the newly
|
||||
added nodes are different from other node Action
|
||||
"""
|
||||
|
||||
new_state = node.get_state().get_next_state_with_random_choice()
|
||||
sub_node = Node()
|
||||
sub_node.set_state(new_state)
|
||||
node.expand_child(sub_node)
|
||||
|
||||
return sub_node
|
||||
|
||||
|
||||
def best_child(node, is_exploration):
|
||||
"""
|
||||
Using the UCB algorithm,
|
||||
select the child node with the highest score after weighing the exploration and exploitation.
|
||||
Note that if it is the prediction stage,
|
||||
the current Q-value score with the highest score is directly selected.
|
||||
"""
|
||||
|
||||
best_score = -sys.maxsize
|
||||
best_sub_node = None
|
||||
|
||||
# travel all sub nodes to find the best one
|
||||
for sub_node in node.get_children():
|
||||
# The children nodes of the node contains the children node whose state is empty,
|
||||
# this kind of node comes from the node that does not meet the conditions.
|
||||
if not sub_node.get_state():
|
||||
continue
|
||||
# ignore exploration for inference
|
||||
if is_exploration:
|
||||
C = 1 / math.sqrt(2.0)
|
||||
else:
|
||||
C = 0.0
|
||||
|
||||
# UCB = quality / times + C * sqrt(2 * ln(total_times) / times)
|
||||
left = sub_node.get_quality_value() / sub_node.get_visit_number()
|
||||
right = 2.0 * math.log(node.get_visit_number()) / sub_node.get_visit_number()
|
||||
score = left + C * math.sqrt(right)
|
||||
# get the maximum score, while filtering nodes that do not meet the space constraints and
|
||||
# nodes that have no revenue
|
||||
if score > best_score \
|
||||
and sub_node.get_state().get_current_storage() <= STORAGE_THRESHOLD \
|
||||
and sub_node.get_state().get_current_benefit() > 0:
|
||||
best_sub_node = sub_node
|
||||
best_score = score
|
||||
|
||||
return best_sub_node
|
||||
|
||||
|
||||
def backpropagate(node, reward):
|
||||
"""
|
||||
In the Backpropagation stage of Monte Carlo tree search,
|
||||
input the node that needs to be expended and the reward of the newly executed Action,
|
||||
feed it back to the expend node and all upstream nodes,
|
||||
and update the corresponding data.
|
||||
"""
|
||||
|
||||
# update util the root node
|
||||
while node is not None:
|
||||
# update the visit number
|
||||
node.update_visit_number()
|
||||
|
||||
# update the quality value
|
||||
node.update_quality_value(reward)
|
||||
|
||||
# change the node to the parent node
|
||||
node = node.parent
|
||||
|
||||
|
||||
def monte_carlo_tree_search(node):
|
||||
"""
|
||||
Implement the Monte Carlo tree search algorithm, pass in a root node,
|
||||
expand new nodes and update data according to the
|
||||
tree structure that has been explored before in a limited time,
|
||||
and then return as long as the child node with the highest exploitation.
|
||||
|
||||
When making predictions,
|
||||
you only need to select the node with the largest exploitation according to the Q value,
|
||||
and find the next optimal node.
|
||||
"""
|
||||
|
||||
computation_budget = len(AVAILABLE_CHOICES) * 3
|
||||
|
||||
# run as much as possible under the computation budget
|
||||
for i in range(computation_budget):
|
||||
# 1. find the best node to expand
|
||||
expand_node = tree_policy(node)
|
||||
if not expand_node:
|
||||
# when it is None, it means that all nodes are added but no nodes meet the space limit
|
||||
break
|
||||
# 2. random get next action and get reward
|
||||
reward = default_policy(expand_node)
|
||||
|
||||
# 3. update all passing nodes with reward
|
||||
backpropagate(expand_node, reward)
|
||||
|
||||
# get the best next node
|
||||
best_next_node = best_child(node, False)
|
||||
|
||||
return best_next_node
|
||||
|
||||
|
||||
def MCTS(workload_info, atomic_choices, available_choices, storage_threshold, max_index_num):
|
||||
global ATOMIC_CHOICES, STORAGE_THRESHOLD, WORKLOAD_INFO, AVAILABLE_CHOICES, MAX_INDEX_NUM
|
||||
WORKLOAD_INFO = workload_info
|
||||
AVAILABLE_CHOICES = available_choices
|
||||
ATOMIC_CHOICES = atomic_choices
|
||||
STORAGE_THRESHOLD = storage_threshold
|
||||
MAX_INDEX_NUM = max_index_num if max_index_num else len(available_choices)
|
||||
|
||||
# create the initialized state and initialized node
|
||||
init_state = State()
|
||||
choices = copy.copy(available_choices)
|
||||
init_state.set_available_choices(choices)
|
||||
init_node = Node()
|
||||
init_node.set_state(init_state)
|
||||
current_node = init_node
|
||||
|
||||
opt_config = []
|
||||
# set the rounds to play
|
||||
for i in range(len(AVAILABLE_CHOICES)):
|
||||
if current_node:
|
||||
current_node = monte_carlo_tree_search(current_node)
|
||||
if current_node:
|
||||
opt_config = current_node.state.accumulation_choices
|
||||
else:
|
||||
break
|
||||
return opt_config
|
||||
|
|
@ -27,7 +27,6 @@ from collections.abc import Iterable
|
|||
from collections import defaultdict
|
||||
|
||||
import index_advisor_workload as iaw
|
||||
import mcts
|
||||
|
||||
|
||||
def hash_any(obj):
|
||||
|
|
@ -228,32 +227,6 @@ select * from student_range_part1 where credit=1;
|
|||
|
||||
class IndexAdvisorTester(unittest.TestCase):
|
||||
|
||||
def test_mcts(self):
|
||||
storage_threshold = 12
|
||||
index1 = iaw.IndexItem('public.a', 'col1', index_type='global')
|
||||
index2 = iaw.IndexItem('public.b', 'col1', index_type='global')
|
||||
index3 = iaw.IndexItem('public.c', 'col1', index_type='global')
|
||||
index4 = iaw.IndexItem('public.d', 'col1', index_type='global')
|
||||
|
||||
atomic_index1 = iaw.IndexItem('public.a', 'col1', index_type='global')
|
||||
atomic_index2 = iaw.IndexItem('public.b', 'col1', index_type='global')
|
||||
atomic_index3 = iaw.IndexItem('public.c', 'col1', index_type='global')
|
||||
atomic_index4 = iaw.IndexItem('public.d', 'col1', index_type='global')
|
||||
|
||||
atomic_index1.storage = 10
|
||||
atomic_index2.storage = 4
|
||||
atomic_index3.storage = 7
|
||||
available_choices = [index1, index2, index3, index4]
|
||||
atomic_choices = [[], [atomic_index2], [atomic_index1], [atomic_index3],
|
||||
[atomic_index2, atomic_index3], [atomic_index4]]
|
||||
query = iaw.QueryItem('select * from gia_01', 1)
|
||||
query.cost_list = [10, 7, 5, 9, 4, 11]
|
||||
workload_info = [query]
|
||||
|
||||
results = mcts.MCTS(workload_info, atomic_choices, available_choices, storage_threshold, 2)
|
||||
self.assertLessEqual([index1.atomic_pos, index2.atomic_pos, index3.atomic_pos], [2, 1, 3])
|
||||
self.assertSetEqual({results[0].table, results[1].table}, {'public.b', 'public.c'})
|
||||
|
||||
def test_get_indexable_columns(self):
|
||||
tables = 'table1 table2 table2 table3 table3 table3'.split()
|
||||
columns = 'col1,col2 col2 col3 col1,col2 col2,col3 col2,col5'.split()
|
||||
|
|
|
|||
|
|
@ -90,10 +90,7 @@ static void DropExtensionInListIsSupported(List* objname)
|
|||
}
|
||||
}
|
||||
|
||||
/* Enable DROP operation of the above objects during inplace upgrade or support_extended_features is true */
|
||||
if (!u_sess->attr.attr_common.IsInplaceUpgrade && !g_instance.attr.attr_common.support_extended_features) {
|
||||
ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("EXTENSION is not yet supported.")));
|
||||
}
|
||||
ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("EXTENSION is not yet supported.")));
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -1175,7 +1175,7 @@ void CreateExtension(CreateExtensionStmt* stmt)
|
|||
FEATURE_NOT_PUBLIC_ERROR("EXTENSION is not yet supported.");
|
||||
}
|
||||
|
||||
if (pg_strcasecmp(stmt->extname, "dolphin") == 0 && !DB_IS_CMPT(B_FORMAT)) {
|
||||
if (pg_strcasecmp(stmt->extname, "b_sql_plugin") == 0 && !DB_IS_CMPT(B_FORMAT)) {
|
||||
ereport(ERROR,
|
||||
(errmsg("please create extension \"%s\" with B type DBCOMPATIBILITY", stmt->extname)));
|
||||
}
|
||||
|
|
@ -1418,8 +1418,8 @@ void CreateExtension(CreateExtensionStmt* stmt)
|
|||
|
||||
u_sess->exec_cxt.extension_is_valid = true;
|
||||
|
||||
if (pg_strcasecmp(stmt->extname, "dolphin") == 0) {
|
||||
u_sess->attr.attr_sql.dolphin = true;
|
||||
if (pg_strcasecmp(stmt->extname, "b_sql_plugin") == 0) {
|
||||
u_sess->attr.attr_sql.b_sql_plugin = true;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -23175,7 +23175,7 @@ static void checkValidationForExchangeTable(Relation partTableRel, Relation ordT
|
|||
int2 bucketId = InvalidBktId;
|
||||
|
||||
// get right partition oid for the tuple
|
||||
targetPartOid = heapTupleGetPartitionId(partTableRel, (HeapTuple)tuple, true);
|
||||
targetPartOid = heapTupleGetPartitionId(partTableRel, (HeapTuple) tuple);
|
||||
|
||||
searchFakeReationForPartitionOid(
|
||||
partRelHTAB, CurrentMemoryContext, partTableRel, targetPartOid, partRel, part, RowExclusiveLock);
|
||||
|
|
@ -24797,8 +24797,7 @@ static Oid AddTemporaryPartitionForAlterPartitions(const AlterTableCmd* cmd, Rel
|
|||
destPartOid = AddTemporaryHashPartitionForAlterPartitions(cmd, partTableRel, partSeq, renameTargetPart);
|
||||
break;
|
||||
}
|
||||
case PART_TYPE_RANGE:
|
||||
case PART_TYPE_INTERVAL: {
|
||||
case PART_TYPE_RANGE: {
|
||||
destPartOid = AddTemporaryRangePartitionForAlterPartitions(cmd, partTableRel, partSeq, renameTargetPart);
|
||||
break;
|
||||
}
|
||||
|
|
@ -25099,11 +25098,11 @@ static void readTuplesAndInsertInternal(Relation tempTableRel, Relation partTabl
|
|||
|
||||
/* tableam_tops_copy_tuple is not ready so we add UStore hack path */
|
||||
copyTuple = tableam_tops_copy_tuple(tuple);
|
||||
targetPartOid = heapTupleGetPartitionId(partTableRel, (void *)tuple, true);
|
||||
targetPartOid = heapTupleGetPartitionId(partTableRel, (void *)tuple);
|
||||
searchFakeReationForPartitionOid(
|
||||
partRelHTAB, CurrentMemoryContext, partTableRel, targetPartOid, partRel, part, RowExclusiveLock);
|
||||
if (RelationIsSubPartitioned(partTableRel)) {
|
||||
targetPartOid = heapTupleGetPartitionId(partRel, (void *)tuple, true);
|
||||
targetPartOid = heapTupleGetPartitionId(partRel, (void *)tuple);
|
||||
searchFakeReationForPartitionOid(partRelHTAB, CurrentMemoryContext, partRel, targetPartOid, subPartRel,
|
||||
subPart, RowExclusiveLock);
|
||||
partRel = subPartRel;
|
||||
|
|
|
|||
|
|
@ -1181,17 +1181,6 @@ static Node* pull_up_simple_subquery(PlannerInfo* root, Node* jtnode, RangeTblEn
|
|||
return jtnode;
|
||||
}
|
||||
|
||||
/*
|
||||
* We must flatten any join alias Vars in the subquery's targetlist,
|
||||
* because pulling up the subquery's subqueries might have changed their
|
||||
* expansions into arbitrary expressions, which could affect
|
||||
* pullup_replace_vars' decisions about whether PlaceHolderVar wrappers
|
||||
* are needed for tlist entries. (Likely it'd be better to do
|
||||
* flatten_join_alias_vars on the whole query tree at some earlier stage,
|
||||
* maybe even in the rewriter; but for now let's just fix this case here.)
|
||||
*/
|
||||
subquery->targetList = (List *) flatten_join_alias_vars(subroot, (Node *) subquery->targetList);
|
||||
|
||||
/*
|
||||
* Adjust level-0 varnos in subquery so that we can append its rangetable
|
||||
* to upper query's. We have to fix the subquery's append_rel_list as
|
||||
|
|
|
|||
|
|
@ -1263,7 +1263,7 @@ static void ckpt_pagewriter_main_thread_loop(void)
|
|||
HandlePageWriterMainInterrupts();
|
||||
|
||||
candidate_num = get_curr_candidate_nums(false) + get_curr_candidate_nums(true);
|
||||
if (candidate_num == 0 && !t_thrd.pagewriter_cxt.shutdown_requested) {
|
||||
if (candidate_num == 0) {
|
||||
/* wakeup sub thread scan the buffer pool, init the candidate list */
|
||||
wakeup_sub_thread();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -825,10 +825,13 @@ void client_read_ended(void)
|
|||
#define INIT_PLUGIN_OBJECT "init_plugin_object"
|
||||
void InitBSqlPluginHookIfNeeded()
|
||||
{
|
||||
const char* dolphin = "dolphin";
|
||||
const char* b_sql_plugin = "b_sql_plugin";
|
||||
CFunInfo tmpCF;
|
||||
if (!CheckIfExtensionExists(b_sql_plugin)) {
|
||||
return;
|
||||
}
|
||||
|
||||
tmpCF = load_external_function(dolphin, INIT_PLUGIN_OBJECT, false, false);
|
||||
tmpCF = load_external_function(b_sql_plugin, INIT_PLUGIN_OBJECT, false, false);
|
||||
if (tmpCF.user_fn != NULL) {
|
||||
((void* (*)(void))(tmpCF.user_fn))();
|
||||
}
|
||||
|
|
@ -862,11 +865,9 @@ List* pg_parse_query(const char* query_string, List** query_string_locationlist)
|
|||
|
||||
List* (*parser_hook)(const char*, List**) = raw_parser;
|
||||
#ifndef ENABLE_MULTIPLE_NODES
|
||||
if (u_sess->attr.attr_sql.dolphin) {
|
||||
int id = GetCustomParserId();
|
||||
if (id >= 0 && g_instance.raw_parser_hook[id] != NULL) {
|
||||
parser_hook = (List* (*)(const char*, List**))g_instance.raw_parser_hook[id];
|
||||
}
|
||||
int id = GetCustomParserId();
|
||||
if (id >= 0 && g_instance.raw_parser_hook[id] != NULL) {
|
||||
parser_hook = (List* (*)(const char*, List**))g_instance.raw_parser_hook[id];
|
||||
}
|
||||
#endif
|
||||
raw_parsetree_list = parser_hook(query_string, query_string_locationlist);
|
||||
|
|
@ -6114,9 +6115,6 @@ void ProcessInterrupts(void)
|
|||
|
||||
/* The logical replication launcher can be stopped at any time. */
|
||||
proc_exit(0);
|
||||
} else if (IsLogicalWorker()) {
|
||||
ereport(FATAL, (errcode(ERRCODE_ADMIN_SHUTDOWN),
|
||||
errmsg("terminating logical replication worker due to administrator command")));
|
||||
#endif
|
||||
} else if (IsTxnSnapCapturerProcess()) {
|
||||
ereport(FATAL,
|
||||
|
|
@ -7574,7 +7572,7 @@ int PostgresMain(int argc, char* argv[], const char* dbname, const char* usernam
|
|||
init_set_params_htab();
|
||||
|
||||
#ifndef ENABLE_MULTIPLE_NODES
|
||||
if (u_sess->proc_cxt.MyDatabaseId != InvalidOid && DB_IS_CMPT(B_FORMAT) && u_sess->attr.attr_sql.dolphin) {
|
||||
if (u_sess->proc_cxt.MyDatabaseId != InvalidOid && DB_IS_CMPT(B_FORMAT)) {
|
||||
InitBSqlPluginHookIfNeeded();
|
||||
}
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -848,7 +848,7 @@ static bool InitSession(knl_session_context* session)
|
|||
t_thrd.proc_cxt.PostInit->InitSession();
|
||||
|
||||
#ifndef ENABLE_MULTIPLE_NODES
|
||||
if (u_sess->proc_cxt.MyDatabaseId != InvalidOid && DB_IS_CMPT(B_FORMAT) && u_sess->attr.attr_sql.dolphin) {
|
||||
if (u_sess->proc_cxt.MyDatabaseId != InvalidOid && DB_IS_CMPT(B_FORMAT)) {
|
||||
InitBSqlPluginHookIfNeeded();
|
||||
}
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -720,6 +720,7 @@ static Datum ExecEvalWholeRowVar(
|
|||
{
|
||||
Var* variable = (Var*)wrvstate->xprstate.expr;
|
||||
TupleTableSlot* slot = NULL;
|
||||
TupleDesc slot_tupdesc;
|
||||
bool needslow = false;
|
||||
|
||||
if (isDone != NULL)
|
||||
|
|
@ -801,13 +802,21 @@ static Datum ExecEvalWholeRowVar(
|
|||
if (wrvstate->wrv_junkFilter != NULL)
|
||||
slot = ExecFilterJunk(wrvstate->wrv_junkFilter, slot);
|
||||
|
||||
slot_tupdesc = slot->tts_tupleDescriptor;
|
||||
|
||||
/*
|
||||
* If it's a RECORD Var, we'll use the slot's type ID info. It's likely
|
||||
* that the slot's type is also RECORD; if so, make sure it's been
|
||||
* "blessed", so that the Datum can be interpreted later.
|
||||
*
|
||||
* If the Var identifies a named composite type, we must check that the
|
||||
* actual tuple type is compatible with it.
|
||||
*/
|
||||
if (variable->vartype != RECORDOID) {
|
||||
if (variable->vartype == RECORDOID) {
|
||||
if (slot_tupdesc->tdtypeid == RECORDOID && slot_tupdesc->tdtypmod < 0)
|
||||
assign_record_type_typmod(slot_tupdesc);
|
||||
} else {
|
||||
TupleDesc var_tupdesc;
|
||||
TupleDesc slot_tupdesc;
|
||||
int i;
|
||||
|
||||
/*
|
||||
|
|
@ -824,8 +833,6 @@ static Datum ExecEvalWholeRowVar(
|
|||
*/
|
||||
var_tupdesc = lookup_rowtype_tupdesc(variable->vartype, -1);
|
||||
|
||||
slot_tupdesc = slot->tts_tupleDescriptor;
|
||||
|
||||
if (var_tupdesc->natts != slot_tupdesc->natts)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_DATATYPE_MISMATCH),
|
||||
|
|
@ -879,7 +886,6 @@ static Datum ExecEvalWholeRowFast(
|
|||
{
|
||||
Var* variable = (Var*)wrvstate->xprstate.expr;
|
||||
TupleTableSlot* slot = NULL;
|
||||
TupleDesc slot_tupdesc;
|
||||
HeapTuple tuple;
|
||||
TupleDesc tupleDesc;
|
||||
HeapTupleHeader dtuple;
|
||||
|
|
@ -909,17 +915,6 @@ static Datum ExecEvalWholeRowFast(
|
|||
if (wrvstate->wrv_junkFilter != NULL)
|
||||
slot = ExecFilterJunk(wrvstate->wrv_junkFilter, slot);
|
||||
|
||||
/*
|
||||
* If it's a RECORD Var, we'll use the slot's type ID info. It's likely
|
||||
* that the slot's type is also RECORD; if so, make sure it's been
|
||||
* "blessed", so that the Datum can be interpreted later.
|
||||
*/
|
||||
slot_tupdesc = slot->tts_tupleDescriptor;
|
||||
if (variable->vartype == RECORDOID) {
|
||||
if (slot_tupdesc->tdtypeid == RECORDOID && slot_tupdesc->tdtypmod < 0)
|
||||
assign_record_type_typmod(slot_tupdesc);
|
||||
}
|
||||
|
||||
tuple = ExecFetchSlotTuple(slot);
|
||||
tupleDesc = slot->tts_tupleDescriptor;
|
||||
|
||||
|
|
|
|||
|
|
@ -322,6 +322,7 @@ static bool RelationFindReplTupleByIndex(EState *estate, Relation rel, Relation
|
|||
}
|
||||
if (found) {
|
||||
/* Found tuple, try to lock it in the lockmode. */
|
||||
outslot->tts_tuple = ExecMaterializeSlot(outslot);
|
||||
xwait = TransactionIdIsValid(snap.xmin) ? snap.xmin : snap.xmax;
|
||||
/*
|
||||
* If the tuple is locked, wait for locking transaction to finish
|
||||
|
|
@ -345,16 +346,12 @@ static bool RelationFindReplTupleByIndex(EState *estate, Relation rel, Relation
|
|||
ItemPointer tid = tableam_tops_get_t_self(targetRel, outslot->tts_tuple);
|
||||
|
||||
if (RelationIsUstoreFormat(targetRel)) {
|
||||
/* materialize the slot, so we can visit it after the scan is end */
|
||||
outslot->tts_tuple = UHeapMaterialize(outslot);
|
||||
ItemPointerCopy(tid, &UHeaplocktup.ctid);
|
||||
rc = memset_s(&tbuf, sizeof(tbuf), 0, sizeof(tbuf));
|
||||
securec_check(rc, "\0", "\0");
|
||||
UHeaplocktup.disk_tuple = &tbuf.hdr;
|
||||
locktup = &UHeaplocktup;
|
||||
} else {
|
||||
/* materialize the slot, so we can visit it after the scan is end */
|
||||
outslot->tts_tuple = ExecMaterializeSlot(outslot);
|
||||
ItemPointerCopy(tid, &heaplocktup.t_self);
|
||||
locktup = &heaplocktup;
|
||||
}
|
||||
|
|
@ -404,10 +401,6 @@ static bool tuple_equals_slot(TupleDesc desc, const Tuple tup, TupleTableSlot *s
|
|||
/* Check equality of the attributes. */
|
||||
for (attrnum = 0; attrnum < desc->natts; attrnum++) {
|
||||
TypeCacheEntry *typentry;
|
||||
/* skip generate column */
|
||||
if (GetGeneratedCol(desc, attrnum)) {
|
||||
continue;
|
||||
}
|
||||
/*
|
||||
* If one value is NULL and other is not, then they are certainly not
|
||||
* equal
|
||||
|
|
@ -485,6 +478,7 @@ static bool RelationFindReplTupleSeq(Relation rel, LockTupleMode lockmode, Tuple
|
|||
|
||||
found = true;
|
||||
ExecStoreTuple(scantuple, outslot, InvalidBuffer, false);
|
||||
outslot->tts_tuple = ExecMaterializeSlot(outslot);
|
||||
|
||||
xwait = TransactionIdIsValid(snap.xmin) ? snap.xmin : snap.xmax;
|
||||
/*
|
||||
|
|
@ -517,16 +511,12 @@ static bool RelationFindReplTupleSeq(Relation rel, LockTupleMode lockmode, Tuple
|
|||
ItemPointer tid = tableam_tops_get_t_self(rel, outslot->tts_tuple);
|
||||
|
||||
if (RelationIsUstoreFormat(targetRel)) {
|
||||
/* materialize the slot, so we can visit it after the scan is end */
|
||||
outslot->tts_tuple = UHeapMaterialize(outslot);
|
||||
ItemPointerCopy(tid, &UHeaplocktup.ctid);
|
||||
rc = memset_s(&tbuf, sizeof(tbuf), 0, sizeof(tbuf));
|
||||
securec_check(rc, "\0", "\0");
|
||||
UHeaplocktup.disk_tuple = &tbuf.hdr;
|
||||
locktup = &UHeaplocktup;
|
||||
} else {
|
||||
/* materialize the slot, so we can visit it after the scan is end */
|
||||
outslot->tts_tuple = ExecMaterializeSlot(outslot);
|
||||
ItemPointerCopy(tid, &heaplocktup.t_self);
|
||||
locktup = &heaplocktup;
|
||||
}
|
||||
|
|
@ -663,6 +653,7 @@ void ExecSimpleRelationUpdate(EState *estate, EPQState *epqstate, TupleTableSlot
|
|||
/* Compute stored generated columns */
|
||||
if (rel->rd_att->constr && rel->rd_att->constr->has_generated_stored) {
|
||||
ExecComputeStoredGenerated(resultRelInfo, estate, slot, tuple, CMD_UPDATE);
|
||||
tuple = slot->tts_tuple;
|
||||
}
|
||||
|
||||
/* Check the constraints of the tuple */
|
||||
|
|
@ -681,11 +672,10 @@ void ExecSimpleRelationUpdate(EState *estate, EPQState *epqstate, TupleTableSlot
|
|||
rowMovement = true;
|
||||
}
|
||||
|
||||
tuple = slot->tts_tuple;
|
||||
CommandId cid = GetCurrentCommandId(true);
|
||||
/* OK, update the tuple and index entries for it */
|
||||
if (!rowMovement) {
|
||||
res = tableam_tuple_update(targetRelation, parentRelation, searchSlotTid, tuple, cid,
|
||||
res = tableam_tuple_update(targetRelation, parentRelation, searchSlotTid, slot->tts_tuple, cid,
|
||||
InvalidSnapshot, estate->es_snapshot, true, &oldslot, &tmfd, &updateIndexes, &modifiedIdxAttrs,
|
||||
false, allowInplaceUpdate);
|
||||
CheckTupleModifyRes(res);
|
||||
|
|
|
|||
|
|
@ -2947,9 +2947,9 @@ void SetOneOfCompressOption(DefElem* defElem, TableCreateSupport* tableCreateSup
|
|||
} else if (pg_strcasecmp(defname, "compress_level") == 0) {
|
||||
tableCreateSupport->compressLevel = true;
|
||||
} else if (pg_strcasecmp(defname, "compress_byte_convert") == 0) {
|
||||
tableCreateSupport->compressByteConvert = defGetBoolean(defElem);
|
||||
tableCreateSupport->compressByteConvert = true;
|
||||
} else if (pg_strcasecmp(defname, "compress_diff_convert") == 0) {
|
||||
tableCreateSupport->compressDiffConvert = defGetBoolean(defElem);
|
||||
tableCreateSupport->compressDiffConvert = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1278,10 +1278,13 @@ static const char *MXStatusToString(MultiXactStatus status)
|
|||
|
||||
static char *mxid_to_string(MultiXactId multi, int nmembers, MultiXactMember *members)
|
||||
{
|
||||
char *str = NULL;
|
||||
static char *str = NULL;
|
||||
StringInfoData buf;
|
||||
int i;
|
||||
|
||||
if (str != NULL)
|
||||
pfree(str);
|
||||
|
||||
initStringInfo(&buf);
|
||||
|
||||
appendStringInfo(&buf, XID_FMT " %d[" XID_FMT " (%s)", multi, nmembers,
|
||||
|
|
@ -1292,7 +1295,7 @@ static char *mxid_to_string(MultiXactId multi, int nmembers, MultiXactMember *me
|
|||
}
|
||||
|
||||
appendStringInfoChar(&buf, ']');
|
||||
str = MemoryContextStrdup(SESS_GET_MEM_CXT_GROUP(MEMORY_CONTEXT_STORAGE), buf.data);
|
||||
str = MemoryContextStrdup(TopMemoryContext, buf.data);
|
||||
pfree(buf.data);
|
||||
return str;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8965,8 +8965,6 @@ void StartupXLOG(void)
|
|||
g_instance.comm_cxt.predo_cxt.redoPf.redo_done_time = 0;
|
||||
pg_atomic_write_u32(&(g_instance.comm_cxt.localinfo_cxt.is_finish_redo), 0);
|
||||
|
||||
NotifyGscRecoveryStarted();
|
||||
|
||||
/*
|
||||
* Initialize WAL insert status array and the flush index - lastWalStatusEntryFlushed.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -1818,47 +1818,3 @@ void UHeapSlotStoreUHeapTuple(UHeapTuple utuple, TupleTableSlot *slot, bool shou
|
|||
/* Mark extracted state invalid */
|
||||
slot->tts_nvalid = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Make the contents of the uheap table's slot contents solely depend on the slot(make them a local copy),
|
||||
* and not on underlying external resources like another memory context, buffers etc.
|
||||
*
|
||||
* @pram slot: slot to be materialized.
|
||||
*/
|
||||
Tuple UHeapMaterialize(TupleTableSlot *slot)
|
||||
{
|
||||
Assert(!slot->tts_isempty);
|
||||
Assert(slot->tts_tupslotTableAm == TAM_USTORE);
|
||||
Assert(slot->tts_tupleDescriptor != NULL);
|
||||
/*
|
||||
* If we have a regular physical tuple, and it's locally palloc'd, we have
|
||||
* nothing to do.
|
||||
*/
|
||||
if (slot->tts_tuple && slot->tts_shouldFree) {
|
||||
return slot->tts_tuple;
|
||||
}
|
||||
|
||||
/*
|
||||
* Otherwise, copy or build a physical tuple, and store it into the slot.
|
||||
*
|
||||
* We may be called in a context that is shorter-lived than the tuple
|
||||
* slot, but we have to ensure that the materialized tuple will survive
|
||||
* anyway.
|
||||
*/
|
||||
MemoryContext old_context = MemoryContextSwitchTo(slot->tts_mcxt);
|
||||
if (slot->tts_tuple != NULL) {
|
||||
slot->tts_tuple = UHeapCopyTuple((UHeapTuple)slot->tts_tuple);
|
||||
} else {
|
||||
slot->tts_tuple = UHeapFormTuple(slot->tts_tupleDescriptor, slot->tts_values, slot->tts_isnull);
|
||||
}
|
||||
slot->tts_shouldFree = true;
|
||||
MemoryContextSwitchTo(old_context);
|
||||
|
||||
/*
|
||||
* Have to deform from scratch, otherwise tts_values[] entries could point
|
||||
* into the non-materialized tuple (which might be gone when accessed).
|
||||
*/
|
||||
slot->tts_nvalid = 0;
|
||||
return slot->tts_tuple;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -448,7 +448,9 @@ static void RecycleWaitIfNotUsed()
|
|||
#endif
|
||||
) {
|
||||
uint64 nonRecycled = 0;
|
||||
while (true) {
|
||||
while (g_instance.attr.attr_storage.undo_zone_count == 0) {
|
||||
/* Clear any already-pending wakeups */
|
||||
ResetLatch(&t_thrd.proc->procLatch);
|
||||
if (t_thrd.undorecycler_cxt.shutdown_requested) {
|
||||
ereport(LOG, (errmodule(MOD_UNDO), errmsg(UNDOFORMAT("UndoRecycler: shutting down"))));
|
||||
ResourceOwnerRelease(t_thrd.utils_cxt.CurrentResourceOwner, RESOURCE_RELEASE_BEFORE_LOCKS, false, true);
|
||||
|
|
|
|||
|
|
@ -238,19 +238,15 @@ public:
|
|||
return m_purpose;
|
||||
}
|
||||
|
||||
GcEpochType GcStartInnerTxn()
|
||||
void GcStartTxnMTtests()
|
||||
{
|
||||
m_gcEpoch = GetGlobalEpoch();
|
||||
|
||||
return m_gcEpoch;
|
||||
if (m_gcEpoch != GetGlobalEpoch())
|
||||
m_gcEpoch = GetGlobalEpoch();
|
||||
}
|
||||
|
||||
void GcEndInnerTxn(bool clean_gc)
|
||||
void GcEndTxnMTtests()
|
||||
{
|
||||
if (clean_gc) {
|
||||
RunQuicese();
|
||||
}
|
||||
m_gcEpoch = 0;
|
||||
RunQuicese();
|
||||
}
|
||||
|
||||
void GcStartTxn()
|
||||
|
|
@ -276,7 +272,6 @@ public:
|
|||
RunQuicese();
|
||||
m_managerLock.unlock();
|
||||
}
|
||||
m_gcEpoch = 0;
|
||||
m_isTxnStarted = false;
|
||||
}
|
||||
|
||||
|
|
@ -318,6 +313,7 @@ public:
|
|||
{
|
||||
if (m_performGcEpoch != g_gcActiveEpoch)
|
||||
HardQuiesce(m_rcuFreeCount);
|
||||
m_gcEpoch = 0;
|
||||
}
|
||||
|
||||
/** @brief Clean all object at the end of the session */
|
||||
|
|
|
|||
|
|
@ -258,15 +258,6 @@ bool Index::IndexInsert(Sentinel*& outputSentinel, const Key* key, uint32_t pid,
|
|||
outputSentinel = IndexInsertImpl(key, sentinel, inserted, pid);
|
||||
// sync between rollback/delete and insert
|
||||
if (inserted == false) {
|
||||
if (unlikely(outputSentinel == nullptr)) {
|
||||
MOT_REPORT_ERROR(
|
||||
MOT_ERROR_OOM, "Index Insert", "Failed to insert sentinel to index %s", m_name.c_str());
|
||||
rc = RC_MEMORY_ALLOCATION_ERROR;
|
||||
m_sentinelPool->Release<Sentinel>(sentinel);
|
||||
sentinel = nullptr;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Spin if the counter is 0 - aborting in parallel or sentinel is marks for commit
|
||||
if (outputSentinel->RefCountUpdate(INC, pid) == RC_OK)
|
||||
retryInsert = false;
|
||||
|
|
@ -309,16 +300,8 @@ Sentinel* Index::IndexInsert(const Key* key, Row* row, uint32_t pid)
|
|||
// no need to report to full error stack
|
||||
SetLastError(MOT_ERROR_UNIQUE_VIOLATION, MOT_SEVERITY_NORMAL);
|
||||
m_sentinelPool->Release<Sentinel>(sentinel);
|
||||
sentinel = nullptr;
|
||||
return nullptr;
|
||||
} else {
|
||||
if (inserted == false) {
|
||||
MOT_REPORT_ERROR(MOT_ERROR_OOM, "Index Insert", "Failed to insert sentinel to index %s", m_name.c_str());
|
||||
m_sentinelPool->Release<Sentinel>(sentinel);
|
||||
sentinel = nullptr;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (GetIndexOrder() == IndexOrder::INDEX_ORDER_PRIMARY) {
|
||||
sentinel->SetPrimaryIndex();
|
||||
sentinel->SetNextPtr(row);
|
||||
|
|
@ -360,6 +343,9 @@ Sentinel* Index::IndexReadHeader(const Key* key, uint32_t pid) const
|
|||
Sentinel* Index::IndexRemove(const Key* key, uint32_t pid)
|
||||
{
|
||||
Sentinel* sentinel = IndexRemoveImpl(key, pid);
|
||||
|
||||
MOT_ASSERT(sentinel != nullptr);
|
||||
MOT_ASSERT(sentinel->GetCounter() == 0);
|
||||
return sentinel;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -56,22 +56,12 @@ void* basic_table<P>::insert(MOT::Key const* const& key, void* const& entry, boo
|
|||
5. Update the the key slice, keylen, key suffix and key's value in the
|
||||
leaf
|
||||
6. Add the key's location in permutation's back (key is not visible for
|
||||
readers yet) as key's location is not part of the permutation yet, the key
|
||||
readers yet) As key's location is not part of the permutation yet, the key
|
||||
is not reachable (aka not present). In addition, the leaf is still locked.
|
||||
Unlocking the node and enter the key into the permutation will be done
|
||||
later in finish_insert (done in lp.finish function). */
|
||||
later in finish_insert (called from lp.finish). */
|
||||
|
||||
bool found = false;
|
||||
if (!lp.find_insert(*mtSessionThreadInfo, found)) {
|
||||
// Failed to insert key due to memory allocation failure.
|
||||
MOT_ASSERT(!mtSessionThreadInfo->non_disruptive_error());
|
||||
MOT_ASSERT(found == false);
|
||||
lp.finish(0, *mtSessionThreadInfo);
|
||||
result = false;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
MOT_ASSERT(mtSessionThreadInfo->non_disruptive_error());
|
||||
bool found = lp.find_insert(*mtSessionThreadInfo);
|
||||
|
||||
// If the key is new (not previously existing) then we record the entry under
|
||||
// that key
|
||||
|
|
|
|||
|
|
@ -33,15 +33,15 @@ namespace Masstree {
|
|||
template <typename P>
|
||||
struct gc_layer_rcu_callback_ng : public P::threadinfo_type::mrcu_callback {
|
||||
typedef typename P::threadinfo_type threadinfo;
|
||||
node_base<P>** root_ref_;
|
||||
node_base<P>* root_;
|
||||
int len_;
|
||||
size_t size_;
|
||||
MOT::MasstreePrimaryIndex* index_;
|
||||
char s_[0];
|
||||
gc_layer_rcu_callback_ng(node_base<P>** root_ref, Str prefix, size_t size)
|
||||
: root_ref_(root_ref), len_(prefix.length()), size_(size), index_(mtSessionThreadInfo->get_working_index())
|
||||
gc_layer_rcu_callback_ng(node_base<P>* root, Str prefix, size_t size)
|
||||
: root_(root), len_(prefix.length()), size_(size), index_(mtSessionThreadInfo->get_working_index())
|
||||
{
|
||||
errno_t erc = memcpy_s(s_, len_, prefix.data(), len_);
|
||||
errno_t erc = memcpy_s(s_, size_, prefix.data(), len_);
|
||||
securec_check(erc, "\0", "\0");
|
||||
}
|
||||
size_t operator()(bool drop_index);
|
||||
|
|
@ -51,7 +51,7 @@ struct gc_layer_rcu_callback_ng : public P::threadinfo_type::mrcu_callback {
|
|||
return size_;
|
||||
}
|
||||
|
||||
static void make(node_base<P>** root_ref, Str prefix, threadinfo& ti);
|
||||
static void make(node_base<P>* root, Str prefix, threadinfo& ti);
|
||||
};
|
||||
|
||||
template <typename P>
|
||||
|
|
@ -60,8 +60,8 @@ size_t gc_layer_rcu_callback_ng<P>::operator()(bool drop_index)
|
|||
// If drop_index == true, all index's pools are going to be cleaned, so we can skip gc_layer call (which might add
|
||||
// more elements into GC)
|
||||
if (drop_index == false) {
|
||||
// GC layer remove might delete elements from tree and might create new gc layer removal requests and add them to GC.
|
||||
// Index must be provided to allow access to the memory pools.
|
||||
// GC layer remove might delete elements from tree and add them to the limbolist. Index must be provided to
|
||||
// allow access to the memory pools.
|
||||
mtSessionThreadInfo->set_working_index(index_);
|
||||
(*this)(*mtSessionThreadInfo);
|
||||
mtSessionThreadInfo->set_working_index(NULL);
|
||||
|
|
@ -73,33 +73,30 @@ size_t gc_layer_rcu_callback_ng<P>::operator()(bool drop_index)
|
|||
template <typename P>
|
||||
void gc_layer_rcu_callback_ng<P>::operator()(threadinfo& ti)
|
||||
{
|
||||
masstree_invariant(root_ref_);
|
||||
|
||||
tcursor<P> node_cursor(root_ref_, s_, len_);
|
||||
bool do_remove = node_cursor.gc_layer(ti);
|
||||
if (!do_remove || !node_cursor.finish_remove(ti)) {
|
||||
node_cursor.n_->unlock();
|
||||
// root_ node while creating gc_layer_rcu_callback_ng might not be the current root. Find updated tree's root.
|
||||
while (!root_->is_root()) {
|
||||
root_ = root_->maybe_parent();
|
||||
}
|
||||
ti.add_nodes_to_gc();
|
||||
}
|
||||
|
||||
template <typename P>
|
||||
void gc_layer_rcu_callback_ng<P>::make(node_base<P>** root_ref, Str prefix, threadinfo& ti)
|
||||
{
|
||||
size_t sz = prefix.len + sizeof(gc_layer_rcu_callback_ng<P>);
|
||||
// As we are using slab allocator for allocation, sz is will be updated by ti.allocate with the real allocation
|
||||
// size. We need this size for GC deallocation size report
|
||||
void* data = ti.allocate(sz, memtag_masstree_gc, &sz /* IN/OUT PARAM */);
|
||||
if (!data) {
|
||||
// If allocation fails, gc layer removal command will not be added to GC and this layer wont be removed.
|
||||
// We might deal with this issue in the future by replacing the current mechanism with one of the following options:
|
||||
// 1. Use thread local GC layer removal object (per threadinfo) and keep list of key suffixes to clean (also in threadinfo)
|
||||
// 2. Move this feature to VACUUM process: Create special iterator that adds GC Layer callbacks when it finds empty layers
|
||||
ti.set_last_error(MT_MERR_GC_LAYER_REMOVAL_MAKE);
|
||||
// If root was already deleted, do nothing.
|
||||
if (root_->deleted()) {
|
||||
return;
|
||||
}
|
||||
|
||||
gc_layer_rcu_callback_ng<P>* cb = new (data) gc_layer_rcu_callback_ng<P>(root_ref, prefix, sz);
|
||||
tcursor<P> node_cursor(root_, s_, len_);
|
||||
if (!node_cursor.gc_layer(ti) || !node_cursor.finish_remove(ti)) {
|
||||
node_cursor.n_->unlock();
|
||||
}
|
||||
}
|
||||
|
||||
template <typename P>
|
||||
void gc_layer_rcu_callback_ng<P>::make(node_base<P>* root, Str prefix, threadinfo& ti)
|
||||
{
|
||||
size_t sz = prefix.len + sizeof(gc_layer_rcu_callback_ng<P>);
|
||||
// As we are using slab allocator to allocate the memory, sz is will updated in ti.allocate with the real allocated
|
||||
// size
|
||||
void* data = ti.allocate(sz, memtag_masstree_gc, &sz /*OUT PARAM*/);
|
||||
gc_layer_rcu_callback_ng<P>* cb = new (data) gc_layer_rcu_callback_ng<P>(root, prefix, sz);
|
||||
ti.rcu_register(cb, sz);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -69,17 +69,14 @@ Sentinel* MasstreePrimaryIndex::IndexInsertImpl(const Key* key, Sentinel* sentin
|
|||
mtSessionThreadInfo->set_gc_session(
|
||||
MOTEngine::GetInstance()->GetCurrentGcSession()); // set current GC session in thread-pooled envelope
|
||||
|
||||
mtSessionThreadInfo->set_last_error(MT_MERR_OK);
|
||||
|
||||
existingItem = m_index.insert(key, sentinel, inserted, pid);
|
||||
|
||||
mtSessionThreadInfo->set_gc_session(NULL);
|
||||
mtSessionThreadInfo->set_working_index(NULL);
|
||||
|
||||
if (!inserted && existingItem) { // key mapping already exists in unique index
|
||||
if (!inserted) { // key mapping already exists in unique index
|
||||
result = reinterpret_cast<Sentinel*>(existingItem);
|
||||
} // otherwise return null pointer (if !inserted && !existingItem, Key does not exist and insertation failed due to
|
||||
// memory issue)
|
||||
} // otherwise return null pointer
|
||||
|
||||
return result;
|
||||
}
|
||||
|
|
@ -111,8 +108,6 @@ Sentinel* MasstreePrimaryIndex::IndexRemoveImpl(const Key* key, uint32_t pid)
|
|||
mtSessionThreadInfo->set_gc_session(
|
||||
MOTEngine::GetInstance()->GetCurrentGcSession()); // set current GC session in thread-pooled envelope
|
||||
|
||||
mtSessionThreadInfo->set_last_error(MT_MERR_OK);
|
||||
|
||||
output = m_index.remove(key->GetKeyBuf(), key->GetKeyLength(), result, pid);
|
||||
|
||||
mtSessionThreadInfo->set_gc_session(NULL);
|
||||
|
|
|
|||
|
|
@ -37,7 +37,6 @@
|
|||
#include "masstree/mot_masstree_struct.hpp"
|
||||
#include "masstree/mot_masstree_iterator.hpp"
|
||||
#include <cmath>
|
||||
#include "mot_engine.h"
|
||||
|
||||
namespace MOT {
|
||||
/**
|
||||
|
|
@ -303,38 +302,11 @@ public:
|
|||
/**
|
||||
* @brief Print Masstree pools memory consumption details to log.
|
||||
*/
|
||||
virtual void PrintPoolsStats(LogLevel level = LogLevel::LL_DEBUG)
|
||||
virtual void PrintPoolsStats()
|
||||
{
|
||||
m_leafsPool->Print("Leafs pool", level);
|
||||
m_internodesPool->Print("Internode pool", level);
|
||||
m_ksuffixSlab->Print("Ksuffix slab", level);
|
||||
}
|
||||
|
||||
virtual void GetLeafsPoolStats(uint64_t& objSize, uint64_t& numUsedObj, uint64_t& totalSize, uint64_t& netto)
|
||||
{
|
||||
PoolStatsSt stats = {};
|
||||
m_leafsPool->GetStats(stats);
|
||||
|
||||
objSize = stats.m_objSize;
|
||||
numUsedObj = stats.m_totalObjCount - stats.m_freeObjCount;
|
||||
totalSize = stats.m_poolCount * stats.m_poolGrossSize;
|
||||
netto = numUsedObj * objSize;
|
||||
}
|
||||
|
||||
virtual void GetInternodesPoolStats(uint64_t& objSize, uint64_t& numUsedObj, uint64_t& totalSize, uint64_t& netto)
|
||||
{
|
||||
PoolStatsSt stats = {};
|
||||
m_internodesPool->GetStats(stats);
|
||||
|
||||
objSize = stats.m_objSize;
|
||||
numUsedObj = stats.m_totalObjCount - stats.m_freeObjCount;
|
||||
totalSize = stats.m_poolCount * stats.m_poolGrossSize;
|
||||
netto = numUsedObj * objSize;
|
||||
}
|
||||
|
||||
virtual PoolStatsSt* GetKsuffixSlabStats()
|
||||
{
|
||||
return m_ksuffixSlab->GetStats();
|
||||
m_leafsPool->Print("Leafs pool: ");
|
||||
m_internodesPool->Print("Internode pool: ");
|
||||
m_ksuffixSlab->Print("Ksuffix slab: ");
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -344,8 +316,6 @@ public:
|
|||
{
|
||||
m_initialized = false;
|
||||
DestroyPools();
|
||||
// remove masstree's root pointer (not valid anymore)
|
||||
*(m_index.root_ref()) = nullptr;
|
||||
|
||||
return IndexInitImpl(NULL);
|
||||
}
|
||||
|
|
@ -362,7 +332,7 @@ public:
|
|||
* @param tag Hint to determine which pool to use.
|
||||
* @return Pointer to allocated memory.
|
||||
*/
|
||||
virtual void* AllocateMem(int& size, enum memtag tag)
|
||||
void* AllocateMem(int& size, enum memtag tag)
|
||||
{
|
||||
switch (tag) {
|
||||
case memtag_masstree_leaf:
|
||||
|
|
@ -390,7 +360,7 @@ public:
|
|||
* @param Pointer to allocated memory.
|
||||
* @return True if deallocation succeeded.
|
||||
*/
|
||||
virtual bool DeallocateMem(void* ptr, int size, enum memtag tag)
|
||||
bool DeallocateMem(void* ptr, int size, enum memtag tag)
|
||||
{
|
||||
switch (tag) {
|
||||
case memtag_masstree_leaf:
|
||||
|
|
@ -461,16 +431,10 @@ public:
|
|||
{
|
||||
// If dropIndex == true, all index's pools are going to be cleaned, so we skip the release here
|
||||
mtSessionThreadInfo->set_gc_session(GetCurrentGcSession());
|
||||
GcEpochType local_epoch =
|
||||
GetSessionManager()->GetCurrentSessionContext()->GetTxnManager()->GetGcSession()->GcStartInnerTxn();
|
||||
|
||||
size_t allocationSize = (*static_cast<mrcu_callback*>(gcRemoveLayerFuncObjPtr))(dropIndex);
|
||||
|
||||
if (dropIndex == false) {
|
||||
((SlabAllocator*)slab)->Release(gcRemoveLayerFuncObjPtr, allocationSize);
|
||||
}
|
||||
|
||||
GetSessionManager()->GetCurrentSessionContext()->GetTxnManager()->GetGcSession()->GcEndInnerTxn(false);
|
||||
mtSessionThreadInfo->set_gc_session(NULL);
|
||||
return allocationSize;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -582,7 +582,6 @@ Row* Table::RemoveKeyFromIndex(Row* row, Sentinel* sentinel, uint64_t tid, GcMan
|
|||
#endif
|
||||
currSentinel = ix->IndexRemove(&key, tid);
|
||||
MOT_ASSERT(currSentinel == sentinel);
|
||||
MOT_ASSERT(currSentinel->GetCounter() == 0);
|
||||
if (likely(gc != nullptr)) {
|
||||
if (ix->GetIndexOrder() == IndexOrder::INDEX_ORDER_PRIMARY) {
|
||||
OutputRow = currSentinel->GetData();
|
||||
|
|
|
|||
|
|
@ -413,8 +413,6 @@ RC TxnManager::RollbackInsert(Access* ac)
|
|||
#endif
|
||||
outputSen = index_->IndexRemove(&m_key, GetThdId());
|
||||
MOT_ASSERT(outputSen != nullptr);
|
||||
MOT_ASSERT(outputSen->GetCounter() == 0);
|
||||
|
||||
GcSessionRecordRcu(index_->GetIndexId(), outputSen, nullptr, Index::SentinelDtor, SENTINEL_SIZE(index_));
|
||||
// If we are the owner of the key and insert on top of a deleted row,
|
||||
// lets check if we can reclaim the deleted row
|
||||
|
|
@ -822,8 +820,6 @@ void TxnInsertAction::CleanupOptimisticInsert(
|
|||
MOT_ASSERT(pIndexInsertResult->GetCounter() == 0);
|
||||
Sentinel* outputSen = index_->IndexRemove(currentItem->m_key, m_manager->GetThdId());
|
||||
MOT_ASSERT(outputSen != nullptr);
|
||||
MOT_ASSERT(outputSen->GetCounter() == 0);
|
||||
|
||||
m_manager->GcSessionRecordRcu(
|
||||
index_->GetIndexId(), outputSen, nullptr, Index::SentinelDtor, SENTINEL_SIZE(index_));
|
||||
m_manager->m_accessMgr->IncreaseTableStat(table);
|
||||
|
|
|
|||
|
|
@ -223,7 +223,6 @@ void LogicalDecodingProcessRecord(LogicalDecodingContext *ctx, XLogReaderState *
|
|||
return;
|
||||
}
|
||||
|
||||
ResourceOwner tmpOwner = t_thrd.utils_cxt.CurrentResourceOwner;
|
||||
/* cast so we get a warning when new rmgrs are added */
|
||||
switch ((RmgrIds)XLogRecGetRmid(record)) {
|
||||
/*
|
||||
|
|
@ -258,7 +257,6 @@ void LogicalDecodingProcessRecord(LogicalDecodingContext *ctx, XLogReaderState *
|
|||
default:
|
||||
break;
|
||||
}
|
||||
t_thrd.utils_cxt.CurrentResourceOwner = tmpOwner;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -406,7 +406,7 @@ static void logicalrep_write_tuple(StringInfo out, Relation rel, HeapTuple tuple
|
|||
pfree(outputbytes);
|
||||
}
|
||||
} else {
|
||||
char* outputstr = NULL;
|
||||
char *outputstr;
|
||||
pq_sendbyte(out, LOGICALREP_COLUMN_TEXT);
|
||||
if (!typclass->typbyval && typclass->typlen == -1) {
|
||||
/* definitely detoasted Datum */
|
||||
|
|
@ -464,8 +464,10 @@ static void logicalrep_read_tuple(StringInfo in, LogicalRepTupleData *tuple)
|
|||
len = pq_getmsgint(in, sizeof(uint32)); /* read length */
|
||||
|
||||
/* and data */
|
||||
value->data = (char *)palloc0((len + 1) * sizeof(char));
|
||||
value->data = (char *) palloc((len + 1) * sizeof(char));
|
||||
pq_copymsgbytes(in, value->data, len);
|
||||
/* not strictly necessary but per StringInfo practice */
|
||||
value->data[len] = '\0';
|
||||
/* make StringInfo fully valid */
|
||||
value->len = len;
|
||||
value->cursor = 0;
|
||||
|
|
|
|||
|
|
@ -94,7 +94,7 @@
|
|||
#include "utils/relcache.h"
|
||||
|
||||
static const int NAPTIME_PER_CYCLE = 10; /* max sleep time between cycles (10ms) */
|
||||
static const double HALF = 0.5;
|
||||
static const float HALF = 0.5;
|
||||
|
||||
typedef struct FlushPosition {
|
||||
dlist_node node;
|
||||
|
|
@ -121,6 +121,18 @@ static void LogicalrepWorkerSighub(SIGNAL_ARGS)
|
|||
t_thrd.applyworker_cxt.got_SIGHUP = true;
|
||||
}
|
||||
|
||||
/* SIGTERM: time to die */
|
||||
static void LogicalrepWorkerSigterm(SIGNAL_ARGS)
|
||||
{
|
||||
int saveErrno = errno;
|
||||
|
||||
t_thrd.applyworker_cxt.got_SIGTERM = true;
|
||||
if (t_thrd.proc)
|
||||
SetLatch(&t_thrd.proc->procLatch);
|
||||
|
||||
errno = saveErrno;
|
||||
}
|
||||
|
||||
/*
|
||||
* Make sure that we started local transaction.
|
||||
*
|
||||
|
|
@ -1056,15 +1068,13 @@ static void ApplyLoop(void)
|
|||
/* mark as idle, before starting to loop */
|
||||
pgstat_report_activity(STATE_IDLE, NULL);
|
||||
|
||||
for (;;) {
|
||||
while (!t_thrd.applyworker_cxt.got_SIGTERM) {
|
||||
MemoryContextSwitchTo(t_thrd.applyworker_cxt.messageContext);
|
||||
|
||||
int len;
|
||||
char *buf = NULL;
|
||||
unsigned char type;
|
||||
|
||||
CHECK_FOR_INTERRUPTS();
|
||||
|
||||
/* Wait a while for data to arrive */
|
||||
if ((WalReceiverFuncTable[GET_FUNC_IDX]).walrcv_receive(NAPTIME_PER_CYCLE, &type, &buf, &len)) {
|
||||
StringInfoData s;
|
||||
|
|
@ -1361,7 +1371,7 @@ void ApplyWorkerMain()
|
|||
*/
|
||||
gspqsignal(SIGHUP, LogicalrepWorkerSighub);
|
||||
gspqsignal(SIGINT, StatementCancelHandler);
|
||||
gspqsignal(SIGTERM, die);
|
||||
gspqsignal(SIGTERM, LogicalrepWorkerSigterm);
|
||||
|
||||
gspqsignal(SIGQUIT, quickdie);
|
||||
gspqsignal(SIGALRM, handle_sig_alarm);
|
||||
|
|
@ -1717,11 +1727,3 @@ static void UpdateConninfo(char* standbysInfo)
|
|||
|
||||
ereport(LOG, (errmsg("Update conninfo successfully, new conninfo %s.", standbysInfo)));
|
||||
}
|
||||
|
||||
/*
|
||||
* Is current process a logical replication worker?
|
||||
*/
|
||||
bool IsLogicalWorker(void)
|
||||
{
|
||||
return t_thrd.applyworker_cxt.curWorker != NULL;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -78,7 +78,7 @@ void _PG_output_plugin_init(OutputPluginCallbacks *cb)
|
|||
cb->shutdown_cb = pgoutput_shutdown;
|
||||
}
|
||||
|
||||
static void parse_output_parameters(List *options, PGOutputData *data)
|
||||
static void parse_output_parameters(List* options, PGOutputData* data)
|
||||
{
|
||||
ListCell *lc;
|
||||
bool protocol_version_given = false;
|
||||
|
|
|
|||
|
|
@ -1934,18 +1934,14 @@ ArchiveConfig* formArchiveConfigFromStr(char *content, bool encrypted)
|
|||
ArchiveConnConfig* conn_config = NULL;
|
||||
char* media_type = NULL;
|
||||
errno_t rc = EOK;
|
||||
char *content_copy = NULL;
|
||||
/* SplitIdentifierString will change origin string */
|
||||
char *content_copy = pstrdup(content);
|
||||
char *tmp = NULL;
|
||||
List* elemlist = NIL;
|
||||
int param_num = 0;
|
||||
size_t elem_index = 0;
|
||||
archive_config = (ArchiveConfig *)palloc0(sizeof(ArchiveConfig));
|
||||
char decryptSecretAccessKeyStr[DEST_CIPHER_LENGTH] = {'\0'};
|
||||
if (content == NULL || strlen(content) == 0) {
|
||||
goto FAILURE;
|
||||
}
|
||||
/* SplitIdentifierString will change origin string */
|
||||
content_copy = pstrdup(content);
|
||||
/* Parse string into list of identifiers */
|
||||
if (!SplitIdentifierString(content_copy, ';', &elemlist, false, false)) {
|
||||
goto FAILURE;
|
||||
|
|
|
|||
|
|
@ -401,7 +401,6 @@ int WalSenderMain(void)
|
|||
t_thrd.walsender_cxt.server_run_mode = t_thrd.postmaster_cxt.HaShmData->current_mode;
|
||||
|
||||
SetHaWalSenderChannel();
|
||||
Assert(t_thrd.utils_cxt.CurrentResourceOwner != NULL);
|
||||
/* Handle handshake messages before streaming */
|
||||
WalSndHandshake();
|
||||
|
||||
|
|
@ -497,7 +496,6 @@ static void WalSndHandshake(void)
|
|||
|
||||
while (!repCxt.replicationStarted) {
|
||||
int firstchar;
|
||||
Assert(t_thrd.utils_cxt.CurrentResourceOwner != NULL);
|
||||
|
||||
WalSndSetState(WALSNDSTATE_STARTUP);
|
||||
set_ps_display("idle", false);
|
||||
|
|
@ -2035,8 +2033,6 @@ bool isLogicalSlotExist(char* slotName)
|
|||
}
|
||||
|
||||
static void IdentifyCommand(Node* cmd_node, ReplicationCxt* repCxt, const char *cmd_string){
|
||||
ResourceOwner tmpOwner = t_thrd.utils_cxt.CurrentResourceOwner;
|
||||
Assert(tmpOwner != NULL);
|
||||
switch (cmd_node->type) {
|
||||
case T_IdentifySystemCmd:
|
||||
IdentifySystem();
|
||||
|
|
@ -2144,7 +2140,7 @@ static void IdentifyCommand(Node* cmd_node, ReplicationCxt* repCxt, const char *
|
|||
ereport(FATAL,
|
||||
(errcode(ERRCODE_PROTOCOL_VIOLATION), errmsg("invalid standby query string: %s", cmd_string)));
|
||||
}
|
||||
t_thrd.utils_cxt.CurrentResourceOwner = tmpOwner;
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -3600,12 +3596,8 @@ static int WalSndLoop(WalSndSendDataCallback send_data)
|
|||
t_thrd.walsender_cxt.last_logical_xlog_advanced_timestamp = GetCurrentTimestamp();
|
||||
t_thrd.walsender_cxt.waiting_for_ping_response = false;
|
||||
|
||||
ResourceOwner tmpOwner = t_thrd.utils_cxt.CurrentResourceOwner;
|
||||
Assert(!IsTransactionOrTransactionBlock() &&
|
||||
strcmp(ResourceOwnerGetName(tmpOwner), "walsender top-level resource owner") == 0);
|
||||
/* Loop forever, unless we get an error */
|
||||
for (;;) {
|
||||
t_thrd.utils_cxt.CurrentResourceOwner = tmpOwner;
|
||||
TimestampTz now;
|
||||
|
||||
/* Clear any already-pending wakeups */
|
||||
|
|
@ -4014,7 +4006,6 @@ static int WalSndLoop(WalSndSendDataCallback send_data)
|
|||
}
|
||||
}
|
||||
|
||||
t_thrd.utils_cxt.CurrentResourceOwner = tmpOwner;
|
||||
WalSndShutdown();
|
||||
return 1; /* keep the compiler quiet */
|
||||
}
|
||||
|
|
@ -5823,7 +5814,7 @@ Datum gs_paxos_stat_replication(PG_FUNCTION_ARGS)
|
|||
*/
|
||||
Datum pg_stat_get_wal_senders(PG_FUNCTION_ARGS)
|
||||
{
|
||||
#define PG_STAT_GET_WAL_SENDERS_COLS 21
|
||||
#define PG_STAT_GET_WAL_SENDERS_COLS 22
|
||||
|
||||
TupleDesc tupdesc;
|
||||
int *sync_priority = NULL;
|
||||
|
|
@ -6060,9 +6051,11 @@ Datum pg_stat_get_wal_senders(PG_FUNCTION_ARGS)
|
|||
/* sync_state and sync_prority */
|
||||
if (!SyncRepRequested()) {
|
||||
values[j++] = CStringGetTextDatum("Async");
|
||||
nulls[j++] = true;
|
||||
values[j++] = Int32GetDatum(0);
|
||||
} else {
|
||||
values[j++] = CStringGetTextDatum("Sync");
|
||||
nulls[j++] = true;
|
||||
values[j++] = Int32GetDatum(sync_priority[i]);
|
||||
}
|
||||
} else {
|
||||
|
|
@ -6084,12 +6077,15 @@ Datum pg_stat_get_wal_senders(PG_FUNCTION_ARGS)
|
|||
*/
|
||||
if (priority == 0) {
|
||||
values[j++] = CStringGetTextDatum("Async");
|
||||
nulls[j++] = true;
|
||||
} else if (list_member_int((List*)list_nth(sync_standbys, group), i)) {
|
||||
values[j++] = GetWalsndSyncRepConfig(walsnd)->syncrep_method == SYNC_REP_PRIORITY
|
||||
? CStringGetTextDatum("Sync")
|
||||
: CStringGetTextDatum("Quorum");
|
||||
values[j++] = Int32GetDatum(group);
|
||||
} else {
|
||||
values[j++] = CStringGetTextDatum("Potential");
|
||||
values[j++] = Int32GetDatum(group);
|
||||
}
|
||||
values[j++] = Int32GetDatum(priority);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -394,6 +394,8 @@ void mdcreate(SMgrRelation reln, ForkNumber forkNum, bool isRedo)
|
|||
}
|
||||
|
||||
if (fd < 0) {
|
||||
int save_errno = errno;
|
||||
|
||||
/*
|
||||
* During bootstrap, there are cases where a system relation will be
|
||||
* accessed (by internal backend processes) before the bootstrap
|
||||
|
|
@ -405,7 +407,26 @@ void mdcreate(SMgrRelation reln, ForkNumber forkNum, bool isRedo)
|
|||
* new catalogs can by no means be used by other relations, we simply
|
||||
* truncate them.
|
||||
*/
|
||||
fd = RetryDataFileIdOpenFile(isRedo, path, filenode, flags);
|
||||
if (isRedo || IsBootstrapProcessingMode() ||
|
||||
(u_sess->attr.attr_common.IsInplaceUpgrade && filenode.rnode.node.relNode < FirstNormalObjectId)) {
|
||||
ADIO_RUN()
|
||||
{
|
||||
flags = O_RDWR | PG_BINARY | O_DIRECT | (u_sess->attr.attr_common.IsInplaceUpgrade ? O_TRUNC : 0);
|
||||
}
|
||||
ADIO_ELSE()
|
||||
{
|
||||
flags = O_RDWR | PG_BINARY | (u_sess->attr.attr_common.IsInplaceUpgrade ? O_TRUNC : 0);
|
||||
}
|
||||
ADIO_END();
|
||||
|
||||
fd = DataFileIdOpenFile(path, filenode, flags, 0600);
|
||||
}
|
||||
|
||||
if (fd < 0) {
|
||||
/* be sure to report the error reported by create, not open */
|
||||
errno = save_errno;
|
||||
ereport(ERROR, (errcode_for_file_access(), errmsg("could not create file \"%s\": %m", path)));
|
||||
}
|
||||
}
|
||||
|
||||
File fd_pca = -1;
|
||||
|
|
|
|||
|
|
@ -145,29 +145,6 @@ then
|
|||
plat_form_str=ubuntu18.04_"$cpu_bit"
|
||||
fi
|
||||
|
||||
##################################################################################
|
||||
# the modification here will also lead to the synchronous modification of the 3rd-party compilation library path
|
||||
# PR link : https://gitee.com/opengauss/openGauss-third_party/pulls/130
|
||||
# redflag platform
|
||||
# the result form like this: asianux_x86_64
|
||||
##################################################################################
|
||||
if [ "$kernel"x = "redflag"x ]
|
||||
then
|
||||
plat_form_str=asianux7.6_"$cpu_bit"
|
||||
fi
|
||||
|
||||
|
||||
##################################################################################
|
||||
# the modification here will also lead to the synchronous modification of the 3rd-party compilation library path
|
||||
# PR link : https://gitee.com/opengauss/openGauss-third_party/pulls/130
|
||||
# asianux platform
|
||||
# the result form like this: asianux_aarch64
|
||||
##################################################################################
|
||||
if [ "$kernel"x = "asianux"x ]
|
||||
then
|
||||
plat_form_str=asianux7.5_"$cpu_bit"
|
||||
fi
|
||||
|
||||
##################################################################################
|
||||
#
|
||||
# other platform
|
||||
|
|
|
|||
|
|
@ -314,5 +314,4 @@ template<bool hasnull>
|
|||
void UHeapFillDiskTuple(TupleDesc tupleDesc, Datum *values, const bool *isnull, UHeapDiskTupleData *diskTuple,
|
||||
uint32 dataSize, bool enableReverseBitmap, bool enableReserve);
|
||||
void CheckTupleValidity(Relation rel, UHeapTuple utuple);
|
||||
Tuple UHeapMaterialize(TupleTableSlot *slot);
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -165,7 +165,7 @@ extern void addNewPartitionTuple(Relation pg_part_desc, Partition new_part_desc,
|
|||
Datum interval, Datum maxValues, Datum transitionPoint, Datum reloptions);
|
||||
|
||||
extern void heap_truncate_one_part(Relation rel , Oid partOid);
|
||||
extern Oid heapTupleGetPartitionId(Relation rel, void *tuple, bool isDDL = false);
|
||||
extern Oid heapTupleGetPartitionId(Relation rel, void *tuple);
|
||||
extern Oid heapTupleGetSubPartitionId(Relation rel, void *tuple);
|
||||
extern void heap_truncate(List *relids);
|
||||
extern void heap_truncate_one_rel(Relation rel);
|
||||
|
|
@ -240,7 +240,7 @@ extern char* make_column_map(TupleDesc tuple_desc);
|
|||
*/
|
||||
extern bool* CheckPartkeyHasTimestampwithzone(Relation partTableRel, bool isForSubPartition = false);
|
||||
|
||||
extern Oid AddNewIntervalPartition(Relation rel, void* insertTuple, bool isDDL = false);
|
||||
extern Oid AddNewIntervalPartition(Relation rel, void* insertTuple);
|
||||
|
||||
extern int GetIndexKeyAttsByTuple(Relation relation, HeapTuple indexTuple);
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,37 @@
|
|||
-- for any x group
|
||||
DO $$
|
||||
DECLARE
|
||||
ans boolean;
|
||||
BEGIN
|
||||
select case when working_version_num()=92301 then true else false end as ans into ans;
|
||||
if ans = false then
|
||||
DROP FUNCTION IF EXISTS pg_catalog.pg_stat_get_wal_senders() CASCADE;
|
||||
SET LOCAL inplace_upgrade_next_system_object_oids = IUO_PROC, 3099;
|
||||
CREATE FUNCTION pg_catalog.pg_stat_get_wal_senders(
|
||||
OUT pid bigint,
|
||||
OUT sender_pid integer,
|
||||
OUT local_role text,
|
||||
OUT peer_role text,
|
||||
OUT peer_state text,
|
||||
OUT state text,
|
||||
OUT catchup_start timestamp with time zone,
|
||||
OUT catchup_end timestamp with time zone,
|
||||
OUT sender_sent_location text,
|
||||
OUT sender_write_location text,
|
||||
OUT sender_flush_location text,
|
||||
OUT sender_replay_location text,
|
||||
OUT receiver_received_location text,
|
||||
OUT receiver_write_location text,
|
||||
OUT receiver_flush_location text,
|
||||
OUT receiver_replay_location text,
|
||||
OUT sync_percent text,
|
||||
OUT sync_state text,
|
||||
OUT sync_priority integer,
|
||||
OUT sync_most_available text,
|
||||
OUT channel text
|
||||
) RETURNS SETOF record
|
||||
STABLE NOT FENCED NOT SHIPPABLE ROWS 10
|
||||
LANGUAGE internal AS 'pg_stat_get_wal_senders';
|
||||
end if;
|
||||
END$$;
|
||||
SET LOCAL inplace_upgrade_next_system_object_oids = IUO_PROC, 0;
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
-- for any x group
|
||||
DO $$
|
||||
DECLARE
|
||||
ans boolean;
|
||||
BEGIN
|
||||
select case when working_version_num()=92301 then true else false end as ans into ans;
|
||||
if ans = false then
|
||||
DROP FUNCTION IF EXISTS pg_catalog.pg_stat_get_wal_senders() CASCADE;
|
||||
SET LOCAL inplace_upgrade_next_system_object_oids = IUO_PROC, 3099;
|
||||
CREATE FUNCTION pg_catalog.pg_stat_get_wal_senders(
|
||||
OUT pid bigint,
|
||||
OUT sender_pid integer,
|
||||
OUT local_role text,
|
||||
OUT peer_role text,
|
||||
OUT peer_state text,
|
||||
OUT state text,
|
||||
OUT catchup_start timestamp with time zone,
|
||||
OUT catchup_end timestamp with time zone,
|
||||
OUT sender_sent_location text,
|
||||
OUT sender_write_location text,
|
||||
OUT sender_flush_location text,
|
||||
OUT sender_replay_location text,
|
||||
OUT receiver_received_location text,
|
||||
OUT receiver_write_location text,
|
||||
OUT receiver_flush_location text,
|
||||
OUT receiver_replay_location text,
|
||||
OUT sync_percent text,
|
||||
OUT sync_state text,
|
||||
OUT sync_priority integer,
|
||||
OUT sync_most_available text,
|
||||
OUT channel text
|
||||
) RETURNS SETOF record
|
||||
STABLE NOT FENCED NOT SHIPPABLE ROWS 10
|
||||
LANGUAGE internal AS 'pg_stat_get_wal_senders';
|
||||
end if;
|
||||
END$$;
|
||||
SET LOCAL inplace_upgrade_next_system_object_oids = IUO_PROC, 0;
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
-- for any x group
|
||||
DO $$
|
||||
DECLARE
|
||||
ans boolean;
|
||||
BEGIN
|
||||
select case when working_version_num()=92301 then true else false end as ans into ans;
|
||||
if ans = false then
|
||||
DROP FUNCTION IF EXISTS pg_catalog.pg_stat_get_wal_senders() CASCADE;
|
||||
SET LOCAL inplace_upgrade_next_system_object_oids = IUO_PROC, 3099;
|
||||
CREATE FUNCTION pg_catalog.pg_stat_get_wal_senders(
|
||||
OUT pid bigint,
|
||||
OUT sender_pid integer,
|
||||
OUT local_role text,
|
||||
OUT peer_role text,
|
||||
OUT peer_state text,
|
||||
OUT state text,
|
||||
OUT catchup_start timestamp with time zone,
|
||||
OUT catchup_end timestamp with time zone,
|
||||
OUT sender_sent_location text,
|
||||
OUT sender_write_location text,
|
||||
OUT sender_flush_location text,
|
||||
OUT sender_replay_location text,
|
||||
OUT receiver_received_location text,
|
||||
OUT receiver_write_location text,
|
||||
OUT receiver_flush_location text,
|
||||
OUT receiver_replay_location text,
|
||||
OUT sync_percent text,
|
||||
OUT sync_state text,
|
||||
OUT sync_group integer,
|
||||
OUT sync_priority integer,
|
||||
OUT sync_most_available text,
|
||||
OUT channel text
|
||||
) RETURNS SETOF record
|
||||
STABLE NOT FENCED NOT SHIPPABLE ROWS 10
|
||||
LANGUAGE internal AS 'pg_stat_get_wal_senders';
|
||||
end if;
|
||||
END$$;
|
||||
SET LOCAL inplace_upgrade_next_system_object_oids = IUO_PROC, 0;
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
-- for any x group
|
||||
DO $$
|
||||
DECLARE
|
||||
ans boolean;
|
||||
BEGIN
|
||||
select case when working_version_num()=92301 then true else false end as ans into ans;
|
||||
if ans = false then
|
||||
DROP FUNCTION IF EXISTS pg_catalog.pg_stat_get_wal_senders() CASCADE;
|
||||
SET LOCAL inplace_upgrade_next_system_object_oids = IUO_PROC, 3099;
|
||||
CREATE FUNCTION pg_catalog.pg_stat_get_wal_senders(
|
||||
OUT pid bigint,
|
||||
OUT sender_pid integer,
|
||||
OUT local_role text,
|
||||
OUT peer_role text,
|
||||
OUT peer_state text,
|
||||
OUT state text,
|
||||
OUT catchup_start timestamp with time zone,
|
||||
OUT catchup_end timestamp with time zone,
|
||||
OUT sender_sent_location text,
|
||||
OUT sender_write_location text,
|
||||
OUT sender_flush_location text,
|
||||
OUT sender_replay_location text,
|
||||
OUT receiver_received_location text,
|
||||
OUT receiver_write_location text,
|
||||
OUT receiver_flush_location text,
|
||||
OUT receiver_replay_location text,
|
||||
OUT sync_percent text,
|
||||
OUT sync_state text,
|
||||
OUT sync_group integer,
|
||||
OUT sync_priority integer,
|
||||
OUT sync_most_available text,
|
||||
OUT channel text
|
||||
) RETURNS SETOF record
|
||||
STABLE NOT FENCED NOT SHIPPABLE ROWS 10
|
||||
LANGUAGE internal AS 'pg_stat_get_wal_senders';
|
||||
end if;
|
||||
END$$;
|
||||
SET LOCAL inplace_upgrade_next_system_object_oids = IUO_PROC, 0;
|
||||
|
|
@ -238,7 +238,7 @@ typedef struct knl_session_attr_sql {
|
|||
#ifndef ENABLE_MULTIPLE_NODES
|
||||
bool enable_custom_parser;
|
||||
#endif
|
||||
bool dolphin;
|
||||
bool b_sql_plugin;
|
||||
} knl_session_attr_sql;
|
||||
|
||||
#endif /* SRC_INCLUDE_KNL_KNL_SESSION_ATTR_SQL */
|
||||
|
|
|
|||
|
|
@ -31,7 +31,6 @@
|
|||
#include "access/extreme_rto/spsc_blocking_queue.h"
|
||||
#include "access/parallel_recovery/redo_item.h"
|
||||
|
||||
#include "nodes/parsenodes_common.h"
|
||||
#include "nodes/replnodes.h"
|
||||
#include "access/ustore/knl_utuple.h"
|
||||
#include "replication/logical_queue.h"
|
||||
|
|
|
|||
|
|
@ -13,6 +13,5 @@
|
|||
#define LOGICALWORKER_H
|
||||
|
||||
extern void ApplyWorkerMain();
|
||||
extern bool IsLogicalWorker(void);
|
||||
|
||||
#endif /* LOGICALWORKER_H */
|
||||
|
|
|
|||
|
|
@ -229,15 +229,10 @@ private:
|
|||
bool m_syscache_relids[FirstNormalObjectId];
|
||||
|
||||
};
|
||||
void NotifyGscRecoveryStarted();
|
||||
void NotifyGscRecoveryFinished();
|
||||
extern Datum gs_gsc_dbstat_info(PG_FUNCTION_ARGS);
|
||||
extern Datum gs_gsc_clean(PG_FUNCTION_ARGS);
|
||||
extern Datum gs_gsc_catalog_detail(PG_FUNCTION_ARGS);
|
||||
extern Datum gs_gsc_table_detail(PG_FUNCTION_ARGS);
|
||||
extern int ResizeHashBucket(int origin_nbucket, DynamicHashBucketStrategy strategy);
|
||||
|
||||
/* only primary node check recovery, recovery from upgrade may have misorder cacheids */
|
||||
#define IsPrimaryRecoveryFinished() \
|
||||
(g_instance.global_sysdbcache.recovery_finished || t_thrd.postmaster_cxt.HaShmData->current_mode == STANDBY_MODE)
|
||||
#endif
|
||||
#endif
|
||||
|
|
@ -213,7 +213,7 @@ extern bool check_rel_is_partitioned(Oid relid);
|
|||
extern Oid partid_get_parentid(Oid partid);
|
||||
extern bool is_not_strict_agg(Oid funcOid);
|
||||
extern bool is_pgxc_class_table(Oid tableoid);
|
||||
extern Oid get_valid_relname_relid(const char* relnamespace, const char* relname, bool nsp_missing_ok = false);
|
||||
extern Oid get_valid_relname_relid(const char* relnamespace, const char* relname);
|
||||
extern bool get_func_iswindow(Oid funcid);
|
||||
extern char get_func_prokind(Oid funcid);
|
||||
extern char get_typecategory(Oid typid);
|
||||
|
|
|
|||
|
|
@ -1385,8 +1385,6 @@ typedef struct PlDebugEntry {
|
|||
PLpgSQL_function* func;
|
||||
} PlDebugEntry;
|
||||
|
||||
typedef List* (*RawParserHook)(const char*, List**);
|
||||
|
||||
const int MAXINT8LEN = 25;
|
||||
const int DEFAULT_DEBUG_BUF_SIZE = 1024;
|
||||
const long NANOSECOND_PER_SECOND = 1000000000L; /* 1s */
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
# src/test/ipv6/create_server.py
|
||||
#
|
||||
# ---------------------------------------------------------------------------------------
|
||||
# 增加注释
|
||||
|
||||
import getopt, sys, os
|
||||
import shutil
|
||||
import time
|
||||
|
|
|
|||
|
|
@ -1,37 +0,0 @@
|
|||
--
|
||||
-- check for over-optimization of whole-row Var referencing an Append plan
|
||||
--
|
||||
create table int4_test(f1 int4);
|
||||
select (select q from (select 1,2,3 where f1>0 union all select 4,5,6 where f1<=0) q) from int4_test;
|
||||
q
|
||||
---
|
||||
(0 rows)
|
||||
|
||||
select (select q from (select 1,2,3 where f1>0 union all select 4,5,6.0 where f1<=0) q) from int4_test;
|
||||
q
|
||||
---
|
||||
(0 rows)
|
||||
|
||||
insert into int4_test(f1) values(' 0 ');
|
||||
insert into int4_test(f1) values('123456 ');
|
||||
select * from int4_test;
|
||||
f1
|
||||
--------
|
||||
0
|
||||
123456
|
||||
(2 rows)
|
||||
|
||||
select (select q from (select 1,2,3 where f1>0 union all select 4,5,6 where f1<=0) q) from int4_test;
|
||||
q
|
||||
---------
|
||||
(4,5,6)
|
||||
(1,2,3)
|
||||
(2 rows)
|
||||
|
||||
select (select q from (select 1,2,3 where f1>0 union all select 4,5,6.0 where f1<=0) q) from int4_test;
|
||||
q
|
||||
-----------
|
||||
(4,5,6.0)
|
||||
(1,2,3)
|
||||
(2 rows)
|
||||
|
||||
|
|
@ -1,116 +0,0 @@
|
|||
create schema deserialize_func1;
|
||||
set current_schema = deserialize_func1;
|
||||
create sequence test_seq;
|
||||
create or replace function test_func() return int
|
||||
as
|
||||
begin
|
||||
return 1;
|
||||
end;
|
||||
/
|
||||
create table t1(key int, id int default nextval('test_seq'));
|
||||
create table t2(key int, id int default test_func());
|
||||
select * from pg_get_tabledef('deserialize_func1.t1');
|
||||
pg_get_tabledef
|
||||
------------------------------------------------------
|
||||
SET search_path = deserialize_func1; +
|
||||
CREATE TABLE t1 ( +
|
||||
key integer, +
|
||||
id integer DEFAULT nextval('test_seq'::regclass)+
|
||||
) +
|
||||
WITH (orientation=row, compression=no);
|
||||
(1 row)
|
||||
|
||||
select * from pg_get_tabledef('deserialize_func1.t2');
|
||||
pg_get_tabledef
|
||||
-----------------------------------------
|
||||
SET search_path = deserialize_func1; +
|
||||
CREATE TABLE t2 ( +
|
||||
key integer, +
|
||||
id integer DEFAULT test_func() +
|
||||
) +
|
||||
WITH (orientation=row, compression=no);
|
||||
(1 row)
|
||||
|
||||
alter schema deserialize_func1 rename to deserialize_func2;
|
||||
select * from pg_get_tabledef('deserialize_func2.t1');
|
||||
pg_get_tabledef
|
||||
------------------------------------------------------------------------
|
||||
SET search_path = deserialize_func2; +
|
||||
CREATE TABLE t1 ( +
|
||||
key integer, +
|
||||
id integer DEFAULT nextval('deserialize_func2.test_seq'::regclass)+
|
||||
) +
|
||||
WITH (orientation=row, compression=no);
|
||||
(1 row)
|
||||
|
||||
select * from pg_get_tabledef('deserialize_func2.t2');
|
||||
pg_get_tabledef
|
||||
------------------------------------------------------
|
||||
SET search_path = deserialize_func2; +
|
||||
CREATE TABLE t2 ( +
|
||||
key integer, +
|
||||
id integer DEFAULT deserialize_func2.test_func()+
|
||||
) +
|
||||
WITH (orientation=row, compression=no);
|
||||
(1 row)
|
||||
|
||||
alter table deserialize_func2.t1 alter column id drop default;
|
||||
alter table deserialize_func2.t1 alter column id set default nextval('deserialize_func2.test_seq');
|
||||
select * from pg_get_tabledef('deserialize_func2.t1');
|
||||
pg_get_tabledef
|
||||
------------------------------------------------------------------------
|
||||
SET search_path = deserialize_func2; +
|
||||
CREATE TABLE t1 ( +
|
||||
key integer, +
|
||||
id integer DEFAULT nextval('deserialize_func2.test_seq'::regclass)+
|
||||
) +
|
||||
WITH (orientation=row, compression=no);
|
||||
(1 row)
|
||||
|
||||
alter table deserialize_func2.t2 alter column id drop default;
|
||||
alter table deserialize_func2.t2 alter column id set default deserialize_func2.test_func();
|
||||
select * from pg_get_tabledef('deserialize_func2.t2');
|
||||
pg_get_tabledef
|
||||
------------------------------------------------------
|
||||
SET search_path = deserialize_func2; +
|
||||
CREATE TABLE t2 ( +
|
||||
key integer, +
|
||||
id integer DEFAULT deserialize_func2.test_func()+
|
||||
) +
|
||||
WITH (orientation=row, compression=no);
|
||||
(1 row)
|
||||
|
||||
set current_schema = deserialize_func2;
|
||||
create type type1 as (a int);
|
||||
create view v1 as select '(1)'::type1;
|
||||
alter type type1 rename to type2;
|
||||
select pg_get_viewdef('v1');
|
||||
pg_get_viewdef
|
||||
-------------------------------
|
||||
SELECT '(1)'::type2 AS type1;
|
||||
(1 row)
|
||||
|
||||
drop view v1 cascade;
|
||||
create table atest12 as select x as a, 10001-x as b from generate_series(1, 10000) x;
|
||||
create function func1(integer, integer) returns boolean as $$begin return $1 < $2; end $$ language plpgsql immutable;
|
||||
create operator <<< (procedure=func1, leftarg=integer, rightarg=integer, restrict=scalarltsel);
|
||||
create view atest12v as select * from atest12 where b <<< 5;
|
||||
select pg_get_viewdef('atest12v');
|
||||
pg_get_viewdef
|
||||
-------------------------------------------------
|
||||
SELECT * FROM atest12 WHERE (atest12.b <<< 5);
|
||||
(1 row)
|
||||
|
||||
drop schema if exists deserialize_func1 cascade;
|
||||
NOTICE: schema "deserialize_func1" does not exist, skipping
|
||||
drop schema if exists deserialize_func2 cascade;
|
||||
NOTICE: drop cascades to 9 other objects
|
||||
DETAIL: drop cascades to sequence test_seq
|
||||
drop cascades to function test_func()
|
||||
drop cascades to table t1
|
||||
drop cascades to table t2
|
||||
drop cascades to type type2
|
||||
drop cascades to table atest12
|
||||
drop cascades to function func1(integer,integer)
|
||||
drop cascades to operator <<<(integer,integer)
|
||||
drop cascades to view atest12v
|
||||
|
|
@ -132,14 +132,11 @@ DROP EXTENSION test_extension_exists;
|
|||
ERROR: extension "test_extension_exists" does not exist
|
||||
DROP EXTENSION IF EXISTS test_extension_exists;
|
||||
NOTICE: extension "test_extension_exists" does not exist, skipping
|
||||
-- only extension in white list support drop, but the guc support_extended_features is true in pg_regress mode, so hdfs_fdw can be droped
|
||||
CREATE DATABASE ext_test_db;
|
||||
\c ext_test_db
|
||||
DROP EXTENSION hdfs_fdw;
|
||||
DROP EXTENSION IF EXISTS hdfs_fdw;
|
||||
NOTICE: extension "hdfs_fdw" does not exist, skipping
|
||||
\c regression
|
||||
DROP DATABASE ext_test_db;
|
||||
-- exists but doesn't support drop
|
||||
DROP EXTENSION plpgsql;
|
||||
ERROR: EXTENSION is not yet supported.
|
||||
DROP EXTENSION IF EXISTS plpgsql;
|
||||
ERROR: EXTENSION is not yet supported.
|
||||
-- functions
|
||||
DROP FUNCTION test_function_exists();
|
||||
ERROR: function test_function_exists does not exist
|
||||
|
|
|
|||
|
|
@ -215,107 +215,3 @@ select * from interval_normal_exchange where logdate > '2020-06-01' order by log
|
|||
(0 rows)
|
||||
|
||||
drop table interval_normal_exchange;
|
||||
drop table table_001;
|
||||
ERROR: table "table_001" does not exist
|
||||
create table table_001(
|
||||
COL_1 smallint,
|
||||
COL_2 char(5),
|
||||
COL_3 int,
|
||||
COL_4 date,
|
||||
COL_5 boolean,
|
||||
COL_6 nchar(5),
|
||||
COL_7 float
|
||||
);
|
||||
drop table partition_table_001;
|
||||
ERROR: table "partition_table_001" does not exist
|
||||
create table partition_table_001(
|
||||
COL_1 smallint,
|
||||
COL_2 char(5),
|
||||
COL_3 int,
|
||||
COL_4 date,
|
||||
COL_5 boolean,
|
||||
COL_6 nchar(5),
|
||||
COL_7 float
|
||||
)
|
||||
PARTITION BY RANGE (COL_4)
|
||||
INTERVAL ('1 month')
|
||||
(
|
||||
PARTITION partition_table_001_p1 VALUES LESS THAN ('2020-03-01'),
|
||||
PARTITION partition_table_001_p2 VALUES LESS THAN ('2020-04-01'),
|
||||
PARTITION partition_table_001_p3 VALUES LESS THAN ('2020-05-01')
|
||||
);
|
||||
insert into partition_table_001 values (1,'aaa',1,'2020-02-23',true,'aaa',1.1);
|
||||
insert into partition_table_001 values (2,'bbb',2,'2020-03-23',false,'bbb',2.2);
|
||||
insert into partition_table_001 values (3,'ccc',3,'2020-04-23',true,'ccc',3.3);
|
||||
insert into partition_table_001 values (4,'ddd',4,'2020-05-23',false,'ddd',4.4);
|
||||
insert into partition_table_001 values (5,'eee',5,'2020-06-23',true,'eee',5.5);
|
||||
insert into partition_table_001 values (6,'fff',6,'2020-07-23',false,'fff',6.6);
|
||||
ALTER TABLE partition_table_001 EXCHANGE PARTITION (sys_p1) WITH TABLE table_001;
|
||||
select * from table_001 order by 1;
|
||||
col_1 | col_2 | col_3 | col_4 | col_5 | col_6 | col_7
|
||||
-------+-------+-------+--------------------------+-------+-------+-------
|
||||
4 | ddd | 4 | Sat May 23 00:00:00 2020 | f | ddd | 4.4
|
||||
(1 row)
|
||||
|
||||
select * from partition_table_001 order by 1;
|
||||
col_1 | col_2 | col_3 | col_4 | col_5 | col_6 | col_7
|
||||
-------+-------+-------+--------------------------+-------+-------+-------
|
||||
1 | aaa | 1 | Sun Feb 23 00:00:00 2020 | t | aaa | 1.1
|
||||
2 | bbb | 2 | Mon Mar 23 00:00:00 2020 | f | bbb | 2.2
|
||||
3 | ccc | 3 | Thu Apr 23 00:00:00 2020 | t | ccc | 3.3
|
||||
5 | eee | 5 | Tue Jun 23 00:00:00 2020 | t | eee | 5.5
|
||||
6 | fff | 6 | Thu Jul 23 00:00:00 2020 | f | fff | 6.6
|
||||
(5 rows)
|
||||
|
||||
select relname, parttype, partstrategy, boundaries from pg_partition
|
||||
where parentid = (select oid from pg_class where relname = 'partition_table_001')
|
||||
order by relname;
|
||||
relname | parttype | partstrategy | boundaries
|
||||
------------------------+----------+--------------+------------------------------
|
||||
partition_table_001 | r | i |
|
||||
partition_table_001_p1 | p | r | {2020-03-01}
|
||||
partition_table_001_p2 | p | r | {2020-04-01}
|
||||
partition_table_001_p3 | p | r | {2020-05-01}
|
||||
sys_p1 | p | i | {"Mon Jun 01 00:00:00 2020"}
|
||||
sys_p2 | p | i | {"Wed Jul 01 00:00:00 2020"}
|
||||
sys_p3 | p | i | {"Sat Aug 01 00:00:00 2020"}
|
||||
(7 rows)
|
||||
|
||||
ALTER TABLE partition_table_001 EXCHANGE PARTITION (sys_p1) WITH TABLE table_001;
|
||||
select * from table_001 order by 1;
|
||||
col_1 | col_2 | col_3 | col_4 | col_5 | col_6 | col_7
|
||||
-------+-------+-------+-------+-------+-------+-------
|
||||
(0 rows)
|
||||
|
||||
select * from partition_table_001 order by 1;
|
||||
col_1 | col_2 | col_3 | col_4 | col_5 | col_6 | col_7
|
||||
-------+-------+-------+--------------------------+-------+-------+-------
|
||||
1 | aaa | 1 | Sun Feb 23 00:00:00 2020 | t | aaa | 1.1
|
||||
2 | bbb | 2 | Mon Mar 23 00:00:00 2020 | f | bbb | 2.2
|
||||
3 | ccc | 3 | Thu Apr 23 00:00:00 2020 | t | ccc | 3.3
|
||||
4 | ddd | 4 | Sat May 23 00:00:00 2020 | f | ddd | 4.4
|
||||
5 | eee | 5 | Tue Jun 23 00:00:00 2020 | t | eee | 5.5
|
||||
6 | fff | 6 | Thu Jul 23 00:00:00 2020 | f | fff | 6.6
|
||||
(6 rows)
|
||||
|
||||
insert into table_001 values (7,'eee',7,'2020-08-23',true,'eee',7.7);
|
||||
ALTER TABLE partition_table_001 EXCHANGE PARTITION (sys_p1) WITH TABLE table_001 with validation verbose;
|
||||
select * from table_001 order by 1;
|
||||
col_1 | col_2 | col_3 | col_4 | col_5 | col_6 | col_7
|
||||
-------+-------+-------+--------------------------+-------+-------+-------
|
||||
4 | ddd | 4 | Sat May 23 00:00:00 2020 | f | ddd | 4.4
|
||||
(1 row)
|
||||
|
||||
select * from partition_table_001 order by 1;
|
||||
col_1 | col_2 | col_3 | col_4 | col_5 | col_6 | col_7
|
||||
-------+-------+-------+--------------------------+-------+-------+-------
|
||||
1 | aaa | 1 | Sun Feb 23 00:00:00 2020 | t | aaa | 1.1
|
||||
2 | bbb | 2 | Mon Mar 23 00:00:00 2020 | f | bbb | 2.2
|
||||
3 | ccc | 3 | Thu Apr 23 00:00:00 2020 | t | ccc | 3.3
|
||||
5 | eee | 5 | Tue Jun 23 00:00:00 2020 | t | eee | 5.5
|
||||
6 | fff | 6 | Thu Jul 23 00:00:00 2020 | f | fff | 6.6
|
||||
7 | eee | 7 | Sun Aug 23 00:00:00 2020 | t | eee | 7.7
|
||||
(6 rows)
|
||||
|
||||
drop table table_001;
|
||||
drop table partition_table_001;
|
||||
|
|
|
|||
|
|
@ -1,55 +0,0 @@
|
|||
CREATE TABLE t11 (
|
||||
sec_code character(6) NOT NULL,
|
||||
issue_type character(3) NOT NULL
|
||||
);
|
||||
CREATE TABLE t22 (
|
||||
company_code character(6) NOT NULL,
|
||||
list_profit_flag character(1) NOT NULL
|
||||
);
|
||||
CREATE TABLE t33 (
|
||||
company_code character(6) NOT NULL,
|
||||
issue_flag character(6) NOT NULL
|
||||
);
|
||||
insert into t11 values(1,'S04');
|
||||
insert into t22 values(1,'Y');
|
||||
insert into t33 values(1,'1');
|
||||
insert into t33 values(2,'2');
|
||||
select
|
||||
T5.issue_type
|
||||
,T6.is_type
|
||||
from
|
||||
(
|
||||
select T1.sec_code
|
||||
,issue_type
|
||||
--,case when list_profit_flag='Y' then '是' else '否' end as list_profit_flag
|
||||
from
|
||||
(
|
||||
select sec_code
|
||||
,case when issue_type in ('S04','S05','S06','S09') then '增发'
|
||||
when issue_type in ('S01','S02') then '首发'
|
||||
else '其他' end as issue_type
|
||||
from t11
|
||||
)T1
|
||||
left join
|
||||
(
|
||||
select list_profit_flag
|
||||
,company_code
|
||||
from t22
|
||||
)T2
|
||||
on T1.sec_code=T2.company_code
|
||||
)T5
|
||||
full join
|
||||
(
|
||||
SELECT CASE
|
||||
WHEN issue_flag = ANY (ARRAY['1'::bpchar, '3'::bpchar, '11'::bpchar]) THEN '首发'::text
|
||||
ELSE '增发'::text
|
||||
END AS is_type from t33
|
||||
)T6
|
||||
on T5.issue_type=T6.is_type
|
||||
;
|
||||
issue_type | is_type
|
||||
------------+---------
|
||||
增发 | 增发
|
||||
| 首发
|
||||
(2 rows)
|
||||
|
||||
|
|
@ -89,8 +89,5 @@ ERROR: Can not use compress option in ustore index.
|
|||
-- segment
|
||||
CREATE TABLE unspported_feature.segment_table(id int, c1 text) WITH(compresstype=2, segment=on); --failed
|
||||
ERROR: only row orientation table support compresstype.
|
||||
CREATE INDEX on unspported_feature.index_test(c1) WITH(compresstype=2, segment=on); --failed
|
||||
CREATE INDEX on unspported_feature.index_test(c1) WITH(compresstype=2, segment=on); --faled
|
||||
ERROR: Can not use compress option in segment storage.
|
||||
-- set compress_diff_convert
|
||||
create table unspported_feature.compress_byte_test(id int) with (compresstype=2, compress_byte_convert=false, compress_diff_convert = true); -- failed
|
||||
ERROR: compress_diff_convert should be used with compress_byte_convert.
|
||||
|
|
|
|||
|
|
@ -1062,73 +1062,6 @@ select /*+ indexscan(tg_hash i_tg_hash_local_a) */ * from tg_hash where a < 9;
|
|||
(81 rows)
|
||||
|
||||
drop table tg_hash;
|
||||
drop table if exists test_ugi_045;
|
||||
NOTICE: table "test_ugi_045" does not exist, skipping
|
||||
create table test_ugi_045
|
||||
(
|
||||
c_id integer not null,
|
||||
c_date DATE,
|
||||
c_info varchar(20) not null
|
||||
)
|
||||
partition by range(c_date)
|
||||
interval('2 day')
|
||||
(
|
||||
partition p1 values less than ('2021-06-01 00:00:00'),
|
||||
partition p2 values less than ('2021-06-03 00:00:00'),
|
||||
partition p3 values less than ('2021-06-05 00:00:00'),
|
||||
partition p4 values less than ('2021-06-07 00:00:00'),
|
||||
partition p5 values less than ('2021-06-09 00:00:00')
|
||||
);
|
||||
insert into test_ugi_045(c_id, c_date, c_info) values(1, '2021-05-30 00:00:00', '1-1');
|
||||
insert into test_ugi_045(c_id, c_date, c_info) values(2, '2021-05-31 00:00:00', '1-1');
|
||||
insert into test_ugi_045(c_id, c_date, c_info) values(3, '2021-06-01 00:00:00', '1-1');
|
||||
insert into test_ugi_045(c_id, c_date, c_info) values(4, '2021-06-02 00:00:00', '1-2');
|
||||
insert into test_ugi_045(c_id, c_date, c_info) values(5, '2021-06-03 00:00:00', '1-2');
|
||||
insert into test_ugi_045(c_id, c_date, c_info) values(6, '2021-06-04 00:00:00', '1-3');
|
||||
insert into test_ugi_045(c_id, c_date, c_info) values(7, '2021-06-05 00:00:00', '1-3');
|
||||
insert into test_ugi_045(c_id, c_date, c_info) values(8, '2021-06-06 00:00:00', '1-4');
|
||||
insert into test_ugi_045(c_id, c_date, c_info) values(9, '2021-06-07 00:00:00', '1-4');
|
||||
insert into test_ugi_045(c_id, c_date, c_info) values(10, '2021-06-08 00:00:00', '1-5');
|
||||
create index global_index_id_045 on test_ugi_045(c_date) global;
|
||||
create index global_index_info_045 on test_ugi_045(c_info) global;
|
||||
select *from test_ugi_045;
|
||||
c_id | c_date | c_info
|
||||
------+---------------------+--------
|
||||
1 | 2021-05-30 00:00:00 | 1-1
|
||||
2 | 2021-05-31 00:00:00 | 1-1
|
||||
3 | 2021-06-01 00:00:00 | 1-1
|
||||
4 | 2021-06-02 00:00:00 | 1-2
|
||||
5 | 2021-06-03 00:00:00 | 1-2
|
||||
6 | 2021-06-04 00:00:00 | 1-3
|
||||
7 | 2021-06-05 00:00:00 | 1-3
|
||||
8 | 2021-06-06 00:00:00 | 1-4
|
||||
9 | 2021-06-07 00:00:00 | 1-4
|
||||
10 | 2021-06-08 00:00:00 | 1-5
|
||||
(10 rows)
|
||||
|
||||
alter table test_ugi_045 truncate partition p3 update global index;
|
||||
set enable_seqscan = off;
|
||||
set enable_bitmapscan = off;
|
||||
select *from test_ugi_045;
|
||||
c_id | c_date | c_info
|
||||
------+---------------------+--------
|
||||
1 | 2021-05-30 00:00:00 | 1-1
|
||||
2 | 2021-05-31 00:00:00 | 1-1
|
||||
3 | 2021-06-01 00:00:00 | 1-1
|
||||
4 | 2021-06-02 00:00:00 | 1-2
|
||||
7 | 2021-06-05 00:00:00 | 1-3
|
||||
8 | 2021-06-06 00:00:00 | 1-4
|
||||
9 | 2021-06-07 00:00:00 | 1-4
|
||||
10 | 2021-06-08 00:00:00 | 1-5
|
||||
(8 rows)
|
||||
|
||||
select *from test_ugi_045 where c_info = '1-2';
|
||||
c_id | c_date | c_info
|
||||
------+---------------------+--------
|
||||
4 | 2021-06-02 00:00:00 | 1-2
|
||||
(1 row)
|
||||
|
||||
drop table if exists test_ugi_045;
|
||||
-- 清理过程
|
||||
drop view check_truncate_results;
|
||||
drop materialized view pg_partition_before_truncate;
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ test: pldeveloper_gs_source
|
|||
test: index_advisor
|
||||
test: pl_debugger_server pl_debugger_client
|
||||
test: update_for_wait_s1 update_for_wait_s2
|
||||
test: plan_hint plan_hint_set plan_hint_no_expand plan_hint_iud null_test_opt deserialize_func
|
||||
test: plan_hint plan_hint_set plan_hint_no_expand plan_hint_iud null_test_opt
|
||||
test: large_sequence int16 gs_dump_sequence
|
||||
test: gs_dump_tableof
|
||||
test: analyze_commands
|
||||
|
|
@ -916,5 +916,3 @@ test: fdw_audit
|
|||
test: gs_global_config_audit
|
||||
test: detail
|
||||
test: gs_dump_encrypt
|
||||
test: composite_datum_record
|
||||
test: join_test_alias
|
||||
|
|
|
|||
|
|
@ -5238,7 +5238,7 @@ static void check_global_variables()
|
|||
}
|
||||
}
|
||||
|
||||
#define BASE_PGXC_LIKE_MACRO_NUM 1402
|
||||
#define BASE_PGXC_LIKE_MACRO_NUM 1401
|
||||
static void check_pgxc_like_macros()
|
||||
{
|
||||
#ifdef BUILD_BY_CMAKE
|
||||
|
|
|
|||
|
|
@ -1,11 +0,0 @@
|
|||
--
|
||||
-- check for over-optimization of whole-row Var referencing an Append plan
|
||||
--
|
||||
create table int4_test(f1 int4);
|
||||
select (select q from (select 1,2,3 where f1>0 union all select 4,5,6 where f1<=0) q) from int4_test;
|
||||
select (select q from (select 1,2,3 where f1>0 union all select 4,5,6.0 where f1<=0) q) from int4_test;
|
||||
insert into int4_test(f1) values(' 0 ');
|
||||
insert into int4_test(f1) values('123456 ');
|
||||
select * from int4_test;
|
||||
select (select q from (select 1,2,3 where f1>0 union all select 4,5,6 where f1<=0) q) from int4_test;
|
||||
select (select q from (select 1,2,3 where f1>0 union all select 4,5,6.0 where f1<=0) q) from int4_test;
|
||||
|
|
@ -1,63 +0,0 @@
|
|||
create schema deserialize_func1;
|
||||
set current_schema = deserialize_func1;
|
||||
|
||||
create sequence test_seq;
|
||||
|
||||
create or replace function test_func() return int
|
||||
as
|
||||
begin
|
||||
return 1;
|
||||
end;
|
||||
/
|
||||
|
||||
create table t1(key int, id int default nextval('test_seq'));
|
||||
|
||||
create table t2(key int, id int default test_func());
|
||||
|
||||
select * from pg_get_tabledef('deserialize_func1.t1');
|
||||
|
||||
select * from pg_get_tabledef('deserialize_func1.t2');
|
||||
|
||||
alter schema deserialize_func1 rename to deserialize_func2;
|
||||
|
||||
select * from pg_get_tabledef('deserialize_func2.t1');
|
||||
|
||||
select * from pg_get_tabledef('deserialize_func2.t2');
|
||||
|
||||
alter table deserialize_func2.t1 alter column id drop default;
|
||||
|
||||
alter table deserialize_func2.t1 alter column id set default nextval('deserialize_func2.test_seq');
|
||||
|
||||
select * from pg_get_tabledef('deserialize_func2.t1');
|
||||
|
||||
alter table deserialize_func2.t2 alter column id drop default;
|
||||
|
||||
alter table deserialize_func2.t2 alter column id set default deserialize_func2.test_func();
|
||||
|
||||
select * from pg_get_tabledef('deserialize_func2.t2');
|
||||
|
||||
set current_schema = deserialize_func2;
|
||||
|
||||
create type type1 as (a int);
|
||||
|
||||
create view v1 as select '(1)'::type1;
|
||||
|
||||
alter type type1 rename to type2;
|
||||
|
||||
select pg_get_viewdef('v1');
|
||||
|
||||
drop view v1 cascade;
|
||||
|
||||
create table atest12 as select x as a, 10001-x as b from generate_series(1, 10000) x;
|
||||
|
||||
create function func1(integer, integer) returns boolean as $$begin return $1 < $2; end $$ language plpgsql immutable;
|
||||
|
||||
create operator <<< (procedure=func1, leftarg=integer, rightarg=integer, restrict=scalarltsel);
|
||||
|
||||
create view atest12v as select * from atest12 where b <<< 5;
|
||||
|
||||
select pg_get_viewdef('atest12v');
|
||||
|
||||
drop schema if exists deserialize_func1 cascade;
|
||||
|
||||
drop schema if exists deserialize_func2 cascade;
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue