!1584 同步主线若干问题修复

Merge pull request !1584 from 杨皓/master
This commit is contained in:
opengauss-bot 2022-03-15 07:25:57 +00:00 committed by Gitee
commit 97bd39fcfa
No known key found for this signature in database
GPG Key ID: 173E9B9CA92EEF8F
247 changed files with 15106 additions and 11284 deletions

View File

@ -1151,7 +1151,6 @@ static void deparseRelation(StringInfo buf, Relation rel)
const char *nspname = NULL;
const char *relname = NULL;
ListCell *lc;
char parttype = PARTTYPE_NON_PARTITIONED_RELATION;
/* obtain additional catalog information. */
ForeignTable* table = GetForeignTable(RelationGetRelid(rel));
@ -1180,31 +1179,34 @@ static void deparseRelation(StringInfo buf, Relation rel)
relname = RelationGetRelationName(rel);
}
/* foreign table could not be built from a partitioned table */
UserMapping* user = GetUserMapping(rel->rd_rel->relowner, table->serverid);
ForeignServer *server = GetForeignServer(table->serverid);
PGconn* conn = GetConnection(server, user, false);
/* In current version, there are some unpredictable operations (delete/update, etc.) of foreign table built on
* partitioned table. We forbid all operations in this condition by default. */
if (!ENABLE_SQL_BETA_FEATURE(PARTITION_FDW_ON)) {
char parttype = PARTTYPE_NON_PARTITIONED_RELATION;
UserMapping* user = GetUserMapping(GetUserId(), table->serverid);
ForeignServer *server = GetForeignServer(table->serverid);
PGconn* conn = GetConnection(server, user, false);
PQExpBuffer query = createPQExpBuffer();
appendPQExpBuffer(query,
"SELECT c.parttype FROM pg_class c, pg_namespace n "
"WHERE c.relname = '%s' and c.relnamespace = n.oid and n.nspname = '%s'",
quote_identifier(relname), quote_identifier(nspname));
PQExpBuffer query = createPQExpBuffer();
appendPQExpBuffer(query,
"SELECT c.parttype FROM pg_class c, pg_namespace n "
"WHERE c.relname = '%s' and c.relnamespace = n.oid and n.nspname = '%s'",
quote_identifier(relname), quote_identifier(nspname));
PGresult* res = pgfdw_exec_query(conn, query->data);
if (PQresultStatus(res) != PGRES_TUPLES_OK) {
pgfdw_report_error(ERROR, res, conn, true, query->data);
}
/* res may be empty as the relname/nspname validation is not checked */
if (PQntuples(res) > 0) {
parttype = *PQgetvalue(res, 0, 0);
}
PQclear(res);
destroyPQExpBuffer(query);
PGresult* res = pgfdw_exec_query(conn, query->data);
if (PQresultStatus(res) != PGRES_TUPLES_OK) {
pgfdw_report_error(ERROR, res, conn, true, query->data);
}
/* res may be empty as the relname/nspname validation is not checked */
if (PQntuples(res) > 0) {
parttype = *PQgetvalue(res, 0, 0);
}
PQclear(res);
destroyPQExpBuffer(query);
if (!ENABLE_SQL_BETA_FEATURE(PARTITION_FDW_ON) &&
(parttype == PARTTYPE_PARTITIONED_RELATION || parttype == PARTTYPE_SUBPARTITIONED_RELATION)) {
ereport(ERROR, (errmsg("could not operate foreign table on partitioned table")));
if ((parttype == PARTTYPE_PARTITIONED_RELATION || parttype == PARTTYPE_SUBPARTITIONED_RELATION)) {
ereport(ERROR, (errmsg("could not operate foreign table on partitioned table")));
}
}
appendStringInfo(buf, "%s.%s", quote_identifier(nspname), quote_identifier(relname));

View File

@ -80,6 +80,7 @@ For example:
* verbose: 0 (no output), 1 (less output), or 2 (full output)
# Hyperparameter list for 'xgboost_regression_logistic', 'xgboost_binary_logistic', 'xgboost_regression_gamma' and 'xgboost_regression_squarederror':
* n_iter: Maximum iterations until convergence
* batch_size: Number of tuples in each processing batch
* booster: Which booster to use, e.g., gbtree, gblinear or dart (default: gbtree)
* tree_method: The tree construction algorithm used in XGBoost. Choices: auto, exact, approx, hist, gpu_hist (gpu_hist only supported with GPU)

View File

@ -2547,10 +2547,6 @@ int main(int argc, char** argv)
hba_param = ((char**)pg_malloc_zero(arraysize * sizeof(char *)));
config_value = ((char**)pg_malloc_zero(arraysize * sizeof(char*)));
}
if (false == allocate_memory_list()) {
write_stderr(_("ERROR: Failed to allocate memory to list.\n"));
exit(1);
}
key_mode = SERVER_MODE;
/*
@ -2769,8 +2765,54 @@ int main(int argc, char** argv)
do_advice();
exit(1);
}
char arguments[MAX_BUF_SIZE] = {0x00};
for (int i = 0; i < argc; i++) {
if ((strlen(arguments) + strlen(argv[i])) >= (MAX_BUF_SIZE - 2)) {
if (*arguments) {
(void)write_log("The gs_guc run with the following arguments: [%s].\n", arguments);
}
(void)write_log("The gs_guc run with the following arguments: [%s].\n", argv[i]);
rc = memset_s(arguments, MAX_BUF_SIZE, 0, MAX_BUF_SIZE - 1);
securec_check_c(rc, "\0", "\0");
continue;
}
errno_t rc = strcat_s(arguments, MAX_BUF_SIZE, argv[i]);
size_t len = strlen(arguments);
if (rc != EOK) {
break;
}
arguments[len] = ' ';
arguments[len + 1] = '\0';
}
if (*arguments) {
(void)write_log("The gs_guc run with the following arguments: [%s].\n", arguments);
}
check_encrypt_options();
if (ctl_command == ENCRYPT_KEY_COMMAND) {
process_encrypt_cmd(pgdata_D, pgdata_C, pgdata_R);
(void)write_log("gs_guc encrypt %s\n", loginfo);
} else if (ctl_command == GENERATE_KEY_COMMAND) {
doGenerateOperation(pgdata_D, loginfo);
}
if (ctl_command == ENCRYPT_KEY_COMMAND || ctl_command == GENERATE_KEY_COMMAND) {
GS_FREE(g_prefix);
GS_FREE(g_plainkey);
GS_FREE(g_cipherkey);
GS_FREE(key_username);
GS_FREE(pgdata_D);
GS_FREE(pgdata_R);
GS_FREE(pgdata_C);
return 0;
}
if (false == allocate_memory_list()) {
write_stderr(_("ERROR: Failed to allocate memory to list.\n"));
exit(1);
}
if (ctl_command != ENCRYPT_KEY_COMMAND && ctl_command != GENERATE_KEY_COMMAND && (!bhave_param && !is_hba_conf)) {
write_stderr(_("%s: the form of this command is incorrect\n"), progname);
do_advice();
@ -2832,30 +2874,6 @@ int main(int argc, char** argv)
// log output redirect
init_log(PROG_NAME);
/* print the log about arguments of gs_guc */
char arguments[MAX_BUF_SIZE] = {0x00};
for (int i = 0; i < argc; i++) {
if ((strlen(arguments) + strlen(argv[i])) >= (MAX_BUF_SIZE - 2)) {
if (*arguments) {
(void)write_log("The gs_guc run with the following arguments: [%s].\n", arguments);
}
(void)write_log("The gs_guc run with the following arguments: [%s].\n", argv[i]);
rc = memset_s(arguments, MAX_BUF_SIZE, 0, MAX_BUF_SIZE - 1);
securec_check_c(rc, "\0", "\0");
continue;
}
errno_t rc = strcat_s(arguments, MAX_BUF_SIZE, argv[i]);
size_t len = strlen(arguments);
if (rc != EOK) {
break;
}
arguments[len] = ' ';
arguments[len + 1] = '\0';
}
if (*arguments) {
(void)write_log("The gs_guc run with the following arguments: [%s].\n", arguments);
}
if ((true == is_hba_conf) &&
((nodetype != INSTANCE_COORDINATOR) && (nodetype != INSTANCE_DATANODE))) {
write_stderr(_("%s: authentication operation (-h) is not supported for \"gtm\" or \"gtm_proxy\"\n"), progname);
@ -2863,54 +2881,38 @@ int main(int argc, char** argv)
exit(1);
}
if (ctl_command == ENCRYPT_KEY_COMMAND) {
process_encrypt_cmd(pgdata_D, pgdata_C, pgdata_R);
(void)write_log("gs_guc encrypt %s\n", loginfo);
} else if (ctl_command == GENERATE_KEY_COMMAND) {
doGenerateOperation(pgdata_D, loginfo);
} else {
// the number of -Z is equal to 2
if (node_type_number == LARGE_INSTANCE_NUM) {
if (node_type_value[0] == node_type_value[1]) {
(void)write_stderr("When the number of -Z is equal to 2, the value must be different.\n");
exit(1);
}
for (int index = 0; index < LARGE_INSTANCE_NUM; index++) {
if (node_type_value[index] != INSTANCE_COORDINATOR && node_type_value[index] != INSTANCE_DATANODE) {
(void)write_stderr("ERROR: When the number of -Z is equal to 2, the parameter value of -Z must be "
"coordinator or datanode.\n");
exit(1);
}
checkLcName(node_type_value[index]);
}
nodetype = INSTANCE_COORDINATOR;
if (0 != validate_cluster_guc_options(nodename, nodetype, instance_name, pgdata_D)) {
exit(1);
}
process_cluster_guc_option(nodename, nodetype, instance_name, pgdata_D);
} else {
checkLcName(nodetype);
if (0 != validate_cluster_guc_options(nodename, nodetype, instance_name, pgdata_D)) {
exit(1);
}
process_cluster_guc_option(nodename, nodetype, instance_name, pgdata_D);
// the number of -Z is equal to 2
if (node_type_number == LARGE_INSTANCE_NUM) {
if (node_type_value[0] == node_type_value[1]) {
(void)write_stderr("When the number of -Z is equal to 2, the value must be different.\n");
exit(1);
}
for (int index = 0; index < LARGE_INSTANCE_NUM; index++) {
if (node_type_value[index] != INSTANCE_COORDINATOR && node_type_value[index] != INSTANCE_DATANODE) {
(void)write_stderr("ERROR: When the number of -Z is equal to 2, the parameter value of -Z must be "
"coordinator or datanode.\n");
exit(1);
}
checkLcName(node_type_value[index]);
}
nodetype = INSTANCE_COORDINATOR;
if (0 != validate_cluster_guc_options(nodename, nodetype, instance_name, pgdata_D)) {
exit(1);
}
process_cluster_guc_option(nodename, nodetype, instance_name, pgdata_D);
} else {
checkLcName(nodetype);
if (0 != validate_cluster_guc_options(nodename, nodetype, instance_name, pgdata_D)) {
exit(1);
}
process_cluster_guc_option(nodename, nodetype, instance_name, pgdata_D);
}
GS_FREE(g_prefix);
GS_FREE(g_plainkey);
GS_FREE(g_cipherkey);
GS_FREE(key_username);
GS_FREE(pgdata_D);
GS_FREE(pgdata_R);
GS_FREE(pgdata_C);
GS_FREE(instance_name);
if (ctl_command == ENCRYPT_KEY_COMMAND || ctl_command == GENERATE_KEY_COMMAND)
return 0;
nRet = print_guc_result((const char*)nodename);
GS_FREE(nodename);
clear_g_incorrect_nodeInfo();

View File

@ -25,6 +25,7 @@
#include "bin/elog.h"
#include "nodes/pg_list.h"
#include "replication/replicainternal.h"
#include "storage/smgr/fd.h"
#include "utils/builtins.h"
#include "utils/datetime.h"
@ -64,6 +65,7 @@ char g_buildprimary_slotname[MAX_VALUE_LEN] = {0};
char g_str_replication_type[MAX_VALUE_LEN] = {0};
int g_replconn_idx = -1;
int g_replication_type = -1;
bool is_cross_region_build = false;
#define RT_WITH_DUMMY_STANDBY 0
#define RT_WITH_MULTI_STANDBY 1
@ -576,7 +578,9 @@ void get_conninfo(const char* filename)
exit(1);
}
if (IS_CROSS_CLUSTER_BUILD) {
if (build_mode == CROSS_CLUSTER_FULL_BUILD || build_mode == CROSS_CLUSTER_INC_BUILD ||
build_mode == CROSS_CLUSTER_STANDBY_FULL_BUILD) {
/* For shared storage cluster */
conninfo_para = config_para_cross_cluster_build;
} else {
conninfo_para = config_para_build;
@ -864,10 +868,11 @@ PGconn* check_and_conn(int conn_timeout, int recv_timeout, uint32 term)
tnRet = memset_s(repl_conninfo_str, MAXPGPATH, 0, MAXPGPATH);
securec_check_ss_c(tnRet, "", "");
is_cross_region_build = false;
if (register_username != NULL && register_password != NULL) {
if (*register_username == '.') {
register_username += 2;
}
}
tnRet = snprintf_s(repl_conninfo_str,
sizeof(repl_conninfo_str),
sizeof(repl_conninfo_str) - 1,
@ -882,6 +887,7 @@ PGconn* check_and_conn(int conn_timeout, int recv_timeout, uint32 term)
repl_conn_info.remoteport,
conn_timeout,
recv_timeout, register_username, register_password);
is_cross_region_build = true;
} else {
tnRet = snprintf_s(repl_conninfo_str,
sizeof(repl_conninfo_str),

View File

@ -244,7 +244,9 @@ bool SensitiveStrCheck(const char* target)
if (strstr(target_copy, "PASSWORD") != NULL || strstr(target_copy, "IDENTIFIED") != NULL ||
strstr(target_copy, "GS_ENCRYPT_AES128") != NULL || strstr(target_copy, "GS_DECRYPT_AES128") != NULL ||
strstr(target_copy, "GS_ENCRYPT") != NULL || strstr(target_copy, "GS_DECRYPT") != NULL) {
strstr(target_copy, "GS_ENCRYPT") != NULL || strstr(target_copy, "GS_DECRYPT") != NULL ||
strstr(target_copy, "PG_CREATE_PHYSICAL_REPLICATION_SLOT_EXTERN") != NULL ||
strstr(target_copy, "SECRETKEY") != NULL || strstr(target_copy, "CREATE_CREDENTIAL") != NULL) {
free(target_copy);
return TRUE;
} else {

View File

@ -46,8 +46,6 @@ PsqlSettings pset;
/* Used for change child process name in gsql parallel execute mode. */
char* argv_para;
int argv_num;
static int PASSWORD_STR_LEN = 9;
static bool dbname_alloced = false;
static bool is_pipeline = false;
static bool is_interactive = true;
#ifndef ENABLE_MULTIPLE_NODES
@ -630,6 +628,10 @@ int main(int argc, char* argv[])
/* Stored connection and guc info for new connections in gsql parallel mode. */
values_free[3] = true;
if (options.dbname != NULL) {
/* When we use a new dbname or exit the program, we need to free the value. */
values_free[4] = true; /* The dbname index is 4 */
}
pset.connInfo.keywords = keywords;
pset.connInfo.values = values;
@ -828,6 +830,12 @@ int main(int argc, char* argv[])
for (int i = 0; i < PARAMS_ARRAY_SIZE; i++) {
if (pset.connInfo.values_free[i] && NULL != pset.connInfo.values[i]) {
if (strlen(pset.connInfo.values[i]) != 0) {
/* Erase the connection information in the memory. */
rc = memset_s(pset.connInfo.values[i],
strlen(pset.connInfo.values[i]),
0,
strlen(pset.connInfo.values[i]));
securec_check_c(rc, "\0", "\0");
free(pset.connInfo.values[i]);
pset.connInfo.values[i] = NULL;
}
@ -859,13 +867,6 @@ int main(int argc, char* argv[])
ResetQueryRetryController();
EmptyRetryErrcodesList(pset.errcodes_list);
if (dbname_alloced) {
rc = memset_s(options.dbname, strlen(options.dbname), 0, strlen(options.dbname));
securec_check_c(rc, "\0", "\0");
free(options.dbname);
options.dbname = NULL;
}
return successResult;
}
@ -1014,7 +1015,7 @@ static void parse_psql_options(int argc, char* const argv[], struct adhoc_opts*
bool is_action_file = false;
/* Database Security: Data importing/dumping support AES128. */
char* dencrypt_key = NULL;
char* needmask = NULL;
char* dbname = NULL;
errno_t rc = EOK;
#ifdef USE_READLINE
useReadline = false;
@ -1054,9 +1055,7 @@ static void parse_psql_options(int argc, char* const argv[], struct adhoc_opts*
}
break;
case 'd':
options->dbname = pg_strdup(optarg);
dbname_alloced = true;
needmask = optarg;
dbname = optarg;
break;
case 'e':
if (!SetVariable(pset.vars, "ECHO", "queries")) {
@ -1263,10 +1262,8 @@ static void parse_psql_options(int argc, char* const argv[], struct adhoc_opts*
* if we still have arguments, use it as the database name and username
*/
while (argc - optind >= 1) {
if (options->dbname == NULL) {
options->dbname = pg_strdup(argv[optind]);
dbname_alloced = true;
needmask = argv[optind];
if (dbname == NULL) {
dbname = argv[optind];
} else if (options->username == NULL) {
options->username = argv[optind];
} else if (!pset.quiet) {
@ -1276,21 +1273,25 @@ static void parse_psql_options(int argc, char* const argv[], struct adhoc_opts*
optind++;
}
if (needmask != NULL) {
/* mask Password information stored in dbname */
if (dbname != NULL) {
/* Save a copy for connection before masking the password. */
options->dbname = pg_strdup(dbname);
/* mask informations in URI string. */
if (strncmp(options->dbname, "postgresql://", strlen("postgresql://")) == 0) {
char *off_argv = needmask + strlen("postgresql://");
if (strncmp(dbname, "postgresql://", strlen("postgresql://")) == 0) {
char *off_argv = dbname + strlen("postgresql://");
rc = memset_s(off_argv, strlen(off_argv), '*', strlen(off_argv));
check_memset_s(rc);
} else if (strncmp(options->dbname, "postgres://", strlen("postgres://")) == 0) {
char *off_argv = needmask + strlen("postgres://");
} else if (strncmp(dbname, "postgres://", strlen("postgres://")) == 0) {
char *off_argv = dbname + strlen("postgres://");
rc = memset_s(off_argv, strlen(off_argv), '*', strlen(off_argv));
check_memset_s(rc);
}
/* mask password */
/* mask password in key/value string. */
char *temp = NULL;
if ((temp = strstr(needmask, "password")) != NULL) {
char *off_argv = temp + PASSWORD_STR_LEN;
if ((temp = strstr(dbname, "password")) != NULL) {
char *off_argv = temp + strlen("password");
rc = memset_s(off_argv, strlen(off_argv), '*', strlen(off_argv));
check_memset_s(rc);
}

View File

@ -3031,6 +3031,10 @@
"get_byte", 1,
AddBuiltinFunc(_0(721), _1("get_byte"), _2(2), _3(true), _4(false), _5(byteaGetByte), _6(23), _7(PG_CATALOG_NAMESPACE), _8(BOOTSTRAP_SUPERUSERID), _9(INTERNALlanguageId), _10(1), _11(0), _12(0), _13(0), _14(false), _15(false), _16(false), _17(false), _18('i'), _19(0), _20(2, 17, 23), _21(NULL), _22(NULL), _23(NULL), _24(NULL), _25("byteaGetByte"), _26(NULL), _27(NULL), _28(NULL), _29(0), _30(false), _31(NULL), _32(false), _33("get byte"), _34('f'), _35(NULL), _36(0), _37(false), _38(NULL), _39(NULL), _40(0))
),
AddFuncGroup(
"get_client_info", 1,
AddBuiltinFunc(_0(7732), _1("get_client_info"), _2(0), _3(false), _4(true), _5(get_client_info), _6(2249), _7(PG_CATALOG_NAMESPACE), _8(BOOTSTRAP_SUPERUSERID), _9(INTERNALlanguageId), _10(1), _11(100), _12(0), _13(0), _14(false), _15(false), _16(false), _17(false), _18('s'), _19(0), _20(0), _21(2, 20, 25), _22(2, 'o', 'o'), _23(2, "sid", "client_info"), _24(NULL), _25("get_client_info"), _26(NULL), _27(NULL), _28(NULL), _29(0), _30(false), _31(true), _32(false), _33("read current client"), _34('f'), _35(NULL), _36(0), _37(false), _38(NULL), _39(NULL), _40(0))
),
AddFuncGroup(
"get_current_ts_config", 1,
AddBuiltinFunc(_0(3759), _1("get_current_ts_config"), _2(0), _3(true), _4(false), _5(get_current_ts_config), _6(3734), _7(PG_CATALOG_NAMESPACE), _8(BOOTSTRAP_SUPERUSERID), _9(INTERNALlanguageId), _10(1), _11(0), _12(0), _13(0), _14(false), _15(false), _16(false), _17(false), _18('s'), _19(0), _20(0), _21(NULL), _22(NULL), _23(NULL), _24(NULL), _25("get_current_ts_config"), _26(NULL), _27(NULL), _28(NULL), _29(0), _30(false), _31(NULL), _32(false), _33("get current tsearch configuration"), _34('f'), _35(NULL), _36(0), _37(false), _38(NULL), _39(NULL), _40(0))
@ -8173,14 +8177,14 @@
"pg_rotate_logfile", 1,
AddBuiltinFunc(_0(2622), _1("pg_rotate_logfile"), _2(0), _3(true), _4(false), _5(pg_rotate_logfile), _6(16), _7(PG_CATALOG_NAMESPACE), _8(BOOTSTRAP_SUPERUSERID), _9(INTERNALlanguageId), _10(1), _11(0), _12(0), _13(0), _14(false), _15(false), _16(false), _17(false), _18('v'), _19(0), _20(0), _21(NULL), _22(NULL), _23(NULL), _24(NULL), _25("pg_rotate_logfile"), _26(NULL), _27(NULL), _28(NULL), _29(0), _30(false), _31(NULL), _32(false), _33("rotate log file - old version for adminpack 1.0"), _34('f'), _35(NULL), _36(0), _37(false), _38(NULL), _39(NULL), _40(0))
),
AddFuncGroup(
"pg_sequence_parameters", 1,
AddBuiltinFunc(_0(3078), _1("pg_sequence_parameters"), _2(1), _3(true), _4(false), _5(pg_sequence_parameters), _6(2249), _7(PG_CATALOG_NAMESPACE), _8(BOOTSTRAP_SUPERUSERID), _9(INTERNALlanguageId), _10(1), _11(0), _12(0), _13(0), _14(false), _15(false), _16(false), _17(false), _18('s'), _19(0), _20(1, 26), _21(6, 26, 34, 34, 34, 34, 16), _22(6, 'i', 'o', 'o', 'o', 'o', 'o'), _23(6, "sequence_oid", "start_value", "minimum_value", "maximum_value", "increment", "cycle_option"), _24(NULL), _25("pg_sequence_parameters"), _26(NULL), _27(NULL), _28(NULL), _29(0), _30(false), _31(NULL), _32(false), _33("sequence parameters, for use by information schema"), _34('f'), _35(NULL), _36(0), _37(false), _38(NULL), _39(NULL), _40(0))
),
AddFuncGroup(
"pg_sequence_last_value", 1,
AddBuiltinFunc(_0(3080), _1("pg_sequence_last_value"), _2(1), _3(true), _4(false), _5(pg_sequence_last_value), _6(2249), _7(PG_CATALOG_NAMESPACE), _8(BOOTSTRAP_SUPERUSERID), _9(INTERNALlanguageId), _10(1), _11(0), _12(0), _13(0), _14(false), _15(false), _16(false), _17(false), _18('s'), _19(0), _20(1, 26), _21(3, 26, 34, 34), _22(3, 'i', 'o', 'o'), _23(3, "sequence_oid", "cache_value", "last_value"), _24(NULL), _25("pg_sequence_last_value"), _26(NULL), _27(NULL), _28(NULL), _29(0), _30(false), _31(NULL), _32(false), _33(NULL), _34('f'), _35(NULL), _36(0), _37(false))
),
AddFuncGroup(
"pg_sequence_parameters", 1,
AddBuiltinFunc(_0(3078), _1("pg_sequence_parameters"), _2(1), _3(true), _4(false), _5(pg_sequence_parameters), _6(2249), _7(PG_CATALOG_NAMESPACE), _8(BOOTSTRAP_SUPERUSERID), _9(INTERNALlanguageId), _10(1), _11(0), _12(0), _13(0), _14(false), _15(false), _16(false), _17(false), _18('s'), _19(0), _20(1, 26), _21(6, 26, 34, 34, 34, 34, 16), _22(6, 'i', 'o', 'o', 'o', 'o', 'o'), _23(6, "sequence_oid", "start_value", "minimum_value", "maximum_value", "increment", "cycle_option"), _24(NULL), _25("pg_sequence_parameters"), _26(NULL), _27(NULL), _28(NULL), _29(0), _30(false), _31(NULL), _32(false), _33("sequence parameters, for use by information schema"), _34('f'), _35(NULL), _36(0), _37(false), _38(NULL), _39(NULL), _40(0))
),
AddFuncGroup(
"pg_shared_memctx_detail", 1,
AddBuiltinFunc(_0(3987), _1("pg_shared_memctx_detail"), _2(1), _3(false), _4(true), _5(pg_shared_memctx_detail), _6(16), _7(PG_CATALOG_NAMESPACE), _8(BOOTSTRAP_SUPERUSERID), _9(INTERNALlanguageId), _10(1), _11(100), _12(0), _13(0), _14(false), _15(false), _16(false), _17(false), _18('s'), _19(0), _20(1, 2275), _21(NULL), _22(NULL), _23(NULL), _24(NULL), _25("pg_shared_memctx_detail"), _26(NULL), _27(NULL), _28(NULL), _29(0), _30(false), _31(NULL), _32(false), _33(NULL), _34('f'), _35(NULL), _36(0), _37(false), _38(NULL), _39(NULL), _40(0))

View File

@ -2509,6 +2509,8 @@ char* getObjectDescription(const ObjectAddress* object)
initStringInfo(&buffer);
char* signature = NULL;
switch (getObjectClass(object)) {
case OCLASS_CLASS:
getRelationDescription(&buffer, object->objectId);
@ -2518,11 +2520,15 @@ char* getObjectDescription(const ObjectAddress* object)
break;
case OCLASS_PROC:
appendStringInfo(&buffer, _("function %s"), format_procedure(object->objectId));
signature = format_procedure(object->objectId);
appendStringInfo(&buffer, _("function %s"), signature);
pfree_ext(signature);
break;
case OCLASS_PACKAGE:
appendStringInfo(&buffer, _("package %s"), format_procedure(object->objectId));
signature = format_procedure(object->objectId);
appendStringInfo(&buffer, _("package %s"), signature);
pfree_ext(signature);
break;
case OCLASS_TYPE:
@ -2776,7 +2782,7 @@ char* getObjectDescription(const ObjectAddress* object)
initStringInfo(&opfam);
getOpFamilyDescription(&opfam, amprocForm->amprocfamily);
signature = format_procedure(amprocForm->amproc);
/* ------
translator: %d is the function number, the first two %s's
are data type names, the third %s is the description of the
@ -2788,8 +2794,9 @@ char* getObjectDescription(const ObjectAddress* object)
format_type_be(amprocForm->amproclefttype),
format_type_be(amprocForm->amprocrighttype),
opfam.data,
format_procedure(amprocForm->amproc));
signature);
pfree_ext(signature);
pfree_ext(opfam.data);
systable_endscan(amscan);

View File

@ -1105,8 +1105,29 @@ static List* BuildFuncInfoList(PLpgSQL_execstate* estate)
void BuildSessionPackageRuntimeForAutoSession(uint64 sessionId, uint64 parentSessionId,
PLpgSQL_execstate* estate, PLpgSQL_function* func)
{
SessionPackageRuntime* parentSessionPkgs = NULL;
MemoryContext pkgRuntimeCtx = AllocSetContextCreate(CurrentMemoryContext,
"SessionPackageRuntime",
ALLOCSET_SMALL_MINSIZE,
ALLOCSET_SMALL_INITSIZE,
ALLOCSET_DEFAULT_MAXSIZE);
MemoryContext oldCtx = MemoryContextSwitchTo(pkgRuntimeCtx);
SessionPackageRuntime* resultSessionPkgs = (SessionPackageRuntime*)palloc0(sizeof(SessionPackageRuntime));
resultSessionPkgs->context = pkgRuntimeCtx;
/* doing insert gs_source, no need to restore package value */
if (func->is_insert_gs_source) {
resultSessionPkgs->is_insert_gs_source = true;
g_instance.global_session_pkg->Add(sessionId, resultSessionPkgs);
MemoryContextSwitchTo(oldCtx);
MemoryContextDelete(resultSessionPkgs->context);
return;
}
if (u_sess->plsql_cxt.plpgsqlpkg_dlist_objects != NULL) {
CopyCurrentSessionPkgs(resultSessionPkgs, u_sess->plsql_cxt.plpgsqlpkg_dlist_objects);
}
SessionPackageRuntime* parentSessionPkgs = NULL;
/* get parent session pkgs, build current session pkgs need include them */
if (parentSessionId != 0) {
if (!u_sess->plsql_cxt.not_found_parent_session_pkgs) {
@ -1120,17 +1141,6 @@ void BuildSessionPackageRuntimeForAutoSession(uint64 sessionId, uint64 parentSes
}
}
}
MemoryContext pkgRuntimeCtx = AllocSetContextCreate(CurrentMemoryContext,
"SessionPackageRuntime",
ALLOCSET_SMALL_MINSIZE,
ALLOCSET_SMALL_INITSIZE,
ALLOCSET_DEFAULT_MAXSIZE);
MemoryContext oldCtx = MemoryContextSwitchTo(pkgRuntimeCtx);
SessionPackageRuntime* resultSessionPkgs = (SessionPackageRuntime*)palloc0(sizeof(SessionPackageRuntime));
resultSessionPkgs->context = pkgRuntimeCtx;
if (u_sess->plsql_cxt.plpgsqlpkg_dlist_objects != NULL) {
CopyCurrentSessionPkgs(resultSessionPkgs, u_sess->plsql_cxt.plpgsqlpkg_dlist_objects);
}
if (parentSessionPkgs) {
List* parentPkgList = parentSessionPkgs->runtimes;
@ -1387,6 +1397,9 @@ void initAutoSessionPkgsValue(uint64 sessionId)
if (sessionPkgs->runtimes == NULL) {
return;
}
if (sessionPkgs->is_insert_gs_source) {
return;
}
foreach(cell, sessionPkgs->runtimes) {
pkgState = (PackageRuntimeState*)lfirst(cell);
@ -1510,11 +1523,7 @@ void initAutonomousPkgValue(PLpgSQL_package* targetPkg, uint64 sessionId)
List *processAutonmSessionPkgs(PLpgSQL_function* func, PLpgSQL_execstate* estate, bool isAutonm)
{
List *autonmsList = NULL;
/* ignore inline_code_block function */
if (!OidIsValid(func->fn_oid)) {
return NULL;
}
List *autonmsList = NIL;
uint64 currentSessionId = IS_THREAD_POOL_WORKER ? u_sess->session_id : t_thrd.proc_cxt.MyProcPid;
@ -1525,6 +1534,13 @@ List *processAutonmSessionPkgs(PLpgSQL_function* func, PLpgSQL_execstate* estate
* sessionpkgs from g_instance.global_session_pkg
*/
uint64 automnSessionId = u_sess->SPI_cxt.autonomous_session->current_attach_sessionid;
if (func->is_insert_gs_source) {
/* doing insert gs_source, need do noting */
g_instance.global_session_pkg->Remove(automnSessionId);
g_instance.global_session_pkg->Remove(currentSessionId);
return NIL;
}
SessionPackageRuntime* sessionpkgs = g_instance.global_session_pkg->Fetch(automnSessionId);
RestoreAutonmSessionPkgs(sessionpkgs);
if (sessionpkgs != NULL) {
@ -1546,7 +1562,11 @@ List *processAutonmSessionPkgs(PLpgSQL_function* func, PLpgSQL_execstate* estate
* and restore package values by it.
*/
if (u_sess->is_autonomous_session == true && u_sess->SPI_cxt._connected == 0) {
BuildSessionPackageRuntimeForParentSession(currentSessionId, estate);
/* doing insert gs_source, need do noting */
if (u_sess->plsql_cxt.auto_parent_session_pkgs == NULL
|| !u_sess->plsql_cxt.auto_parent_session_pkgs->is_insert_gs_source) {
BuildSessionPackageRuntimeForParentSession(currentSessionId, estate);
}
/* autonomous session will be reused by next autonomous procedure, need clean it */
if (u_sess->plsql_cxt.auto_parent_session_pkgs != NULL) {
MemoryContextDelete(u_sess->plsql_cxt.auto_parent_session_pkgs->context);
@ -1560,11 +1580,6 @@ List *processAutonmSessionPkgs(PLpgSQL_function* func, PLpgSQL_execstate* estate
void processAutonmSessionPkgsInException(PLpgSQL_function* func)
{
/* ignore inline_code_block function */
if (!OidIsValid(func->fn_oid)) {
return;
}
uint64 currentSessionId = IS_THREAD_POOL_WORKER ? u_sess->session_id : t_thrd.proc_cxt.MyProcPid;
if (IsAutonomousTransaction(func->action->isAutonomous)) {
@ -1578,6 +1593,13 @@ void processAutonmSessionPkgsInException(PLpgSQL_function* func)
return;
}
uint64 automnSessionId = u_sess->SPI_cxt.autonomous_session->current_attach_sessionid;
if (func->is_insert_gs_source) {
/* doing insert gs_source, need do noting */
g_instance.global_session_pkg->Remove(automnSessionId);
g_instance.global_session_pkg->Remove(currentSessionId);
return;
}
SessionPackageRuntime* sessionpkgs = g_instance.global_session_pkg->Fetch(automnSessionId);
RestoreAutonmSessionPkgs(sessionpkgs);
if (sessionpkgs != NULL) {
@ -1596,7 +1618,11 @@ void processAutonmSessionPkgsInException(PLpgSQL_function* func)
* and restore package values by it.
*/
if (u_sess->is_autonomous_session == true && u_sess->SPI_cxt._connected == 0) {
BuildSessionPackageRuntimeForParentSession(currentSessionId, NULL);
/* doing insert gs_source, need do noting */
if (u_sess->plsql_cxt.auto_parent_session_pkgs == NULL
|| !u_sess->plsql_cxt.auto_parent_session_pkgs->is_insert_gs_source) {
BuildSessionPackageRuntimeForParentSession(currentSessionId, NULL);
}
/* autonomous session will be reused by next autonomous procedure, need clean it */
if (u_sess->plsql_cxt.auto_parent_session_pkgs != NULL) {
MemoryContextDelete(u_sess->plsql_cxt.auto_parent_session_pkgs->context);

View File

@ -6245,14 +6245,21 @@ Oid AddNewIntervalPartition(Relation rel, void* insertTuple)
CacheInvalidateRelcache(rel);
}
/*
* to avoid dead lock, we should release AccessShareLock on ADD_PARTITION_ACTION
* locked by the transaction before aquire AccessExclusiveLock.
*/
UnlockRelationForAccessIntervalPartTabIfHeld(rel);
/* it will accept invalidation messages generated by other sessions in lockRelationForAddIntervalPartition. */
lockRelationForAddIntervalPartition(rel);
LockRelationForAddIntervalPartition(rel);
partitionRoutingForTuple(rel, insertTuple, u_sess->catalog_cxt.route);
/* if the partition exists, return partition's oid */
if (u_sess->catalog_cxt.route->fileExist) {
Assert(OidIsValid(u_sess->catalog_cxt.route->partitionId));
unLockRelationForAddIntervalPartition(rel);
/* we should take AccessShareLock again before release AccessExclusiveLock for consistency. */
LockRelationForAccessIntervalPartitionTab(rel);
UnlockRelationForAddIntervalPartition(rel);
return u_sess->catalog_cxt.route->partitionId;
}
@ -6320,6 +6327,8 @@ Oid AddNewIntervalPartition(Relation rel, void* insertTuple)
*/
CommandCounterIncrement();
UpdatePgObjectChangecsn(RelationGetRelid(rel), rel->rd_rel->relkind);
return newPartOid;
}

View File

@ -5862,7 +5862,7 @@ void AddGPIForSubPartition(Oid partTableOid, Oid partOid, Oid subPartOid)
* @@GaussDB@@
* Target : This routine is used to scan partition tuples and delete them from all global partition indexes.
*/
void ScanPartitionDeleteGPITuples(Relation partTableRel, Relation partRel, const List* indexRelList,
void ScanPartitionDeleteGPITuples(Relation partTableRel, Relation partRel, const List* indexRelList,
const List* indexInfoList)
{
TableScanDesc scan = NULL;
@ -5893,9 +5893,8 @@ void ScanPartitionDeleteGPITuples(Relation partTableRel, Relation partRel, const
Relation indexRel = (Relation)lfirst(cell);
IndexInfo* indexInfo = static_cast<IndexInfo*>(lfirst(cell1));
if (!RelationIsUstoreIndex(indexRel)) {
continue; /* only ubtree have index_delete routine */
}
/* only ubtree have index_delete routine */
Assert(RelationIsUstoreIndex(indexRel));
Datum values[tupleDesc->natts];
bool isNull[tupleDesc->natts];
@ -5988,7 +5987,7 @@ bool DeleteGPITuplesForPartition(Oid partTableOid, Oid partOid)
* Description :
* Notes :
*/
void DeleteGPITuplesForSubPartition(Oid partTableOid, Oid partOid, Oid subPartOid)
bool DeleteGPITuplesForSubPartition(Oid partTableOid, Oid partOid, Oid subPartOid)
{
Relation partTableRel = NULL;
Relation partRel = NULL;
@ -5999,6 +5998,7 @@ void DeleteGPITuplesForSubPartition(Oid partTableOid, Oid partOid, Oid subPartOi
List* indexRelList = NIL;
List* indexInfoList = NIL;
ListCell* cell = NULL;
bool all_ubtree = true;
partTableRel = heap_open(partTableOid, AccessShareLock);
part = partitionOpen(partTableRel, partOid, AccessShareLock);
@ -6012,6 +6012,12 @@ void DeleteGPITuplesForSubPartition(Oid partTableOid, Oid partOid, Oid subPartOi
Relation indexRel = relation_open(indexOid, RowExclusiveLock);
IndexInfo* indexInfo = BuildIndexInfo(indexRel);
if (!RelationIsUstoreIndex(indexRel)) {
all_ubtree = false;
relation_close(indexRel, RowExclusiveLock);
continue;
}
indexRelList = lappend(indexRelList, indexRel);
indexInfoList = lappend(indexInfoList, indexInfo);
}
@ -6033,6 +6039,8 @@ void DeleteGPITuplesForSubPartition(Oid partTableOid, Oid partOid, Oid subPartOi
releaseDummyRelation(&partRel);
partitionClose(partTableRel, part, NoLock);
heap_close(partTableRel, NoLock);
return all_ubtree;
}
void mergeBTreeIndexes(List* mergingBtreeIndexes, List* srcPartMergeOffset, int2 bktId)

View File

@ -285,6 +285,7 @@ Oid RangeVarGetRelidExtended(const RangeVar* relation, LOCKMODE lockmode, bool m
(errcode(ERRCODE_INVALID_TABLE_DEFINITION),
errmsg("temporary tables cannot specify a schema name")));
}
pfree_ext(errDetail);
errDetail = get_relname_relid_extend(
relation->relname, u_sess->catalog_cxt.myTempNamespace, &relId, isSupportSynonym, refSynOid);
}
@ -293,6 +294,7 @@ Oid RangeVarGetRelidExtended(const RangeVar* relation, LOCKMODE lockmode, bool m
/* use exact schema given */
namespaceId = LookupExplicitNamespace(relation->schemaname);
pfree_ext(errDetail);
errDetail = get_relname_relid_extend(relation->relname, namespaceId, &relId, isSupportSynonym, refSynOid);
if (OidIsValid(relId) && namespaceId == u_sess->catalog_cxt.myTempNamespace)
@ -300,6 +302,7 @@ Oid RangeVarGetRelidExtended(const RangeVar* relation, LOCKMODE lockmode, bool m
} else {
/* search the namespace path */
if (isSupportSynonym) {
pfree_ext(errDetail);
errDetail = RelnameGetRelidExtended(relation->relname, &relId, refSynOid, detailInfo);
} else {
relId = RelnameGetRelid(relation->relname, detailInfo);
@ -419,8 +422,8 @@ Oid RangeVarGetRelidExtended(const RangeVar* relation, LOCKMODE lockmode, bool m
/* Skipping report error, but store the error detail info and report later. */
appendStringInfo(detailInfo, _("%s"), errDetail);
}
pfree_ext(errDetail);
}
pfree_ext(errDetail);
if (!OidIsValid(relId) && !missing_ok) {
if (relation->schemaname)

View File

@ -377,6 +377,9 @@ void UpdatePgObjectChangecsn(Oid objectOid, PgObjectType objectType)
if (!CheckObjectExist(objectOid, objectType)) {
return;
}
if (u_sess->exec_cxt.isExecTrunc) {
return;
}
relation = heap_open(PgObjectRelationId, RowExclusiveLock);
tup = SearchSysCache2(PGOBJECTID, ObjectIdGetDatum(objectOid), CharGetDatum(objectType));
if (!HeapTupleIsValid(tup)) {

View File

@ -1425,3 +1425,41 @@ Oid GetBaseRelOidOfParition(Relation relation)
return relation->parentId;
}
/* NB: all operations on ADD_PARTITION_ACTION sequence lock must use TopTransactionResourceOwner. */
void LockRelationForAddIntervalPartition(Relation rel)
{
ResourceOwner currentOwner = t_thrd.utils_cxt.CurrentResourceOwner;
t_thrd.utils_cxt.CurrentResourceOwner = t_thrd.utils_cxt.TopTransactionResourceOwner;
LockPartition(RelationGetRelid(rel), ADD_PARTITION_ACTION,
AccessExclusiveLock, PARTITION_SEQUENCE_LOCK);
t_thrd.utils_cxt.CurrentResourceOwner = currentOwner;
}
void LockRelationForAccessIntervalPartitionTab(Relation rel)
{
ResourceOwner currentOwner = t_thrd.utils_cxt.CurrentResourceOwner;
t_thrd.utils_cxt.CurrentResourceOwner = t_thrd.utils_cxt.TopTransactionResourceOwner;
LockPartition(RelationGetRelid(rel), ADD_PARTITION_ACTION,
AccessShareLock, PARTITION_SEQUENCE_LOCK);
t_thrd.utils_cxt.CurrentResourceOwner = currentOwner;
}
void UnlockRelationForAccessIntervalPartTabIfHeld(Relation rel)
{
ResourceOwner currentOwner = t_thrd.utils_cxt.CurrentResourceOwner;
t_thrd.utils_cxt.CurrentResourceOwner = t_thrd.utils_cxt.TopTransactionResourceOwner;
UnlockPartitionSeqIfHeld(RelationGetRelid(rel), ADD_PARTITION_ACTION, AccessShareLock);
t_thrd.utils_cxt.CurrentResourceOwner = currentOwner;
}
void UnlockRelationForAddIntervalPartition(Relation rel)
{
ResourceOwner currentOwner = t_thrd.utils_cxt.CurrentResourceOwner;
t_thrd.utils_cxt.CurrentResourceOwner = t_thrd.utils_cxt.TopTransactionResourceOwner;
UnlockPartition(RelationGetRelid(rel), ADD_PARTITION_ACTION,
AccessExclusiveLock, PARTITION_SEQUENCE_LOCK);
t_thrd.utils_cxt.CurrentResourceOwner = currentOwner;
}

View File

@ -245,7 +245,7 @@ CREATE VIEW pg_rlspolicies AS
END AS policypermissive,
CASE
WHEN pol.polroles = '{0}' THEN
string_to_array('public', ' ')
pg_catalog.string_to_array('public', ' ')
ELSE
ARRAY
(
@ -549,33 +549,33 @@ REVOKE ALL on pg_statistic FROM public;
REVOKE ALL on pg_statistic_ext FROM public;
CREATE VIEW pg_locks AS
SELECT * FROM pg_lock_status() AS L;
SELECT * FROM pg_catalog.pg_lock_status() AS L;
CREATE VIEW pg_cursors AS
SELECT * FROM pg_cursor() AS C;
SELECT * FROM pg_catalog.pg_cursor() AS C;
CREATE VIEW pg_available_extensions AS
SELECT E.name, E.default_version, X.extversion AS installed_version,
E.comment
FROM pg_available_extensions() AS E
FROM pg_catalog.pg_available_extensions() AS E
LEFT JOIN pg_extension AS X ON E.name = X.extname;
CREATE VIEW pg_available_extension_versions AS
SELECT E.name, E.version, (X.extname IS NOT NULL) AS installed,
E.superuser, E.relocatable, E.schema, E.requires, E.comment
FROM pg_available_extension_versions() AS E
FROM pg_catalog.pg_available_extension_versions() AS E
LEFT JOIN pg_extension AS X
ON E.name = X.extname AND E.version = X.extversion;
CREATE VIEW pg_prepared_xacts AS
SELECT P.transaction, P.gid, P.prepared,
U.rolname AS owner, D.datname AS database
FROM pg_prepared_xact() AS P
FROM pg_catalog.pg_prepared_xact() AS P
LEFT JOIN pg_authid U ON P.ownerid = U.oid
LEFT JOIN pg_database D ON P.dbid = D.oid;
CREATE VIEW pg_prepared_statements AS
SELECT * FROM pg_prepared_statement() AS P;
SELECT * FROM pg_catalog.pg_prepared_statement() AS P;
CREATE VIEW pg_seclabels AS
SELECT
@ -719,7 +719,7 @@ FROM
JOIN pg_authid rol ON l.classoid = rol.tableoid AND l.objoid = rol.oid;
CREATE VIEW pg_settings AS
SELECT * FROM pg_show_all_settings() AS A;
SELECT * FROM pg_catalog.pg_show_all_settings() AS A;
CREATE RULE pg_settings_u AS
ON UPDATE TO pg_settings
@ -733,13 +733,13 @@ CREATE RULE pg_settings_n AS
GRANT SELECT, UPDATE ON pg_settings TO PUBLIC;
CREATE VIEW pg_timezone_abbrevs AS
SELECT * FROM pg_timezone_abbrevs();
SELECT * FROM pg_catalog.pg_timezone_abbrevs();
CREATE VIEW pg_timezone_names AS
SELECT * FROM pg_timezone_names();
SELECT * FROM pg_catalog.pg_timezone_names();
CREATE VIEW pg_control_group_config AS
SELECT * FROM pg_control_group_config();
SELECT * FROM pg_catalog.pg_control_group_config();
-- Statistics views
@ -824,7 +824,7 @@ CREATE VIEW pg_statio_all_tables AS
pg_catalog.pg_stat_get_blocks_hit(C.oid) AS heap_blks_hit,
pg_catalog.sum(pg_catalog.pg_stat_get_blocks_fetched(I.indexrelid) -
pg_catalog.pg_stat_get_blocks_hit(I.indexrelid))::bigint AS idx_blks_read,
pg_catalog.sum(pg_stat_get_blocks_hit(I.indexrelid))::bigint AS idx_blks_hit,
pg_catalog.sum(pg_catalog.pg_stat_get_blocks_hit(I.indexrelid))::bigint AS idx_blks_hit,
pg_catalog.pg_stat_get_blocks_fetched(T.oid) -
pg_catalog.pg_stat_get_blocks_hit(T.oid) AS toast_blks_read,
pg_catalog.pg_stat_get_blocks_hit(T.oid) AS toast_blks_hit,
@ -882,7 +882,7 @@ CREATE VIEW pg_statio_all_indexes AS
N.nspname AS schemaname,
C.relname AS relname,
I.relname AS indexrelname,
pg_stat_get_blocks_fetched(I.oid) -
pg_catalog.pg_stat_get_blocks_fetched(I.oid) -
pg_catalog.pg_stat_get_blocks_hit(I.oid) AS idx_blks_read,
pg_catalog.pg_stat_get_blocks_hit(I.oid) AS idx_blks_hit
FROM pg_class C JOIN
@ -906,7 +906,7 @@ CREATE VIEW pg_statio_all_sequences AS
C.oid AS relid,
N.nspname AS schemaname,
C.relname AS relname,
pg_stat_get_blocks_fetched(C.oid) -
pg_catalog.pg_stat_get_blocks_fetched(C.oid) -
pg_catalog.pg_stat_get_blocks_hit(C.oid) AS blks_read,
pg_catalog.pg_stat_get_blocks_hit(C.oid) AS blks_hit
FROM pg_class C
@ -1141,7 +1141,7 @@ SELECT
FROM pg_stat_activity_ng AS S, pg_catalog.pg_stat_get_wlm_realtime_session_info(NULL) AS T
WHERE S.pid = T.threadid;
CREATE OR REPLACE FUNCTION gs_wlm_get_all_user_resource_info()
CREATE OR REPLACE FUNCTION pg_catalog.gs_wlm_get_all_user_resource_info()
RETURNS setof record
AS $$
DECLARE
@ -1162,7 +1162,7 @@ DECLARE
LANGUAGE 'plpgsql' NOT FENCED;
CREATE VIEW pg_total_user_resource_info_oid AS
SELECT * FROM gs_wlm_get_all_user_resource_info() AS
SELECT * FROM pg_catalog.gs_wlm_get_all_user_resource_info() AS
(userid Oid,
used_memory int,
total_memory int,
@ -1228,7 +1228,7 @@ create table gs_wlm_user_resource_history
REVOKE all on gs_wlm_user_resource_history FROM public;
CREATE OR REPLACE FUNCTION gs_wlm_persistent_user_resource_info()
CREATE OR REPLACE FUNCTION pg_catalog.gs_wlm_persistent_user_resource_info()
RETURNS setof record
AS $$
DECLARE
@ -1270,7 +1270,7 @@ create table gs_wlm_instance_history
REVOKE ALL on gs_wlm_instance_history FROM public;
CREATE OR REPLACE FUNCTION create_wlm_instance_statistics_info()
CREATE OR REPLACE FUNCTION pg_catalog.create_wlm_instance_statistics_info()
RETURNS int
AS $$
DECLARE
@ -1612,18 +1612,18 @@ CREATE VIEW gs_wlm_workload_records AS
WHERE P.query_pid = S.threadpid AND
S.usesysid = U.oid;
CREATE VIEW gs_os_run_info AS SELECT * FROM pv_os_run_info();
CREATE VIEW gs_session_memory_context AS SELECT * FROM pv_session_memory_detail();
CREATE VIEW gs_thread_memory_context AS SELECT * FROM pv_thread_memory_detail();
CREATE VIEW gs_shared_memory_detail AS SELECT * FROM pg_shared_memory_detail();
CREATE VIEW gs_instance_time AS SELECT * FROM pv_instance_time();
CREATE VIEW gs_session_time AS SELECT * FROM pv_session_time();
CREATE VIEW gs_session_memory AS SELECT * FROM pv_session_memory();
CREATE VIEW gs_total_memory_detail AS SELECT * FROM pv_total_memory_detail();
CREATE VIEW pg_total_memory_detail AS SELECT * FROM pv_total_memory_detail();
CREATE VIEW gs_redo_stat AS SELECT * FROM pg_stat_get_redo_stat();
CREATE VIEW gs_session_stat AS SELECT * FROM pv_session_stat();
CREATE VIEW gs_file_stat AS SELECT * FROM pg_stat_get_file_stat();
CREATE VIEW gs_os_run_info AS SELECT * FROM pg_catalog.pv_os_run_info();
CREATE VIEW gs_session_memory_context AS SELECT * FROM pg_catalog.pv_session_memory_detail();
CREATE VIEW gs_thread_memory_context AS SELECT * FROM pg_catalog.pv_thread_memory_detail();
CREATE VIEW gs_shared_memory_detail AS SELECT * FROM pg_catalog.pg_shared_memory_detail();
CREATE VIEW gs_instance_time AS SELECT * FROM pg_catalog.pv_instance_time();
CREATE VIEW gs_session_time AS SELECT * FROM pg_catalog.pv_session_time();
CREATE VIEW gs_session_memory AS SELECT * FROM pg_catalog.pv_session_memory();
CREATE VIEW gs_total_memory_detail AS SELECT * FROM pg_catalog.pv_total_memory_detail();
CREATE VIEW pg_total_memory_detail AS SELECT * FROM pg_catalog.pv_total_memory_detail();
CREATE VIEW gs_redo_stat AS SELECT * FROM pg_catalog.pg_stat_get_redo_stat();
CREATE VIEW gs_session_stat AS SELECT * FROM pg_catalog.pv_session_stat();
CREATE VIEW gs_file_stat AS SELECT * FROM pg_catalog.pg_stat_get_file_stat();
CREATE OR REPLACE FUNCTION pg_catalog.gs_session_memory_detail_tp(OUT sessid TEXT, OUT sesstype TEXT, OUT contextname TEXT, OUT level INT2, OUT parent TEXT, OUT totalsize INT8, OUT freesize INT8, OUT usedsize INT8)
RETURNS setof record
@ -1718,7 +1718,7 @@ BEGIN
END; $$
LANGUAGE plpgsql NOT FENCED;
CREATE VIEW gs_session_memory_detail AS SELECT * FROM gs_session_memory_detail_tp() ORDER BY sessid;
CREATE VIEW gs_session_memory_detail AS SELECT * FROM pg_catalog.gs_session_memory_detail_tp() ORDER BY sessid;
CREATE VIEW pg_stat_replication AS
SELECT
@ -1754,7 +1754,7 @@ CREATE VIEW pg_replication_slots AS
L.catalog_xmin,
L.restart_lsn,
L.dummy_standby
FROM pg_get_replication_slots() AS L
FROM pg_catalog.pg_get_replication_slots() AS L
LEFT JOIN pg_database D ON (L.datoid = D.oid);
@ -1819,17 +1819,17 @@ CREATE VIEW pg_stat_xact_user_functions AS
CREATE VIEW pg_stat_bgwriter AS
SELECT
pg_stat_get_bgwriter_timed_checkpoints() AS checkpoints_timed,
pg_stat_get_bgwriter_requested_checkpoints() AS checkpoints_req,
pg_stat_get_checkpoint_write_time() AS checkpoint_write_time,
pg_stat_get_checkpoint_sync_time() AS checkpoint_sync_time,
pg_stat_get_bgwriter_buf_written_checkpoints() AS buffers_checkpoint,
pg_stat_get_bgwriter_buf_written_clean() AS buffers_clean,
pg_stat_get_bgwriter_maxwritten_clean() AS maxwritten_clean,
pg_stat_get_buf_written_backend() AS buffers_backend,
pg_stat_get_buf_fsync_backend() AS buffers_backend_fsync,
pg_stat_get_buf_alloc() AS buffers_alloc,
pg_stat_get_bgwriter_stat_reset_time() AS stats_reset;
pg_catalog.pg_stat_get_bgwriter_timed_checkpoints() AS checkpoints_timed,
pg_catalog.pg_stat_get_bgwriter_requested_checkpoints() AS checkpoints_req,
pg_catalog.pg_stat_get_checkpoint_write_time() AS checkpoint_write_time,
pg_catalog.pg_stat_get_checkpoint_sync_time() AS checkpoint_sync_time,
pg_catalog.pg_stat_get_bgwriter_buf_written_checkpoints() AS buffers_checkpoint,
pg_catalog.pg_stat_get_bgwriter_buf_written_clean() AS buffers_clean,
pg_catalog.pg_stat_get_bgwriter_maxwritten_clean() AS maxwritten_clean,
pg_catalog.pg_stat_get_buf_written_backend() AS buffers_backend,
pg_catalog.pg_stat_get_buf_fsync_backend() AS buffers_backend_fsync,
pg_catalog.pg_stat_get_buf_alloc() AS buffers_alloc,
pg_catalog.pg_stat_get_bgwriter_stat_reset_time() AS stats_reset;
CREATE VIEW pg_user_mappings AS
SELECT
@ -1856,7 +1856,7 @@ REVOKE ALL on pg_user_mapping FROM public;
-- these functions are added for supporting default format transformation
CREATE OR REPLACE FUNCTION pg_catalog.to_char(NUMERIC)
RETURNS VARCHAR2
AS $$ SELECT CAST(numeric_out($1) AS VARCHAR2) $$
AS $$ SELECT CAST(pg_catalog.numeric_out($1) AS VARCHAR2) $$
LANGUAGE SQL STRICT IMMUTABLE NOT FENCED;
CREATE OR REPLACE FUNCTION pg_catalog.to_char(INT2)
@ -1891,7 +1891,7 @@ LANGUAGE SQL STRICT IMMUTABLE NOT FENCED;
CREATE OR REPLACE FUNCTION pg_catalog.to_number(TEXT)
RETURNS NUMERIC
AS $$ SELECT pg_catalog.numeric_in(textout($1), 0::Oid, -1) $$
AS $$ SELECT pg_catalog.numeric_in(pg_catalog.textout($1), 0::Oid, -1) $$
LANGUAGE SQL STRICT IMMUTABLE NOT FENCED;
CREATE CAST (VARCHAR2 AS RAW) WITH FUNCTION pg_catalog.hextoraw(text) AS IMPLICIT;
@ -2413,7 +2413,7 @@ begin
end if;
--source string to source_array
for i in 1..pg_catalog.length($1) loop
if substr($1,i,1) ~ '\n' then
if pg_catalog.substr($1,i,1) ~ '\n' then
if position = i then
source_array(source_line) := '\n';
else
@ -2469,12 +2469,12 @@ begin
exit;
end if;
end loop;
if left($2,1) = '^' then
if pg_catalog.left($2,1) = '^' then
regex_temp := pg_catalog.substr($2,2);
else
regex_temp := $2;
end if;
if right($2,1) = '$' then
if pg_catalog.right($2,1) = '$' then
regex_temp := pg_catalog.substr(regex_temp,1,pg_catalog.length(regex_temp)-1);
end if;
if flag then
@ -2497,7 +2497,7 @@ begin
return false;
end if;
end loop;
case right($3, 1)
case pg_catalog.right($3, 1)
when 'i' then return $1 ~* $2;
when 'c' then return $1 ~ $2;
when 'm' then return pg_catalog.regex_like_m($1,$2);
@ -2523,13 +2523,13 @@ SQL_STMT VARCHAR2(500);
fail_cursor REFCURSOR;
success_cursor REFCURSOR;
BEGIN
SELECT text(oid) FROM pg_catalog.pg_authid WHERE rolname=SESSION_USER INTO user_id;
SELECT pg_catalog.text(oid) FROM pg_catalog.pg_authid WHERE rolname=SESSION_USER INTO user_id;
SELECT SESSION_USER INTO user_name;
SELECT pg_catalog.CURRENT_DATABASE() INTO db_name;
IF flag = true THEN
SQL_STMT := 'SELECT username,database,time,type,result,client_conninfo FROM pg_catalog.pg_query_audit(''1970-1-1'',''9999-12-31'') WHERE
type IN (''login_success'') AND username =' || quote_literal(user_name) ||
' AND database =' || quote_literal(db_name) || ' AND userid =' || quote_literal(user_id) || ';';
type IN (''login_success'') AND username =' || pg_catalog.quote_literal(user_name) ||
' AND database =' || pg_catalog.quote_literal(db_name) || ' AND userid =' || pg_catalog.quote_literal(user_id) || ';';
OPEN success_cursor FOR EXECUTE SQL_STMT;
--search bottom up for all the success login info
FETCH LAST FROM success_cursor into username, database, logintime, mytype, result, client_conninfo;
@ -2540,8 +2540,8 @@ BEGIN
CLOSE success_cursor;
ELSE
SQL_STMT := 'SELECT username,database,time,type,result,client_conninfo FROM pg_catalog.pg_query_audit(''1970-1-1'',''9999-12-31'') WHERE
type IN (''login_success'', ''login_failed'') AND username =' || quote_literal(user_name) ||
' AND database =' || quote_literal(db_name) || ' AND userid =' || quote_literal(user_id) || ';';
type IN (''login_success'', ''login_failed'') AND username =' || pg_catalog.quote_literal(user_name) ||
' AND database =' || pg_catalog.quote_literal(db_name) || ' AND userid =' || pg_catalog.quote_literal(user_id) || ';';
OPEN fail_cursor FOR EXECUTE SQL_STMT;
--search bottom up
FETCH LAST FROM fail_cursor into username, database, logintime, mytype, result, client_conninfo;
@ -2580,15 +2580,15 @@ success_cursor REFCURSOR;
mybackendid bigint;
curSessionFound boolean;
BEGIN
SELECT text(oid) FROM pg_catalog.pg_authid WHERE rolname=SESSION_USER INTO user_id;
SELECT pg_catalog.text(oid) FROM pg_catalog.pg_authid WHERE rolname=SESSION_USER INTO user_id;
SELECT SESSION_USER INTO user_name;
SELECT pg_catalog.CURRENT_DATABASE() INTO db_name;
SELECT pg_catalog.pg_backend_pid() INTO mybackendid;
curSessionFound = false;
IF flag = true THEN
SQL_STMT := 'SELECT username,database,time,type,result,client_conninfo, pg_catalog.split_part(thread_id,''@'',1) backendid FROM pg_catalog.pg_query_audit(''1970-1-1'',''9999-12-31'') WHERE
type IN (''login_success'') AND username =' || quote_literal(user_name) ||
' AND database =' || quote_literal(db_name) || ' AND userid =' || quote_literal(user_id) || ';';
type IN (''login_success'') AND username =' || pg_catalog.quote_literal(user_name) ||
' AND database =' || pg_catalog.quote_literal(db_name) || ' AND userid =' || pg_catalog.quote_literal(user_id) || ';';
OPEN success_cursor FOR EXECUTE SQL_STMT;
--search bottom up for all the success login info
FETCH LAST FROM success_cursor into username, database, logintime, mytype, result, client_conninfo, backendid;
@ -2785,14 +2785,14 @@ DECLARE
execute_query text;
BEGIN
if row_num = 0 then
EXECUTE 'select count(1) from ' || table_name into tolal_num;
execute_query = 'select seqNum, count(1) as num
from (select table_data_skewness(row(' || column_name ||'), ''H'') as seqNum from ' || table_name ||
EXECUTE 'select pg_catalog.count(1) from ' || table_name into tolal_num;
execute_query = 'select seqNum, pg_catalog.count(1) as num
from (select pg_catalog.table_data_skewness(row(' || column_name ||'), ''H'') as seqNum from ' || table_name ||
') group by seqNum order by num DESC';
else
tolal_num = row_num;
execute_query = 'select seqNum, count(1) as num
from (select table_data_skewness(row(' || column_name ||'), ''H'') as seqNum from ' || table_name ||
execute_query = 'select seqNum, pg_catalog.count(1) as num
from (select pg_catalog.table_data_skewness(row(' || column_name ||'), ''H'') as seqNum from ' || table_name ||
' limit ' || row_num ||') group by seqNum order by num DESC';
end if;
@ -2965,11 +2965,11 @@ DECLARE
ec_username,
ec_query,
ec_libodbc_type
FROM pg_stat_get_wlm_ec_operator_info(0) where ec_operator > 0';
FROM pg_catalog.pg_stat_get_wlm_ec_operator_info(0) where ec_operator > 0';
query_plan_str := 'SELECT * FROM gs_stat_get_wlm_plan_operator_info(0)';
query_plan_str := 'SELECT * FROM pg_catalog.gs_stat_get_wlm_plan_operator_info(0)';
query_str := 'SELECT * FROM pg_stat_get_wlm_operator_info(1)';
query_str := 'SELECT * FROM pg_catalog.pg_stat_get_wlm_operator_info(1)';
IF flag > 0 THEN
EXECUTE 'INSERT INTO gs_wlm_ec_operator_info ' || query_ec_str;
@ -3060,7 +3060,7 @@ DECLARE
dop = row_data.query_dop;
condition = row_data.condition;
projection = row_data.projection;
query_str_encode := 'SELECT encode_plan_node($tag$'|| operation ||'$tag$,$tag$'|| orientation ||'$tag$,$tag$'|| strategy ||'$tag$,$tag$ '|| options || '$tag$,$tag$'|| dop ||'$tag$,$tag$' || condition || '$tag$,$tag$' || projection || '$tag$) as result;';
query_str_encode := 'SELECT pg_catalog.encode_plan_node($tag$'|| operation ||'$tag$,$tag$'|| orientation ||'$tag$,$tag$'|| strategy ||'$tag$,$tag$ '|| options || '$tag$,$tag$'|| dop ||'$tag$,$tag$' || condition || '$tag$,$tag$' || projection || '$tag$) as result;';
EXECUTE query_str_encode INTO encoded_data;
encode = encoded_data.result;
return next;
@ -3255,7 +3255,7 @@ DECLARE
IF row_info_data.parttype = 'n' THEN
query_str := 'SELECT relname,oid from pg_class where oid= '||row_info_data.reldeltarelid||'';
EXECUTE(query_str) INTO row_data;
query_select_str := 'select count(*) from cstore.' || row_data.relname || '';
query_select_str := 'select pg_catalog.count(*) from cstore.' || row_data.relname || '';
EXECUTE (query_select_str) INTO live_tuple;
query_size_str := 'select * from pg_catalog.pg_relation_size(' || row_data.oid || ')';
EXECUTE (query_size_str) INTO data_size;
@ -3268,7 +3268,7 @@ DECLARE
query_str := 'SELECT relname,oid from pg_class where oid = '||row_part_info.reldeltarelid||'';
part_name := row_part_info.relname;
FOR row_data IN EXECUTE(query_str) LOOP
query_select_str := 'select count(*) from cstore.' || row_data.relname || '';
query_select_str := 'select pg_catalog.count(*) from cstore.' || row_data.relname || '';
EXECUTE (query_select_str) INTO live_tuple;
query_size_str := 'select * from pg_catalog.pg_relation_size(' || row_data.oid || ')';
EXECUTE (query_size_str) INTO data_size;
@ -3321,7 +3321,7 @@ DECLARE
BEGIN
query_database_oid := 'SELECT datname FROM pg_database WHERE datallowconn = true order by datname';
for databse_name in EXECUTE(query_database_oid) LOOP
unlock_str = format('SELECT * FROM pg_catalog.pgxc_unlock_for_sp_database(''%s'')', databse_name.datname);
unlock_str = pg_catalog.format('SELECT * FROM pg_catalog.pgxc_unlock_for_sp_database(''%s'')', databse_name.datname);
begin
EXECUTE(unlock_str) into unlock_result;
if unlock_result = 'f' then
@ -3522,11 +3522,11 @@ CREATE VIEW pg_catalog.gs_db_privileges AS
FROM pg_catalog.gs_db_privilege;
CREATE OR REPLACE VIEW pg_catalog.gs_gsc_memory_detail AS
SELECT db_id, sum(totalsize) AS totalsize, sum(freesize) AS freesize, sum(usedsize) AS usedsize
SELECT db_id, pg_catalog.sum(totalsize) AS totalsize, pg_catalog.sum(freesize) AS freesize, pg_catalog.sum(usedsize) AS usedsize
FROM (
SELECT
CASE WHEN contextname like '%GlobalSysDBCacheEntryMemCxt%' THEN substring(contextname, 29)
ELSE substring(parent, 29) END AS db_id,
CASE WHEN contextname like '%GlobalSysDBCacheEntryMemCxt%' THEN pg_catalog.substring(contextname, 29)
ELSE pg_catalog.substring(parent, 29) END AS db_id,
totalsize,
freesize,
usedsize

View File

@ -745,9 +745,11 @@ static void InitTempToastNamespace(void)
/* Advance command counter to make namespace visible */
CommandCounterIncrement();
Assert(OidIsValid(u_sess->catalog_cxt.myTempNamespace) && OidIsValid(u_sess->catalog_cxt.myTempToastNamespace));
if (!OidIsValid(u_sess->catalog_cxt.myTempToastNamespace)) {
ereport(ERROR,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("Temp toast namespace create failed")));
}
u_sess->catalog_cxt.baseSearchPathValid = false;
}

View File

@ -50,6 +50,7 @@
#include "tcop/utility.h"
#include "pgxc/pgxc.h"
#include "utils/fmgroids.h"
#include "funcapi.h"
const size_t ENCRYPTED_VALUE_MIN_LENGTH = 170;
const size_t ENCRYPTED_VALUE_MAX_LENGTH = 1024;
@ -1324,3 +1325,28 @@ ClientLogicColumnRef *get_column_enc_def(Oid rel_oid, const char *col_name)
return enc_def;
}
Datum get_client_info(PG_FUNCTION_ARGS)
{
ReturnSetInfo* rsinfo = (ReturnSetInfo*)fcinfo->resultinfo;
TupleDesc tupdesc;
Tuplestorestate* tupstore = NULL;
const int COLUMN_NUM = 2;
MemoryContext oldcontext = MemoryContextSwitchTo(rsinfo->econtext->ecxt_per_query_memory);
tupdesc = CreateTemplateTupleDesc(COLUMN_NUM, false, TAM_HEAP);
TupleDescInitEntry(tupdesc, (AttrNumber)1, "sid", INT8OID, -1, 0);
TupleDescInitEntry(tupdesc, (AttrNumber)2, "client_info", TEXTOID, -1, 0);
tupstore = tuplestore_begin_heap(true, false, u_sess->attr.attr_memory.work_mem);
rsinfo->returnMode = SFRM_Materialize;
rsinfo->setResult = tupstore;
rsinfo->setDesc = BlessTupleDesc(tupdesc);
(void)MemoryContextSwitchTo(oldcontext);
if (ENABLE_THREAD_POOL) {
g_threadPoolControler->GetSessionCtrl()->getSessionClientInfo(rsinfo->setResult, rsinfo->setDesc);
}
tuplestore_donestoring(rsinfo->setResult);
return (Datum)0;
}

View File

@ -678,6 +678,9 @@ static void _outPruningResult(StringInfo str, PruningResult* node)
if (t_thrd.proc->workingVersionNum >= num) {
WRITE_NODE_FIELD(expr);
}
if (t_thrd.proc->workingVersionNum >= PBESINGLEPARTITION_VERSION_NUM) {
WRITE_BOOL_FIELD(isPbeSinlePartition);
}
}
static void _outSubPartitionPruningResult(StringInfo str, SubPartitionPruningResult* node)

View File

@ -3312,6 +3312,9 @@ static PruningResult* _readPruningResult(PruningResult* local_node)
if (t_thrd.proc->workingVersionNum >= num) {
READ_NODE_FIELD(expr);
}
IF_EXIST(isPbeSinlePartition) {
READ_BOOL_FIELD(isPbeSinlePartition);
}
READ_DONE();
}

View File

@ -19590,6 +19590,11 @@ for_locking_items:
for_locking_item:
FOR UPDATE hint_string locked_rels_list opt_nowait
{
if (u_sess->parser_cxt.isTimeCapsule) {
u_sess->parser_cxt.isTimeCapsule = false;
ereport(errstate, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("SELECT TIMECAPSULE FOR UPDATE is not supported.")));
}
LockingClause *n = makeNode(LockingClause);
n->lockedRels = $4;
n->forUpdate = TRUE;
@ -20193,22 +20198,22 @@ timecapsule_clause:
TIMECAPSULE opt_timecapsule_clause { $$ = $2; }
opt_timecapsule_clause:
CSN a_expr
CSN {u_sess->parser_cxt.isTimeCapsule = true;} a_expr
{
TcapFeatureEnsure();
RangeTimeCapsule *n = makeNode(RangeTimeCapsule);
n->tvtype = TV_VERSION_CSN;
n->tvver = (Node *)$2;
n->location = @2;
n->tvver = (Node *)$3;
n->location = @3;
$$ = (Node *) n;
}
| TIMESTAMP a_expr
| TIMESTAMP {u_sess->parser_cxt.isTimeCapsule = true;} a_expr
{
TcapFeatureEnsure();
RangeTimeCapsule *n = makeNode(RangeTimeCapsule);
n->tvtype = TV_VERSION_TIMESTAMP;
n->tvver = (Node *)$2;
n->location = @2;
n->tvver = (Node *)$3;
n->location = @3;
$$ = (Node *) n;
}
;

View File

@ -402,6 +402,10 @@ static void PredpushHintDesc(PredpushHint* hint, StringInfo buf)
relnamesToBuf(base_hint.relnames, buf);
if (hint->dest_name != NULL) {
appendStringInfo(buf, ", %s", hint->dest_name);
}
if (hint->candidates != NULL)
appendStringInfo(buf, ")");
@ -3325,6 +3329,50 @@ static void transform_skew_hint(PlannerInfo* root, Query* parse, List* skew_hint
parse->hintState->skew_hint = skew_hint_transf_l;
}
/*
* Check Predpush hint rely on each other.
*/
static void check_predpush_cycle_hint(PlannerInfo *root,
List *predpush_hint_list,
PredpushHint *predpush_hint)
{
ListCell *lc = NULL;
if (bms_num_members(predpush_hint->candidates) != 1) {
return;
}
if (predpush_hint->dest_id == 0) {
return;
}
int cur_dest = predpush_hint->dest_id;
foreach(lc, predpush_hint_list) {
PredpushHint *prev_hint = (PredpushHint *)lfirst(lc);
if (prev_hint == predpush_hint) {
break;
}
if (bms_num_members(prev_hint->candidates) != 1) {
continue;
}
if (prev_hint->dest_id == 0) {
continue;
}
int prev_dest = prev_hint->dest_id;
if (bms_is_member(prev_dest, predpush_hint->candidates) &&
bms_is_member(cur_dest, prev_hint->candidates)) {
append_warning_to_list(
root, (Hint*)predpush_hint, "Error hint:%s, Predpush cannot rely on each other.", hint_string);
}
}
return;
}
/*
* @Description: Transform predpush hint into processible type, including:
* transfrom subquery name
@ -3350,6 +3398,7 @@ static void transform_predpush_hint(PlannerInfo* root, Query* parse, List* predp
}
predpush_hint->dest_id = relid;
check_predpush_cycle_hint(root, predpush_hint_list, predpush_hint);
}
return;
@ -3866,4 +3915,4 @@ bool CheckNodeNameHint(HintState* hintstate)
}
}
return false;
}
}

View File

@ -1134,6 +1134,11 @@ Relation parserOpenTable(ParseState *pstate, const RangeVar *relation, int lockm
TryUnlockAllAccounts();
}
if (rel->partMap && rel->partMap->type == PART_TYPE_INTERVAL) {
/* take AccessShareLock on ADD_PARTITION_ACTION to avoid concurrency with new partition operations. */
LockRelationForAccessIntervalPartitionTab(rel);
}
if (IS_PGXC_COORDINATOR && !IsConnFromCoord()) {
if (u_sess->attr.attr_sql.enable_parallel_ddl && !isFirstNode && isCreateView) {
UnlockRelation(rel, lockmode);

View File

@ -1091,10 +1091,12 @@ static void transformStartWithClause(StartWithTransformContext *context, SelectS
raw_expression_tree_walker((Node*)context->connectByExpr,
(bool (*)())pseudo_level_rownum_walker, (Node*)context->connectByExpr);
checkConnectByExprValidity((Node*)connectByExpr);
StartWithWalker(context, connectByExpr);
context->relInfoList = context->pstate->p_start_info;
context->connect_by_type = CONNECT_BY_LEVEL;
context->connectByLevelExpr = connectByExpr;
context->connectByOtherExpr = NULL;
if (context->connect_by_type != CONNECT_BY_PRIOR) {
context->connectByLevelExpr = connectByExpr;
context->connectByOtherExpr = NULL;
}
}
/* transform start with ... connect by's expr */
@ -1103,12 +1105,24 @@ static void transformStartWithClause(StartWithTransformContext *context, SelectS
StartWithWalker(context, connectByExpr);
}
/* now handle where quals which could whole push down */
/*
* now handle where quals which might need to be pushed down.
* 1. this is necessary only for implicitly joined tables
* such as ... FROM t1,t2 WHERE t1.xx = t2.yy ...
* 2. note that only join quals should be pushed down while
* non-join quals such as (t1.xx < n) should be kept in the outer loop
* of the CTE scan, otherwise the end-result will be different from
* those produced by the standard swcb syntax.
* (the issue here is that implicitly joined tables are difficult to handle
* in our implementation of start with .. connect by .. syntax,
* as we don't have a clear cut of join quals from the non-join quals at this stage.
* users should be encouraged to use explicity joined tables whenever
* possible before a clear-cut solution is implemented.)
*/
int lens = list_length(context->pstate->p_start_info);
if (lens != 1) {
Node *whereClause = (Node *)copyObject(stmt->whereClause);
context->whereClause = whereClause;
stmt->whereClause = NULL;
}
@ -1256,6 +1270,36 @@ static void AddWithClauseToBranch(ParseState *pstate, SelectStmt *stmt, List *re
return;
}
static bool walker_to_exclude_non_join_quals(Node *node, Node *context_node)
{
if (node == NULL) {
return false;
}
if (!IsA(node, A_Expr)) {
return raw_expression_tree_walker(node, (bool (*)()) walker_to_exclude_non_join_quals, (void*)NULL);
}
A_Expr* expr = (A_Expr*) node;
/*
* this is to achieve consistent result sets with those produced by the original
* start with .. connect by syntax, which does not push filter quals down to connect quals.
* if non-column item appears on any side of an operator, we guess that it is
* not a join qual so should not be filtered in sw op, and force it to be true.
* this rule is not always correct but should work fine most of the time.
* could be improved later on, e.g. find better ways to extract non-join quals
* from the where clause.
*/
if (expr->kind == AEXPR_OP &&
(!IsA(expr->lexpr, ColumnRef) || !IsA(expr->rexpr, ColumnRef))) {
expr->lexpr = makeBoolAConst(true, -1);
expr->rexpr = makeBoolAConst(true, -1);
expr->kind = AEXPR_OR;
}
return false;
}
/*
* --------------------------------------------------------------------------------------
* @Brief: Create SWCB's conversion CTE's inner branch, normally we add ConnectByExpr to
@ -1314,6 +1358,10 @@ static SelectStmt *CreateStartWithCTEInnerBranch(ParseState* pstate,
JoinExpr *final_join = (JoinExpr *)origin_table;
/* pushdown requires deep copying of the quals */
Node *whereCopy = (Node *)copyObject(whereClause);
/* only join quals can be pushed down */
raw_expression_tree_walker((Node *)whereCopy,
(bool (*)())walker_to_exclude_non_join_quals, (void*)NULL);
if (final_join->quals == NULL) {
final_join->quals = whereCopy;
} else {
@ -1420,11 +1468,18 @@ static SelectStmt *CreateStartWithCTEOuterBranch(ParseState *pstate,
/* push whereClause down to init part, taking care to avoid NULL in expr. */
quals = (Node *)startWithExpr;
Node* whereClauseCopy = (Node *)copyObject(whereClause);
if (whereClause != NULL) {
/* only join quals can be pushed down */
raw_expression_tree_walker((Node*)whereClauseCopy,
(bool (*)())walker_to_exclude_non_join_quals, (void*)NULL);
}
if (quals == NULL) {
/* pushdown requires deep copying of the quals */
quals = (Node *)copyObject(whereClause);
quals = whereClauseCopy;
} else if (whereClause != NULL) {
quals = (Node *)makeA_Expr(AEXPR_AND, NULL, (Node *)copyObject(whereClause),
quals = (Node *)makeA_Expr(AEXPR_AND, NULL, whereClauseCopy,
(Node*)startWithExpr, -1);
}

View File

@ -28,6 +28,11 @@
extern void resetOperatorPlusFlag();
static void resetIsTimeCapsuleFlag()
{
u_sess->parser_cxt.isTimeCapsule = false;
}
static void resetCreateFuncFlag()
{
u_sess->parser_cxt.isCreateFuncOrProc = false;
@ -48,6 +53,9 @@ List* raw_parser(const char* str, List** query_string_locationlist)
/* reset u_sess->parser_cxt.stmt_contains_operator_plus */
resetOperatorPlusFlag();
/* reset u_sess->parser_cxt.isTimeCapsule */
resetIsTimeCapsuleFlag();
/* reset u_sess->parser_cxt.isCreateFuncOrProc */
resetCreateFuncFlag();

View File

@ -871,12 +871,14 @@ static void ExecuteBarrier(const char* id, bool isSwitchoverBarrier)
/* Only obs-based disaster recovery needs the following processing */
if (g_instance.archive_obs_cxt.archive_slot_num != 0 && g_instance.archive_obs_cxt.barrier_lsn_info != NULL) {
#ifdef ENABLE_MULTIPLE_NODES
if (IS_HADR_BARRIER(id) || IS_CSN_BARRIER(id)) {
SpinLockAcquire(&g_instance.archive_obs_cxt.barrier_lock);
SaveAllNodeBarrierLsnInfo(id, conn_handles);
g_instance.archive_obs_cxt.barrier_lsn_info[connCnt].barrierLsn = recptr;
SpinLockRelease(&g_instance.archive_obs_cxt.barrier_lock);
}
#endif
if (t_thrd.role == BARRIER_CREATOR && !isSwitchoverBarrier) {
UpdateGlobalBarrierListOnMedia(id, g_instance.attr.attr_common.PGXCNodeName);
@ -1017,7 +1019,7 @@ static void RequestXLogFromStream()
static void barrier_redo_pause(char* barrierId)
{
if (!is_barrier_pausable(barrierId)) {
if (!is_barrier_pausable(barrierId) || t_thrd.xlog_cxt.recoveryTarget == RECOVERY_TARGET_TIME_OBS) {
return;
}
volatile WalRcvData *walrcv = t_thrd.walreceiverfuncs_cxt.WalRcv;
@ -1035,7 +1037,7 @@ static void barrier_redo_pause(char* barrierId)
SpinLockRelease(&walrcv->mutex);
pg_usleep(1000L);
RedoInterruptCallBack();
if(IS_OBS_DISASTER_RECOVER_MODE) {
if (IS_OBS_DISASTER_RECOVER_MODE) {
update_recovery_barrier();
} else if (IS_DISASTER_RECOVER_MODE) {
RequestXLogFromStream();

View File

@ -232,9 +232,9 @@ static char* pg_get_triggerdef_worker(Oid trigid, bool pretty);
static void decompile_column_index_array(Datum column_index_array, Oid relId, StringInfo buf);
static char* pg_get_ruledef_worker(Oid ruleoid, int prettyFlags);
static char *pg_get_indexdef_worker(Oid indexrelid, int colno, const Oid *excludeOps, bool attrsOnly, bool showTblSpc,
int prettyFlags, bool dumpSchemaOnly = false, bool showSubpartitionLocal = true);
int prettyFlags, bool dumpSchemaOnly = false, bool showPartitionLocal = true, bool showSubpartitionLocal = true);
static void pg_get_indexdef_partitions(Oid indexrelid, Form_pg_index idxrec, bool showTblSpc, StringInfoData *buf,
bool dumpSchemaOnly, bool showSubpartitionLocal);
bool dumpSchemaOnly, bool showPartitionLocal, bool showSubpartitionLocal);
static char* pg_get_constraintdef_worker(Oid constraintId, bool fullCommand, int prettyFlags);
static text* pg_get_expr_worker(text* expr, Oid relid, const char* relname, int prettyFlags);
static int print_function_arguments(StringInfo buf, HeapTuple proctup, bool print_table_args, bool print_defaults);
@ -2960,7 +2960,7 @@ Datum pg_get_indexdef_for_dump(PG_FUNCTION_ARGS)
bool dumpSchemaOnly = PG_GETARG_BOOL(1);
PG_RETURN_TEXT_P(string_to_text(pg_get_indexdef_worker(indexrelid, 0, NULL, false, true, 0, dumpSchemaOnly,
false)));
true, false)));
}
Datum pg_get_indexdef_ext(PG_FUNCTION_ARGS)
@ -2972,7 +2972,7 @@ Datum pg_get_indexdef_ext(PG_FUNCTION_ARGS)
prettyFlags = pretty ? (PRETTYFLAG_PAREN | PRETTYFLAG_INDENT) : 0;
PG_RETURN_TEXT_P(string_to_text(pg_get_indexdef_worker(indexrelid, colno, NULL, colno != 0, true, prettyFlags,
false, false)));
false, false, false)));
}
/**
@ -3051,7 +3051,7 @@ static void GetIndexdefForIntervalPartTabDumpSchemaOnly(Oid indexrelid, RangePar
}
static void pg_get_indexdef_partitions(Oid indexrelid, Form_pg_index idxrec, bool showTblSpc, StringInfoData *buf,
bool dumpSchemaOnly, bool showSubpartitionLocal)
bool dumpSchemaOnly, bool showPartitionLocal, bool showSubpartitionLocal)
{
Oid relid = idxrec->indrelid;
/*
@ -3067,12 +3067,12 @@ static void pg_get_indexdef_partitions(Oid indexrelid, Form_pg_index idxrec, boo
appendStringInfo(buf, " LOCAL");
/*
* The LOCAL index information of the subpartition table is more.
* The LOCAL index information of the partition and subpartition table is more.
* And the meta-statements (e.g. \d \d+ \dS) are used more.
* Therefore, when the meta-statement is called, the subpartition LOCAL index information is not displayed.
* Therefore, when the meta-statement is called, the LOCAL index information is not displayed.
*/
bool isSub = RelationIsSubPartitioned(rel);
if (isSub && !showSubpartitionLocal) {
if ((!isSub && !showPartitionLocal) || (isSub && !showSubpartitionLocal)) {
heap_close(rel, NoLock);
return;
}
@ -3112,7 +3112,7 @@ static void pg_get_indexdef_partitions(Oid indexrelid, Form_pg_index idxrec, boo
* NULL then it points to an array of exclusion operator OIDs.
*/
static char *pg_get_indexdef_worker(Oid indexrelid, int colno, const Oid *excludeOps, bool attrsOnly, bool showTblSpc,
int prettyFlags, bool dumpSchemaOnly, bool showSubpartitionLocal)
int prettyFlags, bool dumpSchemaOnly, bool showPartitionLocal, bool showSubpartitionLocal)
{
/* might want a separate isConstraint parameter later */
bool isConstraint = (excludeOps != NULL);
@ -3316,7 +3316,8 @@ static char *pg_get_indexdef_worker(Oid indexrelid, int colno, const Oid *exclud
if (idxrelrec->parttype == PARTTYPE_PARTITIONED_RELATION &&
idxrelrec->relkind != RELKIND_GLOBAL_INDEX) {
pg_get_indexdef_partitions(indexrelid, idxrec, showTblSpc, &buf, dumpSchemaOnly, showSubpartitionLocal);
pg_get_indexdef_partitions(indexrelid, idxrec, showTblSpc, &buf, dumpSchemaOnly,
showPartitionLocal, showSubpartitionLocal);
}
/*

View File

@ -746,7 +746,7 @@ static Datum text_length_huge(Datum str)
*/
Datum textlen(PG_FUNCTION_ARGS)
{
Datum str = PG_GETARG_DATUM(0);
Datum str = fetch_real_lob_if_need(PG_GETARG_DATUM(0));
if (VARATT_IS_HUGE_TOAST_POINTER((varlena *)DatumGetTextPP(str))) {
return text_length_huge(str);
@ -1899,7 +1899,7 @@ Datum textne(PG_FUNCTION_ARGS)
{
Datum arg1 = PG_GETARG_DATUM(0);
Datum arg2 = PG_GETARG_DATUM(1);
if (VARATT_IS_HUGE_TOAST_POINTER(DatumGetPointer(arg1)) || VARATT_IS_HUGE_TOAST_POINTER(DatumGetPointer(arg2))) {
if (VARATT_IS_HUGE_TOAST_POINTER(DatumGetPointer(arg1)) && VARATT_IS_HUGE_TOAST_POINTER(DatumGetPointer(arg2))) {
ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("textne could not support more than 1GB clob/blob data")));
}
@ -2063,7 +2063,7 @@ Datum text_ge(PG_FUNCTION_ARGS)
{
text* arg1 = PG_GETARG_TEXT_PP(0);
text* arg2 = PG_GETARG_TEXT_PP(1);
if (VARATT_IS_HUGE_TOAST_POINTER((varlena *)arg1) || VARATT_IS_HUGE_TOAST_POINTER((varlena *)arg2)) {
if (VARATT_IS_HUGE_TOAST_POINTER((varlena *)arg1) && VARATT_IS_HUGE_TOAST_POINTER((varlena *)arg2)) {
ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("text_ge could not support more than 1GB clob/blob data")));
}

View File

@ -211,7 +211,7 @@ void LocalPartDefCache::Init()
}
m_global_partdefcache = t_thrd.lsc_cxt.lsc->GetGlobalPartDefCache();
m_db_id = t_thrd.lsc_cxt.lsc->my_database_id;
part_cache_need_eoxact_work = false;
PartCacheNeedEOXActWork = false;
m_is_inited = true;
}
@ -298,7 +298,7 @@ void LocalPartDefCache::AtEOXact_PartitionCache(bool isCommit)
* transaction, even though we could clear it at subtransaction end in
* some cases.
*/
if (!part_cache_need_eoxact_work
if (!GetPartCacheNeedEOXActWork()
#ifdef USE_ASSERT_CHECKING
&& !assert_enabled
#endif
@ -356,7 +356,7 @@ void LocalPartDefCache::AtEOXact_PartitionCache(bool isCommit)
}
/* Once done with the transaction, we can reset need_eoxact_work */
part_cache_need_eoxact_work = false;
SetPartCacheNeedEOXActWork(false);
}
void LocalPartDefCache::AtEOSubXact_PartitionCache(bool isCommit, SubTransactionId mySubid,
@ -366,7 +366,7 @@ void LocalPartDefCache::AtEOSubXact_PartitionCache(bool isCommit, SubTransaction
* Skip the relcache scan if nothing to do --- see notes for
* AtEOXact_PartitionCache.
*/
if (!part_cache_need_eoxact_work)
if (!GetPartCacheNeedEOXActWork())
return;
Dlelem *bucket_elt;

View File

@ -432,7 +432,6 @@ Size *GetSizeVfdCachePtr()
}
}
int GetVfdNfile()
{
if (EnableLocalSysCache()) {
@ -524,19 +523,49 @@ bool LocalSysDBCache::LocalSysDBCacheNeedClearMyDB(Oid db_id, const char *db_nam
strcmp(t_thrd.proc_cxt.MyProgName, "BootStrap") == 0
));
}
/* it is a weird design that we need access mydatabaseid before initsession.
* but for GSC mode, we do need aquire lock when cache hit and there are invalid msgs
* with session uninited and so u_sess->proc_cxt.MyDatabaseId is InvalidOid.
* 1 the publication feature will send all rels' invalmsgs even no refered ddl.
* 2 relations may have refcount leak, so we must rebuild them if cache hit.
* when we rebuild a relation, the session may be not uninited,
* and so u_sess->proc_cxt.MyDatabaseId is InvalidOid,
* so we use t_thrd.lsc_cxt.lsc->my_database_id on GSC mode */
Assert(CheckMyDatabaseMatch());
Assert(m_global_db != NULL);
/* if u_sess->proc_cxt.MyDatabaseId is InvalidOid, the session's status is uninit
* we will call SetDatabase to rewrite it.
* but beofre SetDatabase, we need the dbid to Accept Invalid msg */
bool lock_db_advance = u_sess->proc_cxt.MyDatabaseId == InvalidOid && IS_THREAD_POOL_WORKER;
/* cache hit, when initsession, we lock db to avoid alter db */
Oid old_db_id = t_thrd.proc->databaseId;
if (u_sess->proc_cxt.MyDatabaseId == InvalidOid && IS_THREAD_POOL_WORKER) {
LockSharedObject(DatabaseRelationId, my_database_id, 0, RowExclusiveLock);
if (lock_db_advance) {
Assert(u_sess->proc_cxt.MyDatabaseTableSpace == InvalidOid);
Assert(u_sess->proc_cxt.DatabasePath == NULL);
Assert(t_thrd.proc->databaseId == InvalidOid);
u_sess->proc_cxt.MyDatabaseId = my_database_id;
u_sess->proc_cxt.MyDatabaseTableSpace = my_database_tablespace;
/* use refer not copy, it will be rewritten when initsession */
u_sess->proc_cxt.DatabasePath = my_database_path;
/* we dont want to accept inval msg here, so use LockSharedObjectForSession to avoid it. */
LockSharedObjectForSession(DatabaseRelationId, my_database_id, 0, RowExclusiveLock);
t_thrd.proc->databaseId = my_database_id;
UnlockSharedObject(DatabaseRelationId, my_database_id, 0, RowExclusiveLock);
}
Assert(m_global_db != NULL);
if (m_global_db->m_isDead) {
t_thrd.proc->databaseId = old_db_id;
UnlockSharedObjectForSession(DatabaseRelationId, my_database_id, 0, RowExclusiveLock);
/* when we acquired the dblock, alter db transaction happened, and we should clear cache of mydb. */
if (m_global_db->m_isDead) {
t_thrd.proc->databaseId = InvalidOid;
u_sess->proc_cxt.MyDatabaseId = InvalidOid;
u_sess->proc_cxt.MyDatabaseTableSpace = InvalidOid;
u_sess->proc_cxt.DatabasePath = NULL;
return true;
}
} else if (m_global_db->m_isDead) {
return true;
}
return false;
}
@ -564,7 +593,6 @@ void LocalSysDBCache::LocalSysDBCacheClearMyDB(Oid db_id, const char *db_name)
MemoryContextResetAndDeleteChildren(lsc_mydb_memcxt);
is_inited = false;
other_space = ((AllocSet)lsc_top_memcxt)->totalSpace + ((AllocSet)lsc_share_memcxt)->totalSpace;
rel_index_rule_space = 0;
}
@ -593,29 +621,26 @@ void LocalSysDBCache::LocalSysDBCacheReSet()
UnRegisterRelCacheCallBack(&inval_cxt, RelfilenodeMapInvalidateCallback);
UnRegisterSysCacheCallBack(&inval_cxt, TABLESPACEOID, InvalidateTableSpaceCacheCallback);
MemoryContextResetAndDeleteChildren(lsc_mydb_memcxt);
MemoryContextResetAndDeleteChildren(lsc_share_memcxt);
MemoryContextDelete(lsc_mydb_memcxt);
MemoryContextDelete(lsc_share_memcxt);
lsc_share_memcxt =
AllocSetContextCreate(lsc_top_memcxt, "LocalSysCacheShareMemoryContext", ALLOCSET_DEFAULT_MINSIZE,
ALLOCSET_DEFAULT_INITSIZE, ALLOCSET_DEFAULT_MAXSIZE, STANDARD_CONTEXT);
lsc_mydb_memcxt =
AllocSetContextCreate(lsc_top_memcxt, "LocalSysCacheMyDBMemoryContext", ALLOCSET_DEFAULT_MINSIZE,
ALLOCSET_DEFAULT_INITSIZE, ALLOCSET_DEFAULT_MAXSIZE, STANDARD_CONTEXT);
MemoryContext old = MemoryContextSwitchTo(lsc_share_memcxt);
knl_u_relmap_init(&relmap_cxt);
MemoryContextSwitchTo(old);
other_space = ((AllocSet)lsc_top_memcxt)->totalSpace + ((AllocSet)lsc_share_memcxt)->totalSpace;
rel_index_rule_space = 0;
is_inited = false;
is_closed = false;
is_lsc_catbucket_created = false;
}
static bool LSCMemroyOverflow(uint64 total_space)
{
const uint32 kb_bit_double = 10;
if (unlikely(total_space < ((uint64)g_instance.attr.attr_memory.local_syscache_threshold << kb_bit_double))) {
return false;
}
return true;
}
bool LocalSysDBCache::LocalSysDBCacheNeedReBuild()
{
/* we have recovered from startup, redo may dont tell us inval msgs, so discard all lsc */
@ -626,15 +651,21 @@ bool LocalSysDBCache::LocalSysDBCacheNeedReBuild()
return true;
}
/* it seems only fmgr_info_cxt has no resowner to avoid mem leak.
* we assum 1kb memory leaked once */
/* we assum 1kb memory leaked once */
if (unlikely(abort_count > (uint64)g_instance.attr.attr_memory.local_syscache_threshold)) {
return true;
}
uint64 total_space = other_space + AllocSetContextUsedSpace((AllocSet)lsc_mydb_memcxt) +
AllocSetContextUsedSpace((AllocSet)u_sess->cache_mem_cxt) + rel_index_rule_space;
return LSCMemroyOverflow(total_space);
uint64 total_space =
((AllocSet)lsc_top_memcxt)->totalSpace +
((AllocSet)lsc_share_memcxt)->totalSpace +
((AllocSet)lsc_mydb_memcxt)->totalSpace +
((AllocSet)u_sess->cache_mem_cxt)->totalSpace +
rel_index_rule_space;
uint64 memory_upper_limit = ((uint64)g_instance.attr.attr_memory.local_syscache_threshold) << 10;
return total_space * (1 - MAX_LSC_FREESIZE_RATIO) > memory_upper_limit;
}
/* rebuild cache on memcxt of mydb or share, call it only before initsyscache */
@ -664,8 +695,23 @@ void LocalSysDBCache::LocalSysDBCacheReBuild()
bool LocalSysDBCache::LocalSysDBCacheNeedSwapOut()
{
uint64 total_space = other_space + rel_index_rule_space + ((AllocSet)lsc_mydb_memcxt)->totalSpace;
return LSCMemroyOverflow(total_space);
uint64 used_space =
AllocSetContextUsedSpace((AllocSet)lsc_top_memcxt) +
AllocSetContextUsedSpace((AllocSet)lsc_share_memcxt) +
AllocSetContextUsedSpace((AllocSet)lsc_mydb_memcxt) +
AllocSetContextUsedSpace((AllocSet)u_sess->cache_mem_cxt) +
rel_index_rule_space;
uint64 memory_upper_limit =
(((uint64)g_instance.attr.attr_memory.local_syscache_threshold) << 10) * cur_swapout_ratio;
bool need_swapout = used_space > memory_upper_limit;
/* swapout until memory used space is from MAX_LSC_SWAPOUT_RATIO=90% to MIN_LSC_SWAPOUT_RATIO=70% */
if (unlikely(need_swapout && cur_swapout_ratio == MAX_LSC_SWAPOUT_RATIO)) {
cur_swapout_ratio = MIN_LSC_SWAPOUT_RATIO;
} else if (unlikely(!need_swapout && cur_swapout_ratio == MIN_LSC_SWAPOUT_RATIO)) {
cur_swapout_ratio = MAX_LSC_SWAPOUT_RATIO;
}
return need_swapout;
}
void LocalSysDBCache::CloseLocalSysDBCache()
@ -688,7 +734,6 @@ void LocalSysDBCache::ClearSysCacheIfNecessary(Oid db_id, const char *db_name)
if (unlikely(!is_inited)) {
return;
}
other_space = ((AllocSet)lsc_top_memcxt)->totalSpace + ((AllocSet)lsc_share_memcxt)->totalSpace;
/* rebuild if memory gt double of threshold */
if (unlikely(LocalSysDBCacheNeedReBuild())) {
recovery_finished = g_instance.global_sysdbcache.recovery_finished;
@ -740,7 +785,6 @@ void LocalSysDBCache::CreateDBObject()
knl_u_relmap_init(&relmap_cxt);
MemoryContextSwitchTo(old);
m_shared_global_db = g_instance.global_sysdbcache.GetSharedGSCEntry();
other_space = ((AllocSet)lsc_top_memcxt)->totalSpace + ((AllocSet)lsc_share_memcxt)->totalSpace;
rel_index_rule_space = 0;
is_lsc_catbucket_created = false;
}
@ -753,9 +797,9 @@ void LocalSysDBCache::CreateCatBucket()
MemoryContext old = MemoryContextSwitchTo(lsc_share_memcxt);
systabcache.CreateCatBuckets();
MemoryContextSwitchTo(old);
other_space = ((AllocSet)lsc_top_memcxt)->totalSpace + ((AllocSet)lsc_share_memcxt)->totalSpace;
rel_index_rule_space = 0;
is_lsc_catbucket_created = true;
cur_swapout_ratio = MAX_LSC_SWAPOUT_RATIO;
}
void LocalSysDBCache::SetDatabaseName(const char *db_name)
@ -924,6 +968,8 @@ LocalSysDBCache::LocalSysDBCache()
got_pool_reload = false;
m_shared_global_db = NULL;
cur_swapout_ratio = MAX_LSC_SWAPOUT_RATIO;
is_lsc_catbucket_created = false;
is_closed = false;
is_inited = false;

View File

@ -356,7 +356,7 @@ void LocalSysTupCache::InitPhase2Impl()
{
Assert(m_is_inited);
Assert(!m_is_inited_phase2);
Assert(m_db_id == InvalidOid);
/* CacheIdGetGlobalSysTupCache maybe fail when memory fault */
Assert(m_global_systupcache == NULL);
/* for now we even dont know which db to connect */
if (m_relinfo.cc_relisshared) {
@ -509,7 +509,7 @@ LocalCatCTup *LocalSysTupCache::SearchTupleInternal(int nkeys, Datum v1, Datum v
/* if not found, search from global cache */
if (unlikely(!found)) {
ct = SearchTupleFromGlobal(arguments, hash_value, hash_index, level);
if (ct == NULL) {
if (unlikely(ct == NULL)) {
return NULL;
}
}
@ -529,8 +529,10 @@ LocalCatCTup *LocalSysTupCache::SearchTupleInternal(int nkeys, Datum v1, Datum v
cc_neg_hits++;
ct = NULL;
}
if (unlikely(!found)) {
RemoveTailTupleElements(hash_index);
}
RemoveTailTupleElements(hash_index);
return ct;
}
@ -665,15 +667,16 @@ LocalCatCList *LocalSysTupCache::SearchListInternal(int nkeys, Datum v1, Datum v
CACHE2_elog(DEBUG2, "SearchLocalCatCacheList(%s): found list", m_relinfo.cc_relname);
cc_lhits++;
found = true;
ResourceOwnerRememberLocalCatCList(LOCAL_SYSDB_RESOWNER, cl);
break;
}
if (unlikely(!found)) {
cl = SearchListFromGlobal(nkeys, arguments, hash_value, level);
ResourceOwnerRememberLocalCatCList(LOCAL_SYSDB_RESOWNER, cl);
RemoveTailListElements();
}
ResourceOwnerRememberLocalCatCList(LOCAL_SYSDB_RESOWNER, cl);
RemoveTailListElements();
return cl;
}
@ -817,12 +820,14 @@ LocalCatCTup *LocalSysTupCache::SearchLocalCatCTupleForProcAllArgs(
*/
if (likely(ct->global_ct != NULL)) {
CACHE3_elog(DEBUG2, "SearchLocalCatCache(%s): found in bucket %d", m_relinfo.cc_relname, hash_index);
ResourceOwnerEnlargeLocalCatCTup(LOCAL_SYSDB_RESOWNER);
ct->refcount++;
cc_hits++;
ResourceOwnerRememberLocalCatCTup(LOCAL_SYSDB_RESOWNER, ct);
}
RemoveTailTupleElements(hash_index);
if (unlikely(!found)) {
RemoveTailTupleElements(hash_index);
}
pfree_ext(argModes);
return ct;

View File

@ -367,7 +367,7 @@ void LocalTabDefCache::Init()
relcacheInvalsReceived = 0;
initFileRelationIds = NIL;
need_eoxact_work = false;
RelCacheNeedEOXActWork = false;
g_bucketmap_cache = NIL;
max_bucket_map_size = BUCKET_MAP_SIZE;
@ -816,8 +816,9 @@ void LocalTabDefCache::RememberToFreeTupleDescAtEOX(TupleDesc td)
{
if (EOXactTupleDescArray == NULL) {
MemoryContext oldcxt = MemoryContextSwitchTo(LocalMyDBCacheMemCxt());
EOXactTupleDescArrayLen = 16;
EOXactTupleDescArray = (TupleDesc *)palloc(EOXactTupleDescArrayLen * sizeof(TupleDesc));
const int default_len = 16;
EOXactTupleDescArray = (TupleDesc *)palloc(default_len * sizeof(TupleDesc));
EOXactTupleDescArrayLen = default_len;
NextEOXactTupleDescNum = 0;
MemoryContextSwitchTo(oldcxt);
} else if (NextEOXactTupleDescNum >= EOXactTupleDescArrayLen) {
@ -873,7 +874,7 @@ void LocalTabDefCache::AtEOXact_RelationCache(bool isCommit)
* transaction, even though we could clear it at subtransaction end in
* some cases.
*/
if (!LocalRelCacheNeedEOXactWork()
if (!GetRelCacheNeedEOXActWork()
#ifdef USE_ASSERT_CHECKING
&& !assert_enabled
#endif
@ -962,7 +963,7 @@ void LocalTabDefCache::AtEOXact_RelationCache(bool isCommit)
}
}
/* Once done with the transaction, we can reset u_sess->relcache_cxt.need_eoxact_work */
SetLocalRelCacheNeedEOXactWork(false);
SetRelCacheNeedEOXActWork(false);
}
/*
@ -979,7 +980,7 @@ void LocalTabDefCache::AtEOSubXact_RelationCache(bool isCommit, SubTransactionId
* Skip the relcache scan if nothing to do --- see notes for
* AtEOXact_RelationCache.
*/
if (!LocalRelCacheNeedEOXactWork())
if (!GetRelCacheNeedEOXActWork())
return;
Dlelem *bucket_elt;
@ -1117,7 +1118,7 @@ void LocalTabDefCache::ResetInitFlag()
relcacheInvalsReceived = 0;
initFileRelationIds = NIL;
need_eoxact_work = false;
RelCacheNeedEOXActWork = false;
g_bucketmap_cache = NIL;
max_bucket_map_size = 0;

View File

@ -473,7 +473,7 @@ Partition PartitionBuildLocalPartition(const char *relname, Oid partid, Oid part
part->pd_newRelfilenodeSubid = InvalidSubTransactionId;
/* must flag that we have rels created in this transaction */
SetPartCacheNeedEoxactWork(true);
SetPartCacheNeedEOXActWork(true);
/*
* initialize partition tuple form (caller may add/override data later)
@ -986,7 +986,7 @@ void AtEOXact_PartitionCache(bool isCommit)
* transaction, even though we could clear it at subtransaction end in
* some cases.
*/
if (!u_sess->cache_cxt.part_cache_need_eoxact_work
if (!GetPartCacheNeedEOXActWork()
#ifdef USE_ASSERT_CHECKING
&& !assert_enabled
#endif
@ -1040,7 +1040,7 @@ void AtEOXact_PartitionCache(bool isCommit)
}
/* Once done with the transaction, we can reset need_eoxact_work */
u_sess->cache_cxt.part_cache_need_eoxact_work = false;
SetPartCacheNeedEOXActWork(false);
}
/*
@ -1063,7 +1063,7 @@ void AtEOSubXact_PartitionCache(bool isCommit, SubTransactionId mySubid, SubTran
* Skip the relcache scan if nothing to do --- see notes for
* AtEOXact_PartitionCache.
*/
if (!u_sess->cache_cxt.part_cache_need_eoxact_work)
if (!GetPartCacheNeedEOXActWork())
return;
hash_seq_init(&status, u_sess->cache_cxt.PartitionIdCache);
@ -1705,7 +1705,7 @@ void PartitionSetNewRelfilenode(Relation parent, Partition part, TransactionId f
part->pd_newRelfilenodeSubid = GetCurrentSubTransactionId();
/* ... and now we have eoxact cleanup work to do */
SetPartCacheNeedEoxactWork(true);
SetPartCacheNeedEOXActWork(true);
}
static void PartitionParseRelOptions(Partition partition, HeapTuple tuple)

View File

@ -2456,7 +2456,7 @@ void RelationInitPhysicalAddr(Relation relation)
* tables and on user tables declared as additional catalog
* tables.
*/
if (HistoricSnapshotActive() && RelationIsAccessibleInLogicalDecoding(relation) && IsTransactionState()) {
if (HistoricSnapshotActive() && RelationIsAccessibleInLogicalDecoding(relation)) {
HeapTuple phys_tuple;
Form_pg_class physrel;
@ -4161,7 +4161,7 @@ void AtEOXact_RelationCache(bool isCommit)
* transaction, even though we could clear it at subtransaction end in
* some cases.
*/
if (!u_sess->relcache_cxt.need_eoxact_work
if (!GetRelCacheNeedEOXActWork()
#ifdef USE_ASSERT_CHECKING
&& !assert_enabled
#endif
@ -4253,7 +4253,7 @@ void AtEOXact_RelationCache(bool isCommit)
}
/* Once done with the transaction, we can reset u_sess->relcache_cxt.need_eoxact_work */
u_sess->relcache_cxt.need_eoxact_work = false;
SetRelCacheNeedEOXActWork(false);
}
/*
@ -4276,7 +4276,7 @@ void AtEOSubXact_RelationCache(bool isCommit, SubTransactionId mySubid, SubTrans
* Skip the relcache scan if nothing to do --- see notes for
* AtEOXact_RelationCache.
*/
if (!u_sess->relcache_cxt.need_eoxact_work)
if (!GetRelCacheNeedEOXActWork())
return;
hash_seq_init(&status, u_sess->relcache_cxt.RelationIdCache);
@ -4416,7 +4416,7 @@ Relation RelationBuildLocalRelation(const char* relname, Oid relnamespace, Tuple
rel->rd_newRelfilenodeSubid = InvalidSubTransactionId;
/* must flag that we have rels created in this transaction */
SetLocalRelCacheNeedEOXactWork(true);
SetRelCacheNeedEOXActWork(true);
/*
* create a new tuple descriptor from the one passed in. We do this
@ -4784,7 +4784,7 @@ void RelationSetNewRelfilenode(Relation relation, TransactionId freezeXid, Multi
*/
relation->rd_newRelfilenodeSubid = GetCurrentSubTransactionId();
/* ... and now we have eoxact cleanup work to do */
SetLocalRelCacheNeedEOXactWork(true);
SetRelCacheNeedEOXActWork(true);
}
RelFileNodeBackend CreateNewRelfilenode(Relation relation, TransactionId freezeXid)
@ -6064,7 +6064,7 @@ void RelationSetIndexList(Relation relation, List* indexIds, Oid oidIndex)
relation->rd_pkindex = InvalidOid;
relation->rd_indexvalid = 2; /* mark list as forced */
/* must flag that we have a forced index list */
SetLocalRelCacheNeedEOXactWork(true);
SetRelCacheNeedEOXActWork(true);
}
/*

View File

@ -3945,6 +3945,10 @@ void getElevelAndSqlstate(int* eLevel, int* sqlState)
*sqlState = t_thrd.log_cxt.errordata[t_thrd.log_cxt.errordata_stack_depth].sqlerrcode;
}
/*
* When the SQL statement is truncated, this function cannot perform normal password masking.
* maskPassword will return null if the statement does not need to be masked or any error occurs.
*/
char* maskPassword(const char* query_string)
{
char* mask_string = NULL;
@ -4232,6 +4236,19 @@ static void inline ClearYylval(const core_YYSTYPE *yylval)
securec_check(rc, "\0", "\0");
}
static int get_reallen_of_credential(char *param)
{
int len = 0;
for (int i = 0; param[i] != '\0'; i++) {
if (param[i] == '\'') {
len += 2;
} else {
len++;
}
}
return len;
}
/*
* Mask the password in statment CREATE ROLE, CREATE USER, ALTER ROLE, ALTER USER, CREATE GROUP
* SET ROLE, CREATE DATABASE LINK, and some function
@ -4248,7 +4265,9 @@ static char* mask_Password_internal(const char* query_string)
bool isPassword = false;
char* mask_string = NULL;
/* the function list need mask */
const char* funcs[] = {"dblink_connect", "create_credential", "pg_create_physical_replication_slot_extern"};
const char* funcs[] = {"dblink_connect", "create_credential"};
bool is_create_credential = false;
bool is_create_credential_passwd = false;
int funcNum = sizeof(funcs) / sizeof(funcs[0]);
int position[16] = {0};
int length[16] = {0};
@ -4260,7 +4279,8 @@ static char* mask_Password_internal(const char* query_string)
YYLTYPE conninfoStartPos = 0; /* connection start postion for CreateSubscriptionStmt */
/* the functions need to mask all contents */
const char* funCrypt[] = {"gs_encrypt_aes128", "gs_decrypt_aes128", "gs_encrypt", "gs_decrypt"};
const char* funCrypt[] = {"gs_encrypt_aes128", "gs_decrypt_aes128", "gs_encrypt", "gs_decrypt",
"pg_create_physical_replication_slot_extern"};
int funCryptNum = sizeof(funCrypt) / sizeof(funCrypt[0]);
bool isCryptFunc = false;
@ -4365,10 +4385,11 @@ static char* mask_Password_internal(const char* query_string)
if (subQueryLen < childStmtLen) {
/* Need more space, enlarge length is (childStmtLen - subQueryLen) */
maskStringLen += (childStmtLen - subQueryLen) + 1;
char* maskStrNew = (char*)selfpalloc0(maskStringLen);
char* maskStrNew = (char*)MemoryContextAllocZero(
SESS_GET_MEM_CXT_GROUP(MEMORY_CONTEXT_SECURITY), maskStringLen);
rc = memcpy_s(maskStrNew, maskStringLen, mask_string, strlen(mask_string));
securec_check(rc, "\0", "\0");
selfpfree(mask_string);
pfree_ext(mask_string);
mask_string = maskStrNew;
}
@ -4409,7 +4430,18 @@ static char* mask_Password_internal(const char* query_string)
/* Calcute the difference between origin password length and mask password length */
position[idx] -= truncateLen;
length[idx] = strlen(yylval.str);
if (!is_create_credential) {
length[idx] = strlen(yylval.str);
} else if (isPassword) {
is_create_credential_passwd = true;
length[idx] = strlen(yylval.str);
} else {
if (idx == 2 && !is_create_credential_passwd) {
length[idx] = get_reallen_of_credential(yylval.str);
} else {
length[idx] = 0;
}
}
++idx;
/* record the conninfo start pos, we will use it to calculate the actual length of conninfo */
@ -4463,10 +4495,11 @@ static char* mask_Password_internal(const char* query_string)
if (length[i] < maskLen) {
/* need more space. */
int plen = strlen(mask_string) + maskLen - length[i] + 1;
char* maskStrNew = (char*)selfpalloc0(plen);
char* maskStrNew = (char*)MemoryContextAllocZero(
SESS_GET_MEM_CXT_GROUP(MEMORY_CONTEXT_SECURITY), plen);
rc = memcpy_s(maskStrNew, plen, mask_string, strlen(mask_string));
securec_check(rc, "\0", "\0");
selfpfree(mask_string);
pfree_ext(mask_string);
mask_string = maskStrNew;
}
@ -4597,6 +4630,10 @@ static char* mask_Password_internal(const char* query_string)
/* first, check funcs[] */
for (i = 0; i < funcNum; ++i) {
if (pg_strcasecmp(yylval.str, funcs[i]) == 0) {
is_create_credential = false;
if (pg_strcasecmp(yylval.str, "create_credential") == 0) {
is_create_credential = true;
}
curStmtType = 8;
break;
}
@ -4962,6 +4999,7 @@ static char* mask_Password_internal(const char* query_string)
}
return mask_string;
}
static void eraseSingleQuotes(char* query_string)

View File

@ -59,12 +59,13 @@ bool open_join_children = true;
bool will_shutdown = false;
/* hard-wired binary version number */
const uint32 GRAND_VERSION_NUM = 92604;
const uint32 GRAND_VERSION_NUM = 92605;
const uint32 PREDPUSH_SAME_LEVEL_VERSION_NUM = 92522;
const uint32 UPSERT_WHERE_VERSION_NUM = 92514;
const uint32 FUNC_PARAM_COL_VERSION_NUM = 92500;
const uint32 SUBPARTITION_VERSION_NUM = 92436;
const uint32 PBESINGLEPARTITION_VERSION_NUM = 92523;
const uint32 DEFAULT_MAT_CTE_NUM = 92429;
const uint32 MATERIALIZED_CTE_NUM = 92424;
const uint32 HINT_ENHANCEMENT_VERSION_NUM = 92359;
@ -113,6 +114,8 @@ const uint32 SUPPORT_HASH_XLOG_VERSION_NUM = 92603;
/* This variable indicates wheather the instance is in progress of upgrade as a whole */
uint32 volatile WorkingGrandVersionNum = GRAND_VERSION_NUM;
const uint32 INVALID_INVISIBLE_TUPLE_VERSION = 92605;
const uint32 ENHANCED_TUPLE_LOCK_VERSION_NUM = 92583;
const uint32 TWOPHASE_FILE_VERSION = 92414;
@ -129,6 +132,8 @@ bool InplaceUpgradePrecommit = false;
const uint32 DISASTER_READ_VERSION_NUM = 92592;
const uint32 PITR_INIT_VERSION_NUM = 92599;
#ifdef PGXC
bool useLocalXid = false;
#endif

View File

@ -66,6 +66,7 @@
#include "storage/ipc.h"
#include "storage/smgr/knl_usync.h"
#include "storage/lmgr.h"
#include "storage/predicate.h"
#include "storage/proc.h"
#include "storage/procarray.h"
#include "storage/procsignal.h"
@ -2031,7 +2032,6 @@ void PostgresInitializer::InitThread()
on_shmem_exit(ShutdownXLOG, 0);
}
}
void PostgresInitializer::InitLoadLocalSysCache(Oid db_oid, const char *db_name)
{
if(!EnableLocalSysCache()) {
@ -2068,6 +2068,11 @@ void PostgresInitializer::InitLoadLocalSysCache(Oid db_oid, const char *db_name)
ResourceOwnerRelease(t_thrd.lsc_cxt.lsc->local_sysdb_resowner, RESOURCE_RELEASE_LOCKS, false, true);
ResourceOwnerRelease(t_thrd.lsc_cxt.lsc->local_sysdb_resowner, RESOURCE_RELEASE_AFTER_LOCKS, false, true);
/* we are not in transaction, so resowner cannot help us release proclocks and predicatelocks.
* we do nothing above except init and load syscache, so no undowork need. ProcReleaseLocks always need
* */
ProcReleaseLocks(false);
ReleasePredicateLocks(false);
/* lwlocks arre released at sigsetjmp */
/* recovery CurrentResourceOwner */
@ -2590,8 +2595,9 @@ void PostgresInitializer::SetDatabasePath()
ValidatePgVersion(m_fullpath);
/* This should happen only once per process */
Assert(!u_sess->proc_cxt.DatabasePath);
/* This should happen only once per process, for gsc, it may equal the pointer belongs to lsc */
Assert(!u_sess->proc_cxt.DatabasePath ||
(EnableLocalSysCache() && u_sess->proc_cxt.DatabasePath == t_thrd.lsc_cxt.lsc->my_database_path));
u_sess->proc_cxt.DatabasePath = MemoryContextStrdup(
SESS_GET_MEM_CXT_GROUP(MEMORY_CONTEXT_EXECUTOR), m_fullpath);
if (EnableLocalSysCache()) {

View File

@ -829,10 +829,6 @@ int pg_mbstrlen_with_len_toast(const char* mbstr, int* limit)
{
int len = 0;
/* optimization for single byte encoding */
if (pg_database_encoding_max_length() == 1) {
return *limit;
}
while (*limit > 0 && *mbstr) {
int l = pg_mblen(mbstr);

View File

@ -26,15 +26,6 @@
#include "utils/oidrbtree.h"
#include "utils/memutils.h"
MemoryContext GetOidRBTreeMemory()
{
if (!t_thrd.security_policy_cxt.OidRBTreeMemoryContext) {
t_thrd.security_policy_cxt.OidRBTreeMemoryContext = AllocSetContextCreate(TopMemoryContext, "OidRBTreeMemory",
ALLOCSET_DEFAULT_MINSIZE, ALLOCSET_DEFAULT_INITSIZE, ALLOCSET_DEFAULT_MAXSIZE);
}
return t_thrd.security_policy_cxt.OidRBTreeMemoryContext;
}
void DeleteOidRBTreeMemory()
{
if (t_thrd.security_policy_cxt.OidRBTreeMemoryContext != NULL) {
@ -72,9 +63,7 @@ static void OidRBCombine(RBNode* existing, const RBNode* newdata, void* arg)
/* Allocator function for oid rbtree */
static RBNode* OidRBAlloc(void* arg)
{
MemoryContext oldContext = MemoryContextSwitchTo(GetOidRBTreeMemory());
OidRBNode* oidRBNode = static_cast<OidRBNode*>(palloc(sizeof(OidRBNode)));
(void)MemoryContextSwitchTo(oldContext);
return (RBNode*)oidRBNode;
}
@ -87,9 +76,7 @@ static void OidRBDealloc(RBNode* rbNode, void* arg)
OidRBTree* CreateOidRBTree()
{
MemoryContext oldContext = MemoryContextSwitchTo(GetOidRBTreeMemory());
OidRBTree* oidRBTree = rb_create(sizeof(OidRBNode), OidRBComparator, OidRBCombine, OidRBAlloc, OidRBDealloc, NULL);
(void)MemoryContextSwitchTo(oldContext);
return oidRBTree;
}
@ -97,14 +84,12 @@ static List* OidRBTreeGetNodeList(OidRBTree& oidRBtree)
{
List* nodeList = NIL;
OidRBTree* tree = &oidRBtree;
MemoryContext oldContext = MemoryContextSwitchTo(GetOidRBTreeMemory());
rb_begin_iterate(tree, InvertedWalk);
RBNode *node = rb_iterate(tree);
while (node != NULL) {
nodeList = lappend(nodeList, node);
node = rb_iterate(tree);
}
(void)MemoryContextSwitchTo(oldContext);
return nodeList;
}

View File

@ -39,7 +39,9 @@
#include "catalog/pg_hashbucket_fn.h"
/*
* ResourceOwner objects look like this
* ResourceOwner objects look like this. When tracking new types of resource,
* you must at least add the 'Remember' interface for that resource and adapt
* the 'ResourceOwnerConcat' function.
*/
typedef struct ResourceOwnerData {
ResourceOwner parent; /* NULL if no parent (toplevel owner) */
@ -542,6 +544,174 @@ void ResourceOwnerDelete(ResourceOwner owner)
ResourceOwnerFreeOwner(owner, true);
}
/*
* Part 1 of 'ResourceOwnerConcat'. Concatenate the top 12 resources of two owners.
*/
static void ResourceOwnerConcatPart1(ResourceOwner target, ResourceOwner source)
{
int i;
for (i = 0; i < source->nbuffers; i++) {
ResourceOwnerEnlargeBuffers(target);
ResourceOwnerRememberBuffer(target, source->buffers[i]);
}
for (i = 0; i < source->nlocalcatclist; i++) {
ResourceOwnerEnlargeLocalCatCList(target);
ResourceOwnerRememberLocalCatCList(target, source->localcatclists[i]);
}
for (i = 0; i < source->nlocalcatctup; i++) {
ResourceOwnerEnlargeLocalCatCTup(target);
ResourceOwnerRememberLocalCatCTup(target, source->localcatctups[i]);
}
for (i = 0; i < source->nglobalcatctup; i++) {
ResourceOwnerEnlargeGlobalCatCTup(target);
ResourceOwnerRememberGlobalCatCTup(target, source->globalcatctups[i]);
}
for (i = 0; i < source->nglobalcatclist; i++) {
ResourceOwnerEnlargeGlobalCatCList(target);
ResourceOwnerRememberGlobalCatCList(target, source->globalcatclists[i]);
}
for (i = 0; i < source->nglobalbaseentry; i++) {
ResourceOwnerEnlargeGlobalBaseEntry(target);
ResourceOwnerRememberGlobalBaseEntry(target, source->globalbaseentries[i]);
}
for (i = 0; i < source->nglobaldbentry; i++) {
ResourceOwnerEnlargeGlobalDBEntry(target);
ResourceOwnerRememberGlobalDBEntry(target, source->globaldbentries[i]);
}
for (i = 0; i < source->nglobalisexclusive; i++) {
ResourceOwnerEnlargeGlobalIsExclusive(target);
ResourceOwnerRememberGlobalIsExclusive(target, source->globalisexclusives[i]);
}
for (i = 0; i < source->ncatrefs; i++) {
ResourceOwnerEnlargeCatCacheRefs(target);
ResourceOwnerRememberCatCacheRef(target, source->catrefs[i]);
}
for (i = 0; i < source->ncatlistrefs; i++) {
ResourceOwnerEnlargeCatCacheListRefs(target);
ResourceOwnerRememberCatCacheListRef(target, source->catlistrefs[i]);
}
for (i = 0; i < source->nrelrefs; i++) {
ResourceOwnerEnlargeRelationRefs(target);
ResourceOwnerRememberRelationRef(target, source->relrefs[i]);
}
for (i = 0; i < source->npartrefs; i++) {
ResourceOwnerEnlargePartitionRefs(target);
ResourceOwnerRememberPartitionRef(target, source->partrefs[i]);
}
}
/*
* Part 2 of 'ResourceOwnerConcat'. Concatenate the remaining resources of two owners.
*/
static void ResourceOwnerConcatPart2(ResourceOwner target, ResourceOwner source)
{
int i;
for (i = 0; i < source->nfakerelrefs; i++) {
dlist_push_tail(&(target->fakerelrefs_list), dlist_pop_head_node(&(source->fakerelrefs_list)));
target->nfakerelrefs++;
}
for (i = 0; i < source->nfakepartrefs; i++) {
ResourceOwnerEnlargeFakepartRefs(target);
ResourceOwnerRememberFakepartRef(target, source->fakepartrefs[i]);
}
for (i = 0; i < source->nplanrefs; i++) {
ResourceOwnerEnlargePlanCacheRefs(target);
ResourceOwnerRememberPlanCacheRef(target, source->planrefs[i]);
}
for (i = 0; i < source->ntupdescs; i++) {
ResourceOwnerEnlargeTupleDescs(target);
ResourceOwnerRememberTupleDesc(target, source->tupdescs[i]);
}
for (i = 0; i < source->nsnapshots; i++) {
ResourceOwnerEnlargeSnapshots(target);
ResourceOwnerRememberSnapshot(target, source->snapshots[i]);
}
for (i = 0; i < source->nfiles; i++) {
ResourceOwnerEnlargeFiles(target);
ResourceOwnerRememberFile(target, source->files[i]);
}
for (i = 0; i < source->nDataCacheSlots; i++) {
ResourceOwnerEnlargeDataCacheSlot(target);
ResourceOwnerRememberDataCacheSlot(target, source->dataCacheSlots[i]);
}
for (i = 0; i < source->nMetaCacheSlots; i++) {
ResourceOwnerEnlargeMetaCacheSlot(target);
ResourceOwnerRememberMetaCacheSlot(target, source->metaCacheSlots[i]);
}
for (i = 0; i < source->nPthreadMutex; i++) {
ResourceOwnerEnlargePthreadMutex(target);
ResourceOwnerRememberPthreadMutex(target, source->pThdMutexs[i]);
}
for (i = 0; i < source->nPthreadRWlock; i++) {
ResourceOwnerEnlargePthreadRWlock(target);
ResourceOwnerRememberPthreadRWlock(target, source->pThdRWlocks[i]);
}
for (i = 0; i < source->npartmaprefs; i++) {
ResourceOwnerEnlargePartitionMapRefs(target);
ResourceOwnerRememberPartitionMapRef(target, source->partmaprefs[i]);
}
for (i = 0; i < source->nglobalMemContext; i++) {
ResourceOwnerEnlargeGMemContext(target);
ResourceOwnerRememberGMemContext(target, source->globalMemContexts[i]);
}
}
/* ResourceOwnerConcat
* Concatenate two owners.
*
* The resources traced by the 'source' are placed in the 'target' for tracing.
* The advantage is that the memory occupied by the 'source' owner can be released
* to reduce the memory consumed by tracing resources. When using a stream-plan,
* this is useful for preventing "memory is temporarily unavailable" error when
* executing a large number of SQLs in a single transaction/procedure.
*
* Note: After the invoking is complete, the memory of the 'source' should be release.
*/
void ResourceOwnerConcat(ResourceOwner target, ResourceOwner source)
{
Assert(target && source);
/*
* When modifying the structure of ResourceOwnerData, note that the ResourceOwnerConcat
* function needs to be adapted when tracing new types of resources.
*/
Assert(sizeof(ResourceOwnerData) == 448); /* The current size of ResourceOwnerData is 448 */
while (source->firstchild != NULL) {
ResourceOwnerConcat(target, source->firstchild);
}
/*
* ResourceOwner traces too many resources. To reduce cyclomatic complexity,
* the Concatenate operation is divided into two parts.
*/
ResourceOwnerConcatPart1(target, source);
ResourceOwnerConcatPart2(target, source);
}
/*
* Fetch parent of a ResourceOwner (returns NULL if top-level owner)
*/
@ -575,6 +745,14 @@ ResourceOwner ResourceOwnerGetFirstChild(ResourceOwner owner)
return owner->firstchild;
}
/*
* Fetch memory context of a ResourceOwner
*/
MemoryContext ResourceOwnerGetMemCxt(ResourceOwner owner)
{
return owner->memCxt;
}
/*
* Reassign a ResourceOwner to have a new parent
*/

View File

@ -2958,11 +2958,18 @@ for_control : for_variable K_IN
if ($1.rec)
{
#ifndef ENABLE_MULTIPLE_NODES
if (u_sess->attr.attr_sql.sql_compatibility == A_FORMAT && IMPLICIT_FOR_LOOP_VARIABLE) {
/* only A format and not in upgrade, IMPLICIT_FOR_LOOP_VARIABLE is valid */
if (u_sess->attr.attr_sql.sql_compatibility == A_FORMAT
&& IMPLICIT_FOR_LOOP_VARIABLE
&& u_sess->attr.attr_common.upgrade_mode == 0) {
BuildForQueryVariable(expr1, &newp->row, &newp->rec, $1.name, $1.lineno);
check_assignable((PLpgSQL_datum *)newp->rec ?
(PLpgSQL_datum *)newp->rec : (PLpgSQL_datum *)newp->row, @1);
} else {
/* check the sql */
if (u_sess->attr.attr_sql.sql_compatibility == A_FORMAT && ALLOW_PROCEDURE_COMPILE_CHECK) {
(void)getCursorTupleDesc(expr1, false, true);
}
newp->rec = $1.rec;
check_assignable((PLpgSQL_datum *) newp->rec, @1);
}
@ -2974,11 +2981,18 @@ for_control : for_variable K_IN
else if ($1.row)
{
#ifndef ENABLE_MULTIPLE_NODES
if (u_sess->attr.attr_sql.sql_compatibility == A_FORMAT && IMPLICIT_FOR_LOOP_VARIABLE) {
/* only A format and not in upgrade, IMPLICIT_FOR_LOOP_VARIABLE is valid */
if (u_sess->attr.attr_sql.sql_compatibility == A_FORMAT
&& IMPLICIT_FOR_LOOP_VARIABLE
&& u_sess->attr.attr_common.upgrade_mode == 0) {
BuildForQueryVariable(expr1, &newp->row, &newp->rec, $1.name, $1.lineno);
check_assignable((PLpgSQL_datum *)newp->rec ?
(PLpgSQL_datum *)newp->rec : (PLpgSQL_datum *)newp->row, @1);
} else {
/* check the sql */
if (u_sess->attr.attr_sql.sql_compatibility == A_FORMAT && ALLOW_PROCEDURE_COMPILE_CHECK) {
(void)getCursorTupleDesc(expr1, false, true);
}
newp->row = $1.row;
check_assignable((PLpgSQL_datum *) newp->row, @1);
}
@ -2990,11 +3004,18 @@ for_control : for_variable K_IN
else if ($1.scalar)
{
#ifndef ENABLE_MULTIPLE_NODES
if (u_sess->attr.attr_sql.sql_compatibility == A_FORMAT && IMPLICIT_FOR_LOOP_VARIABLE) {
/* only A format and not in upgrade, IMPLICIT_FOR_LOOP_VARIABLE is valid */
if (u_sess->attr.attr_sql.sql_compatibility == A_FORMAT
&& IMPLICIT_FOR_LOOP_VARIABLE
&& u_sess->attr.attr_common.upgrade_mode == 0) {
BuildForQueryVariable(expr1, &newp->row, &newp->rec, $1.name, $1.lineno);
check_assignable((PLpgSQL_datum *)newp->rec ?
(PLpgSQL_datum *)newp->rec : (PLpgSQL_datum *)newp->row, @1);
} else {
/* check the sql */
if (u_sess->attr.attr_sql.sql_compatibility == A_FORMAT && ALLOW_PROCEDURE_COMPILE_CHECK) {
(void)getCursorTupleDesc(expr1, false, true);
}
/* convert single scalar to list */
newp->row = make_scalar_list1($1.name, $1.scalar, $1.dno, $1.lineno, @1);
/* no need for check_assignable */
@ -4342,6 +4363,7 @@ stmt_open : K_OPEN cursor_variable
yyerror("syntax error");
}
}
#ifndef ENABLE_MULTIPLE_NODES
if (newp->query != NULL && u_sess->attr.attr_sql.sql_compatibility == A_FORMAT && ALLOW_PROCEDURE_COMPILE_CHECK) {
(void)getCursorTupleDesc(newp->query, false, true);
}
@ -4349,6 +4371,7 @@ stmt_open : K_OPEN cursor_variable
{
(void)getCursorTupleDesc(newp->dynquery, false, true);
}
#endif
}
else
{
@ -8773,9 +8796,11 @@ make_execsql_stmt(int firsttoken, int location)
pfree_ext(ds.data);
check_sql_expr(expr->query, location, 0);
#ifndef ENABLE_MULTIPLE_NODES
if (firsttoken == K_SELECT && u_sess->attr.attr_sql.sql_compatibility == A_FORMAT && ALLOW_PROCEDURE_COMPILE_CHECK) {
(void)getCursorTupleDesc(expr, false, true);
}
#endif
execsql = (PLpgSQL_stmt_execsql *)palloc(sizeof(PLpgSQL_stmt_execsql));
execsql->cmd_type = PLPGSQL_STMT_EXECSQL;
execsql->lineno = plpgsql_location_to_lineno(location);

View File

@ -752,6 +752,7 @@ static PLpgSQL_function* do_compile(FunctionCallInfo fcinfo, HeapTuple proc_tup,
func->resolve_option = GetResolveOption();
func->invalItems = NIL;
func->is_autonomous = false;
func->is_insert_gs_source = false;
func->pkg_oid = pkgoid;
func->fn_searchpath->addCatalog = true;
@ -1420,6 +1421,7 @@ PLpgSQL_function* plpgsql_compile_inline(char* proc_source)
func->fn_retbyval = true;
func->fn_rettyplen = sizeof(int32);
func->is_autonomous = false;
func->is_insert_gs_source = false;
getTypeInputInfo(VOIDOID, &typinput, &func->fn_rettypioparam);
fmgr_info(typinput, &(func->fn_retinput));

View File

@ -258,7 +258,7 @@ static PLpgSQL_rec* copyPLpgsqlRec(PLpgSQL_rec* src);
static PLpgSQL_recfield* copyPLpgsqlRecfield(PLpgSQL_recfield* src);
static List* invalid_depend_func_and_packgae(Oid pkgOid);
static void ReportCompileConcurrentError(const char* objName, bool isPackage);
static Datum CopyFcinfoArgValue(Oid typOid, Datum value);
/* ----------
* plpgsql_check_line_validity Called by the debugger plugin for
* validating a given linenumber
@ -838,9 +838,7 @@ Datum plpgsql_exec_autonm_function(PLpgSQL_function* func,
#ifndef ENABLE_MULTIPLE_NODES
uint64 sessionId = IS_THREAD_POOL_WORKER ? u_sess->session_id : t_thrd.proc_cxt.MyProcPid;
/* add session package values to global for autonm session, to restore package values */
if (OidIsValid(func->fn_oid)) {
BuildSessionPackageRuntimeForAutoSession(sessionId, u_sess->autonomous_parent_sessionid, &estate, func);
}
BuildSessionPackageRuntimeForAutoSession(sessionId, u_sess->autonomous_parent_sessionid, &estate, func);
#endif
/* Statement concatenation. If the block is an anonymous block, the entire anonymous block is returned. */
@ -1011,8 +1009,7 @@ Datum plpgsql_exec_function(PLpgSQL_function* func, FunctionCallInfo fcinfo, boo
#ifndef ENABLE_MULTIPLE_NODES
check_debug(func, &estate);
bool isExecAutoFunc = OidIsValid(func->fn_oid) &&
u_sess->is_autonomous_session == true && u_sess->SPI_cxt._connected == 0;
bool isExecAutoFunc = u_sess->is_autonomous_session == true && u_sess->SPI_cxt._connected == 0;
/* when exec autonomous transaction procedure, need update package values by parent session */
if (isExecAutoFunc) {
initAutoSessionPkgsValue(u_sess->autonomous_parent_sessionid);
@ -1083,12 +1080,12 @@ Datum plpgsql_exec_function(PLpgSQL_function* func, FunctionCallInfo fcinfo, boo
while (argmodes[outArgCnt] == PROARGMODE_OUT) {
outArgCnt++;
}
var->value = fcinfo->arg[outArgCnt];
var->value = CopyFcinfoArgValue(fcinfo->argTypes[outArgCnt], fcinfo->arg[outArgCnt]);
var->isnull = fcinfo->argnull[outArgCnt];
var->freeval = false;
outArgCnt++;
} else {
var->value = fcinfo->arg[i];
var->value = CopyFcinfoArgValue(fcinfo->argTypes[i], fcinfo->arg[i]);
var->isnull = fcinfo->argnull[i];
var->freeval = false;
}
@ -1469,6 +1466,25 @@ Datum plpgsql_exec_function(PLpgSQL_function* func, FunctionCallInfo fcinfo, boo
return estate.retval;
}
static Datum CopyFcinfoArgValue(Oid typOid, Datum value)
{
#ifdef ENABLE_MULTIPLE_NODES
return value;
#endif
if (!OidIsValid(typOid)) {
return value;
}
/*
* For centralized database, package value may be in param.
* In this case, the value should be copyed, becaues the ref
* value may be influenced by procedure.
*/
bool typByVal = false;
int16 typLen;
get_typlenbyval(typOid, &typLen, &typByVal);
return datumCopy(value, typByVal, typLen);
}
static void RecordSetGeneratedField(PLpgSQL_rec *recNew)
{
int natts = recNew->tupdesc->natts;
@ -4580,16 +4596,10 @@ static int exec_stmt_return(PLpgSQL_execstate* estate, PLpgSQL_stmt_return* stmt
case PLPGSQL_DTYPE_VAR: {
PLpgSQL_var* var = (PLpgSQL_var*)retvar;
Datum value = var->value;
if (is_external_clob(var->datatype->typoid, var->isnull, value)) {
bool is_null = false;
bool is_have_huge_clob = false;
struct varatt_lob_pointer* lob_pointer = (varatt_lob_pointer*)(VARDATA_EXTERNAL(value));
value = fetch_lob_value_from_tuple(lob_pointer, InvalidOid, &is_null, &is_have_huge_clob);
if (is_have_huge_clob) {
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("huge clob do not support as return parameter")));
}
if (is_huge_clob(var->datatype->typoid, var->isnull, value)) {
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("huge clob do not support as return parameter")));
}
if (need_param_seperation) {
estate->paramval = value;
@ -5435,7 +5445,7 @@ static int exec_stmt_execsql(PLpgSQL_execstate* estate, PLpgSQL_stmt_execsql* st
bool has_alloc = false;
TransactionId oldTransactionId = SPI_get_top_transaction_id();
/*
* On the first call for this statement generate the plan, and detect
* whether the statement is INSERT/UPDATE/DELETE/MERGE
@ -5467,7 +5477,19 @@ static int exec_stmt_execsql(PLpgSQL_execstate* estate, PLpgSQL_stmt_execsql* st
if (ENABLE_CN_GPC && g_instance.plan_cache->CheckRecreateSPICachePlan(expr->plan)) {
g_instance.plan_cache->RecreateSPICachePlan(expr->plan);
}
#ifndef ENABLE_MULTIPLE_NODES
ListCell* l = NULL;
bool isforbid = true;
bool savedisAllowCommitRollback = false;
bool needResetErrMsg = false;
foreach (l, SPI_plan_get_plan_sources(expr->plan)) {
CachedPlanSource* plansource = (CachedPlanSource*)lfirst(l);
isforbid = CheckElementParsetreeTag(plansource->raw_parse_tree);
if (isforbid) {
needResetErrMsg = stp_disable_xact_and_set_err_msg(&savedisAllowCommitRollback, STP_XACT_COMPL_SQL);
}
}
#endif
/*
* Set up ParamListInfo (hook function and possibly data values)
*/
@ -5513,10 +5535,6 @@ static int exec_stmt_execsql(PLpgSQL_execstate* estate, PLpgSQL_stmt_execsql* st
plpgsql_estate = estate;
#ifndef ENABLE_MULTIPLE_NODES
t_thrd.xact_cxt.isSelectInto = stmt->into;
#endif
/*
* Execute the plan
*/
@ -5529,7 +5547,11 @@ static int exec_stmt_execsql(PLpgSQL_execstate* estate, PLpgSQL_stmt_execsql* st
// This is used for nested STP. If the transaction Id changed,
// then need to create new econtext for the TopTransaction.
stp_check_transaction_and_create_econtext(estate,oldTransactionId);
#ifndef ENABLE_MULTIPLE_NODES
if (isforbid) {
stp_reset_xact_state_and_err_msg(savedisAllowCommitRollback, needResetErrMsg);
}
#endif
plpgsql_estate = NULL;
/*
@ -5721,7 +5743,6 @@ static int exec_stmt_execsql(PLpgSQL_execstate* estate, PLpgSQL_stmt_execsql* st
estate->cursor_return_data = saved_cursor_data;
estate->cursor_return_numbers = saved_cursor_numbers;
t_thrd.xact_cxt.isSelectInto = false;
return PLPGSQL_RC_OK;
}
@ -5900,6 +5921,9 @@ static int exec_stmt_dynexecute(PLpgSQL_execstate* estate, PLpgSQL_stmt_dynexecu
bool savedisAllowCommitRollback = false;
bool needResetErrMsg = false;
needResetErrMsg = stp_disable_xact_and_set_err_msg(&savedisAllowCommitRollback, STP_XACT_USED_AS_EXPR);
#else
/* Saves the status of whether to send commandId. */
bool saveSetSendCommandId = IsSendCommandId();
#endif
/*
* First we evaluate the string expression after the EXECUTE keyword. Its
@ -5994,6 +6018,8 @@ static int exec_stmt_dynexecute(PLpgSQL_execstate* estate, PLpgSQL_stmt_dynexecu
FormatCallStack* plcallstack = t_thrd.log_cxt.call_stack;
#ifndef ENABLE_MULTIPLE_NODES
estate_cursor_set(plcallstack);
#else
SetSendCommandId(saveSetSendCommandId);
#endif
if (plcallstack != NULL) {
t_thrd.log_cxt.call_stack = plcallstack->prev;
@ -6004,6 +6030,10 @@ static int exec_stmt_dynexecute(PLpgSQL_execstate* estate, PLpgSQL_stmt_dynexecu
}
PG_END_TRY();
#ifdef ENABLE_MULTIPLE_NODES
SetSendCommandId(saveSetSendCommandId);
#endif
/*
* This is used for nested STP. If the transaction Id changed,
* then need to create new econtext for the TopTransaction.
@ -6485,7 +6515,10 @@ static int exec_stmt_open(PLpgSQL_execstate* estate, PLpgSQL_stmt_open* stmt)
errmsg("cursor \"%s\" already in use in OPEN statement.", curname)));
}
}
#ifdef ENABLE_MULTIPLE_NODES
/* In distributed mode, the commandId is sent when a cursor is opened. */
SetSendCommandId(true);
#endif
/* ----------
* Process the OPEN according to it's type.
* ----------
@ -7395,16 +7428,10 @@ void exec_assign_value(PLpgSQL_execstate* estate, PLpgSQL_datum* target, Datum v
MemoryContext oldcontext = NULL;
AttrNumber attrno = ((PLpgSQL_arrayelem*)target)->assignattrno;
if (is_external_clob(valtype, *isNull, value)) {
bool is_null = false;
bool is_have_huge_clob = false;
struct varatt_lob_pointer* lob_pointer = (varatt_lob_pointer*)(VARDATA_EXTERNAL(value));
value = fetch_lob_value_from_tuple(lob_pointer, InvalidOid, &is_null, &is_have_huge_clob);
if (is_have_huge_clob) {
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("huge clob do not support as array element.")));
}
if (is_huge_clob(valtype, *isNull, value)) {
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("huge clob do not support as array element.")));
}
/*
* We need to do subscript evaluation, which might require
@ -7683,16 +7710,10 @@ void exec_assign_value(PLpgSQL_execstate* estate, PLpgSQL_datum* target, Datum v
MemoryContext oldcontext = NULL;
AttrNumber attrno = ((PLpgSQL_tableelem*)target)->assignattrno;
if (is_external_clob(valtype, *isNull, value)) {
bool is_null = false;
bool is_have_huge_clob = false;
struct varatt_lob_pointer* lob_pointer = (varatt_lob_pointer*)(VARDATA_EXTERNAL(value));
value = fetch_lob_value_from_tuple(lob_pointer, InvalidOid, &is_null, &is_have_huge_clob);
if (is_have_huge_clob) {
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("huge clob do not support as table of element.")));
}
if (is_huge_clob(valtype, *isNull, value)) {
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("huge clob do not support as table of element.")));
}
/*
@ -7965,17 +7986,6 @@ void exec_assign_value(PLpgSQL_execstate* estate, PLpgSQL_datum* target, Datum v
/*
* Target has a assign list
*/
if (is_external_clob(valtype, *isNull, value)) {
bool is_null = false;
bool is_have_huge_clob = false;
struct varatt_lob_pointer* lob_pointer = (varatt_lob_pointer*)(VARDATA_EXTERNAL(value));
value = fetch_lob_value_from_tuple(lob_pointer, InvalidOid, &is_null, &is_have_huge_clob);
if (is_have_huge_clob) {
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("huge clob do not support as record element.")));
}
}
PLpgSQL_assignlist* assignvar = (PLpgSQL_assignlist*)target;
List* assignlist = assignvar->assignlist;
PLpgSQL_datum* assigntarget = estate->datums[assignvar->targetno];
@ -9422,7 +9432,7 @@ static Datum exec_eval_expr(PLpgSQL_execstate* estate, PLpgSQL_expr* expr, bool*
static int exec_run_select(PLpgSQL_execstate* estate, PLpgSQL_expr* expr, long maxtuples,
Portal* portalP, bool isCollectParam)
{
ParamListInfo paramLI;
ParamListInfo paramLI = NULL;
int rc;
/*
@ -9437,8 +9447,12 @@ static int exec_run_select(PLpgSQL_execstate* estate, PLpgSQL_expr* expr, long m
/*
* Set up ParamListInfo (hook function and possibly data values)
* For validation estate->datums should be NULL, since there is
* no parameter set vo validation
*/
paramLI = setup_param_list(estate, expr);
if (estate->datums) {
paramLI = setup_param_list(estate, expr);
}
/*
* If a portal was requested, put the query into the portal
@ -10646,12 +10660,6 @@ static void exec_move_row(PLpgSQL_execstate* estate,
valtype = InvalidOid;
}
if (valtype == CLOBOID && !isnull && VARATT_IS_HUGE_TOAST_POINTER(value)) {
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("huge clob do not support as record element.")));
}
/* accept function's return value for cursor */
if (isnull == false && CheckTypeIsCursor(row, valtype, fnum) &&
estate->cursor_return_data != NULL) {
@ -10773,17 +10781,10 @@ HeapTuple make_tuple_from_row(PLpgSQL_execstate* estate, PLpgSQL_row* row, Tuple
exec_eval_datum(estate, estate->datums[row->varnos[i]], &fieldtypeid, &fieldtypmod, &dvalues[i], &nulls[i]);
}
if (is_external_clob(fieldtypeid, nulls[i], dvalues[i])) {
bool is_null = false;
bool is_have_huge_clob = false;
struct varatt_lob_pointer* lob_pointer = (varatt_lob_pointer*)(VARDATA_EXTERNAL(dvalues[i]));
dvalues[i] = fetch_lob_value_from_tuple(lob_pointer, InvalidOid, &is_null, &is_have_huge_clob);
if (is_have_huge_clob) {
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("huge clob do not support concat a row")));
}
nulls[i] = is_null;
if (is_huge_clob(fieldtypeid, nulls[i], dvalues[i])) {
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("huge clob do not support concat a row")));
}
if (estate->is_exception && fieldtypeid == REFCURSOROID) {

View File

@ -186,6 +186,7 @@ static SessionPackageRuntime* CopySessionPackageRuntime(SessionPackageRuntime *r
sessPkgRuntime->portalContext = CopyPortalContexts(runtime->portalContext);
sessPkgRuntime->portalData = CopyPortalDatas(runtime);
sessPkgRuntime->funcValInfo = CopyFuncInfoDatas(runtime);
sessPkgRuntime->is_insert_gs_source = runtime->is_insert_gs_source;
MemoryContextSwitchTo(oldCtx);
return sessPkgRuntime;
}

View File

@ -219,7 +219,9 @@ static void InsertGsSource(Oid objId, Oid nspid, const char* name, const char* t
{
(void)CompileStatusSwtichTo(NONE_STATUS);
u_sess->plsql_cxt.curr_compile_context = NULL;
u_sess->plsql_cxt.is_insert_gs_source = true;
ExecuteDoStmt(stmt, true);
u_sess->plsql_cxt.is_insert_gs_source = false;
}
PG_CATCH();
{
@ -228,6 +230,7 @@ static void InsertGsSource(Oid objId, Oid nspid, const char* name, const char* t
}
(void)CompileStatusSwtichTo(save_compile_status);
u_sess->plsql_cxt.curr_compile_context = save_compile_context;
u_sess->plsql_cxt.is_insert_gs_source = false;
clearCompileContextList(save_compile_list_length);
PG_RE_THROW();
}
@ -745,6 +748,8 @@ Datum plpgsql_call_handler(PG_FUNCTION_ARGS)
u_sess->opt_cxt.is_stream = true;
u_sess->opt_cxt.is_stream_support = true;
}
/* Saves the status of whether to send commandId. */
bool saveSetSendCommandId = IsSendCommandId();
#else
int outerDop = u_sess->opt_cxt.query_dop;
u_sess->opt_cxt.query_dop = 1;
@ -821,6 +826,7 @@ Datum plpgsql_call_handler(PG_FUNCTION_ARGS)
PLpgSQL_compile_context* save_compile_context = u_sess->plsql_cxt.curr_compile_context;
int save_compile_list_length = list_length(u_sess->plsql_cxt.compile_context_list);
int save_compile_status = u_sess->plsql_cxt.compile_status;
PG_TRY();
{
/*
@ -873,7 +879,6 @@ Datum plpgsql_call_handler(PG_FUNCTION_ARGS)
estate_cursor_set(plcallstack);
#endif
if (plcallstack != NULL) {
t_thrd.log_cxt.call_stack = plcallstack->prev;
}
@ -970,7 +975,9 @@ Datum plpgsql_call_handler(PG_FUNCTION_ARGS)
if (u_sess->SPI_cxt._connected == 0) {
t_thrd.utils_cxt.STPSavedResourceOwner = NULL;
}
#ifdef ENABLE_MULTIPLE_NODES
SetSendCommandId(saveSetSendCommandId);
#endif
/* ErrorData could be allocted in SPI's MemoryContext, copy it. */
oldContext = MemoryContextSwitchTo(oldContext);
ErrorData *edata = CopyErrorData();
@ -992,6 +999,10 @@ Datum plpgsql_call_handler(PG_FUNCTION_ARGS)
if (u_sess->SPI_cxt._connected == 0) {
t_thrd.utils_cxt.STPSavedResourceOwner = NULL;
}
#ifdef ENABLE_MULTIPLE_NODES
SetSendCommandId(saveSetSendCommandId);
#endif
/*
* Disconnect from SPI manager
*/
@ -1039,8 +1050,12 @@ Datum plpgsql_inline_handler(PG_FUNCTION_ARGS)
#ifndef ENABLE_MULTIPLE_NODES
int outerDop = u_sess->opt_cxt.query_dop;
u_sess->opt_cxt.query_dop = 1;
#else
/* Saves the status of whether to send commandId. */
bool saveSetSendCommandId = IsSendCommandId();
#endif
_PG_init();
AssertEreport(IsA(codeblock, InlineCodeBlock), MOD_PLSQL, "Inline code block is required.");
@ -1075,6 +1090,7 @@ Datum plpgsql_inline_handler(PG_FUNCTION_ARGS)
PG_END_TRY();
PGSTAT_END_PLSQL_TIME_RECORD(PL_COMPILATION_TIME);
func->is_insert_gs_source = u_sess->plsql_cxt.is_insert_gs_source;
/* Mark packages the function use, so them can't be deleted from under us */
AddPackageUseCount(func);
/* Mark the function as busy, just pro forma */
@ -1093,7 +1109,6 @@ Datum plpgsql_inline_handler(PG_FUNCTION_ARGS)
fake_fcinfo.flinfo = &flinfo;
flinfo.fn_oid = InvalidOid;
flinfo.fn_mcxt = CurrentMemoryContext;
PGSTAT_START_PLSQL_TIME_RECORD();
/* save flag for nest plpgsql compile */
save_compile_context = u_sess->plsql_cxt.curr_compile_context;
@ -1135,11 +1150,18 @@ Datum plpgsql_inline_handler(PG_FUNCTION_ARGS)
clearCompileContextList(save_compile_list_length);
/* AutonomousSession Disconnecting and releasing resources */
DestoryAutonomousSession(true);
#ifdef ENABLE_MULTIPLE_NODES
SetSendCommandId(saveSetSendCommandId);
#endif
PG_RE_THROW();
}
PG_END_TRY();
#ifdef ENABLE_MULTIPLE_NODES
SetSendCommandId(saveSetSendCommandId);
#endif
/* Disconnecting and releasing resources */
DestoryAutonomousSession(false);

View File

@ -1399,12 +1399,10 @@ void instr_stmt_report_basic_info()
}
if (to_update_db_name || to_update_user_name || to_update_client_addr) {
ResourceOwner old_cur_owner = t_thrd.utils_cxt.CurrentResourceOwner;
MemoryContext old_ctx = MemoryContextSwitchTo(t_thrd.mem_cxt.msg_mem_cxt);
t_thrd.utils_cxt.CurrentResourceOwner = ResourceOwnerCreate(NULL, "Full/Slow SQL",
t_thrd.utils_cxt.CurrentResourceOwner = ResourceOwnerCreate(old_cur_owner, "Full/Slow SQL",
THREAD_GET_MEM_CXT_GROUP(MEMORY_CONTEXT_DFX));
(void)MemoryContextSwitchTo(old_ctx);
old_ctx = MemoryContextSwitchTo(u_sess->statement_cxt.stmt_stat_cxt);
MemoryContext old_ctx = MemoryContextSwitchTo(u_sess->statement_cxt.stmt_stat_cxt);
if (to_update_db_name) {
u_sess->statement_cxt.db_name = get_database_name(beentry->st_databaseid);
}

View File

@ -494,30 +494,6 @@ void UpdateUniqueSQLVecSortStats(Batchsortstate* state, uint64 spill_count, Time
}
}
static void mask_unique_sql_str(UniqueSQL* unique_sql)
{
errno_t rc;
/* hide password */
if (unique_sql->unique_sql != NULL) {
char* mask_str = NULL;
mask_str = maskPassword(unique_sql->unique_sql);
if (mask_str != NULL) {
rc = memset_s(unique_sql->unique_sql, UNIQUE_SQL_MAX_LEN - 1, 0, UNIQUE_SQL_MAX_LEN - 1);
securec_check(rc, "\0", "\0");
/* after calling maskPassword, mask_str can be longer than original string,
* now the length of masked password('*..*') is fixed to 'password_min_length'(GUC) */
size_t valid_mask_len = strlen(mask_str) > (size_t)(UNIQUE_SQL_MAX_LEN - 1)
? (size_t)(UNIQUE_SQL_MAX_LEN - 1)
: strlen(mask_str);
rc = memcpy_s(unique_sql->unique_sql, UNIQUE_SQL_MAX_LEN - 1, mask_str, valid_mask_len);
securec_check(rc, "\0", "\0");
pfree(mask_str);
}
}
}
static void set_unique_sql_string_in_entry(UniqueSQL* entry, Query* query, const char* sql, int32 multi_sql_offset)
{
errno_t rc = EOK;
@ -536,7 +512,6 @@ static void set_unique_sql_string_in_entry(UniqueSQL* entry, Query* query, const
// generate and store normalized query string
if (normalized_unique_querystring(query, sql, entry->unique_sql, UNIQUE_SQL_MAX_LEN - 1,
multi_sql_offset)) {
mask_unique_sql_str(entry);
entry->unique_sql = trim(entry->unique_sql);
} else {
ereport(LOG,

View File

@ -203,12 +203,11 @@ bool normalized_unique_querystring(Query* query, const char* query_string, char*
}
bool result = true;
char* norm_query = NULL;
char *norm_query = NULL, *mask_str = NULL;
int encoding = GetDatabaseEncoding();
int query_len;
pgssJumbleState jstate;
errno_t rc;
rc = memset_s(&jstate, sizeof(jstate), 0, sizeof(jstate));
errno_t rc = memset_s(&jstate, sizeof(jstate), 0, sizeof(jstate));
securec_check(rc, "\0", "\0");
query_len = strlen(query_string);
@ -221,6 +220,12 @@ bool normalized_unique_querystring(Query* query, const char* query_string, char*
result = false;
}
}
} else {
mask_str = maskPassword(query_string);
if (mask_str != NULL) {
query_string = mask_str;
query_len = strlen(mask_str);
}
}
if (result) {
@ -235,6 +240,7 @@ bool normalized_unique_querystring(Query* query, const char* query_string, char*
query_string = builtin_unique_sql->unique_sql;
query_len = builtin_unique_sql->unique_sql_len;
}
if (query_len > buf_len) {
query_len = pg_encoding_mbcliplen(encoding, query_string, query_len,
g_instance.attr.attr_common.pgstat_track_activity_query_size - 1);
@ -245,6 +251,7 @@ bool normalized_unique_querystring(Query* query, const char* query_string, char*
}
}
pfree_ext(mask_str);
return result;
}
/*

View File

@ -936,7 +936,7 @@ void RebuildPartitonMap(PartitionMap* oldMap, PartitionMap* newMap)
}
} else {
oldMap->isDirty = true;
SetLocalRelCacheNeedEOXactWork(true);
SetRelCacheNeedEOXActWork(true);
elog(LOG, "map refcount is not zero when RebuildPartitonMap ");
}
}

View File

@ -14,7 +14,7 @@ set(CMAKE_MODULE_PATH
add_subdirectory(kernel)
add_subdirectory(db4ai)
if(NOT "${ENABLE_LITE_MODE}" STREQUAL "ON")
if(NOT "${ENABLE_LITE_MODE}" STREQUAL "ON" AND "${ENABLE_MULTIPLE_NODES}" STREQUAL "OFF")
install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/tools/ DESTINATION bin/dbmind)
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/gs_dbmind
PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE

View File

@ -257,8 +257,9 @@ static Datum pca_predict(const Matrix *features, const Matrix *weights,
static HyperparameterDefinition pca_hyperparameter_definitions[] = {
HYPERPARAMETER_INT4("number_components", 1, 1, true, INT32_MAX, true, HyperparametersGD, number_dimensions,
HP_NO_AUTOML()),
HYPERPARAMETER_INT4("batch_size", 1000, 1, true, INT32_MAX, true, HyperparametersGD, batch_size, HP_NO_AUTOML()),
HYPERPARAMETER_INT4("max_iterations", 100, 1, true, INT32_MAX, true, HyperparametersGD, max_iterations,
HYPERPARAMETER_INT4("batch_size", 1000, 1, true, MAX_BATCH_SIZE, true, HyperparametersGD, batch_size,
HP_NO_AUTOML()),
HYPERPARAMETER_INT4("max_iterations", 100, 1, true, ITER_MAX, true, HyperparametersGD, max_iterations,
HP_NO_AUTOML()),
HYPERPARAMETER_INT4("max_seconds", 0, 0, true, INT32_MAX, true, HyperparametersGD, max_seconds, HP_NO_AUTOML()),
HYPERPARAMETER_FLOAT8("tolerance", 0.0005, 0.0, true, DBL_MAX, true, HyperparametersGD, tolerance, HP_NO_AUTOML()),

View File

@ -1041,10 +1041,11 @@ HyperparameterDefinition kmeans_hyperparameter_definitions[] = {
HYPERPARAMETER_INT4("verbose", 0, 0, true, 2, true, HyperparametersKMeans, verbosity, HP_NO_AUTOML()),
HYPERPARAMETER_INT4("num_centroids", 1, 1, true, 1000000, true, HyperparametersKMeans, num_centroids,
HP_NO_AUTOML()),
HYPERPARAMETER_INT4("max_iterations", 10, 1, true, INT32_MAX, true, HyperparametersKMeans, num_iterations,
HYPERPARAMETER_INT4("max_iterations", 10, 1, true, ITER_MAX, true, HyperparametersKMeans, num_iterations,
HP_NO_AUTOML()),
HYPERPARAMETER_INT4("num_features", 0, 1, true, INT32_MAX, true, HyperparametersKMeans, n_features, HP_NO_AUTOML()),
HYPERPARAMETER_INT4("batch_size", 1000, 1, true, 1000000, true, HyperparametersKMeans, batch_size, HP_NO_AUTOML()),
HYPERPARAMETER_INT4("batch_size", 1000, 1, true, MAX_BATCH_SIZE, true, HyperparametersKMeans, batch_size,
HP_NO_AUTOML()),
HYPERPARAMETER_INT4("seed", 0, 0, true, INT32_MAX, true, HyperparametersKMeans, external_seed,
HP_AUTOML_INT(1, INT32_MAX, 1, ProbabilityDistribution::UNIFORM_RANGE)),
HYPERPARAMETER_FLOAT8("tolerance", 0.00001, 0.0, false, 1.0, true, HyperparametersKMeans, tolerance,

View File

@ -80,8 +80,11 @@ static MemoryContext g_xgboostMcxt = NULL;
#define safe_xgboost(call) { \
int err = (call); \
if (err != 0) { \
char *str = const_cast<char*>(g_xgboostApi->XGBGetLastError()); \
char *res = strchr(str, '\n'); \
*res = '\0'; \
ereport(ERROR, (errmodule(MOD_DB4AI), errcode(ERRCODE_INVALID_PARAMETER_VALUE), \
errmsg("%s:%d: error in %s: %s\n", __FILE__, __LINE__, #call, g_xgboostApi->XGBGetLastError()))); \
errmsg("%s", strrchr(str, ':') + 1))); \
} \
}
@ -225,14 +228,15 @@ const char *xgboost_boost_str[] = {"gbtree", "gblinear", "dart"};
const char *xgboost_tree_method_str[] = {"auto", "exact", "approx", "hist", "gpu_hist"};
const char *xgboost_eval_metric_str[] = {"rmse", "rmsle", "map", "mae", "auc", "aucpr" };
static HyperparameterDefinition xgboost_hyperparameter_definitions[] = {
HYPERPARAMETER_INT4("n_iter", 10, 1, true, INT32_MAX, true, HyperparamsXGBoost, n_iterations, HP_NO_AUTOML()),
HYPERPARAMETER_INT4("batch_size", 10000, 1, true, INT32_MAX, true, HyperparamsXGBoost, batch_size, HP_NO_AUTOML()),
HYPERPARAMETER_INT4("n_iter", 10, 1, true, ITER_MAX, true, HyperparamsXGBoost, n_iterations, HP_NO_AUTOML()),
HYPERPARAMETER_INT4("batch_size", 10000, 1, true, MAX_BATCH_SIZE, true, HyperparamsXGBoost, batch_size,
HP_NO_AUTOML()),
HYPERPARAMETER_INT4("max_depth", 5, 0, true, INT32_MAX, true, HyperparamsXGBoost, max_depth, HP_NO_AUTOML()),
HYPERPARAMETER_INT4("min_child_weight", 1, 0, true, INT32_MAX, true, HyperparamsXGBoost, min_child_weight,
HP_NO_AUTOML()),
HYPERPARAMETER_FLOAT8("gamma", 0.0, 0.0, true, 1, true, HyperparamsXGBoost, gamma, HP_NO_AUTOML()),
HYPERPARAMETER_FLOAT8("gamma", 0.0, 0.0, true, DBL_MAX, true, HyperparamsXGBoost, gamma, HP_NO_AUTOML()),
HYPERPARAMETER_FLOAT8("eta", 0.3, 0.0, true, 1, true, HyperparamsXGBoost, eta, HP_NO_AUTOML()),
HYPERPARAMETER_INT4("nthread", 1, 0, true, INT32_MAX, true, HyperparamsXGBoost, nthread, HP_NO_AUTOML()),
HYPERPARAMETER_INT4("nthread", 1, 0, true, 100, true, HyperparamsXGBoost, nthread, HP_NO_AUTOML()),
HYPERPARAMETER_INT4("verbosity", 1, 0, true, 3, true, HyperparamsXGBoost, verbosity, HP_NO_AUTOML()),
HYPERPARAMETER_INT4("seed", 0, 0, true, INT32_MAX, true, HyperparamsXGBoost, seed,
HP_AUTOML_INT(1, INT32_MAX, 1, ProbabilityDistribution::UNIFORM_RANGE)),
@ -548,12 +552,6 @@ static void xgboost_run(AlgorithmAPI *self, TrainModelState *pstate, Model **mod
ModelTuple const *outer_tuple_slot = nullptr;
// Check max_depth parameter
if (xg_hyperp->max_depth == 0 && (0 != strcmp(xgboost_boost_str[BOOST_GBLINEAR_IDX], xg_hyperp->booster))) {
ereport(ERROR, (errmodule(MOD_DB4AI),
errmsg("Max_depth must be larger than 0 when booster is non_linear value.")));
}
load_xgboost_library();
// data holder for in-between (chunk-wise) invocation of XGBoost training algorithm

View File

@ -16,7 +16,7 @@ except ImportError:
import sys
import os
curr_path = os.path.dirname(os.path.abspath(__file__))
curr_path = os.path.dirname(os.path.realpath(__file__))
root_path = os.path.dirname(curr_path)
sys.path.append(root_path)
from dbmind.cmd import main

View File

@ -11,25 +11,57 @@
# MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
# See the Mulan PSL v2 for more details.
import os
import re
from configparser import ConfigParser
from configparser import NoSectionError, NoOptionError
from dbmind import constants
from dbmind.common import security
from dbmind.common.exceptions import InvalidPasswordException, ConfigSettingError
from dbmind.metadatabase.dao.dynamic_config import dynamic_config_get, dynamic_config_set
from dbmind.common.utils import write_to_terminal
from dbmind.metadatabase.dao.dynamic_config import dynamic_config_get, dynamic_config_set
DBMIND_CONF_HEADER = """\
# Copyright (c) 2022 Huawei Technologies Co.,Ltd.
#
# openGauss is licensed under Mulan PSL v2.
# You can use this software according to the terms and conditions of the Mulan PSL v2.
# You may obtain a copy of Mulan PSL v2 at:
#
# http://license.coscl.org.cn/MulanPSL2
#
# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
# EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
# MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
# See the Mulan PSL v2 for more details.
# Notice:
# 1. (null) explicitly represents empty or null. Meanwhile blank represents undefined.
# 2. DBMind encrypts password parameters. Hence, there is no plain-text password after initialization.
# 3. Users can only configure the plain-text password in this file before initializing
# (that is, using the --initialize option),
# and then if users want to modify the password-related information,
# users need to use the 'set' sub-command to achieve.
# 4. If users use relative path in this file, the current working directory is the directory where this file is located.
"""
NULL_TYPE = '(null)' # empty text.
ENCRYPTED_SIGNAL = 'Encrypted->'
# Used by check_config_validity().
CONFIG_OPTIONS = {
'TSDB-name': ['prometheus'],
'METADATABASE-dbtype': ['sqlite', 'opengauss', 'postgresql'],
'WORKER-type': ['local', 'dist'],
'LOG-level': ['DEBUG', 'INFO', 'WARNING', 'ERROR']
}
def check_config_validity(section, option, value, inline_comment=None):
def check_config_validity(section, option, value):
config_item = '%s-%s' % (section, option)
# exceptional cases:
if config_item == 'METADATABASE-port':
return True, None
# normal inspection process:
if 'port' in option:
valid_port = str.isdigit(value) and 0 < int(value) <= 65535
@ -38,16 +70,14 @@ def check_config_validity(section, option, value, inline_comment=None):
if 'database' in option:
if value == NULL_TYPE or value.strip() == '':
return False, 'Unspecified database name'
if 'Options:' in inline_comment:
# determine setting option whether choose from option list.
results = re.findall(r'Options: (.*)?\.', inline_comment)
if len(results) > 0:
options = list(map(str.strip, results[0].split(',')))
if value not in options:
return False, 'Invalid choice: %s' % value
options = CONFIG_OPTIONS.get(config_item)
if options and value not in options:
return False, 'Invalid choice: %s' % value
if 'dbtype' in option and value == 'opengauss':
write_to_terminal(
'WARN: default PostgresSQL connector (psycopg2-binary) does not support openGauss.\n'
'WARN: default PostgreSQL connector (psycopg2-binary) does not support openGauss.\n'
'It would help if you compiled psycopg2 with openGauss manually or '
'created a connection user after setting the GUC password_encryption_type to 1.',
color='yellow'
@ -96,13 +126,16 @@ def load_sys_configs(confile):
class ConfigUpdater:
def __init__(self, filepath):
self.config = ConfigParser(inline_comment_prefixes=None)
self.filepath = os.path.abspath(filepath)
self.filepath = os.path.realpath(filepath)
self.fp = None
self.readonly = True
def get(self, section, option):
value = self.config.get(section, option)
default_value, inline_comment = map(str.strip, value.rsplit('#', 1))
try:
default_value, inline_comment = map(str.strip, value.rsplit('#', 1))
except ValueError:
default_value, inline_comment = value.strip(), ''
if default_value == '':
default_value = NULL_TYPE
return default_value, inline_comment
@ -132,10 +165,7 @@ class ConfigUpdater:
# output configurations
self.fp.truncate(0)
self.fp.seek(0)
with open(
file=os.path.join(constants.MISC_PATH, constants.CONFILE_HEADER_NAME)
) as header_fp:
self.fp.writelines(header_fp.readlines())
self.fp.write(DBMIND_CONF_HEADER)
self.config.write(self.fp)
self.fp.flush()
self.fp.close()
@ -163,7 +193,7 @@ def set_config_parameter(confpath, section: str, option: str, value: str):
old_value, comment = config.get(section, option)
except (NoSectionError, NoOptionError):
raise ConfigSettingError('Not found the parameter %s-%s.' % (section, option))
valid, reason = check_config_validity(section, option, value, comment)
valid, reason = check_config_validity(section, option, value)
if not valid:
raise ConfigSettingError('Incorrect value due to %s.' % reason)
# If user wants to change password, we should encrypt the plain-text password first.

View File

@ -14,6 +14,7 @@
import logging
import os
import threading
import signal
import sys
import traceback
@ -55,7 +56,6 @@ def _check_confpath(confpath):
def _process_clean(force=False):
global_vars.worker.terminate(cancel_futures=force)
TimedTaskManager.stop()
logging.shutdown()
def signal_handler(signum, frame):
@ -67,7 +67,10 @@ def signal_handler(signum, frame):
elif signum == signal.SIGUSR2:
# used for debugging
utils.write_to_terminal('Stack frames:', color='green')
traceback.print_stack(frame)
for th in threading.enumerate():
print(th)
traceback.print_stack(sys._current_frames()[th.ident])
print()
elif signum == signal.SIGTERM:
signal.signal(signal.SIGTERM, signal.SIG_IGN)
logging.info('DBMind received exit signal.')
@ -87,7 +90,7 @@ class DBMindMain(Daemon):
if not _check_confpath(confpath):
raise SetupError("Invalid directory '%s', please set up first." % confpath)
self.confpath = os.path.abspath(confpath)
self.confpath = os.path.realpath(confpath)
self.worker = None
pid_file = os.path.join(confpath, constants.PIDFILE_NAME)

View File

@ -19,7 +19,7 @@ from dbmind import constants, global_vars
from dbmind.cmd.config_utils import (
ConfigUpdater, check_config_validity,
DynamicConfig, load_sys_configs,
NULL_TYPE, ENCRYPTED_SIGNAL
NULL_TYPE, ENCRYPTED_SIGNAL, DBMIND_CONF_HEADER
)
from dbmind.cmd.edbmind import SKIP_LIST
from dbmind.common import utils, security
@ -35,7 +35,7 @@ from dbmind.metadatabase.dao.dynamic_config import dynamic_config_set, dynamic_c
def initialize_and_check_config(confpath, interactive=False):
if not os.path.exists(confpath):
raise SetupError('Not found the directory %s.' % confpath)
confpath = os.path.abspath(confpath) # in case of dir changed.
confpath = os.path.realpath(confpath) # in case of dir changed.
os.chdir(confpath)
dbmind_conf_path = os.path.join(confpath, constants.CONFILE_NAME)
dynamic_config_path = os.path.join(confpath, constants.DYNAMIC_CONFIG)
@ -70,7 +70,7 @@ def initialize_and_check_config(confpath, interactive=False):
for section, section_comment in config.sections(SKIP_LIST):
for option, value, inline_comment in config.items(section):
valid, invalid_reason = check_config_validity(
section, option, value, inline_comment
section, option, value
)
if not valid:
raise SetupError(
@ -151,7 +151,10 @@ def setup_directory_interactive(confpath):
utils.write_to_terminal(section_comment, color='yellow')
# Get each configuration item.
for option, values in config.items(section):
default_value, inline_comment = map(str.strip, values.rsplit('#', 1))
try:
default_value, inline_comment = map(str.strip, values.rsplit('#', 1))
except ValueError:
default_value, inline_comment = values.strip(), ''
# If not set default value, the default value is null.
if default_value.strip() == '':
default_value = NULL_TYPE
@ -170,7 +173,7 @@ def setup_directory_interactive(confpath):
input_value = default_value
valid, invalid_reason = check_config_validity(
section, option, input_value, inline_comment
section, option, input_value
)
if not valid:
utils.write_to_terminal(
@ -190,8 +193,7 @@ def setup_directory_interactive(confpath):
# output configurations
with open(file=config_dst, mode='w+') as fp:
# Add header comments (including license and notice).
with open(file=os.path.join(confpath, constants.CONFILE_HEADER_NAME)) as header_fp:
fp.writelines(header_fp.readlines())
fp.write(DBMIND_CONF_HEADER)
config.write(fp)
initialize_and_check_config(confpath, interactive=True)
@ -221,8 +223,7 @@ def setup_directory(confpath):
with open(file=os.path.join(confpath, constants.CONFILE_NAME), mode='r+') as fp:
old = fp.readlines()
# Add header comments (including license and notice).
with open(file=os.path.join(constants.MISC_PATH, constants.CONFILE_HEADER_NAME)) as header_fp:
fp.seek(0)
fp.writelines(header_fp.readlines())
fp.seek(0)
fp.write(DBMIND_CONF_HEADER)
fp.writelines(old)
utils.write_to_terminal("Configure directory '%s' has been created successfully." % confpath, color='green')

View File

@ -63,7 +63,7 @@ class Daemon:
RUNNING = 1
def __init__(self, pid_file, stdin='/dev/null', stdout='/dev/null', stderr='/dev/null'):
self.pid_file = os.path.abspath(pid_file)
self.pid_file = os.path.realpath(pid_file)
self.stdin = stdin
self.stdout = stdout
self.stderr = stderr

View File

@ -293,3 +293,10 @@ class PrometheusClient(TsdbClient):
"HTTP Status Code {} ({!r})".format(response.status_code, response.content)
)
return _standardize(data)
def timestamp(self):
seq = self.get_current_metric_value('prometheus_remote_storage_highest_timestamp_in_seconds')
if len(seq) == 0 or len(seq[0]) == 0:
return 0
return seq[0].timestamps[0]

View File

@ -11,6 +11,7 @@
# MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
# See the Mulan PSL v2 for more details.
import time
from datetime import datetime, timedelta
@ -48,3 +49,8 @@ class TsdbClient(object):
params: dict = None):
"""get metric target from tsdb"""
pass
def timestamp(self):
"""get the current unix-timestamp from the time-series database."""
return int(time.time() * 1000)

View File

@ -12,6 +12,7 @@
# See the Mulan PSL v2 for more details.
import threading
import time
from dbmind.common.exceptions import ApiClientException
from dbmind.common.tsdb.tsdb_client import TsdbClient
@ -46,3 +47,9 @@ class TsdbClientFactory(object):
cls.tsdb_client = client
if cls.tsdb_client is None:
raise ApiClientException("Failed to init TSDB client, please check config file")
if abs(cls.tsdb_client.timestamp() - time.time() * 1000) > 60 * 1000: # threshold is 1 minute.
raise ApiClientException('Found clock drift between TSDB client and server, '
'please check and synchronize system clocks.')

View File

@ -153,25 +153,28 @@ class MultiProcessingRFHandler(RotatingFileHandler):
self._queue = multiprocessing.Queue(-1)
self._should_exit = False
self._receiv_thr = threading.Thread(target=self._receive)
self._receiv_thr = threading.Thread(target=self._receive, name='LoggingReceiverThread')
self._receiv_thr.daemon = True
self._receiv_thr.start()
def _receive(self):
while True:
try:
record = self._queue.get_nowait()
if self._should_exit and self._queue.empty():
break
record = self._queue.get(timeout=.2)
super().emit(record)
except Empty:
time.sleep(.1)
except (KeyboardInterrupt, SystemExit):
raise
except EOFError:
except (OSError, EOFError):
break
except Empty:
pass
except:
traceback.print_exc(file=sys.stderr)
if self._should_exit and self._queue.empty():
break
self._queue.close()
self._queue.join_thread()
def _send(self, s):
self._queue.put_nowait(s)
@ -181,6 +184,7 @@ class MultiProcessingRFHandler(RotatingFileHandler):
record.msg = record.msg % record.args
record.args = None
if record.exc_info:
self.format(record)
record.exc_info = None
self._send(record)
except (KeyboardInterrupt, SystemExit):
@ -189,8 +193,10 @@ class MultiProcessingRFHandler(RotatingFileHandler):
self.handleError(record)
def close(self):
super().close()
self._should_exit = True
if not self._should_exit:
self._should_exit = True
self._receiv_thr.join(5)
super().close()
class ExceptionCatch:

View File

@ -20,7 +20,7 @@ from dbmind.common.utils import where_am_i
def list_components():
"""Return all components in current directory."""
curr_dir = os.path.abspath(os.path.dirname(__file__))
curr_dir = os.path.realpath(os.path.dirname(__file__))
components = list(
map(lambda tup: tup[1],
pkgutil.iter_modules((curr_dir,)))

View File

@ -57,7 +57,7 @@ def show(metric, host, start_time, end_time):
for row_ in result:
row = [str(getattr(row_, field)).strip() for field in field_names]
csv_writer.writerow(row)
write_to_terminal('Dumped file is %s.' % os.path.abspath(dump_file_name))
write_to_terminal('Dumped file is %s.' % os.path.realpath(dump_file_name))
elif char == 'N':
print(output_table)
print('(%d rows)' % nb_rows)

View File

@ -0,0 +1,24 @@
# Copyright (c) 2022 Huawei Technologies Co.,Ltd.
#
# openGauss is licensed under Mulan PSL v2.
# You can use this software according to the terms and conditions of the Mulan PSL v2.
# You may obtain a copy of Mulan PSL v2 at:
#
# http://license.coscl.org.cn/MulanPSL2
#
# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
# EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
# MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
# See the Mulan PSL v2 for more details.
import sys
import os
try:
from dbmind.components.index_advisor import main
except ImportError:
libpath = os.path.join(os.path.dirname(os.path.realpath(__file__)), '..')
sys.path.append(libpath)
from index_advisor import main
main(sys.argv[1:])

View File

@ -11,11 +11,13 @@
# MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
# See the Mulan PSL v2 for more details.
import sys
import os
try:
from dbmind.components.opengauss_exporter import main
except ImportError:
sys.path.append('..')
libpath = os.path.join(os.path.dirname(os.path.realpath(__file__)), '..')
sys.path.append(libpath)
from opengauss_exporter import main
main(sys.argv[1:])

View File

@ -29,7 +29,7 @@ from . import controller
from . import service
from .. import __version__
ROOT_DIR_PATH = os.path.abspath(
ROOT_DIR_PATH = os.path.realpath(
os.path.join(os.path.dirname(__file__), '..')
)
@ -70,7 +70,7 @@ def wipe_off_password(dsn):
def path_type(path):
if os.path.exists(path):
return os.path.abspath(path)
return os.path.realpath(path)
else:
raise argparse.ArgumentTypeError('%s is not a valid path.' % path)
@ -102,7 +102,7 @@ def parse_argv(argv):
parser.add_argument('--ssl-certfile', type=path_type, help='set the path of ssl certificate file')
parser.add_argument('--parallel', default=5, type=int,
help='not collect pg_settings.yml metrics.')
parser.add_argument('--log.filepath', type=os.path.abspath, default=os.path.join(os.getcwd(), DEFAULT_LOGFILE),
parser.add_argument('--log.filepath', type=os.path.realpath, default=os.path.join(os.getcwd(), DEFAULT_LOGFILE),
help='the path to log')
parser.add_argument('--log.level', default='info', choices=('debug', 'info', 'warn', 'error', 'fatal'),
help='only log messages with the given severity or above.'

View File

@ -11,11 +11,13 @@
# MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
# See the Mulan PSL v2 for more details.
import sys
import os
try:
from dbmind.components.reprocessing_exporter import main
except ImportError:
sys.path.append('..')
libpath = os.path.join(os.path.dirname(os.path.realpath(__file__)), '..')
sys.path.append(libpath)
from reprocessing_exporter import main
main(sys.argv[1:])

View File

@ -24,7 +24,7 @@ from . import dao
from . import service
from .. import __version__
CURR_DIR = os.path.abspath(
CURR_DIR = os.path.realpath(
os.path.join(os.path.dirname(__file__), '..')
)
DEFAULT_YAML = 'reprocessing_exporter.yml'
@ -35,7 +35,7 @@ with tempfile.NamedTemporaryFile(suffix='.pid') as fp:
def path_type(path):
if os.path.exists(path):
return os.path.abspath(path)
return os.path.realpath(path)
else:
raise argparse.ArgumentTypeError('%s is not a valid path.' % path)
@ -56,7 +56,7 @@ def parse_argv(argv):
help='listen port to expose metrics and web interface')
parser.add_argument('--collector.config', type=path_type, default=os.path.join(CURR_DIR, DEFAULT_YAML),
help='according to the content of the yaml file for metric collection')
parser.add_argument('--log.filepath', type=os.path.abspath,
parser.add_argument('--log.filepath', type=os.path.realpath,
default=os.path.join(os.getcwd(), DEFAULT_LOGFILE),
help='the path to log')
parser.add_argument('--log.level', default='info', choices=('debug', 'info', 'warn', 'error', 'fatal'),

View File

@ -51,7 +51,7 @@ def show(query, start_time, end_time):
dump_file_name = 'slow_queries_%s.txt' % int(time.time())
with open(dump_file_name, 'w+') as fp:
fp.write(str(output_table))
write_to_terminal('Dumped file is %s.' % os.path.abspath(dump_file_name))
write_to_terminal('Dumped file is %s.' % os.path.realpath(dump_file_name))
elif char == 'N':
print(output_table)
print('(%d rows)' % nb_rows)

View File

@ -12,11 +12,13 @@
# See the Mulan PSL v2 for more details.
import sys
import os
try:
from dbmind.components.sqldiag import main
except ImportError:
sys.path.append('..')
libpath = os.path.join(os.path.dirname(os.path.realpath(__file__)), '..')
sys.path.append(libpath)
from sqldiag import main
main(sys.argv[1:])

View File

@ -132,8 +132,8 @@ def check_time_legality(time_string):
def is_valid_conf(filepath):
if os.path.exists(filepath):
file_abs_path = filepath
elif os.path.exists(os.path.abspath(os.path.join(os.getcwd(), filepath))):
file_abs_path = os.path.abspath(os.path.join(os.getcwd(), filepath))
elif os.path.exists(os.path.realpath(os.path.join(os.getcwd(), filepath))):
file_abs_path = os.path.realpath(os.path.join(os.getcwd(), filepath))
else:
print("FATAL: Not found the configuration file %s." % filepath, file=sys.stderr)
return False

View File

@ -12,11 +12,14 @@
# See the Mulan PSL v2 for more details.
import sys
import os
try:
from dbmind.components.xtuner.tuner.main import main
except ImportError:
sys.path.append('..')
libpath = os.path.join(os.path.dirname(os.path.realpath(__file__)), '..')
sys.path.append(libpath)
from xtuner.tuner.main import main
main(sys.argv[1:])

View File

@ -166,10 +166,10 @@ class Knob:
return
self._scale = self._max - self._min
if self._scale < 0:
if self._scale <= 0:
raise ValueError('Knob %s is incorrectly configured. '
'The max value must be greater than '
'or equal to the min value.' % self.name)
'the min value.' % self.name)
if type(self.user_set) is str:
self.current = self.to_numeric(self.user_set)
elif type(self.user_set) in (int, float):

View File

@ -15,11 +15,10 @@ import os
__version__ = '1.0.0'
__description__ = 'openGauss DBMind: An autonomous platform for openGauss'
DBMIND_PATH = os.path.dirname(os.path.abspath(__file__))
DBMIND_PATH = os.path.dirname(os.path.realpath(__file__))
MISC_PATH = os.path.join(DBMIND_PATH, 'misc')
CONFILE_NAME = 'dbmind.conf' # the name of configuration file
CONFILE_HEADER_NAME = 'dbmind.conf.header'
PIDFILE_NAME = 'dbmind.pid'
LOGFILE_NAME = 'dbmind.log'
METRIC_MAP_CONFIG = 'metric_map.conf'

View File

@ -1,22 +0,0 @@
# Copyright (c) 2020 Huawei Technologies Co.,Ltd.
#
# openGauss is licensed under Mulan PSL v2.
# You can use this software according to the terms and conditions of the Mulan PSL v2.
# You may obtain a copy of Mulan PSL v2 at:
#
# http://license.coscl.org.cn/MulanPSL2
#
# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
# EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
# MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
# See the Mulan PSL v2 for more details.
# Notice:
# 1. (null) explicitly represents empty or null. Meanwhile blank represents undefined.
# 2. DBMind encrypts password parameters. Hence, there is no plain-text password after initialization.
# 3. Users can only configure the plain-text password in this file before initializing
# (that is, using the --initialize option),
# and then if users want to modify the password-related information,
# users need to use the 'set' sub-command to achieve.
# 4. If users use relative path in this file, the current working directory is the directory where this file is located.

View File

@ -1,19 +1,439 @@
# Copyright (c) 2022 Huawei Technologies Co.,Ltd.
#
# openGauss is licensed under Mulan PSL v2.
# You can use this software according to the terms and conditions of the Mulan PSL v2.
# You may obtain a copy of Mulan PSL v2 at:
#
# http://license.coscl.org.cn/MulanPSL2
#
# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
# EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
# MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
# See the Mulan PSL v2 for more details.
# The name of different metric collectors may be different,
# so we converte the different metric name here.
# For example, users can get the full list of metrics from Prometheus via the following URI:
# /api/v1/label/__name__/values
# Format:
# metric name in the DBMind = metric name in the collector (e.g., Prometheus-exporter, Agent)
#
os_disk_io_cnt = os_disk_io_cnt
os_disk_io_load = os_disk_io_load
os_disk_read_bytes = os_disk_read_bytes
os_disk_read_time = os_disk_read_time
os_disk_write_bytes = os_disk_write_bytes
os_disk_write_time = os_disk_write_time
os_cpu_usage = os_cpu_usage
os_system_cpu_usage = os_system_cpu_usage
os_user_cpu_usage = os_user_cpu_usage
opengauss_blocks_read_time = opengauss_blocks_read_time
opengauss_blocks_write_time = opengauss_blocks_write_time
opengauss_sql_cpu_time_rate = opengauss_sql_cpu_time_rate
disk_usage = disk_usage
gaussdb_qps_by_instance = gaussdb_qps_by_instance
io_queue_number = io_queue_number
io_read_bytes = io_read_bytes
io_read_delay_time = io_read_delay_time
io_read_total = io_read_total
io_write_bytes = io_write_bytes
io_write_delay_time = io_write_delay_time
io_write_total = io_write_total
node_arp_entries = node_arp_entries
node_boot_time_seconds = node_boot_time_seconds
node_context_switches_total = node_context_switches_total
node_cooling_device_cur_state = node_cooling_device_cur_state
node_cooling_device_max_state = node_cooling_device_max_state
node_cpu_core_throttles_total = node_cpu_core_throttles_total
node_cpu_frequency_max_hertz = node_cpu_frequency_max_hertz
node_cpu_frequency_min_hertz = node_cpu_frequency_min_hertz
node_cpu_guest_seconds_total = node_cpu_guest_seconds_total
node_cpu_package_throttles_total = node_cpu_package_throttles_total
node_cpu_scaling_frequency_hertz = node_cpu_scaling_frequency_hertz
node_cpu_scaling_frequency_max_hertz = node_cpu_scaling_frequency_max_hertz
node_cpu_scaling_frequency_min_hertz = node_cpu_scaling_frequency_min_hertz
node_cpu_seconds_total = node_cpu_seconds_total
node_disk_io_now = node_disk_io_now
node_disk_io_time_seconds_total = node_disk_io_time_seconds_total
node_disk_io_time_weighted_seconds_total = node_disk_io_time_weighted_seconds_total
node_disk_read_bytes_total = node_disk_read_bytes_total
node_disk_read_time_seconds_total = node_disk_read_time_seconds_total
node_disk_reads_completed_total = node_disk_reads_completed_total
node_disk_reads_merged_total = node_disk_reads_merged_total
node_disk_write_time_seconds_total = node_disk_write_time_seconds_total
node_disk_writes_completed_total = node_disk_writes_completed_total
node_disk_writes_merged_total = node_disk_writes_merged_total
node_disk_written_bytes_total = node_disk_written_bytes_total
node_edac_correctable_errors_total = node_edac_correctable_errors_total
node_edac_csrow_correctable_errors_total = node_edac_csrow_correctable_errors_total
node_edac_csrow_uncorrectable_errors_total = node_edac_csrow_uncorrectable_errors_total
node_edac_uncorrectable_errors_total = node_edac_uncorrectable_errors_total
node_entropy_available_bits = node_entropy_available_bits
node_entropy_pool_size_bits = node_entropy_pool_size_bits
node_exporter_build_info = node_exporter_build_info
node_filefd_allocated = node_filefd_allocated
node_filefd_maximum = node_filefd_maximum
node_filesystem_avail_bytes = node_filesystem_avail_bytes
node_filesystem_device_error = node_filesystem_device_error
node_filesystem_files = node_filesystem_files
node_filesystem_files_free = node_filesystem_files_free
node_filesystem_free_bytes = node_filesystem_free_bytes
node_filesystem_readonly = node_filesystem_readonly
node_filesystem_size_bytes = node_filesystem_size_bytes
node_forks_total = node_forks_total
node_hwmon_chip_names = node_hwmon_chip_names
node_hwmon_power_average_interval_max_seconds = node_hwmon_power_average_interval_max_seconds
node_hwmon_power_average_interval_min_seconds = node_hwmon_power_average_interval_min_seconds
node_hwmon_power_average_interval_seconds = node_hwmon_power_average_interval_seconds
node_hwmon_power_average_watt = node_hwmon_power_average_watt
node_hwmon_power_is_battery_watt = node_hwmon_power_is_battery_watt
node_hwmon_sensor_label = node_hwmon_sensor_label
node_hwmon_temp_celsius = node_hwmon_temp_celsius
node_hwmon_temp_crit_alar_celsius = node_hwmon_temp_crit_alar_celsius
node_hwmon_temp_crit_alarm_celsius = node_hwmon_temp_crit_alarm_celsius
node_hwmon_temp_crit_celsius = node_hwmon_temp_crit_celsius
node_hwmon_temp_max_celsius = node_hwmon_temp_max_celsius
node_intr_total = node_intr_total
node_load1 = node_load1
node_load15 = node_load15
node_load5 = node_load5
node_memory_Active_anon_bytes = node_memory_Active_anon_bytes
node_memory_Active_bytes = node_memory_Active_bytes
node_memory_Active_file_bytes = node_memory_Active_file_bytes
node_memory_AnonHugePages_bytes = node_memory_AnonHugePages_bytes
node_memory_AnonPages_bytes = node_memory_AnonPages_bytes
node_memory_Bounce_bytes = node_memory_Bounce_bytes
node_memory_Buffers_bytes = node_memory_Buffers_bytes
node_memory_Cached_bytes = node_memory_Cached_bytes
node_memory_CmaFree_bytes = node_memory_CmaFree_bytes
node_memory_CmaTotal_bytes = node_memory_CmaTotal_bytes
node_memory_CommitLimit_bytes = node_memory_CommitLimit_bytes
node_memory_Committed_AS_bytes = node_memory_Committed_AS_bytes
node_memory_DirectMap1G_bytes = node_memory_DirectMap1G_bytes
node_memory_DirectMap2M_bytes = node_memory_DirectMap2M_bytes
node_memory_DirectMap4k_bytes = node_memory_DirectMap4k_bytes
node_memory_Dirty_bytes = node_memory_Dirty_bytes
node_memory_HardwareCorrupted_bytes = node_memory_HardwareCorrupted_bytes
node_memory_HugePages_Free = node_memory_HugePages_Free
node_memory_HugePages_Rsvd = node_memory_HugePages_Rsvd
node_memory_HugePages_Surp = node_memory_HugePages_Surp
node_memory_HugePages_Total = node_memory_HugePages_Total
node_memory_Hugepagesize_bytes = node_memory_Hugepagesize_bytes
node_memory_Inactive_anon_bytes = node_memory_Inactive_anon_bytes
node_memory_Inactive_bytes = node_memory_Inactive_bytes
node_memory_Inactive_file_bytes = node_memory_Inactive_file_bytes
node_memory_KernelStack_bytes = node_memory_KernelStack_bytes
node_memory_Mapped_bytes = node_memory_Mapped_bytes
node_memory_MemAvailable_bytes = node_memory_MemAvailable_bytes
node_memory_MemFree_bytes = node_memory_MemFree_bytes
node_memory_MemTotal_bytes = node_memory_MemTotal_bytes
node_memory_Mlocked_bytes = node_memory_Mlocked_bytes
node_memory_NFS_Unstable_bytes = node_memory_NFS_Unstable_bytes
node_memory_PageTables_bytes = node_memory_PageTables_bytes
node_memory_SReclaimable_bytes = node_memory_SReclaimable_bytes
node_memory_SUnreclaim_bytes = node_memory_SUnreclaim_bytes
node_memory_Shmem_bytes = node_memory_Shmem_bytes
node_memory_Slab_bytes = node_memory_Slab_bytes
node_memory_SwapCached_bytes = node_memory_SwapCached_bytes
node_memory_SwapFree_bytes = node_memory_SwapFree_bytes
node_memory_SwapTotal_bytes = node_memory_SwapTotal_bytes
node_memory_Unevictable_bytes = node_memory_Unevictable_bytes
node_memory_VmallocChunk_bytes = node_memory_VmallocChunk_bytes
node_memory_VmallocTotal_bytes = node_memory_VmallocTotal_bytes
node_memory_VmallocUsed_bytes = node_memory_VmallocUsed_bytes
node_memory_WritebackTmp_bytes = node_memory_WritebackTmp_bytes
node_memory_Writeback_bytes = node_memory_Writeback_bytes
node_netstat_Icmp6_InErrors = node_netstat_Icmp6_InErrors
node_netstat_Icmp6_InMsgs = node_netstat_Icmp6_InMsgs
node_netstat_Icmp6_OutMsgs = node_netstat_Icmp6_OutMsgs
node_netstat_Icmp_InErrors = node_netstat_Icmp_InErrors
node_netstat_Icmp_InMsgs = node_netstat_Icmp_InMsgs
node_netstat_Icmp_OutMsgs = node_netstat_Icmp_OutMsgs
node_netstat_Ip6_InOctets = node_netstat_Ip6_InOctets
node_netstat_Ip6_OutOctets = node_netstat_Ip6_OutOctets
node_netstat_IpExt_InOctets = node_netstat_IpExt_InOctets
node_netstat_IpExt_OutOctets = node_netstat_IpExt_OutOctets
node_netstat_Ip_Forwarding = node_netstat_Ip_Forwarding
node_netstat_TcpExt_ListenDrops = node_netstat_TcpExt_ListenDrops
node_netstat_TcpExt_ListenOverflows = node_netstat_TcpExt_ListenOverflows
node_netstat_TcpExt_SyncookiesFailed = node_netstat_TcpExt_SyncookiesFailed
node_netstat_TcpExt_SyncookiesRecv = node_netstat_TcpExt_SyncookiesRecv
node_netstat_TcpExt_SyncookiesSent = node_netstat_TcpExt_SyncookiesSent
node_netstat_TcpExt_TCPSynRetrans = node_netstat_TcpExt_TCPSynRetrans
node_netstat_Tcp_ActiveOpens = node_netstat_Tcp_ActiveOpens
node_netstat_Tcp_CurrEstab = node_netstat_Tcp_CurrEstab
node_netstat_Tcp_InErrs = node_netstat_Tcp_InErrs
node_netstat_Tcp_InSegs = node_netstat_Tcp_InSegs
node_netstat_Tcp_OutRsts = node_netstat_Tcp_OutRsts
node_netstat_Tcp_OutSegs = node_netstat_Tcp_OutSegs
node_netstat_Tcp_PassiveOpens = node_netstat_Tcp_PassiveOpens
node_netstat_Tcp_RetransSegs = node_netstat_Tcp_RetransSegs
node_netstat_Udp6_InDatagrams = node_netstat_Udp6_InDatagrams
node_netstat_Udp6_InErrors = node_netstat_Udp6_InErrors
node_netstat_Udp6_NoPorts = node_netstat_Udp6_NoPorts
node_netstat_Udp6_OutDatagrams = node_netstat_Udp6_OutDatagrams
node_netstat_Udp6_RcvbufErrors = node_netstat_Udp6_RcvbufErrors
node_netstat_Udp6_SndbufErrors = node_netstat_Udp6_SndbufErrors
node_netstat_UdpLite6_InErrors = node_netstat_UdpLite6_InErrors
node_netstat_UdpLite_InErrors = node_netstat_UdpLite_InErrors
node_netstat_Udp_InDatagrams = node_netstat_Udp_InDatagrams
node_netstat_Udp_InErrors = node_netstat_Udp_InErrors
node_netstat_Udp_NoPorts = node_netstat_Udp_NoPorts
node_netstat_Udp_OutDatagrams = node_netstat_Udp_OutDatagrams
node_netstat_Udp_RcvbufErrors = node_netstat_Udp_RcvbufErrors
node_netstat_Udp_SndbufErrors = node_netstat_Udp_SndbufErrors
node_network_address_assign_type = node_network_address_assign_type
node_network_carrier = node_network_carrier
node_network_carrier_changes_total = node_network_carrier_changes_total
node_network_device_id = node_network_device_id
node_network_dormant = node_network_dormant
node_network_flags = node_network_flags
node_network_iface_id = node_network_iface_id
node_network_iface_link = node_network_iface_link
node_network_iface_link_mode = node_network_iface_link_mode
node_network_info = node_network_info
node_network_mtu_bytes = node_network_mtu_bytes
node_network_net_dev_group = node_network_net_dev_group
node_network_protocol_type = node_network_protocol_type
node_network_receive_bytes_total = node_network_receive_bytes_total
node_network_receive_compressed_total = node_network_receive_compressed_total
node_network_receive_drop_total = node_network_receive_drop_total
node_network_receive_errs_total = node_network_receive_errs_total
node_network_receive_fifo_total = node_network_receive_fifo_total
node_network_receive_frame_total = node_network_receive_frame_total
node_network_receive_multicast_total = node_network_receive_multicast_total
node_network_receive_packets_total = node_network_receive_packets_total
node_network_speed_bytes = node_network_speed_bytes
node_network_transmit_bytes_total = node_network_transmit_bytes_total
node_network_transmit_carrier_total = node_network_transmit_carrier_total
node_network_transmit_colls_total = node_network_transmit_colls_total
node_network_transmit_compressed_total = node_network_transmit_compressed_total
node_network_transmit_drop_total = node_network_transmit_drop_total
node_network_transmit_errs_total = node_network_transmit_errs_total
node_network_transmit_fifo_total = node_network_transmit_fifo_total
node_network_transmit_packets_total = node_network_transmit_packets_total
node_network_transmit_queue_length = node_network_transmit_queue_length
node_network_up = node_network_up
node_nf_conntrack_entries = node_nf_conntrack_entries
node_nf_conntrack_entries_limit = node_nf_conntrack_entries_limit
node_procs_blocked = node_procs_blocked
node_procs_running = node_procs_running
node_rapl_dram_joules_total = node_rapl_dram_joules_total
node_rapl_package_joules_total = node_rapl_package_joules_total
node_schedstat_running_seconds_total = node_schedstat_running_seconds_total
node_schedstat_timeslices_total = node_schedstat_timeslices_total
node_schedstat_waiting_seconds_total = node_schedstat_waiting_seconds_total
node_scrape_collector_duration_seconds = node_scrape_collector_duration_seconds
node_scrape_collector_success = node_scrape_collector_success
node_sockstat_FRAG6_inuse = node_sockstat_FRAG6_inuse
node_sockstat_FRAG6_memory = node_sockstat_FRAG6_memory
node_sockstat_FRAG_inuse = node_sockstat_FRAG_inuse
node_sockstat_FRAG_memory = node_sockstat_FRAG_memory
node_sockstat_RAW6_inuse = node_sockstat_RAW6_inuse
node_sockstat_RAW_inuse = node_sockstat_RAW_inuse
node_sockstat_TCP6_inuse = node_sockstat_TCP6_inuse
node_sockstat_TCP_alloc = node_sockstat_TCP_alloc
node_sockstat_TCP_inuse = node_sockstat_TCP_inuse
node_sockstat_TCP_mem = node_sockstat_TCP_mem
node_sockstat_TCP_mem_bytes = node_sockstat_TCP_mem_bytes
node_sockstat_TCP_orphan = node_sockstat_TCP_orphan
node_sockstat_TCP_tw = node_sockstat_TCP_tw
node_sockstat_UDP6_inuse = node_sockstat_UDP6_inuse
node_sockstat_UDPLITE6_inuse = node_sockstat_UDPLITE6_inuse
node_sockstat_UDPLITE_inuse = node_sockstat_UDPLITE_inuse
node_sockstat_UDP_inuse = node_sockstat_UDP_inuse
node_sockstat_UDP_mem = node_sockstat_UDP_mem
node_sockstat_UDP_mem_bytes = node_sockstat_UDP_mem_bytes
node_sockstat_sockets_used = node_sockstat_sockets_used
node_softnet_dropped_total = node_softnet_dropped_total
node_softnet_processed_total = node_softnet_processed_total
node_softnet_times_squeezed_total = node_softnet_times_squeezed_total
node_textfile_scrape_error = node_textfile_scrape_error
node_time_seconds = node_time_seconds
node_timex_estimated_error_seconds = node_timex_estimated_error_seconds
node_timex_frequency_adjustment_ratio = node_timex_frequency_adjustment_ratio
node_timex_loop_time_constant = node_timex_loop_time_constant
node_timex_maxerror_seconds = node_timex_maxerror_seconds
node_timex_offset_seconds = node_timex_offset_seconds
node_timex_pps_calibration_total = node_timex_pps_calibration_total
node_timex_pps_error_total = node_timex_pps_error_total
node_timex_pps_frequency_hertz = node_timex_pps_frequency_hertz
node_timex_pps_jitter_seconds = node_timex_pps_jitter_seconds
node_timex_pps_jitter_total = node_timex_pps_jitter_total
node_timex_pps_shift_seconds = node_timex_pps_shift_seconds
node_timex_pps_stability_exceeded_total = node_timex_pps_stability_exceeded_total
node_timex_pps_stability_hertz = node_timex_pps_stability_hertz
node_timex_status = node_timex_status
node_timex_sync_status = node_timex_sync_status
node_timex_tai_offset_seconds = node_timex_tai_offset_seconds
node_timex_tick_seconds = node_timex_tick_seconds
node_udp_queues = node_udp_queues
node_uname_info = node_uname_info
node_vmstat_pgfault = node_vmstat_pgfault
node_vmstat_pgmajfault = node_vmstat_pgmajfault
node_vmstat_pgpgin = node_vmstat_pgpgin
node_vmstat_pgpgout = node_vmstat_pgpgout
node_vmstat_pswpin = node_vmstat_pswpin
node_vmstat_pswpout = node_vmstat_pswpout
og_context_memory_totalsize = og_context_memory_totalsize
og_context_memory_usedsize = og_context_memory_usedsize
og_cpu_load_total_cpu = og_cpu_load_total_cpu
og_memory_info_memorymbytes = og_memory_info_memorymbytes
og_session_memory_totalsize = og_session_memory_totalsize
og_session_memory_usedsize = og_session_memory_usedsize
og_state_memory_totalsize = og_state_memory_totalsize
os_cpu_iowait = os_cpu_iowait
os_cpu_processor_number = os_cpu_processor_number
os_cpu_usage = os_cpu_usage
os_disk_iocapacity = os_disk_iocapacity
os_disk_iops = os_disk_iops
os_disk_ioutils = os_disk_ioutils
os_disk_usage = os_disk_usage
os_mem_usage = os_mem_usage
pg_active_slowsql_query_runtime = pg_active_slowsql_query_runtime
pg_activity_count = pg_activity_count
pg_activity_max_conn_duration = pg_activity_max_conn_duration
pg_activity_max_duration = pg_activity_max_duration
pg_activity_max_tx_duration = pg_activity_max_tx_duration
pg_boot_time = pg_boot_time
pg_checkpoint_checkpoint_lsn = pg_checkpoint_checkpoint_lsn
pg_checkpoint_elapse = pg_checkpoint_elapse
pg_checkpoint_full_page_writes = pg_checkpoint_full_page_writes
pg_checkpoint_newest_commit_ts_xid = pg_checkpoint_newest_commit_ts_xid
pg_checkpoint_next_multi_offset = pg_checkpoint_next_multi_offset
pg_checkpoint_next_multixact_id = pg_checkpoint_next_multixact_id
pg_checkpoint_next_oid = pg_checkpoint_next_oid
pg_checkpoint_next_xid = pg_checkpoint_next_xid
pg_checkpoint_next_xid_epoch = pg_checkpoint_next_xid_epoch
pg_checkpoint_oldest_active_xid = pg_checkpoint_oldest_active_xid
pg_checkpoint_oldest_commit_ts_xid = pg_checkpoint_oldest_commit_ts_xid
pg_checkpoint_oldest_multi_dbid = pg_checkpoint_oldest_multi_dbid
pg_checkpoint_oldest_multi_xid = pg_checkpoint_oldest_multi_xid
pg_checkpoint_oldest_xid = pg_checkpoint_oldest_xid
pg_checkpoint_oldest_xid_dbid = pg_checkpoint_oldest_xid_dbid
pg_checkpoint_prev_tli = pg_checkpoint_prev_tli
pg_checkpoint_redo_lsn = pg_checkpoint_redo_lsn
pg_checkpoint_time = pg_checkpoint_time
pg_checkpoint_tli = pg_checkpoint_tli
pg_class_relage = pg_class_relage
pg_class_relpages = pg_class_relpages
pg_class_relsize = pg_class_relsize
pg_class_reltuples = pg_class_reltuples
pg_conf_reload_time = pg_conf_reload_time
pg_connections_max_conn = pg_connections_max_conn
pg_connections_res_for_normal = pg_connections_res_for_normal
pg_connections_used_conn = pg_connections_used_conn
pg_database_age = pg_database_age
pg_database_allow_conn = pg_database_allow_conn
pg_database_conn_limit = pg_database_conn_limit
pg_database_frozen_xid = pg_database_frozen_xid
pg_database_is_template = pg_database_is_template
pg_database_size_bytes = pg_database_size_bytes
pg_db_blk_read_time = pg_db_blk_read_time
pg_db_blk_write_time = pg_db_blk_write_time
pg_db_blks_access = pg_db_blks_access
pg_db_blks_hit = pg_db_blks_hit
pg_db_blks_read = pg_db_blks_read
pg_db_confl_bufferpin = pg_db_confl_bufferpin
pg_db_confl_deadlock = pg_db_confl_deadlock
pg_db_confl_lock = pg_db_confl_lock
pg_db_confl_snapshot = pg_db_confl_snapshot
pg_db_confl_tablespace = pg_db_confl_tablespace
pg_db_conflicts = pg_db_conflicts
pg_db_deadlocks = pg_db_deadlocks
pg_db_numbackends = pg_db_numbackends
pg_db_stats_reset = pg_db_stats_reset
pg_db_temp_bytes = pg_db_temp_bytes
pg_db_temp_files = pg_db_temp_files
pg_db_tup_deleted = pg_db_tup_deleted
pg_db_tup_fetched = pg_db_tup_fetched
pg_db_tup_inserted = pg_db_tup_inserted
pg_db_tup_returned = pg_db_tup_returned
pg_db_tup_updated = pg_db_tup_updated
pg_db_xact_commit = pg_db_xact_commit
pg_db_xact_rollback = pg_db_xact_rollback
pg_downstream_count = pg_downstream_count
pg_flush_lsn = pg_flush_lsn
pg_index_idx_blks_hit = pg_index_idx_blks_hit
pg_index_idx_blks_read = pg_index_idx_blks_read
pg_index_idx_scan = pg_index_idx_scan
pg_index_idx_tup_fetch = pg_index_idx_tup_fetch
pg_index_idx_tup_read = pg_index_idx_tup_read
pg_insert_lsn = pg_insert_lsn
pg_is_in_recovery = pg_is_in_recovery
pg_is_wal_replay_paused = pg_is_wal_replay_paused
pg_lag = pg_lag
pg_last_replay_time = pg_last_replay_time
pg_lock_count = pg_lock_count
pg_lock_sql_locked_times = pg_lock_sql_locked_times
pg_locker_count = pg_locker_count
pg_lsn = pg_lsn
pg_meta_info = pg_meta_info
pg_need_indexes_idx_scan = pg_need_indexes_idx_scan
pg_need_indexes_idx_tup_fetch = pg_need_indexes_idx_tup_fetch
pg_need_indexes_rate = pg_need_indexes_rate
pg_need_indexes_seq_scan = pg_need_indexes_seq_scan
pg_need_indexes_seq_tup_read = pg_need_indexes_seq_tup_read
pg_never_used_indexes_index_size = pg_never_used_indexes_index_size
pg_node_info_uptime = pg_node_info_uptime
pg_receive_lsn = pg_receive_lsn
pg_replay_lsn = pg_replay_lsn
pg_replication_slots_active = pg_replication_slots_active
pg_replication_slots_delay_lsn = pg_replication_slots_delay_lsn
pg_run_times_db_role = pg_run_times_db_role
pg_run_times_run_time = pg_run_times_run_time
pg_session_connection_count = pg_session_connection_count
pg_setting_block_size = pg_setting_block_size
pg_setting_max_connections = pg_setting_max_connections
pg_setting_max_locks_per_transaction = pg_setting_max_locks_per_transaction
pg_setting_max_prepared_transactions = pg_setting_max_prepared_transactions
pg_setting_max_replication_slots = pg_setting_max_replication_slots
pg_setting_max_wal_senders = pg_setting_max_wal_senders
pg_setting_wal_log_hints = pg_setting_wal_log_hints
pg_settings_setting = pg_settings_setting
pg_sql_statement_full_count = pg_sql_statement_full_count
pg_sql_statement_history_exc_time = pg_sql_statement_history_exc_time
pg_table_analyze_count = pg_table_analyze_count
pg_table_analyze_delay = pg_table_analyze_delay
pg_table_autoanalyze_count = pg_table_autoanalyze_count
pg_table_autovacuum_count = pg_table_autovacuum_count
pg_table_heap_blks_hit = pg_table_heap_blks_hit
pg_table_heap_blks_read = pg_table_heap_blks_read
pg_table_idx_blks_hit = pg_table_idx_blks_hit
pg_table_idx_blks_read = pg_table_idx_blks_read
pg_table_idx_scan = pg_table_idx_scan
pg_table_idx_tup_fetch = pg_table_idx_tup_fetch
pg_table_n_dead_tup = pg_table_n_dead_tup
pg_table_n_live_tup = pg_table_n_live_tup
pg_table_n_mod_since_analyze = pg_table_n_mod_since_analyze
pg_table_n_tup_del = pg_table_n_tup_del
pg_table_n_tup_hot_upd = pg_table_n_tup_hot_upd
pg_table_n_tup_ins = pg_table_n_tup_ins
pg_table_n_tup_mod = pg_table_n_tup_mod
pg_table_n_tup_upd = pg_table_n_tup_upd
pg_table_seq_scan = pg_table_seq_scan
pg_table_seq_tup_read = pg_table_seq_tup_read
pg_table_tbl_scan = pg_table_tbl_scan
pg_table_tidx_blks_hit = pg_table_tidx_blks_hit
pg_table_tidx_blks_read = pg_table_tidx_blks_read
pg_table_toast_blks_hit = pg_table_toast_blks_hit
pg_table_toast_blks_read = pg_table_toast_blks_read
pg_table_tup_read = pg_table_tup_read
pg_table_vacuum_count = pg_table_vacuum_count
pg_table_vacuum_delay = pg_table_vacuum_delay
pg_tables_expansion_rate_analyze_count = pg_tables_expansion_rate_analyze_count
pg_tables_expansion_rate_autoanalyze_count = pg_tables_expansion_rate_autoanalyze_count
pg_tables_expansion_rate_autovacuum_count = pg_tables_expansion_rate_autovacuum_count
pg_tables_expansion_rate_dead_rate = pg_tables_expansion_rate_dead_rate
pg_tables_expansion_rate_vacuum_count = pg_tables_expansion_rate_vacuum_count
pg_tables_size_bytes = pg_tables_size_bytes
pg_tables_size_indexsize = pg_tables_size_indexsize
pg_tables_size_relsize = pg_tables_size_relsize
pg_tables_size_toastsize = pg_tables_size_toastsize
pg_thread_pool_listener = pg_thread_pool_listener
pg_timestamp = pg_timestamp
pg_uptime = pg_uptime
pg_wait_events_total_wait_time = pg_wait_events_total_wait_time
pg_wait_events_wait = pg_wait_events_wait
pg_write_lsn = pg_write_lsn
process_cpu_seconds_total = process_cpu_seconds_total
process_max_fds = process_max_fds
process_open_fds = process_open_fds
process_resident_memory_bytes = process_resident_memory_bytes
process_start_time_seconds = process_start_time_seconds
process_virtual_memory_bytes = process_virtual_memory_bytes
process_virtual_memory_max_bytes = process_virtual_memory_max_bytes
statement_responsetime_percentile_p80 = statement_responsetime_percentile_p80
statement_responsetime_percentile_p95 = statement_responsetime_percentile_p95

View File

@ -28,6 +28,11 @@ from dbmind.common.types import Sequence
from dbmind.common.types.misc import SlowQuery
from dbmind.metadatabase import dao
# Singleton pattern with starving formula
# will capture exception in the main thread.
TsdbClientFactory.get_tsdb_client()
# Notice: 'DISTINGUISHING_INSTANCE_LABEL' is a magic string, i.e., our own name.
# Thus, not all collection agents (such as Prometheus's openGauss-exporter)
# distinguish different instance addresses through this one.

View File

@ -20,7 +20,7 @@ import dbmind.common.process
from dbmind.common.daemon import Daemon
from dbmind.common.platform import WIN32
BASEPATH = os.path.abspath(os.path.dirname(__file__))
BASEPATH = os.path.realpath(os.path.dirname(__file__))
PID_NAME = 'tester.pid'

View File

@ -16,7 +16,7 @@ import os
from dbmind.constants import METRIC_MAP_CONFIG, MISC_PATH
from dbmind.common import utils
CURR_DIR = os.path.abspath(os.path.dirname(__file__))
CURR_DIR = os.path.realpath(os.path.dirname(__file__))
def test_read_simple_conf_file():

View File

@ -1920,6 +1920,15 @@ double CopyUHeapDataInternal(Relation oldHeap, Relation oldIndex, Relation newHe
return tups_vacuumed;
}
static inline bool tuple_invisible_not_hotupdate(HeapTuple tuple, Relation relation)
{
if (HeapKeepInvisibleTuple(tuple, RelationGetDescr(relation)) && !HeapTupleIsHotUpdated(tuple)) {
return false;
} else {
return true;
}
}
double copy_heap_data_internal(Relation OldHeap, Relation OldIndex, Relation NewHeap, TransactionId OldestXmin,
TransactionId FreezeXid, bool verbose, bool use_sort, AdaptMem* memUsage)
{
@ -2071,7 +2080,7 @@ double copy_heap_data_internal(Relation OldHeap, Relation OldIndex, Relation New
switch (HeapTupleSatisfiesVacuum(tuple, OldestXmin, buf)) {
case HEAPTUPLE_DEAD:
/* Definitely dead */
isdead = true;
isdead = tuple_invisible_not_hotupdate(tuple, OldHeap);
break;
case HEAPTUPLE_RECENTLY_DEAD:
tups_recently_dead += 1;

View File

@ -454,6 +454,15 @@ void ExplainQuery(
*/
if (es.format == EXPLAIN_FORMAT_TEXT)
appendStringInfoString(es.str, "Query rewrites to nothing\n");
/*
* In centralized mode, non-stream plans only support EXPLAIN_NORMAL.
* So set explain_perf_mode to EXPLAIN_NORMAL here.
*/
if (t_thrd.explain_cxt.explain_perf_mode != EXPLAIN_NORMAL &&
!(IS_STREAM_PLAN && u_sess->exec_cxt.under_stream_runtime)) {
t_thrd.explain_cxt.explain_perf_mode = EXPLAIN_NORMAL;
}
} else {
ListCell* l = NULL;

View File

@ -6159,6 +6159,11 @@ void renamePartition(RenameStmt* stmt)
/* Do the work */
renamePartitionInternal(partitionedTableOid, partitionOid, stmt->newname);
Relation parentRel = heap_openrv(stmt->relation, AccessExclusiveLock);
Oid relid = RelationGetRelid(parentRel);
UpdatePgObjectChangecsn(relid, parentRel->rd_rel->relkind);
heap_close(parentRel, NoLock);
}
/*
@ -6232,6 +6237,11 @@ void renamePartitionIndex(RenameStmt* stmt)
/* Do the work */
renamePartitionInternal(partitionedTableIndexOid, partitionIndexOid, stmt->newname);
Oid parRelOid = IndexGetRelation(partitionedTableIndexOid, false);
Relation partRel = RelationIdGetRelation(parRelOid);
UpdatePgObjectChangecsn(parRelOid, partRel->rd_rel->relkind);
RelationClose(partRel);
}
/*
@ -6993,7 +7003,7 @@ static LOCKMODE GetPartitionLockLevel(AlterTableType subType)
case AT_DropSubPartition:
case AT_ExchangePartition:
case AT_TruncatePartition:
cmdLockMode = RowExclusiveLock;
cmdLockMode = ShareUpdateExclusiveLock;
break;
default:
cmdLockMode = AccessExclusiveLock;
@ -20816,29 +20826,36 @@ static void renamePartitionIndexes(Oid partitionedTableOid, Oid partitionOid, ch
* Description :
* Notes :
*/
static void heap_truncate_one_part_new(const AlterTableCmd* cmd, Relation rel, Oid srcPartOid) {
static void heap_truncate_one_part_new(const AlterTableCmd* cmd, Relation partRel, Oid srcPartOid,
Relation rel = InvalidRelation)
{
Partition srcPart = NULL;
bool renameTargetPart = false;
char* destPartitionName = NULL;
Oid destPartOid = AddTemporaryPartitionForAlterPartitions(cmd, rel, srcPartOid, &renameTargetPart);
Oid destPartOid = AddTemporaryPartitionForAlterPartitions(cmd, partRel, srcPartOid, &renameTargetPart);
List* indexList = RelationGetSpecificKindIndexList(rel, false);
List* indexList = NULL;
if (RelationIsPartitionOfSubPartitionTable(partRel) && RelationIsValid(rel)) {
indexList = RelationGetSpecificKindIndexList(rel, false);
} else {
indexList = RelationGetSpecificKindIndexList(partRel, false);
}
char** partitionIndexNames = getPartitionIndexesName(srcPartOid, indexList);
srcPart = partitionOpen(rel, srcPartOid, AccessExclusiveLock);
srcPart = partitionOpen(partRel, srcPartOid, AccessExclusiveLock);
destPartitionName = pstrdup(PartitionGetPartitionName(srcPart));
partitionClose(rel, srcPart, NoLock);
partitionClose(partRel, srcPart, NoLock);
CommandCounterIncrement();
fastDropPartition(rel, srcPartOid, "TRUNCATE PARTITION");
fastDropPartition(partRel, srcPartOid, "TRUNCATE PARTITION");
CommandCounterIncrement();
renamePartitionIndexes(rel->rd_id, destPartOid, partitionIndexNames, indexList);
renamePartitionIndexes(partRel->rd_id, destPartOid, partitionIndexNames, indexList);
if (renameTargetPart) {
CommandCounterIncrement();
renamePartitionInternal(rel->rd_id, destPartOid, destPartitionName);
renamePartitionInternal(partRel->rd_id, destPartOid, destPartitionName);
}
list_free_ext(indexList);
@ -20861,13 +20878,20 @@ static void ATExecTruncatePartitionForSubpartitionTable(Relation rel, Oid partOi
}
foreach (subPartOidCell, subPartOidList) {
Oid subPartOid = lfirst_oid(subPartOidCell);
bool all_ubtree = true;
AlterSubPartitionedSetWaitCleanGPI(cmd->alterGPI, rel, partOid, subPartOid);
if (cmd->alterGPI) {
/* Delete subpartition tuples in GPI and add parent to pending vacuum list */
DeleteGPITuplesForSubPartition(RelationGetRelid(rel), partOid, subPartOid);
all_ubtree = DeleteGPITuplesForSubPartition(RelationGetRelid(rel), partOid, subPartOid);
AlterSubPartitionedSetWaitCleanGPI(cmd->alterGPI, rel, partOid, subPartOid);
}
if (all_ubtree) {
/* If no nbtree global index exists */
heap_truncate_one_part(partRel, subPartOid);
} else {
heap_truncate_one_part_new(cmd, partRel, subPartOid, rel);
}
heap_truncate_one_part(partRel, subPartOid);
pgstat_report_truncate(subPartOid, partRel->rd_id, partRel->rd_rel->relisshared);
}
@ -21029,6 +21053,7 @@ static void ATExecTruncateSubPartition(Relation rel, AlterTableCmd* cmd)
List* oidList = NULL;
List* relid = lappend_oid(NULL, rel->rd_id);
Oid subPartOid = InvalidOid;
bool all_ubtree = true;
oidList = heap_truncate_find_FKs(relid);
if (PointerIsValid(oidList)) {
@ -21066,17 +21091,21 @@ static void ATExecTruncateSubPartition(Relation rel, AlterTableCmd* cmd)
Partition part = partitionOpen(rel, partOid, AccessExclusiveLock);
Relation partRel = partitionGetRelation(rel, part);
AlterSubPartitionedSetWaitCleanGPI(cmd->alterGPI, rel, partOid, subPartOid);
if (!cmd->alterGPI) {
// Unusable Global Index
ATUnusableGlobalIndex(rel);
} else {
/* Delete subpartition tuples in GPI and add parent to pending vacuum list */
DeleteGPITuplesForSubPartition(RelationGetRelid(rel), partOid, subPartOid);
all_ubtree = DeleteGPITuplesForSubPartition(RelationGetRelid(rel), partOid, subPartOid);
AlterSubPartitionedSetWaitCleanGPI(cmd->alterGPI, rel, partOid, subPartOid);
}
heap_truncate_one_part(partRel, subPartOid);
if (all_ubtree) {
/* If no nbtree global index exists */
heap_truncate_one_part(partRel, subPartOid);
} else {
heap_truncate_one_part_new(cmd, partRel, subPartOid, rel);
}
pgstat_report_truncate(subPartOid, partRel->rd_id, partRel->rd_rel->relisshared);
releaseDummyRelation(&partRel);
@ -24406,11 +24435,11 @@ static char* GenTemporaryPartitionName(Relation partTableRel, int sequence)
#ifndef ENABLE_MULTIPLE_NODES
static Oid GetNewPartitionOid(Relation pgPartRel, Relation partTableRel, Node *partDef, Oid bucketOid,
bool *isTimestamptz, StorageType stype, Datum new_reloptions)
bool *isTimestamptz, StorageType stype, Datum new_reloptions, bool isSubpartition)
{
#else
static Oid GetNewPartitionOid(Relation pgPartRel, Relation partTableRel, Node *partDef,
Oid bucketOid, bool *isTimestamptz, StorageType stype)
Oid bucketOid, bool *isTimestamptz, StorageType stype, bool isSubpartition)
{
Datum new_reloptions = (Datum)0;
#endif
@ -24426,7 +24455,9 @@ static Oid GetNewPartitionOid(Relation pgPartRel, Relation partTableRel, Node *p
(Datum)new_reloptions,
isTimestamptz,
stype,
AccessExclusiveLock);
AccessExclusiveLock,
NULL,
isSubpartition);
break;
case T_ListPartitionDefState:
newPartOid = HeapAddListPartition(pgPartRel,
@ -24437,7 +24468,9 @@ static Oid GetNewPartitionOid(Relation pgPartRel, Relation partTableRel, Node *p
partTableRel->rd_rel->relowner,
(Datum)new_reloptions,
isTimestamptz,
stype);
stype,
NULL,
isSubpartition);
break;
case T_HashPartitionDefState:
newPartOid = HeapAddHashPartition(pgPartRel,
@ -24448,7 +24481,9 @@ static Oid GetNewPartitionOid(Relation pgPartRel, Relation partTableRel, Node *p
partTableRel->rd_rel->relowner,
(Datum)new_reloptions,
isTimestamptz,
stype);
stype,
NULL,
isSubpartition);
break;
default:
ereport(ERROR,
@ -24480,17 +24515,20 @@ static Oid AddTemporaryPartition(Relation partTableRel, Node* partDef)
Datum rel_reloptions;
Datum new_reloptions;
List* old_reloptions = NIL;
bool isPartitionOfSubPartition = RelationIsPartitionOfSubPartitionTable(partTableRel);
bool* isTimestamptz = CheckPartkeyHasTimestampwithzone(partTableRel);
bucketOid = RelationGetBucketOid(partTableRel);
pgPartRel = relation_open(PartitionRelationId, RowExclusiveLock);
/* add new partition entry in pg_partition */
tuple = SearchSysCache1(RELOID, ObjectIdGetDatum(partTableRel->rd_id));
Oid relOid = isPartitionOfSubPartition ?
ObjectIdGetDatum(partTableRel->parentId) : ObjectIdGetDatum(partTableRel->rd_id);
tuple = SearchSysCache1(RELOID, relOid);
if (!HeapTupleIsValid(tuple)) {
ereport(ERROR,
(errcode(ERRCODE_CACHE_LOOKUP_FAILED),
(errmsg("cache lookup failed"), errdetail("cache lookup failed for relation %u", partTableRel->rd_id),
(errmsg("cache lookup failed"), errdetail("cache lookup failed for relation %u", relOid),
errcause("The oid of the target relation is invalid."),
erraction("Check whether the target relation is correct."))));
}
@ -24508,18 +24546,25 @@ static Oid AddTemporaryPartition(Relation partTableRel, Node* partDef)
/* Temporary tables do not use segment-page */
#ifndef ENABLE_MULTIPLE_NODES
newPartOid = GetNewPartitionOid(pgPartRel, partTableRel, partDef, bucketOid,
isTimestamptz, RelationGetStorageType(partTableRel), new_reloptions);
isTimestamptz, RelationGetStorageType(partTableRel), new_reloptions, isPartitionOfSubPartition);
#else
newPartOid = GetNewPartitionOid(
pgPartRel, partTableRel, partDef, bucketOid, isTimestamptz, RelationGetStorageType(partTableRel));
newPartOid = GetNewPartitionOid(pgPartRel, partTableRel, partDef, bucketOid, isTimestamptz,
RelationGetStorageType(partTableRel), isPartitionOfSubPartition);
#endif
// We must bump the command counter to make the newly-created
// partition tuple visible for opening.
CommandCounterIncrement();
addIndexForPartition(partTableRel, newPartOid);
if (isPartitionOfSubPartition) {
Relation rel = heap_open(partTableRel->parentId, AccessShareLock);
addIndexForPartition(rel, newPartOid);
heap_close(rel, NoLock);
} else {
addIndexForPartition(partTableRel, newPartOid);
}
addToastTableForNewPartition(partTableRel, newPartOid);
addToastTableForNewPartition(partTableRel, newPartOid, isPartitionOfSubPartition);
// invalidate relation
CacheInvalidateRelcache(partTableRel);

View File

@ -6052,6 +6052,9 @@ static Datum gs_calculate_encrypted_sm3_password(const char* password, const cha
Datum calculate_encrypted_password(bool is_encrypted, const char* password, const char* rolname,
const char* salt_string)
{
if (password == NULL || password[0] == '\0') {
ereport(ERROR, (errcode(ERRCODE_INVALID_PASSWORD), errmsg("The password could not be NULL.")));
}
errno_t rc = EOK;
char encrypted_md5_password[MD5_PASSWD_LEN + 1] = {0};
Datum datum_value;

View File

@ -130,7 +130,8 @@ static void DropEmptyPartitionDirectories(Oid relid);
static THR_LOCAL BufferAccessStrategy vac_strategy;
static THR_LOCAL int elevel = -1;
static void UstoreVacuumGPIPartition(Oid relid, Relation rel);
static void UstoreVacuumMainPartitionGPIs(Relation onerel, const VacuumStmt* vacstmt,
LOCKMODE lockmode, BufferAccessStrategy bstrategy);
static void vac_truncate_clog(TransactionId frozenXID, MultiXactId frozenMulti);
static bool vacuum_rel(Oid relid, VacuumStmt* vacstmt, bool do_toast);
@ -2436,13 +2437,13 @@ static bool vacuum_rel(Oid relid, VacuumStmt* vacstmt, bool do_toast)
* relation.
*/
bool isUstoreGPI = RelationIsUstoreIndex(onerel) && RelationIsGlobalIndex(onerel);
bool isPartitionedUHeap = RelationIsUstoreFormat(onerel) && RelationIsPartitioned(onerel);
if (onerel->rd_rel->relkind != RELKIND_RELATION &&
#ifdef ENABLE_MOT
!(RelationIsForeignTable(onerel) && isMOTFromTblOid(onerel->rd_id)) &&
#endif
onerel->rd_rel->relkind != RELKIND_MATVIEW &&
onerel->rd_rel->relkind != RELKIND_TOASTVALUE && !isUstoreGPI) {
onerel->rd_rel->relkind != RELKIND_TOASTVALUE && !isPartitionedUHeap) {
if (vacstmt->options & VACOPT_VERBOSE)
messageLevel = VERBOSEMESSAGE;
@ -2755,16 +2756,16 @@ static bool vacuum_rel(Oid relid, VacuumStmt* vacstmt, bool do_toast)
}
} else if (vacuumMainPartition((uint32)(vacstmt->flags))) {
pgstat_report_waitstatus_relname(STATE_VACUUM, get_nsp_relname(relid));
GPIVacuumMainPartition(onerel, vacstmt, lmode, vac_strategy);
CBIVacuumMainPartition(onerel, vacstmt, lmode, vac_strategy);
if (isPartitionedUHeap) {
UstoreVacuumMainPartitionGPIs(onerel, vacstmt, lmode, vac_strategy);
} else {
GPIVacuumMainPartition(onerel, vacstmt, lmode, vac_strategy);
CBIVacuumMainPartition(onerel, vacstmt, lmode, vac_strategy);
}
pgstat_report_vacuum(relid, InvalidOid, false, 0);
} else {
pgstat_report_waitstatus_relname(STATE_VACUUM, get_nsp_relname(relid));
if (isUstoreGPI) {
UstoreVacuumGPIPartition(relid, onerel);
} else {
TableRelationVacuum(onerel, vacstmt, vac_strategy);
}
TableRelationVacuum(onerel, vacstmt, vac_strategy);
}
}
(void)pgstat_report_waitstatus(oldStatus);
@ -4406,99 +4407,73 @@ static void GPIOpenGlobalIndexes(Relation onerel, LOCKMODE lockmode, int* nindex
}
static void UstoreVacuumGPIPartition(Oid relid, Relation rel)
static void UstoreVacuumMainPartitionGPIs(Relation onerel, const VacuumStmt* vacstmt,
LOCKMODE lockmode, BufferAccessStrategy bstrategy)
{
ScanKeyData skey[2];
/* Open pg_index to find out the relation owning current GPI. */
Relation pgIndex = heap_open(IndexRelationId, AccessShareLock);
ScanKeyInit(&skey[0], Anum_pg_index_indexrelid, BTEqualStrategyNumber, F_OIDEQ, ObjectIdGetDatum(relid));
SysScanDesc scanIndexes = systable_beginscan(pgIndex, IndexRelidIndexId, true, NULL, 1, skey);
HeapTuple indexTuple = systable_getnext(scanIndexes);
if (!HeapTupleIsValid(indexTuple)) {
systable_endscan(scanIndexes);
heap_close(pgIndex, NoLock);
return;
OidRBTree* invisibleParts = CreateOidRBTree();
Oid parentOid = RelationGetRelid(onerel);
if (vacstmt->options & VACOPT_VERBOSE) {
elevel = VERBOSEMESSAGE;
} else {
elevel = DEBUG2;
}
/* Get the Oid of relation. */
Form_pg_index indexTupleForm = (Form_pg_index)GETSTRUCT(indexTuple);
Oid indexOfRelOid = indexTupleForm->indrelid;
systable_endscan(scanIndexes);
heap_close(pgIndex, NoLock);
/* Here we first get the main partition of the relation, and then check its
* wait_cleanup_gpi flag is 'y' or 'n':
* 1. If wait_cleanup_gpi=y, which means we need to vacuum the GPI.
* 2. If wait_cleanup_gpi=n, which means we do not need to vacuum the GPI.
*/
Relation pgPartition = heap_open(PartitionRelationId, RowExclusiveLock);
ScanKeyInit(&skey[0], Anum_pg_partition_parttype, BTEqualStrategyNumber,
F_CHAREQ, CharGetDatum(PART_OBJ_TYPE_PARTED_TABLE));
ScanKeyInit(&skey[1], Anum_pg_partition_parentid, BTEqualStrategyNumber,
F_OIDEQ, ObjectIdGetDatum(indexOfRelOid));
SysScanDesc scanParts = systable_beginscan(pgPartition, PartitionParentOidIndexId,
true, NULL, 2, skey);
HeapTuple partTuple = systable_getnext(scanParts);
if (!HeapTupleIsValid(partTuple)) {
systable_endscan(scanParts);
heap_close(pgPartition, NoLock);
return;
}
Form_pg_partition partTupleForm = (Form_pg_partition)GETSTRUCT(partTuple);
partTuple = SearchSysCache3(PARTPARTOID, PointerGetDatum(partTupleForm->relname.data),
CharGetDatum(PART_OBJ_TYPE_PARTED_TABLE), ObjectIdGetDatum(indexOfRelOid));
systable_endscan(scanParts);
if (!HeapTupleIsValid(partTuple)) {
ereport(ERROR,
(errcode(ERRCODE_CACHE_LOOKUP_FAILED),
errmsg("cache lookup failed for partition %u", indexOfRelOid)));
}
/* Use PartitionInvisibleMetadataKeep to judge the wait_cleanup_gpi flag. */
bool isNull = false;
Datum partOptions = fastgetattr(partTuple, Anum_pg_partition_reloptions,
RelationGetDescr(pgPartition), &isNull);
if (isNull || !PartitionInvisibleMetadataKeep(partOptions)) {
ReleaseSysCache(partTuple);
heap_close(pgPartition, NoLock);
return;
}
/* Find out the invisible parts of the relation. */
OidRBTree *invisibleParts = CreateOidRBTree();
if (ConditionalLockPartition(indexOfRelOid, ADD_PARTITION_ACTION, AccessShareLock, PARTITION_SEQUENCE_LOCK)) {
PartitionGetAllInvisibleParts(indexOfRelOid, &invisibleParts);
UnlockPartition(indexOfRelOid, ADD_PARTITION_ACTION, AccessShareLock, PARTITION_SEQUENCE_LOCK);
/* Get invisable parts */
if (ConditionalLockPartition(parentOid, ADD_PARTITION_ACTION, AccessShareLock, PARTITION_SEQUENCE_LOCK)) {
PartitionGetAllInvisibleParts(parentOid, &invisibleParts);
UnlockPartition(parentOid, ADD_PARTITION_ACTION, AccessShareLock, PARTITION_SEQUENCE_LOCK);
}
/* In rbtree, rb_leftmost will return NULL if rbtree is empty. */
if (rb_leftmost(invisibleParts) == NULL) {
DestroyOidRBTree(&invisibleParts);
ReleaseSysCache(partTuple);
heap_close(pgPartition, NoLock);
return;
}
/* Start the cleanup process and collect the info needed */
IndexVacuumInfo ivinfo;
ivinfo.index = rel;
ivinfo.analyze_only = false;
ivinfo.estimated_count = false;
ivinfo.message_level = elevel;
ivinfo.num_heap_tuples = -1;
ivinfo.strategy = vac_strategy;
ivinfo.invisibleParts = invisibleParts;
/* Cleanup process of index */
index_vacuum_cleanup(&ivinfo, NULL);
OidRBTree *cleanedParts = CreateOidRBTree();
vac_strategy = bstrategy;
/* Open all global indexes of the main partition */
Relation* iRel = NULL;
int nIndexes;
GPIOpenGlobalIndexes(onerel, lockmode, &nIndexes, &iRel);
Relation classRel = heap_open(RelationRelationId, RowExclusiveLock);
for (int i = 0; i < nIndexes; i++) {
/* Start the cleanup process and collect the info needed */
IndexVacuumInfo ivinfo;
ivinfo.index = iRel[i];
ivinfo.analyze_only = false;
ivinfo.estimated_count = false;
ivinfo.message_level = elevel;
ivinfo.num_heap_tuples = -1;
ivinfo.strategy = vac_strategy;
ivinfo.invisibleParts = invisibleParts;
/* Cleanup process of index */
index_bulk_delete(&ivinfo, NULL, NULL, NULL);
index_close(iRel[i], lockmode);
}
heap_close(classRel, RowExclusiveLock);
/*
* Before clearing the global partition index of a partition table,
* acquire a AccessShareLock on ADD_PARTITION_ACTION, and make sure that the interval partition
* creation process will not be performed concurrently.
*/
OidRBTree* cleanedParts = CreateOidRBTree();
OidRBTreeUnionOids(cleanedParts, invisibleParts);
if (ConditionalLockPartition(indexOfRelOid, ADD_PARTITION_ACTION, AccessShareLock, PARTITION_SEQUENCE_LOCK)) {
PartitionSetEnabledClean(indexOfRelOid, cleanedParts, invisibleParts, true);
UnlockPartition(indexOfRelOid, ADD_PARTITION_ACTION, AccessShareLock, PARTITION_SEQUENCE_LOCK);
if (ConditionalLockPartition(parentOid, ADD_PARTITION_ACTION, AccessShareLock, PARTITION_SEQUENCE_LOCK)) {
PartitionSetEnabledClean(parentOid, cleanedParts, invisibleParts, true);
UnlockPartition(parentOid, ADD_PARTITION_ACTION, AccessShareLock, PARTITION_SEQUENCE_LOCK);
} else {
/* Updates reloptions of cleanedParts in pg_partition after GPI vacuum is executed */
PartitionSetEnabledClean(indexOfRelOid, cleanedParts, invisibleParts, false);
PartitionSetEnabledClean(parentOid, cleanedParts, invisibleParts, false);
}
DestroyOidRBTree(&invisibleParts);
DestroyOidRBTree(&cleanedParts);
/* Set wait_cleanup_gpi=n after we finish the vacuum cleanup. */
UpdateWaitCleanGpiRelOptions(pgPartition, partTuple, false, true);
ReleaseSysCache(partTuple);
heap_close(pgPartition, NoLock);
pfree_ext(iRel);
}
// vacuum main partition table to delete invisible tuple in global partition index

View File

@ -1051,9 +1051,11 @@ static IndexBulkDeleteResult** lazy_scan_heap(
OffsetNumber offnum, maxoff;
bool tupgone = false;
bool hastup = false;
bool keepThisInvisbleTuple = false;
bool keepThisInvisibleTuple = false;
int prev_dead_count;
OffsetNumber invalid[MaxOffsetNumber];
OffsetNumber frozen[MaxOffsetNumber];
int ninvalid = 0;
int nfrozen;
Size freespace;
bool all_visible_according_to_vm = false;
@ -1335,7 +1337,7 @@ static IndexBulkDeleteResult** lazy_scan_heap(
tuple.t_bucketId = RelationGetBktid(onerel);
HeapTupleCopyBaseFromPage(&tuple, page);
tupgone = false;
keepThisInvisbleTuple = false;
keepThisInvisibleTuple = false;
if (u_sess->attr.attr_storage.enable_debug_vacuum)
t_thrd.utils_cxt.pRelatedRel = onerel;
@ -1358,8 +1360,8 @@ static IndexBulkDeleteResult** lazy_scan_heap(
* cheaper to get rid of it in the next pruning pass than
* to treat it like an indexed tuple.
*/
keepThisInvisbleTuple = HeapKeepInvisbleTuple(&tuple, RelationGetDescr(onerel));
if (HeapTupleIsHotUpdated(&tuple) || HeapTupleIsHeapOnly(&tuple) || keepThisInvisbleTuple) {
keepThisInvisibleTuple = HeapKeepInvisibleTuple(&tuple, RelationGetDescr(onerel));
if (HeapTupleIsHotUpdated(&tuple) || HeapTupleIsHeapOnly(&tuple) || keepThisInvisibleTuple) {
nkeep += 1;
} else {
tupgone = true; /* we can delete the tuple */
@ -1437,8 +1439,15 @@ static IndexBulkDeleteResult** lazy_scan_heap(
tups_vacuumed += 1;
has_dead_tuples = true;
} else if (keepThisInvisbleTuple) {
vacrelstats->hasKeepInvisbleTuples = true;
} else if (keepThisInvisibleTuple) {
if (t_thrd.proc->workingVersionNum >= INVALID_INVISIBLE_TUPLE_VERSION
&& !HeapTupleIsHotUpdated(&tuple)) {
heap_invalid_invisible_tuple(&tuple);
Assert(tuple.t_tableOid == PartitionRelationId);
invalid[ninvalid++] = offnum;
} else {
vacrelstats->hasKeepInvisbleTuples = true;
}
} else {
num_tuples += 1;
hastup = true;
@ -1478,6 +1487,23 @@ static IndexBulkDeleteResult** lazy_scan_heap(
}
}
if (ninvalid > 0) {
START_CRIT_SECTION();
MarkBufferDirty(buf);
if (RelationNeedsWAL(onerel)) {
XLogRecPtr recptr;
recptr = log_heap_invalid(onerel, buf, u_sess->cmd_cxt.FreezeLimit,
invalid, ninvalid);
PageSetLSN(page, recptr);
}
END_CRIT_SECTION();
if (TransactionIdPrecedes(((HeapPageHeader)page)->pd_xid_base, u_sess->utils_cxt.RecentXmin)) {
if (u_sess->utils_cxt.RecentXmin - ((HeapPageHeader)page)->pd_xid_base > CHANGE_XID_BASE)
(void)heap_change_xidbase_after_freeze(onerel, buf);
}
}
/*
* If there are no indexes then we can vacuum the page right now
* instead of doing a second scan.

View File

@ -873,6 +873,31 @@ static void SetPlainReSizeWithPruningRatio(RelOptInfo *rel, double pruningRatio)
}
}
/*
* This function applies only to single partition key of range partitioned tables in PBE mode.
*/
static bool IsPbeSinglePartition(Relation rel, RelOptInfo* relInfo)
{
if (relInfo->pruning_result->paramArg == NULL) {
return false;
}
if (RelationIsSubPartitioned(rel)) {
return false;
}
if (rel->partMap->type != PART_TYPE_RANGE) {
return false;
}
RangePartitionMap* partMap = (RangePartitionMap*)rel->partMap;
int partKeyNum = partMap->partitionKey->dim1;
if (partKeyNum > 1) {
return false;
}
if (relInfo->pruning_result->isPbeSinlePartition) {
return true;
}
return false;
}
/*
* set_plain_rel_size
* Set size estimates for a plain relation (no subquery, no inheritance)
@ -896,8 +921,7 @@ static void set_plain_rel_size(PlannerInfo* root, RelOptInfo* rel, RangeTblEntry
Assert(rel->pruning_result);
if (rel->pruning_result->expr != NULL) {
if (IsPbeSinglePartition(relation, rel)) {
rel->partItrs = 1;
} else {
/* set flag for dealing with partintioned table */

View File

@ -222,6 +222,8 @@ static bool relIsDeltaNode(PlannerInfo* root, RelOptInfo* relOptInfo);
static void ModifyWorktableWtParam(Node* planNode, int oldWtParam, int newWtParam);
static bool ScanQualsViolateNotNullConstr(PlannerInfo* root, RelOptInfo* rel, Path* best_path);
#define SATISFY_INFORMATIONAL_CONSTRAINT(joinPlan, joinType) \
(u_sess->attr.attr_sql.enable_constraint_optimization && true == innerPlan((joinPlan))->hasUniqueResults && \
JOIN_SEMI != (joinType) && JOIN_ANTI != (joinType))
@ -752,11 +754,49 @@ static Plan* create_scan_plan(PlannerInfo* root, Path* best_path)
*/
if (root->hasPseudoConstantQuals) {
plan = create_gating_plan(root, plan, scan_clauses);
} else if (ScanQualsViolateNotNullConstr(root, rel, best_path)) {
/*
* If there is IS NULL qual on a known NOT-NULL attribute, insert a Result node to prevent needless execution.
*/
plan = (Plan*)make_result(root, plan->targetlist, (Node*)list_make1(makeBoolConst(false, false)), plan);
}
return plan;
}
static bool IsScanPath(NodeTag type)
{
return (
type == T_CStoreScan || type == T_CStoreIndexScan || type == T_CStoreIndexHeapScan || type == T_SeqScan ||
type == T_DfsScan || type == T_IndexScan || type == T_IndexOnlyScan || type == T_BitmapHeapScan
);
}
static bool ScanQualsViolateNotNullConstr(PlannerInfo* root, RelOptInfo* rel, Path* best_path)
{
/* For now, we only support table scan optimization */
if (rel->rtekind != RTE_RELATION || !IsScanPath(best_path->pathtype)) {
return false;
}
List* scan_clauses = rel->baserestrictinfo;
ListCell* lc = NULL;
foreach (lc, scan_clauses) {
Node* clause = (Node*)lfirst(lc);
if (IsA(clause, RestrictInfo) && IsA(((RestrictInfo*)clause)->clause, NullTest)) {
NullTest* expr = (NullTest*)((RestrictInfo*)clause)->clause;
/* For attribute with NOT-NULL constraint, IS-NULL expression can be short-circuited */
if (expr->nulltesttype != IS_NULL || !IsA(expr->arg, Var)) {
continue;
}
if (check_var_nonnullable(root->parse, (Node*)expr->arg)) {
return true;
}
}
}
return false;
}
/*
* Build a target list (ie, a list of TargetEntry) for a relation.
*/

View File

@ -67,6 +67,43 @@
#include "utils/fmgroids.h"
#include "access/heapam.h"
/*
* Check whether the current statement supports Stream based on the status of 'context' and 'query'.
* If Stream is supported, a copy of the 'query' is returned as a backup in case generating a plan
* with Stream fails.
*/
static Query* check_shippable(bool *stream_unsupport, Query* query, shipping_context* context)
{
if (u_sess->attr.attr_sql.rewrite_rule & PARTIAL_PUSH) {
*stream_unsupport = !context->query_shippable;
} else {
*stream_unsupport = !context->global_shippable;
}
if (u_sess->attr.attr_sql.enable_dngather) {
u_sess->opt_cxt.is_dngather_support = !context->disable_dn_gather;
} else {
u_sess->opt_cxt.is_dngather_support = false;
}
/* single node do not support parallel query in cursor */
if (query->utilityStmt && IsA(query->utilityStmt, DeclareCursorStmt)) {
*stream_unsupport = true;
}
if (*stream_unsupport || !IS_STREAM) {
output_unshipped_log();
set_stream_off();
} else {
/*
* make a copy of query, so we can retry to create an unshippable plan
* when we fail to generate a stream plan
*/
return (Query*)copyObject(query);
}
return NULL;
}
PlannedStmt* pgxc_planner(Query* query, int cursorOptions, ParamListInfo boundParams)
{
PlannedStmt* result = NULL;
@ -91,33 +128,7 @@ PlannedStmt* pgxc_planner(Query* query, int cursorOptions, ParamListInfo boundPa
(void)stream_walker((Node*)query, (void*)(&context));
disable_unshipped_log(query, &context);
if (u_sess->attr.attr_sql.rewrite_rule & PARTIAL_PUSH) {
stream_unsupport = !context.query_shippable;
} else {
stream_unsupport = !context.global_shippable;
}
if (u_sess->attr.attr_sql.enable_dngather) {
u_sess->opt_cxt.is_dngather_support = !context.disable_dn_gather;
} else {
u_sess->opt_cxt.is_dngather_support = false;
}
/* single node do not support parallel query in cursor */
if (query->utilityStmt && IsA(query->utilityStmt, DeclareCursorStmt)) {
stream_unsupport = true;
}
if (stream_unsupport || !IS_STREAM) {
output_unshipped_log();
set_stream_off();
} else {
/*
* make a copy of query, so we can retry to create an unshippable plan
* when we fail to generate a stream plan
*/
re_query = (Query*)copyObject(query);
}
re_query = check_shippable(&stream_unsupport, query, &context);
} else {
errno_t sprintf_rc = sprintf_s(u_sess->opt_cxt.not_shipping_info->not_shipping_reason,
NOTPLANSHIPPING_LENGTH,
@ -141,9 +152,26 @@ PlannedStmt* pgxc_planner(Query* query, int cursorOptions, ParamListInfo boundPa
*/
MemoryContext current_context = CurrentMemoryContext;
ResourceOwner currentOwner = t_thrd.utils_cxt.CurrentResourceOwner;
ResourceOwner tempOwner = ResourceOwnerCreate(t_thrd.utils_cxt.CurrentResourceOwner, "pgxc_planner",
SESS_GET_MEM_CXT_GROUP(MEMORY_CONTEXT_OPTIMIZER));
t_thrd.utils_cxt.CurrentResourceOwner = tempOwner;
ResourceOwner tempOwner = NULL;
/*
* If the stream-plan is not used, the currentOwner is used to trace resources instead of
* applying for a temporary owner. This prevents the "memory temporarily unavailable" error
* caused by memory stacking.
*/
if (IS_STREAM_PLAN) {
/*
* If the stream-plan is used, a temporary owner is used to trace resources. This helps release
* resources in a unified manner when a stream-plan fails to be generated, preventing resource
* leakage.
*/
tempOwner = ResourceOwnerCreate(t_thrd.utils_cxt.CurrentResourceOwner, "pgxc_planner",
/*
* The memory context of the temporary owner must be the same as the currentOwner to ensure
* that they have the same lifecycle
*/
ResourceOwnerGetMemCxt(currentOwner));
t_thrd.utils_cxt.CurrentResourceOwner = tempOwner;
}
/* we need Coordinator for evaluation, invoke standard planner */
PG_TRY();
@ -175,8 +203,19 @@ PlannedStmt* pgxc_planner(Query* query, int cursorOptions, ParamListInfo boundPa
result->ng_use_planA = use_planA;
ReSetNgQueryMem(result);
}
/* release resource applied in standard_planner */
t_thrd.utils_cxt.CurrentResourceOwner = currentOwner;
/* If tempOwner is not NULL, the current plan is a stream-plan using the SMP technology. */
if (tempOwner != NULL) {
/*
* When the stream-plan is successfully generated, the temporary owner tracks the
* resources opened during the plan generation. Now we put the resources of the
* stream-plan into the currentOwner for tracking, and release the tempOwner to
* further reduce the memory. This greatly avoid the "memory temporarily unavailable"
* error, caused by a large amount of SQLs being executed in a transaction/procedure.
*/
ResourceOwnerConcat(currentOwner, tempOwner);
t_thrd.utils_cxt.CurrentResourceOwner = currentOwner;
ResourceOwnerDelete(tempOwner);
}
}
PG_CATCH();
{
@ -198,11 +237,13 @@ PlannedStmt* pgxc_planner(Query* query, int cursorOptions, ParamListInfo boundPa
* Release resources applied in standard_planner, release the tempOwner and reinstate the currentOwner
* before PG_RE_THROW().
*/
ResourceOwnerRelease(tempOwner, RESOURCE_RELEASE_BEFORE_LOCKS, false, false);
ResourceOwnerRelease(tempOwner, RESOURCE_RELEASE_LOCKS, false, false);
ResourceOwnerRelease(tempOwner, RESOURCE_RELEASE_AFTER_LOCKS, false, false);
t_thrd.utils_cxt.CurrentResourceOwner = currentOwner;
ResourceOwnerDelete(tempOwner);
if (tempOwner != NULL) {
ResourceOwnerRelease(tempOwner, RESOURCE_RELEASE_BEFORE_LOCKS, false, false);
ResourceOwnerRelease(tempOwner, RESOURCE_RELEASE_LOCKS, false, false);
ResourceOwnerRelease(tempOwner, RESOURCE_RELEASE_AFTER_LOCKS, false, false);
t_thrd.utils_cxt.CurrentResourceOwner = currentOwner;
ResourceOwnerDelete(tempOwner);
}
MemoryContextSwitchTo(ecxt);
PG_RE_THROW();
}
@ -216,11 +257,13 @@ PlannedStmt* pgxc_planner(Query* query, int cursorOptions, ParamListInfo boundPa
}
/* release resource applied in standard_planner of the PG_TRY. */
ResourceOwnerRelease(tempOwner, RESOURCE_RELEASE_BEFORE_LOCKS, false, false);
ResourceOwnerRelease(tempOwner, RESOURCE_RELEASE_LOCKS, false, false);
ResourceOwnerRelease(tempOwner, RESOURCE_RELEASE_AFTER_LOCKS, false, false);
t_thrd.utils_cxt.CurrentResourceOwner = currentOwner;
ResourceOwnerDelete(tempOwner);
if (tempOwner != NULL) {
ResourceOwnerRelease(tempOwner, RESOURCE_RELEASE_BEFORE_LOCKS, false, false);
ResourceOwnerRelease(tempOwner, RESOURCE_RELEASE_LOCKS, false, false);
ResourceOwnerRelease(tempOwner, RESOURCE_RELEASE_AFTER_LOCKS, false, false);
t_thrd.utils_cxt.CurrentResourceOwner = currentOwner;
ResourceOwnerDelete(tempOwner);
}
#ifdef STREAMPLAN
if (OidIsValid(lc_replan_nodegroup)) {

View File

@ -107,8 +107,10 @@ static Node *pull_up_sublinks_targetlist(PlannerInfo *root, Node *node,
Node *jtnode, Relids *relids,
Node **newTargetList,
Node *whereQuals);
#ifndef ENABLE_MULTIPLE_NODES
static bool find_rownum_in_quals(PlannerInfo *root);
static bool contains_swctes(const PlannerInfo *root);
#endif
/*
@ -154,6 +156,34 @@ void replace_empty_jointree(Query *parse)
parse->jointree->fromlist = list_make1(rtr);
}
#ifndef ENABLE_MULTIPLE_NODES
/*
* helper function to check if SWCB ctes contaisn in current SubQuery, normally help us to
* idenfity if it is OK to appy SWCB related optimization steps
*/
static bool contains_swctes(const PlannerInfo *root)
{
if (root->parse == NULL || root->parse->cteList == NIL) {
return false;
}
List *cteList = root->parse->cteList;
ListCell *lc = NULL;
bool found = false;
foreach(lc, cteList) {
CommonTableExpr *cte = (CommonTableExpr *)lfirst(lc);
/* check if cte from parse->ctelist is a swcb converted */
if (cte->swoptions != NULL) {
found = true;
break;
}
}
return found;
}
#endif
/*
* pull_up_sublinks
* Attempt to pull up ANY and EXISTS SubLinks to be treated as
@ -192,6 +222,11 @@ void pull_up_sublinks(PlannerInfo* root)
if (find_rownum_in_quals(root)) {
return;
}
/* check existance of SWCB converted */
if (contains_swctes(root)) {
return;
}
#endif
/* Begin recursion through the jointree */

View File

@ -409,6 +409,7 @@ bool TryConnectRemoteServer(AiEngineConnInfo* conninfo, char** buf)
if (!CheckConnParams(conninfo)) {
return false;
}
bool exceptionCaught = false;
PG_TRY();
{
@ -444,14 +445,19 @@ bool TryConnectRemoteServer(AiEngineConnInfo* conninfo, char** buf)
}
PG_CATCH();
{
exceptionCaught = true;
t_thrd.int_cxt.ImmediateInterruptOK = immediateInterruptOKOld;
DestoryAiHandle(connHandle);
if (buf != NULL) {
*buf = NULL;
}
return false;
FlushErrorState();
}
PG_END_TRY();
if (exceptionCaught) {
return false;
}
if (buf != NULL) {
*buf = pstrdup(connHandle->rec_buf);
}

View File

@ -316,7 +316,7 @@ static void acquireSamplesForPartitionedRelation(
continue;
}
part = partitionOpen(relation, partitionOid, lmode);
part = partitionOpen(relation, partitionOid, NoLock);
currentPartPages = PartitionGetNumberOfBlocksInFork(relation, part, MAIN_FORKNUM, true);
partitionClose(relation, part, lmode);

View File

@ -460,17 +460,21 @@ PruningResult* partitionPruningForExpr(PlannerInfo* root, RangeTblEntry* rte, Re
context->pruningType = PruningPartition;
if (rel->partMap != NULL && (rel->partMap->type == PART_TYPE_LIST || rel->partMap->type == PART_TYPE_HASH)) {
// for List/Hash partitioned table
result = partitionEqualPruningWalker(rel->partMap->type, expr, context);
} else {
// for Range/Interval partitioned table
result = partitionPruningWalker(expr, context);
}
if (result->exprPart != NULL || result->paramArg != NULL) {
Param* paramArg = (Param *)copyObject(result->paramArg);
bool isPbeSinlePartition = result->isPbeSinlePartition;
destroyPruningResult(result);
result = getFullPruningResult(rel);
result->expr = expr;
result->paramArg = paramArg;
result->isPbeSinlePartition = isPbeSinlePartition;
return result;
}
/* Never happen, just to be self-contained */
@ -535,10 +539,12 @@ PruningResult* partitionPruningWalker(Expr* expr, PruningContext* pruningCtx)
result = makeNode(PruningResult);
result->state = PRUNING_RESULT_FULL;
}
result->isPbeSinlePartition = false;
} break;
default: {
result = makeNode(PruningResult);
result->state = PRUNING_RESULT_FULL;
result->isPbeSinlePartition = false;
} break;
}
@ -619,6 +625,7 @@ static PruningResult* partitionPruningFromBoolExpr(const BoolExpr* expr, Pruning
if (expr->boolop == NOT_EXPR) {
result = makeNode(PruningResult);
result->state = PRUNING_RESULT_FULL;
result->isPbeSinlePartition = false;
return result;
}
@ -638,6 +645,7 @@ static PruningResult* partitionPruningFromBoolExpr(const BoolExpr* expr, Pruning
break;
case OR_EXPR:
result = unionChildPruningResult(resultList, context);
result->isPbeSinlePartition = false;
break;
case NOT_EXPR:
default:
@ -750,6 +758,7 @@ static PruningResult* partitionPruningFromNullTest(NullTest* expr, PruningContex
}
result->state = PRUNING_RESULT_SUBSET;
result->isPbeSinlePartition = true;
result->bm_rangeSelectedPartitions = bms_make_singleton(partMap->rangeElementsNum - 1);
@ -832,6 +841,7 @@ static PruningResult* intersectChildPruningResult(const List* resultList, Prunin
AssertEreport(iteratorResult, MOD_OPT, "iteratorResult context is NNULL.");
if (iteratorResult->state == PRUNING_RESULT_EMPTY) {
result->state = PRUNING_RESULT_EMPTY;
result->isPbeSinlePartition = false;
return result;
} else if (iteratorResult->state == PRUNING_RESULT_FULL) {
continue;
@ -875,17 +885,22 @@ static PruningResult* intersectChildPruningResult(const List* resultList, Prunin
if (BoundaryIsEmpty(result->boundary)) {
result->state = PRUNING_RESULT_EMPTY;
result->isPbeSinlePartition = false;
break;
}
result->state = PRUNING_RESULT_SUBSET;
}
if (result->state != PRUNING_RESULT_EMPTY && iteratorResult->isPbeSinlePartition) {
result->isPbeSinlePartition = true;
}
}
if (PruningResultIsEmpty(result)) {
destroyPruningResult(result);
result = makeNode(PruningResult);
result->state = PRUNING_RESULT_EMPTY;
result->isPbeSinlePartition = false;
result->intervalOffset = -1;
}
@ -981,6 +996,7 @@ static PruningResult* partitionPruningFromScalarArrayOpExpr
if (T_Var != nodeTag(larg) || (T_ArrayExpr != nodeTag(rarg) && T_Const != nodeTag(rarg))) {
result = makeNode(PruningResult);
result->state = PRUNING_RESULT_FULL;
result->isPbeSinlePartition = false;
return result;
}
@ -1079,6 +1095,7 @@ static PruningResult* partitionPruningFromScalarArrayOpExpr
} else {
result = makeNode(PruningResult);
result->state = PRUNING_RESULT_FULL;
result->isPbeSinlePartition = false;
return result;
}
}
@ -1258,6 +1275,7 @@ static PruningResult* recordBoundaryFromOpExpr(const OpExpr* expr, PruningContex
/* length of args MUST be 2 */
if (!PointerIsValid(expr) || list_length(expr->args) != 2 || !PointerIsValid(opName = get_opname(expr->opno))) {
result->state = PRUNING_RESULT_FULL;
result->isPbeSinlePartition = false;
return result;
}
@ -1296,6 +1314,7 @@ static PruningResult* recordBoundaryFromOpExpr(const OpExpr* expr, PruningContex
((T_Const == nodeTag(rightArg) || T_Param == nodeTag(rightArg)
|| T_OpExpr == nodeTag(rightArg)) && T_Var == nodeTag(leftArg)))) {
result->state = PRUNING_RESULT_FULL;
result->isPbeSinlePartition = false;
return result;
}
@ -1325,6 +1344,7 @@ static PruningResult* recordBoundaryFromOpExpr(const OpExpr* expr, PruningContex
if (context->rte != NULL &&
context->rte->relid != context->relation->rd_id) {
result->state = PRUNING_RESULT_FULL;
result->isPbeSinlePartition = false;
return result;
}
} else {
@ -1334,6 +1354,7 @@ static PruningResult* recordBoundaryFromOpExpr(const OpExpr* expr, PruningContex
paramArg != NULL ||
exprPart != NULL) {
result->state = PRUNING_RESULT_FULL;
result->isPbeSinlePartition = false;
return result;
}
}
@ -1351,25 +1372,32 @@ static PruningResult* recordBoundaryFromOpExpr(const OpExpr* expr, PruningContex
if (exprPart != NULL) {
if (!PartitionMapIsRange(partMap)) {
result->state = PRUNING_RESULT_FULL;
result->isPbeSinlePartition = false;
return result;
} else {
result->exprPart = exprPart;
result->state = PRUNING_RESULT_SUBSET;
result->isPbeSinlePartition = false;
return result;
}
} else if (paramArg != NULL) {
if (paramArg->paramkind != PARAM_EXTERN || !PartitionMapIsRange(partMap)) {
result->state = PRUNING_RESULT_FULL;
result->isPbeSinlePartition = false;
return result;
} else {
result->paramArg = paramArg;
result->state = PRUNING_RESULT_SUBSET;
if (0 == strcmp("=", opName)) {
result->isPbeSinlePartition = true;
}
return result;
}
}
if (constArg->constisnull) {
result->state = PRUNING_RESULT_EMPTY;
result->isPbeSinlePartition = false;
return result;
}
@ -1377,6 +1405,7 @@ static PruningResult* recordBoundaryFromOpExpr(const OpExpr* expr, PruningContex
result->boundary = makePruningBoundary(partKeyNum);
boundary = result->boundary;
result->isPbeSinlePartition = false;
/* decide the const is the top or bottom of boundary */
if ((0 == strcmp(">", opName) && rightArgIsConst) || (0 == strcmp("<", opName) && !rightArgIsConst)) {
@ -1409,6 +1438,7 @@ static PruningResult* recordBoundaryFromOpExpr(const OpExpr* expr, PruningContex
boundary->state = PRUNING_RESULT_SUBSET;
result->state = PRUNING_RESULT_SUBSET;
result->isPbeSinlePartition = true;
} else if ((0 == strcmp("<=", opName) && rightArgIsConst) || (0 == strcmp(">=", opName) && !rightArgIsConst)) {
boundary->maxClose[attrOffset] = true;
boundary->max[attrOffset] = PointerGetDatum(constArg);

View File

@ -2070,6 +2070,25 @@ static void do_autovacuum(void)
continue;
}
/* Here we skipped relation_support_autoavac() and relation_needs_vacanalyze() checks
* for Ustore partitioned tables
*/
bytea *rawRelopts = extractRelOptions(tuple, pg_class_desc, InvalidOid);
if (rawRelopts != NULL && RelationIsTableAccessMethodUStoreType(rawRelopts) &&
isPartitionedRelation(classForm)) {
vacObj = (vacuum_object*)palloc(sizeof(vacuum_object));
vacObj->tab_oid = relid;
vacObj->parent_oid = InvalidOid;
vacObj->dovacuum = true;
vacObj->dovacuum_toast = false;
vacObj->doanalyze = false;
vacObj->need_freeze = false;
vacObj->is_internal_relation = false;
vacObj->flags = VACFLG_MAIN_PARTITION;
table_oids = lappend(table_oids, vacObj);
continue;
}
/* Fetch reloptions for this table */
relopts = extract_autovac_opts(tuple, pg_class_desc);
@ -2176,7 +2195,6 @@ static void do_autovacuum(void)
pfree_ext(relopts);
}
}
tableam_scan_end(relScan);
DEBUG_MOD_STOP_TIMER(MOD_AUTOVAC, "AUTOVAC TIMER: Scan pg_class to determine which tables to vacuum");
@ -2277,7 +2295,6 @@ static void do_autovacuum(void)
}
}
}
/* Close the pg_partition */
tableam_scan_end(partScan);
heap_close(partRel, AccessShareLock);
@ -2376,51 +2393,9 @@ static void do_autovacuum(void)
pfree_ext(relopts);
}
}
tableam_scan_end(relScan);
DEBUG_MOD_STOP_TIMER(MOD_AUTOVAC, "AUTOVAC TIMER: Scan pg_class to determine which toast tables to vacuum");
/* On the fourth pass: check USTORE GPI tables */
ScanKeyInit(&key[0], Anum_pg_class_relkind, BTEqualStrategyNumber, F_CHAREQ, CharGetDatum(RELKIND_GLOBAL_INDEX));
relScan = tableam_scan_begin(classRel, SnapshotNow, 1, &key[0]);
while ((tuple = (HeapTuple)tableam_scan_getnexttuple(relScan, ForwardScanDirection)) != NULL) {
Form_pg_class classForm = (Form_pg_class) GETSTRUCT(tuple);
Oid relid = HeapTupleGetOid(tuple);
AutoVacOpts *relopts = NULL;
/*
* We cannot safely process other backends' temp tables, so skip them.
*/
if (classForm->relpersistence == RELPERSISTENCE_TEMP ||
classForm->relpersistence == RELPERSISTENCE_GLOBAL_TEMP)
continue;
/* only UBTree supports vacuum independently */
if (classForm->relam != UBTREE_AM_OID) {
continue;
}
/* fetch reloptions */
relopts = extract_autovac_opts(tuple, pg_class_desc);
/* only UBTree supports vacuum, and enabled will be set true */
if (relopts == NULL || !relopts->enabled) {
continue;
}
/* we skipped relation_support_autoavac() and relation_needs_vacanalyze() checks here */
vacObj = (vacuum_object*)palloc(sizeof(vacuum_object));
vacObj->tab_oid = relid;
vacObj->parent_oid = InvalidOid;
vacObj->dovacuum = true;
vacObj->dovacuum_toast = false;
vacObj->doanalyze = false;
vacObj->need_freeze = false;
vacObj->is_internal_relation = false;
/* VACFLG_MAIN_PARTITION makes no sense when vacuuming UBTree */
vacObj->flags = VACFLG_SIMPLE_HEAP; /* ignore this flag as we will not use it,
* and to be safe we can use VACFLG_SIMPLE_HEAP.
*/
table_oids = lappend(table_oids, vacObj);
}
tableam_scan_end(relScan);
heap_close(classRel, AccessShareLock);
DEBUG_MOD_STOP_TIMER(MOD_AUTOVAC, "AUTOVAC TIMER: Scan pg_class to determine which UBTree tables to vacuum");
DEBUG_MOD_STOP_TIMER(MOD_AUTOVAC, "AUTOVAC TIMER: Scan pg_class to determine which toast tables to vacuum");
/*
* Create one buffer access strategy object per buffer pool for VACUUM to use.
@ -2754,8 +2729,7 @@ AutoVacOpts* extract_autovac_opts(HeapTuple tup, TupleDesc pg_class_desc)
Assert(((Form_pg_class)GETSTRUCT(tup))->relkind == RELKIND_RELATION ||
((Form_pg_class) GETSTRUCT(tup))->relkind == RELKIND_MATVIEW ||
((Form_pg_class)GETSTRUCT(tup))->relkind == RELKIND_TOASTVALUE ||
((Form_pg_class)GETSTRUCT(tup))->relkind == RELKIND_GLOBAL_INDEX);
((Form_pg_class)GETSTRUCT(tup))->relkind == RELKIND_TOASTVALUE);
relopts = extractRelOptions(tup, pg_class_desc, InvalidOid);
if (relopts == NULL)
@ -2765,15 +2739,9 @@ AutoVacOpts* extract_autovac_opts(HeapTuple tup, TupleDesc pg_class_desc)
rc = memcpy_s(av, sizeof(AutoVacOpts), &(((StdRdOptions*)relopts)->autovacuum), sizeof(AutoVacOpts));
securec_check(rc, "\0", "\0");
/* autovacuum for ustore table is disabled */
/* autovacuum for ustore unpartitioned table is disabled */
if (RelationIsTableAccessMethodUStoreType(relopts)) {
av->enabled = false;
}
/* force set av->enabled in ustore's GPI */
if ((((Form_pg_class)GETSTRUCT(tup))->relkind == RELKIND_GLOBAL_INDEX) &&
RelationIsTableAccessMethodUStoreType(relopts)) {
av->enabled = true;
av->enabled = isPartitionedRelation((Form_pg_class)GETSTRUCT(tup));
}
pfree_ext(relopts);
@ -2898,8 +2866,10 @@ static autovac_table* table_recheck_autovac(
if (!HeapTupleIsValid(classTup))
return NULL;
classForm = (Form_pg_class)GETSTRUCT(classTup);
/* this is UBTree, use another bypass */
if (classForm->relam == UBTREE_AM_OID) {
bytea *rawRelopts = extractRelOptions(classTup, pg_class_desc, InvalidOid);
/* this is Ustore partitioned table, use another bypass */
if (rawRelopts != NULL && RelationIsTableAccessMethodUStoreType(rawRelopts) &&
isPartitionedRelation(classForm)) {
avopts = extract_autovac_opts(classTup, pg_class_desc);
tab = calculate_vacuum_cost_and_freezeages(avopts, false, false);
if (tab != NULL) {

View File

@ -57,13 +57,14 @@ void GetCsnBarrierName(char* barrierRet, bool isSwitchoverBarrier)
struct timeval tv;
int rc;
CommitSeqNo csn;
gettimeofday(&tv, NULL);
if (GTM_MODE)
csn = GetCSNGTM();
else
csn = CommitCSNGTM(false);
gettimeofday(&tv, NULL);
if (isSwitchoverBarrier) {
rc = snprintf_s(barrierRet, BARRIER_NAME_LEN, BARRIER_NAME_LEN - 1, CSN_SWITCHOVER_BARRIER_PATTREN_STR, csn);
} else {
@ -206,6 +207,7 @@ uint64 GetObsFirstCNBarrierTimeline(const List *archiveSlotNames)
return timeline;
}
#ifdef ENABLE_MULTIPLE_NODES
static void AllocBarrierLsnInfo(int nodeSize)
{
int rc;
@ -216,6 +218,7 @@ static void AllocBarrierLsnInfo(int nodeSize)
sizeof(ArchiveBarrierLsnInfo) * nodeSize);
securec_check(rc, "", "");
}
#endif
#ifdef ENABLE_MULTIPLE_NODES
static void BarrierCreatorPoolerReload(void)
@ -402,6 +405,7 @@ void barrier_creator_main(void)
long time_diff = last_barrier_time - current_time;
ereport(LOG, (errmsg("[BarrierCreator] current time %ld is smaller than barrier time %ld, and sleep %ld ms",
current_time, last_barrier_time, time_diff)));
CHECK_FOR_INTERRUPTS();
pg_usleep(time_diff * 1000L);
} while (1);
if (t_thrd.barrier_creator_cxt.is_first_barrier) {
@ -410,6 +414,7 @@ void barrier_creator_main(void)
}
#ifdef ENABLE_MULTIPLE_NODES
while (!START_AUTO_CSN_BARRIER) {
CHECK_FOR_INTERRUPTS();
pg_usleep(1000000L);
}
#endif
@ -436,6 +441,7 @@ void barrier_creator_main(void)
t_thrd.barrier_creator_cxt.barrier_update_last_time_info = (BarrierUpdateLastTimeInfo*)palloc0(
sizeof(BarrierUpdateLastTimeInfo) * g_instance.attr.attr_storage.max_replication_slots);
}
#ifdef ENABLE_MULTIPLE_NODES
if (g_instance.archive_obs_cxt.barrier_lsn_info == NULL) {
int nodeSize = *t_thrd.pgxc_cxt.shmemNumCoords + *t_thrd.pgxc_cxt.shmemNumDataNodes;
AllocBarrierLsnInfo(nodeSize);
@ -443,6 +449,7 @@ void barrier_creator_main(void)
g_instance.archive_obs_cxt.max_node_cnt = nodeSize;
SpinLockRelease(&g_instance.archive_obs_cxt.barrier_lock);
}
#endif
archiveSlotNames = GetAllArchiveSlotsName();
if (archiveSlotNames == NIL || archiveSlotNames->length == 0) {
ereport(WARNING, (errmsg("[BarrierCreator] could not get archive slot name when barrier start")));

View File

@ -173,10 +173,11 @@ void BarrierPreParseMain(void)
XLogReaderState *xlogreader = NULL;
char *errormsg = NULL;
XLogPageReadPrivate readprivate;
XLogRecPtr startLSN;
XLogRecPtr preStartLSN;
XLogRecPtr startLSN = InvalidXLogRecPtr;
XLogRecPtr preStartLSN = InvalidXLogRecPtr;
XLogRecPtr lastReadLSN = InvalidXLogRecPtr;
bool found = false;
XLogRecPtr barrierLSN;
XLogRecPtr barrierLSN = InvalidXLogRecPtr;
char *xLogBarrierId = NULL;
char barrierId[MAX_BARRIER_ID_LENGTH] = {0};
const uint32 shiftSize = 32;
@ -258,10 +259,13 @@ void BarrierPreParseMain(void)
found = false;
preStartLSN = startLSN;
ereport(DEBUG1, (errmsg("[BarrierPreParse] start to preparse at: %08X/%08X",
(uint32)(startLSN >> shiftSize), (uint32)startLSN)));
startLSN = XLogFindNextRecord(xlogreader, startLSN);
if (XLogRecPtrIsInvalid(startLSN)) {
startLSN = preStartLSN;
if (!XLByteEQ(walrcv->receiver_flush_location, startLSN)) {
if (!XLByteEQ(walrcv->receiver_flush_location, startLSN) &&
!XLByteEQ(walrcv->lastRecoveredBarrierLSN, startLSN)) {
/* reset startLSN */
startLSN = walrcv->lastRecoveredBarrierLSN;
ereport(LOG, (errmsg("[BarrierPreParse] reset startLSN with lastRecoveredBarrierLSN: %08X/%08X",
@ -275,6 +279,7 @@ void BarrierPreParseMain(void)
if (record == NULL) {
break;
}
lastReadLSN = xlogreader->EndRecPtr;
uint8 info = XLogRecGetInfo(xlogreader) & ~XLR_INFO_MASK;
if (NEED_INSERT_INTO_HASH) {
xLogBarrierId = XLogRecGetData(xlogreader);
@ -304,7 +309,7 @@ void BarrierPreParseMain(void)
SetBarrieID(barrierId, barrierLSN);
}
startLSN = XLogRecPtrIsInvalid(xlogreader->ReadRecPtr) ? preStartLSN : xlogreader->ReadRecPtr;
startLSN = XLogRecPtrIsInvalid(lastReadLSN) ? preStartLSN : lastReadLSN;
if (XLogRecPtrIsInvalid(xlogreader->ReadRecPtr) && errormsg) {
ereport(LOG, (errmsg("[BarrierPreParse] preparse thread get an error info %s", errormsg)));

View File

@ -1216,9 +1216,12 @@ static void HandlePageWriterMainInterrupts()
ProcessConfigFile(PGC_SIGHUP);
}
if (t_thrd.pagewriter_cxt.sync_requested) {
if (t_thrd.pagewriter_cxt.sync_requested || t_thrd.pagewriter_cxt.sync_retry) {
t_thrd.pagewriter_cxt.sync_requested = false;
t_thrd.pagewriter_cxt.sync_retry = true;
PageWriterSyncWithAbsorption();
t_thrd.pagewriter_cxt.sync_retry = false;
}
/* main thread should finally exit. */

View File

@ -425,6 +425,7 @@ static void pgarch_MainLoop(void)
XLogRecPtr replayPtr;
bool got_recptr = false;
bool amSync = false;
int retryTimes = 3;
/* FlushPtr <= ConsensusPtr on DCF mode */
if (IS_PGXC_COORDINATOR || g_instance.attr.attr_storage.dcf_attr.enable_dcf) {
flushPtr = GetFlushRecPtr();
@ -441,8 +442,16 @@ static void pgarch_MainLoop(void)
"and init last lsn is %08X%08X", (uint32)(t_thrd.arch.pitr_task_last_lsn >> 32),
(uint32)t_thrd.arch.pitr_task_last_lsn)));
}
got_recptr = SyncRepGetSyncRecPtr(&receivePtr, &writePtr, &flushPtr, &replayPtr, &amSync, false);
if (got_recptr != true) {
while (retryTimes--) {
got_recptr =
SyncRepGetSyncRecPtr(&receivePtr, &writePtr, &flushPtr, &replayPtr, &amSync, false);
if (got_recptr == true) {
break;
} else {
pg_usleep(1000000L);
}
}
if (got_recptr == false) {
ereport(ERROR,
(errmsg("pgarch_ArchiverObsCopyLoop failed when call SyncRepGetSyncRecPtr")));
}
@ -739,6 +748,10 @@ static void pgarch_ArchiverObsCopyLoop(XLogRecPtr flushPtr, doArchive fun)
(uint32)(targetLsn >> 32), (uint32)(targetLsn))));
pg_usleep(1000000L); /* wait a bit before retrying */
} else {
if (g_instance.roach_cxt.isXLogForceRecycled && !g_instance.roach_cxt.forceAdvanceSlotTigger) {
g_instance.roach_cxt.isXLogForceRecycled = false;
ereport(LOG, (errmsg("PgArch force advance slot success")));
}
gettimeofday(&tv, NULL);
currTimestamp = TIME_GET_MILLISEC(tv);
t_thrd.arch.pitr_task_last_lsn = targetLsn;
@ -1026,6 +1039,11 @@ static void pgarch_archiveRoachForPitrStandby()
(uint32)(archive_task_status->archive_task.targetLsn),
archive_task_status->archive_task.term,
archive_task_status->archive_task.sub_term)));
if (archive_task_status->archive_task.targetLsn == InvalidXLogSegPtr) {
volatile unsigned int *pitr_task_status = &archive_task_status->pitr_task_status;
pg_atomic_write_u32(pitr_task_status, PITR_TASK_NONE);
ereport(LOG, (errmsg("PgArch standby receive invalid lsn for slot force advance")));
}
if (ArchiveReplicationAchiver(&archive_task_status->archive_task) == 0) {
archive_task_status->pitr_finish_result = true;
} else {
@ -1057,6 +1075,11 @@ static bool pgarch_archiveRoachForPitrMaster(XLogRecPtr targetLsn)
archive_task_status->archive_task.tli = get_controlfile_timeline();
archive_task_status->archive_task.term = Max(g_instance.comm_cxt.localinfo_cxt.term_from_file,
g_instance.comm_cxt.localinfo_cxt.term_from_xlog);
if (g_instance.roach_cxt.forceAdvanceSlotTigger) {
archive_task_status->archive_task.targetLsn = InvalidXLogRecPtr;
g_instance.roach_cxt.forceAdvanceSlotTigger = false;
ereport(LOG, (errmsg("PgArch need force advance this time in primary")));
}
/* subterm update when walsender changed */
int rc = strcpy_s(archive_task_status->archive_task.slot_name, NAMEDATALEN, t_thrd.arch.slot_name);
securec_check(rc, "\0", "\0");
@ -1085,8 +1108,8 @@ static bool pgarch_archiveRoachForPitrMaster(XLogRecPtr targetLsn)
return false;
}
/*
* check targetLsn and g_instance.archive_obs_cxt.archive_task.targetLsn for deal message with wrong order
*/
* check targetLsn and g_instance.archive_obs_cxt.archive_task.targetLsn for deal message with wrong order
*/
if (archive_task_status->pitr_finish_result == true
&& XLByteEQ(archive_task_status->archive_task.targetLsn, targetLsn)) {
archive_task_status->pitr_finish_result = false;
@ -1191,6 +1214,26 @@ static WalSnd* pgarch_chooseWalsnd(XLogRecPtr targetLsn)
return NULL;
}
static XLogRecPtr GetLastTaskLsnFromServer(ArchiveSlotConfig* obs_archive_slot)
{
ArchiveXlogMessage obs_archive_info;
XLogRecPtr pitr_task_last_lsn;
if (archive_replication_get_last_xlog(&obs_archive_info, &obs_archive_slot->archive_config) == 0) {
pitr_task_last_lsn = obs_archive_info.targetLsn;
ereport(LOG,
(errmsg("initLastTaskLsn update lsn to %X/%X from server", (uint32)(pitr_task_last_lsn >> 32),
(uint32)(pitr_task_last_lsn))));
} else {
XLogRecPtr targetLsn = GetFlushRecPtr();
pitr_task_last_lsn = targetLsn - (targetLsn % XLogSegSize);
ereport(LOG,
(errmsg("initLastTaskLsn update lsn to %X/%X from local", (uint32)(pitr_task_last_lsn >> 32),
(uint32)(pitr_task_last_lsn))));
}
return pitr_task_last_lsn;
}
static void InitArchiverLastTaskLsn(ArchiveSlotConfig* obs_archive_slot)
{
struct timeval tv;
@ -1207,8 +1250,19 @@ static void InitArchiverLastTaskLsn(ArchiveSlotConfig* obs_archive_slot)
ReplicationSlot *slot = &t_thrd.slot_cxt.ReplicationSlotCtl->replication_slots[*slot_idx];
SpinLockAcquire(&slot->mutex);
if (slot->in_use == true && slot->archive_config != NULL) {
t_thrd.arch.pitr_task_last_lsn = slot->data.restart_lsn;
SpinLockRelease(&slot->mutex);
/*
* In old version(<92599), the last task lsn is initialized from archive server or current flush
* position, but in new version is initialized from local slot.
* During the upgrade, the local restart lsn may be 0, so initialize it with old version way.
*/
if (slot->data.restart_lsn == InvalidXLogRecPtr &&
t_thrd.proc->workingVersionNum < PITR_INIT_VERSION_NUM) {
SpinLockRelease(&slot->mutex);
t_thrd.arch.pitr_task_last_lsn = GetLastTaskLsnFromServer(obs_archive_slot);
} else {
t_thrd.arch.pitr_task_last_lsn = slot->data.restart_lsn;
SpinLockRelease(&slot->mutex);
}
} else {
SpinLockRelease(&slot->mutex);
ereport(ERROR, (errcode_for_file_access(), errmsg("slot idx not valid, obs slot %X/%X not advance ",

View File

@ -203,7 +203,7 @@ typedef struct AuditIndexItem {
* Brief : audit index table
* Description :
*/
typedef struct AuditIndexTable {
typedef struct AuditIndexTableNew {
uint32 maxnum; /* max count of the audit index item */
uint32 begidx; /* the position of the first audit index item */
uint32 thread_num; /* the running audit thread num */
@ -212,25 +212,25 @@ typedef struct AuditIndexTable {
uint32 count; /* the count of the audit index item */
pg_time_t last_audit_time; /* the audit time of the latest audit record */
AuditIndexItem data[1];
} AuditIndexTable;
} AuditIndexTableNew;
/*
* Brief : old audit index table
* Description :
*/
typedef struct AuditIndexTableOld {
typedef struct AuditIndexTable {
uint32 maxnum; /* max count of the audit index item */
uint32 begidx; /* the position of the first audit index item */
uint32 curidx; /* the position of the current audit index item */
uint32 count; /* the count of the audit index item */
pg_time_t last_audit_time; /* the audit time of the latest audit record */
AuditIndexItem data[1];
} AuditIndexTableOld;
} AuditIndexTable;
static const char audit_indextbl_file[] = "index_table_new";
static const char audit_indextbl_old_file[] = "index_table";
static const int indextbl_header_size = offsetof(AuditIndexTable, data);
static const int old_indextbl_header_size = offsetof(AuditIndexTableOld, data);
static const int indextbl_header_size = offsetof(AuditIndexTableNew, data);
static const int old_indextbl_header_size = offsetof(AuditIndexTable, data);
static const char* AuditTypeDescs[] = {"unknown",
"login_success",
@ -401,7 +401,6 @@ static void pgaudit_indexfile_upgrade(void);
static void pgaudit_indexfile_sync(const char* mode, bool allow_errors);
static void pgaudit_rewrite_indexfile(void);
static void pgaudit_indextbl_init_new(void);
void extracted836(errno_t &errorno, int thread_num);
static void pgaudit_reset_indexfile();
static const char* pgaudit_string_field(AuditData* adata, int num);
static void deserialization_to_tuple(Datum (&values)[PGAUDIT_QUERY_COLS],
@ -808,11 +807,11 @@ void pgaudit_stop_all(void)
{
for (int i = 0; i < g_instance.audit_cxt.thread_num; ++i) {
if (g_instance.pid_cxt.PgAuditPID[i] != 0) {
Assert(!dummyStandbyMode);
signal_child(g_instance.pid_cxt.PgAuditPID[i], SIGQUIT, -1);
}
}
audit_process_cxt_exit();
ereport(LOG, (errmsg("parameter audit_enabled is set to false, terminate auditor process.")));
}
/*
@ -1471,7 +1470,6 @@ static void pgaudit_cleanup(void)
if (g_instance.audit_cxt.audit_indextbl->count > 0) {
--g_instance.audit_cxt.audit_indextbl->count;
}
g_instance.audit_cxt.audit_indextbl->begidx = (index + 1) % g_instance.audit_cxt.audit_indextbl->maxnum;
errorno = memset_s(item, sizeof(AuditIndexItem), 0, sizeof(AuditIndexItem));
securec_check(errorno, "\0", "\0");
@ -1487,7 +1485,9 @@ static void pgaudit_cleanup(void)
if (index == earliest_idx) {
break;
}
/* udpate audit index for next loop */
g_instance.audit_cxt.audit_indextbl->begidx = (index + 1) % g_instance.audit_cxt.audit_indextbl->maxnum;
index = g_instance.audit_cxt.audit_indextbl->begidx;
}
LWLockRelease(g_instance.audit_cxt.index_file_lock);
@ -2018,7 +2018,7 @@ static void pgaudit_read_indexfile(const char* audit_directory)
struct stat statbuf;
char tblfile_path[MAXPGPATH] = {0};
size_t nread = 0;
AuditIndexTable indextbl;
AuditIndexTableNew indextbl;
int rc = snprintf_s(tblfile_path, MAXPGPATH, MAXPGPATH - 1, "%s/%s", audit_directory, audit_indextbl_file);
securec_check_intval(rc,,);
@ -2057,7 +2057,7 @@ static void pgaudit_read_indexfile(const char* audit_directory)
pfree_ext(g_instance.audit_cxt.audit_indextbl);
/* read the whole audit index table */
g_instance.audit_cxt.audit_indextbl = (AuditIndexTable *)MemoryContextAllocZero(
g_instance.audit_cxt.audit_indextbl = (AuditIndexTableNew *)MemoryContextAllocZero(
g_instance.audit_cxt.global_audit_context,
(indextbl.maxnum * sizeof(AuditIndexItem) + indextbl_header_size));
errorno =
@ -2258,7 +2258,7 @@ static void pgaudit_rewrite_indexfile(void)
FILE* fp = NULL;
char tblfile_path[MAXPGPATH] = {0};
size_t nread = 0;
AuditIndexTableOld old_index_tbl;
AuditIndexTable old_index_tbl;
int rc = snprintf_s(tblfile_path,
MAXPGPATH,
@ -2288,7 +2288,7 @@ static void pgaudit_rewrite_indexfile(void)
pfree_ext(g_instance.audit_cxt.audit_indextbl);
pfree_ext(g_instance.audit_cxt.audit_indextbl_old);
/* read the whole audit index table */
g_instance.audit_cxt.audit_indextbl_old = (AuditIndexTableOld *)MemoryContextAllocZero(
g_instance.audit_cxt.audit_indextbl_old = (AuditIndexTable *)MemoryContextAllocZero(
g_instance.audit_cxt.global_audit_context,
(old_index_tbl.maxnum * sizeof(AuditIndexItem) + old_indextbl_header_size));
errorno = memcpy_s(g_instance.audit_cxt.audit_indextbl_old,
@ -2296,7 +2296,7 @@ static void pgaudit_rewrite_indexfile(void)
&old_index_tbl, old_indextbl_header_size);
securec_check(errorno, "\0", "\0");
/* rewrite old index table to new index table */
g_instance.audit_cxt.audit_indextbl = (AuditIndexTable *)MemoryContextAllocZero(
g_instance.audit_cxt.audit_indextbl = (AuditIndexTableNew *)MemoryContextAllocZero(
g_instance.audit_cxt.global_audit_context,
(old_index_tbl.maxnum * sizeof(AuditIndexItem) + indextbl_header_size));
g_instance.audit_cxt.audit_indextbl->maxnum = old_index_tbl.maxnum;
@ -2334,7 +2334,7 @@ static void pgaudit_indextbl_init_new(void)
if (g_instance.audit_cxt.audit_indextbl == NULL) {
ereport(LOG, (errmsg("pgaudit_indextbl_init_new first init")));
g_instance.audit_cxt.audit_indextbl =
(AuditIndexTable *)MemoryContextAllocZero(g_instance.audit_cxt.global_audit_context,
(AuditIndexTableNew *)MemoryContextAllocZero(g_instance.audit_cxt.global_audit_context,
(u_sess->attr.attr_security.Audit_RemainThreshold + 1) * sizeof(AuditIndexItem) + indextbl_header_size);
g_instance.audit_cxt.audit_indextbl->maxnum = u_sess->attr.attr_security.Audit_RemainThreshold + 1;
g_instance.audit_cxt.audit_indextbl->count = 0; /* audit files count will be updated by auditfile_open */
@ -2417,27 +2417,31 @@ static void pgaudit_indextbl_init_new(void)
return;
}
static void pgaudit_udpate_maxnum()
static void pgaudit_update_maxnum()
{
errno_t errorno = EOK;
int thread_num = g_instance.attr.attr_security.audit_thread_num;
int new_indextbl_data_lenth = (u_sess->attr.attr_security.Audit_RemainThreshold + 1) * sizeof(AuditIndexItem);
AuditIndexTable *new_indextbl = (AuditIndexTable *)MemoryContextAllocZero(
AuditIndexTableNew *new_indextbl = (AuditIndexTableNew *)MemoryContextAllocZero(
g_instance.audit_cxt.global_audit_context, new_indextbl_data_lenth + indextbl_header_size);
/* curidx and latest_idx should be updated later from old index table file */
new_indextbl->begidx = 0;
new_indextbl->maxnum = u_sess->attr.attr_security.Audit_RemainThreshold + 1;
new_indextbl->last_audit_time = g_instance.audit_cxt.audit_indextbl->last_audit_time;
new_indextbl->thread_num = g_instance.audit_cxt.audit_indextbl->thread_num;
if (g_instance.audit_cxt.audit_indextbl->count > 0) {
AuditIndexItem *item = NULL;
uint32 latest_idx = g_instance.audit_cxt.audit_indextbl->latest_idx;
uint32 last_idx = (latest_idx == 0) ? (g_instance.audit_cxt.audit_indextbl->maxnum - 1): (latest_idx - 1);
uint32 index = g_instance.audit_cxt.audit_indextbl->begidx;
uint32 pos = new_indextbl->begidx;
do {
item = g_instance.audit_cxt.audit_indextbl->data + index;
errorno = memcpy_s(new_indextbl->data + pos, (new_indextbl_data_lenth - pos), item, sizeof(AuditIndexItem));
errorno = memcpy_s(new_indextbl->data + pos, (new_indextbl_data_lenth - (pos * sizeof(AuditIndexItem))),
item, sizeof(AuditIndexItem));
securec_check(errorno, "\0", "\0");
new_indextbl->count++;
@ -2445,11 +2449,11 @@ static void pgaudit_udpate_maxnum()
* finished copy old index table file from range [begin, latest_idx)
* then update new index table file curidxes
*/
if (index == (latest_idx - 1)) {
if (index == last_idx) {
for (int i = 0; i < thread_num; ++i) {
new_indextbl->curidx[i] = pos - thread_num + i;
new_indextbl->curidx[i] = pos - thread_num + 1 + i;
}
new_indextbl->latest_idx = pos;
new_indextbl->latest_idx = pos + 1;
break;
}
@ -2487,7 +2491,7 @@ static void pgaudit_reset_indexfile()
/* If file remain threshold parameter changed, than copy the old audit index table to the new table */
if (old_maxnum != (uint32)u_sess->attr.attr_security.Audit_RemainThreshold + 1) {
LWLockAcquire(g_instance.audit_cxt.index_file_lock, LW_EXCLUSIVE);
pgaudit_udpate_maxnum();
pgaudit_update_maxnum();
LWLockRelease(g_instance.audit_cxt.index_file_lock);
}
@ -2996,17 +3000,19 @@ Datum pg_query_audit(PG_FUNCTION_ARGS)
* load the index audit table from global index audit table instance
* then use the local thread one when iterate all audit files
*/
pgaudit_read_indexfile(audit_dir);
LWLockAcquire(g_instance.audit_cxt.index_file_lock, LW_SHARED);
t_thrd.audit.audit_indextbl = NULL;
int indextbl_len =
(u_sess->attr.attr_security.Audit_RemainThreshold + 1) * sizeof(AuditIndexItem) + indextbl_header_size;
t_thrd.audit.audit_indextbl = (AuditIndexTable *)palloc0(indextbl_len);
error_t errorno =
memcpy_s(t_thrd.audit.audit_indextbl, indextbl_len, g_instance.audit_cxt.audit_indextbl, indextbl_len);
securec_check(errorno, "\0", "\0");
pfree_ext(t_thrd.audit.audit_indextbl);
if (g_instance.audit_cxt.audit_indextbl != NULL) {
int indextbl_len =
(u_sess->attr.attr_security.Audit_RemainThreshold + 1) * sizeof(AuditIndexItem) + indextbl_header_size;
t_thrd.audit.audit_indextbl = (AuditIndexTableNew *)palloc0(indextbl_len);
error_t errorno =
memcpy_s(t_thrd.audit.audit_indextbl, indextbl_len, g_instance.audit_cxt.audit_indextbl, indextbl_len);
securec_check(errorno, "\0", "\0");
}
LWLockRelease(g_instance.audit_cxt.index_file_lock);
per_query_ctx = rsinfo->econtext->ecxt_per_query_memory;
oldcontext = MemoryContextSwitchTo(per_query_ctx);
@ -3017,8 +3023,6 @@ Datum pg_query_audit(PG_FUNCTION_ARGS)
MemoryContextSwitchTo(oldcontext);
ereport(DEBUG1,
(errmsg("pg_query_audit count: %d indextbl_len: %d", t_thrd.audit.audit_indextbl->count, indextbl_len)));
if (begtime < endtime && t_thrd.audit.audit_indextbl != NULL && t_thrd.audit.audit_indextbl->count > 0) {
bool satisfied = false;
uint32 index = 0;
@ -3073,14 +3077,17 @@ Datum pg_delete_audit(PG_FUNCTION_ARGS)
* load the index audit table from global index audit table instance
* then use the local thread one when iterate all audit files
*/
pgaudit_read_indexfile(g_instance.attr.attr_security.Audit_directory);
LWLockAcquire(g_instance.audit_cxt.index_file_lock, LW_SHARED);
pfree_ext(t_thrd.audit.audit_indextbl);
int indextbl_len =
(u_sess->attr.attr_security.Audit_RemainThreshold + 1) * sizeof(AuditIndexItem) + indextbl_header_size;
t_thrd.audit.audit_indextbl = (AuditIndexTable *)palloc0(indextbl_len);
error_t errorno =
memcpy_s(t_thrd.audit.audit_indextbl, indextbl_len, g_instance.audit_cxt.audit_indextbl, indextbl_len);
securec_check(errorno, "\0", "\0");
if (g_instance.audit_cxt.audit_indextbl != NULL) {
int indextbl_len =
(u_sess->attr.attr_security.Audit_RemainThreshold + 1) * sizeof(AuditIndexItem) + indextbl_header_size;
t_thrd.audit.audit_indextbl = (AuditIndexTableNew *)palloc0(indextbl_len);
error_t errorno =
memcpy_s(t_thrd.audit.audit_indextbl, indextbl_len, g_instance.audit_cxt.audit_indextbl, indextbl_len);
securec_check(errorno, "\0", "\0");
}
LWLockRelease(g_instance.audit_cxt.index_file_lock);
int thread_num = g_instance.audit_cxt.thread_num;

View File

@ -3532,9 +3532,29 @@ void pgstat_report_activity(BackendState state, const char* cmd_str)
beentry->st_state_start_timestamp = current_timestamp;
if (cmd_str != NULL) {
rc = memcpy_s(
(char*)beentry->st_activity, g_instance.attr.attr_common.pgstat_track_activity_query_size, cmd_str, len);
securec_check(rc, "\0", "\0");
char *mask_string = NULL;
if (len == g_instance.attr.attr_common.pgstat_track_activity_query_size - 1 &&
t_thrd.mem_cxt.mask_password_mem_cxt != NULL) {
/* mask the cmd_str when the cmd_str is truncated. */
mask_string = maskPassword(cmd_str);
}
/* If mask successfully, store the mask_string. Otherwise, the cmd_str is recorded. */
if (mask_string == NULL) {
rc = memcpy_s((char*)beentry->st_activity, g_instance.attr.attr_common.pgstat_track_activity_query_size,
cmd_str, len);
securec_check(rc, "\0", "\0");
} else {
int copy_len = strlen(mask_string);
if (len < copy_len) {
copy_len = len;
}
rc = memcpy_s((char*)beentry->st_activity, g_instance.attr.attr_common.pgstat_track_activity_query_size,
mask_string, copy_len);
securec_check(rc, "\0", "\0");
pfree(mask_string);
}
beentry->st_activity[len] = '\0';
beentry->st_activity_start_timestamp = start_timestamp;
}

Some files were not shown because too many files have changed in this diff Show More