diff --git a/src/common/backend/catalog/gs_package.cpp b/src/common/backend/catalog/gs_package.cpp index f336b8ea3..d7c53a832 100644 --- a/src/common/backend/catalog/gs_package.cpp +++ b/src/common/backend/catalog/gs_package.cpp @@ -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); diff --git a/src/common/pl/plpgsql/src/pl_comp.cpp b/src/common/pl/plpgsql/src/pl_comp.cpp index 3d8b90fbc..528d51802 100644 --- a/src/common/pl/plpgsql/src/pl_comp.cpp +++ b/src/common/pl/plpgsql/src/pl_comp.cpp @@ -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)); diff --git a/src/common/pl/plpgsql/src/pl_exec.cpp b/src/common/pl/plpgsql/src/pl_exec.cpp index 1359a67eb..d70ff6a41 100644 --- a/src/common/pl/plpgsql/src/pl_exec.cpp +++ b/src/common/pl/plpgsql/src/pl_exec.cpp @@ -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); diff --git a/src/common/pl/plpgsql/src/pl_global_package_runtime_cache.cpp b/src/common/pl/plpgsql/src/pl_global_package_runtime_cache.cpp index 05e08da4a..4ee0bd190 100644 --- a/src/common/pl/plpgsql/src/pl_global_package_runtime_cache.cpp +++ b/src/common/pl/plpgsql/src/pl_global_package_runtime_cache.cpp @@ -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; } diff --git a/src/common/pl/plpgsql/src/pl_handler.cpp b/src/common/pl/plpgsql/src/pl_handler.cpp index 8be0a334b..725fac0d6 100755 --- a/src/common/pl/plpgsql/src/pl_handler.cpp +++ b/src/common/pl/plpgsql/src/pl_handler.cpp @@ -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(); } @@ -1075,6 +1078,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 +1097,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; diff --git a/src/gausskernel/process/threadpool/knl_session.cpp b/src/gausskernel/process/threadpool/knl_session.cpp index 85abb97b7..baff01734 100755 --- a/src/gausskernel/process/threadpool/knl_session.cpp +++ b/src/gausskernel/process/threadpool/knl_session.cpp @@ -842,6 +842,7 @@ static void knl_u_plpgsql_init(knl_u_plpgsql_context* plsql_cxt) plsql_cxt->cur_exception_cxt = NULL; plsql_cxt->pragma_autonomous = false; plsql_cxt->ActiveLobToastOid = InvalidOid; + plsql_cxt->is_insert_gs_source = false; } static void knl_u_stat_init(knl_u_stat_context* stat_cxt) diff --git a/src/include/knl/knl_session.h b/src/include/knl/knl_session.h index 604ca95b4..0db24ac16 100644 --- a/src/include/knl/knl_session.h +++ b/src/include/knl/knl_session.h @@ -1583,10 +1583,12 @@ typedef struct knl_u_plpgsql_context { uint64 parent_session_id; ThreadId parent_thread_id; MemoryContext parent_context; /* parent_context from parent session */ + Oid ActiveLobToastOid; struct ExceptionContext* cur_exception_cxt; bool pragma_autonomous; /* save autonomous flag */ char* debug_query_string; + bool is_insert_gs_source; /* is doing insert gs_source? */ } knl_u_plpgsql_context; //this is used to define functions in package diff --git a/src/include/utils/pl_global_package_runtime_cache.h b/src/include/utils/pl_global_package_runtime_cache.h index 1610faf45..c36370ceb 100644 --- a/src/include/utils/pl_global_package_runtime_cache.h +++ b/src/include/utils/pl_global_package_runtime_cache.h @@ -42,6 +42,7 @@ typedef struct SessionPackageRuntime List* portalContext; List* portalData; List* funcValInfo; + bool is_insert_gs_source; } SessionPackageRuntime; typedef struct GPRCValue diff --git a/src/include/utils/plpgsql.h b/src/include/utils/plpgsql.h index 0c9b3b429..98b20c126 100644 --- a/src/include/utils/plpgsql.h +++ b/src/include/utils/plpgsql.h @@ -1053,6 +1053,7 @@ typedef struct PLpgSQL_function { /* Complete compiled function */ bool is_autonomous; bool is_plpgsql_func_with_outparam; + bool is_insert_gs_source; } PLpgSQL_function; class AutonomousSession; diff --git a/src/test/regress/expected/autonomous_test.out b/src/test/regress/expected/autonomous_test.out index 47e5c0d60..a9855c741 100644 --- a/src/test/regress/expected/autonomous_test.out +++ b/src/test/regress/expected/autonomous_test.out @@ -2007,3 +2007,82 @@ CONTEXT: referenced column: p1 drop package pck1; NOTICE: drop cascades to function public.p1(integer,integer) +-- anoymous block with autonomous +create or replace package pck1 as +type r1 is record(a int, b int); +va int; +vb r1; +vc varchar2(20); +end pck1; +/ +declare +begin +pck1.va := 1; +pck1.vb := (2,3); +pck1.vc := 'before auto'; +end; +/ +-- (a) autonomous anoymous block +declare +PRAGMA AUTONOMOUS_TRANSACTION; +begin +raise info 'pck1.va: %',pck1.va; +raise info 'pck1.vb: %',pck1.vb; +raise info 'pck1.vc: %',pck1.vc; +pck1.va := 11; +pck1.vb := (22,33); +pck1.vc := 'after auto'; +end; +/ +INFO: pck1.va: 1 + +INFO: pck1.vb: (2,3) + +INFO: pck1.vc: before auto + +declare +begin +raise info 'pck1.va: %',pck1.va; +raise info 'pck1.vb: %',pck1.vb; +raise info 'pck1.vc: %',pck1.vc; +pck1.va := 111; +pck1.vb := (222,333); +pck1.vc := 'before after auto'; +end; +/ +INFO: pck1.va: 11 +INFO: pck1.vb: (22,33) +INFO: pck1.vc: after auto +-- (b) autonomous anoymous block with error +declare +PRAGMA AUTONOMOUS_TRANSACTION; +begin +raise info 'pck1.va: %',pck1.va; +raise info 'pck1.vb: %',pck1.vb; +raise info 'pck1.vc: %',pck1.vc; +pck1.va := 1111; +pck1.vb := (2222,3333); +pck1.vc := 'after after auto'; +pck1.va := 3/0; +end; +/ +INFO: pck1.va: 111 + +INFO: pck1.vb: (222,333) + +INFO: pck1.vc: before after auto + +ERROR: ERROR: division by zero +CONTEXT: SQL statement "SELECT 3/0" +PL/pgSQL function inline_code_block line 10 at assignment + +declare +begin +raise info 'pck1.va: %',pck1.va; +raise info 'pck1.vb: %',pck1.vb; +raise info 'pck1.vc: %',pck1.vc; +end; +/ +INFO: pck1.va: 1111 +INFO: pck1.vb: (2222,3333) +INFO: pck1.vc: after after auto diff --git a/src/test/regress/sql/autonomous_test.sql b/src/test/regress/sql/autonomous_test.sql index c561ae27a..47356acdc 100644 --- a/src/test/regress/sql/autonomous_test.sql +++ b/src/test/regress/sql/autonomous_test.sql @@ -1478,3 +1478,66 @@ call pck1.p1(10,20); call pck1.p1(10,20); drop package pck1; + +-- anoymous block with autonomous +create or replace package pck1 as +type r1 is record(a int, b int); +va int; +vb r1; +vc varchar2(20); +end pck1; +/ + +declare +begin +pck1.va := 1; +pck1.vb := (2,3); +pck1.vc := 'before auto'; +end; +/ + +-- (a) autonomous anoymous block +declare +PRAGMA AUTONOMOUS_TRANSACTION; +begin +raise info 'pck1.va: %',pck1.va; +raise info 'pck1.vb: %',pck1.vb; +raise info 'pck1.vc: %',pck1.vc; +pck1.va := 11; +pck1.vb := (22,33); +pck1.vc := 'after auto'; +end; +/ + +declare +begin +raise info 'pck1.va: %',pck1.va; +raise info 'pck1.vb: %',pck1.vb; +raise info 'pck1.vc: %',pck1.vc; +pck1.va := 111; +pck1.vb := (222,333); +pck1.vc := 'before after auto'; +end; +/ + +-- (b) autonomous anoymous block with error +declare +PRAGMA AUTONOMOUS_TRANSACTION; +begin +raise info 'pck1.va: %',pck1.va; +raise info 'pck1.vb: %',pck1.vb; +raise info 'pck1.vc: %',pck1.vc; +pck1.va := 1111; +pck1.vb := (2222,3333); +pck1.vc := 'after after auto'; +pck1.va := 3/0; +end; +/ + +declare +begin +raise info 'pck1.va: %',pck1.va; +raise info 'pck1.vb: %',pck1.vb; +raise info 'pck1.vc: %',pck1.vc; +end; +/ \ No newline at end of file