autonomous package value support anonymous block

Offering: openGaussDev

More detail: autonomous package value support anonymous block

Match-id-f3ca9de6f1d4d47382dad1566a600a1aa0e8d0ba
This commit is contained in:
openGaussDev 2022-03-03 22:02:14 +08:00 committed by yanghao
parent 06c8f2afcf
commit 0319403518
11 changed files with 206 additions and 30 deletions

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

@ -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

@ -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);

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();
}
@ -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;

View File

@ -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)

View File

@ -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

View File

@ -42,6 +42,7 @@ typedef struct SessionPackageRuntime
List* portalContext;
List* portalData;
List* funcValInfo;
bool is_insert_gs_source;
} SessionPackageRuntime;
typedef struct GPRCValue

View File

@ -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;

View File

@ -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

View File

@ -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;
/