diff --git a/contrib/security_plugin/gs_policy_plugin.cpp b/contrib/security_plugin/gs_policy_plugin.cpp index 5f739f5b0..226251ad6 100644 --- a/contrib/security_plugin/gs_policy_plugin.cpp +++ b/contrib/security_plugin/gs_policy_plugin.cpp @@ -97,6 +97,7 @@ PG_MODULE_MAGIC; extern "C" void _PG_init(void); extern "C" void _PG_fini(void); +extern "C" void set_gsaudit_prehook(ProcessUtility_hook_type func); #define POLICY_STR_BUFF_LEN 512 #define POLICY_TMP_BUFF_LEN 256 @@ -1781,7 +1782,7 @@ void install_audit_hook() * preserve the chains. */ next_ExecutorStart_hook = ExecutorStart_hook; - next_ProcessUtility_hook = ProcessUtility_hook; + set_gsaudit_prehook(ProcessUtility_hook); /* * Install audit hooks, the interface for GaussDB kernel user as below @@ -1821,6 +1822,19 @@ void install_label_hook() } } +/* + * This function is used for setting prev_ProcessUtility to rewrite + * standard_ProcessUtility by other extension. + */ +void set_gsaudit_prehook(ProcessUtility_hook_type func) +{ + if (next_ProcessUtility_hook != NULL) { + ereport(WARNING, (errmsg("next_ProcessUtility_hook in security_plugin cannot be set since it's not null"))); + return; + } + next_ProcessUtility_hook = func; +} + /* * Define GUC variables and install hooks upon module load. * NOTE: _PG_init will be invoked(installed) many times diff --git a/src/common/backend/catalog/pg_builtin_proc.cpp b/src/common/backend/catalog/pg_builtin_proc.cpp index c7b525d28..33f5e3732 100755 --- a/src/common/backend/catalog/pg_builtin_proc.cpp +++ b/src/common/backend/catalog/pg_builtin_proc.cpp @@ -52,6 +52,10 @@ static_assert(sizeof(false) == sizeof(char), "illegal bool size"); static struct HTAB* nameHash = NULL; static struct HTAB* oidHash = NULL; +/* for b_sql_plugin */ +struct HTAB* b_nameHash = NULL; +struct HTAB* b_oidHash = NULL; + const int g_nfuncgroups = sizeof(g_func_groups) / sizeof(FuncGroup); static const int MAX_PROC_NAME_LEN = NAMEDATALEN; @@ -114,7 +118,11 @@ static const FuncGroup* NameHashTableAccess(HASHACTION action, const char* name, Assert(name != NULL); - result = (HashEntryNameToFuncGroup *)hash_search(nameHash, &temp_name, action, &found); + if (DB_IS_CMPT(B_FORMAT) && b_nameHash != NULL && u_sess->attr.attr_sql.b_sql_plugin) { + result = (HashEntryNameToFuncGroup *)hash_search(b_nameHash, &temp_name, action, &found); + } else { + result = (HashEntryNameToFuncGroup *)hash_search(nameHash, &temp_name, action, &found); + } if (action == HASH_ENTER) { Assert(!found); result->group = group; @@ -136,7 +144,11 @@ static const Builtin_func* OidHashTableAccess(HASHACTION action, Oid oid, const bool found = false; Assert(oid > 0); - result = (HashEntryOidToBuiltinFunc *)hash_search(oidHash, &oid, action, &found); + if (DB_IS_CMPT(B_FORMAT) && b_oidHash != NULL && u_sess->attr.attr_sql.b_sql_plugin) { + result = (HashEntryOidToBuiltinFunc *)hash_search(b_oidHash, &oid, action, &found); + } else { + result = (HashEntryOidToBuiltinFunc *)hash_search(oidHash, &oid, action, &found); + } if (action == HASH_ENTER) { Assert(!found); result->func = func; diff --git a/src/common/backend/parser/analyze.cpp b/src/common/backend/parser/analyze.cpp index 4c9bf3b49..2baa41849 100644 --- a/src/common/backend/parser/analyze.cpp +++ b/src/common/backend/parser/analyze.cpp @@ -287,6 +287,10 @@ Query* transformTopLevelStmt(ParseState* pstate, Node* parseTree, bool isFirstNo } } + if (u_sess->hook_cxt.transformStmtHook != NULL) { + return + ((transformStmtFunc)(u_sess->hook_cxt.transformStmtHook))(pstate, parseTree, isFirstNode, isCreateView); + } return transformStmt(pstate, parseTree, isFirstNode, isCreateView); } diff --git a/src/common/backend/utils/init/postinit.cpp b/src/common/backend/utils/init/postinit.cpp index f448b775a..3d88a2746 100644 --- a/src/common/backend/utils/init/postinit.cpp +++ b/src/common/backend/utils/init/postinit.cpp @@ -94,6 +94,7 @@ #include "instruments/instr_workload.h" #include "gs_policy/policy_common.h" #include "utils/knl_relcache.h" +#include "commands/extension.h" #ifndef WIN32_ONLY_COMPILER #include "dynloader.h" #else @@ -2703,6 +2704,10 @@ void PostgresInitializer::InitExtensionVariable() if (init_session_vars != NULL) (*init_session_vars)(); } + + /* check whether the extension has been created */ + const char* b_sql_plugin = "b_sql_plugin"; + u_sess->attr.attr_sql.b_sql_plugin = CheckIfExtensionExists(b_sql_plugin); } void PostgresInitializer::FinishInit() diff --git a/src/gausskernel/dbmind/kernel/hypopg_index.cpp b/src/gausskernel/dbmind/kernel/hypopg_index.cpp index fd6e61971..af40c4d60 100644 --- a/src/gausskernel/dbmind/kernel/hypopg_index.cpp +++ b/src/gausskernel/dbmind/kernel/hypopg_index.cpp @@ -104,10 +104,23 @@ void InitHypopg() isExplain = false; } +/* + * This function is used for setting prev_utility_hook to rewrite + * standard_ProcessUtility by extension. + */ +void set_hypopg_prehook(ProcessUtility_hook_type func) +{ + if (prev_utility_hook != NULL) { + ereport(WARNING, (errmsg("prev_utility_hook in hypopg cannot be set since it's not null"))); + return; + } + prev_utility_hook = func; +} + void hypopg_register_hook() { // register hooks - prev_utility_hook = ProcessUtility_hook; + set_hypopg_prehook(ProcessUtility_hook); ProcessUtility_hook = hypo_utility_hook; prev_ExecutorEnd_hook = ExecutorEnd_hook; diff --git a/src/gausskernel/optimizer/commands/extension.cpp b/src/gausskernel/optimizer/commands/extension.cpp index 0caa0cf92..9e4dbf546 100644 --- a/src/gausskernel/optimizer/commands/extension.cpp +++ b/src/gausskernel/optimizer/commands/extension.cpp @@ -1175,6 +1175,10 @@ void CreateExtension(CreateExtensionStmt* stmt) FEATURE_NOT_PUBLIC_ERROR("EXTENSION is not yet supported."); } + if (pg_strcasecmp(stmt->extname, "b_sql_plugin") == 0 && !DB_IS_CMPT(B_FORMAT)) { + ereport(ERROR, + (errmsg("please create extension \"%s\" with B type DBCOMPATIBILITY", stmt->extname))); + } /* Check extension name validity before any filesystem access */ check_valid_extension_name(stmt->extname); @@ -1414,6 +1418,10 @@ void CreateExtension(CreateExtensionStmt* stmt) u_sess->exec_cxt.extension_is_valid = true; + if (pg_strcasecmp(stmt->extname, "b_sql_plugin") == 0) { + u_sess->attr.attr_sql.b_sql_plugin = true; + } + /* * Insert new tuple into pg_extension, and create dependency entries. */ @@ -2917,3 +2925,26 @@ void RepallocSessionVarsArrayIfNecessary() u_sess->attr.attr_common.extension_session_vars_array_size = currExtensionNum * 2; } } + +bool CheckIfExtensionExists(const char* extname) +{ + Relation rel; + ScanKeyData entry[1]; + SysScanDesc scandesc; + HeapTuple tuple; + bool isExists = false; + + /* search pg_extension to check if extension exists. */ + rel = heap_open(ExtensionRelationId, AccessShareLock); + ScanKeyInit(&entry[0], Anum_pg_extension_extname, BTEqualStrategyNumber, F_NAMEEQ, CStringGetDatum(extname)); + scandesc = systable_beginscan(rel, ExtensionNameIndexId, true, NULL, 1, entry); + tuple = systable_getnext(scandesc); + + isExists = HeapTupleIsValid(tuple); + + systable_endscan(scandesc); + + heap_close(rel, AccessShareLock); + + return isExists; +} diff --git a/src/gausskernel/process/tcop/auditfuncs.cpp b/src/gausskernel/process/tcop/auditfuncs.cpp index fcba9cdeb..e270056ee 100644 --- a/src/gausskernel/process/tcop/auditfuncs.cpp +++ b/src/gausskernel/process/tcop/auditfuncs.cpp @@ -124,6 +124,19 @@ static const AuditFuncMap g_auditFuncMap[] = { }; static const int g_auditFuncMapNum = sizeof(g_auditFuncMap) / sizeof(AuditFuncMap); +/* + * This function is used for setting prev_ProcessUtility to rewrite + * standard_ProcessUtility by extension. + */ +void set_pgaudit_prehook(ProcessUtility_hook_type func) +{ + if (prev_ProcessUtility != NULL) { + ereport(WARNING, (errmsg("prev_ProcessUtility in pgaudit cannot be set since it's not null"))); + return; + } + prev_ProcessUtility = func; +} + /* * Brief : perfstat_agent_init() * Description : Module load callback. @@ -137,7 +150,7 @@ void pgaudit_agent_init(void) } prev_ExecutorEnd = ExecutorEnd_hook; ExecutorEnd_hook = pgaudit_ExecutorEnd; - prev_ProcessUtility = ProcessUtility_hook; + set_pgaudit_prehook(ProcessUtility_hook); ProcessUtility_hook = (ProcessUtility_hook_type)pgaudit_ProcessUtility; u_sess->exec_cxt.g_pgaudit_agent_attached = true; } diff --git a/src/gausskernel/process/tcop/postgres.cpp b/src/gausskernel/process/tcop/postgres.cpp index 22d14f8b4..580d5976e 100755 --- a/src/gausskernel/process/tcop/postgres.cpp +++ b/src/gausskernel/process/tcop/postgres.cpp @@ -48,7 +48,9 @@ #include "catalog/pg_database.h" #include "catalog/pg_proc.h" #include "catalog/pg_type.h" +#include "catalog/pg_extension.h" #include "commands/async.h" +#include "commands/extension.h" #include "commands/matview.h" #include "commands/prepare.h" #include "commands/user.h" @@ -819,6 +821,22 @@ void client_read_ended(void) } } +#ifndef ENABLE_MULTIPLE_NODES +#define INIT_PLUGIN_OBJECT "init_plugin_object" +void InitBSqlPluginHookIfNeeded() +{ + const char* b_sql_plugin = "b_sql_plugin"; + CFunInfo tmpCF; + if (!CheckIfExtensionExists(b_sql_plugin)) { + return; + } + + tmpCF = load_external_function(b_sql_plugin, INIT_PLUGIN_OBJECT, false, false); + if (tmpCF.user_fn != NULL) { + ((void* (*)(void))(tmpCF.user_fn))(); + } +} +#endif /* * Do raw parsing (only). @@ -847,11 +865,9 @@ List* pg_parse_query(const char* query_string, List** query_string_locationlist) List* (*parser_hook)(const char*, List**) = raw_parser; #ifndef ENABLE_MULTIPLE_NODES - if (u_sess->attr.attr_sql.enable_custom_parser) { - int id = GetCustomParserId(); - if (id >= 0 && g_instance.raw_parser_hook[id] != NULL) { - parser_hook = (List* (*)(const char*, List**))g_instance.raw_parser_hook[id]; - } + int id = GetCustomParserId(); + if (id >= 0 && g_instance.raw_parser_hook[id] != NULL) { + parser_hook = (List* (*)(const char*, List**))g_instance.raw_parser_hook[id]; } #endif raw_parsetree_list = parser_hook(query_string, query_string_locationlist); @@ -7554,6 +7570,12 @@ int PostgresMain(int argc, char* argv[], const char* dbname, const char* usernam if (IS_PGXC_COORDINATOR) init_set_params_htab(); +#ifndef ENABLE_MULTIPLE_NODES + if (u_sess->proc_cxt.MyDatabaseId != InvalidOid && DB_IS_CMPT(B_FORMAT)) { + InitBSqlPluginHookIfNeeded(); + } +#endif + /* * Remember stand-alone backend startup time */ diff --git a/src/gausskernel/process/threadpool/threadpool_worker.cpp b/src/gausskernel/process/threadpool/threadpool_worker.cpp index bb7ab3aa9..c31561c25 100644 --- a/src/gausskernel/process/threadpool/threadpool_worker.cpp +++ b/src/gausskernel/process/threadpool/threadpool_worker.cpp @@ -767,6 +767,10 @@ static void init_session_share_memory() #endif } +#ifndef ENABLE_MULTIPLE_NODES +extern void InitBSqlPluginHookIfNeeded(); +#endif + static bool InitSession(knl_session_context* session) { /* non't send ereport to client now */ @@ -840,6 +844,13 @@ static bool InitSession(knl_session_context* session) char* username = session->proc_cxt.MyProcPort->user_name; t_thrd.proc_cxt.PostInit->SetDatabaseAndUser(dbname, InvalidOid, username); t_thrd.proc_cxt.PostInit->InitSession(); + +#ifndef ENABLE_MULTIPLE_NODES + if (u_sess->proc_cxt.MyDatabaseId != InvalidOid && DB_IS_CMPT(B_FORMAT)) { + InitBSqlPluginHookIfNeeded(); + } +#endif + Assert(CheckMyDatabaseMatch()); SetProcessingMode(NormalProcessing); diff --git a/src/include/commands/extension.h b/src/include/commands/extension.h index 5516ecdcb..cba945ad7 100644 --- a/src/include/commands/extension.h +++ b/src/include/commands/extension.h @@ -48,5 +48,5 @@ extern bool CheckExtensionValid(const char *extentName); extern bool CheckExtensionSqlValid(char *queryString); extern void RepallocSessionVarsArrayIfNecessary(); - +extern bool CheckIfExtensionExists(const char* extname); #endif /* EXTENSION_H */ diff --git a/src/include/knl/knl_guc/knl_session_attr_sql.h b/src/include/knl/knl_guc/knl_session_attr_sql.h index 89e055eef..155bb0547 100644 --- a/src/include/knl/knl_guc/knl_session_attr_sql.h +++ b/src/include/knl/knl_guc/knl_session_attr_sql.h @@ -238,6 +238,7 @@ typedef struct knl_session_attr_sql { #ifndef ENABLE_MULTIPLE_NODES bool enable_custom_parser; #endif + bool b_sql_plugin; } knl_session_attr_sql; #endif /* SRC_INCLUDE_KNL_KNL_SESSION_ATTR_SQL */ diff --git a/src/include/knl/knl_session.h b/src/include/knl/knl_session.h index 636706693..2c3d61a20 100644 --- a/src/include/knl/knl_session.h +++ b/src/include/knl/knl_session.h @@ -2623,6 +2623,7 @@ typedef struct knl_u_clientConnTime_context { typedef struct knl_u_hook_context { void *analyzerRoutineHook; + void *transformStmtHook; } knl_u_hook_context; typedef struct knl_session_context { diff --git a/src/include/parser/analyze.h b/src/include/parser/analyze.h index 3fdfd660e..2a9f1b275 100644 --- a/src/include/parser/analyze.h +++ b/src/include/parser/analyze.h @@ -88,6 +88,8 @@ typedef struct AnalyzerRoutine { transformSelectStmtHook transSelect; } AnalyzerRoutine; +typedef Query* (*transformStmtFunc)(ParseState* pstate, Node* parseTree, bool isFirstNode, bool isCreateView); + extern void transformOperatorPlus(ParseState* pstate, Node** whereClause); extern bool IsColumnRefPlusOuterJoin(const ColumnRef* cf); extern PlusJoinRTEItem* makePlusJoinRTEItem(RangeTblEntry* rte, bool hasplus);