From 9717117500b1e74ff2177003d8fdd9afada3a801 Mon Sep 17 00:00:00 2001 From: jiang_jianyu Date: Sat, 29 Aug 2020 10:41:31 +0800 Subject: [PATCH] forbidden nested autonomous transaction --- src/common/backend/libpq/pqmq.cpp | 7 +++++ src/common/pl/plpgsql/src/pl_exec.cpp | 26 +++++++++---------- src/gausskernel/process/tcop/autonomous.cpp | 20 +++++++++++--- .../process/threadpool/knl_thread.cpp | 7 +++++ src/include/knl/knl_thread.h | 8 ++++++ 5 files changed, 51 insertions(+), 17 deletions(-) diff --git a/src/common/backend/libpq/pqmq.cpp b/src/common/backend/libpq/pqmq.cpp index 274c285a0..fd3197de2 100644 --- a/src/common/backend/libpq/pqmq.cpp +++ b/src/common/backend/libpq/pqmq.cpp @@ -224,6 +224,13 @@ void pq_parse_errornotice(StringInfo msg, ErrorData *edata) case PG_DIAG_SEVERITY: /* ignore, trusting we'll get a nonlocalized version */ break; + case PG_DIAG_INTERNEL_ERRCODE: + /* ignore */ + break; + case PG_DIAG_MODULE_ID: + /* It is always MOD_MAX */ + edata->mod_id = MOD_MAX; + break; case PG_DIAG_SQLSTATE: if (strlen(value) != 5) { elog(ERROR, "invalid SQLSTATE: \"%s\"", value); diff --git a/src/common/pl/plpgsql/src/pl_exec.cpp b/src/common/pl/plpgsql/src/pl_exec.cpp index 15eca2aa7..ac073f06d 100755 --- a/src/common/pl/plpgsql/src/pl_exec.cpp +++ b/src/common/pl/plpgsql/src/pl_exec.cpp @@ -198,7 +198,6 @@ static int check_line_validity_in_for_query(PLpgSQL_stmt_forq* stmt, int, int); static void bind_cursor_with_portal(Portal portal, PLpgSQL_execstate *estate, int varno); static char* transform_anonymous_block(char* query); static bool need_recompile_plan(SPIPlanPtr plan); -static THR_LOCAL PLpgSQL_expr* sqlstmt = NULL; /* ---------- * plpgsql_check_line_validity Called by the debugger plugin for @@ -1420,6 +1419,9 @@ static int exec_stmt_block(PLpgSQL_execstate* estate, PLpgSQL_stmt_block* block) (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("Un-support feature"), errdetail("Trigger doesnot support autonomous transaction"))); + } else if (t_thrd.autonomous_cxt.isnested) { + ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("Un-support feature : Autonomous transaction doesnot support nesting"))); } else { estate->autonomous_session = AutonomousSessionStart(); } @@ -3905,7 +3907,7 @@ static int exec_stmt_execsql(PLpgSQL_execstate* estate, PLpgSQL_stmt_execsql* st Datum *values = NULL; bool *nulls = NULL; AutonomousResult *aresult = NULL; - sqlstmt = stmt->sqlstmt; + t_thrd.autonomous_cxt.sqlstmt = stmt->sqlstmt; build_symbol_table(estate, stmt->sqlstmt->ns, &nparams, ¶m_names, ¶m_types); astmt = AutonomousSessionPrepare(estate->autonomous_session, stmt->sqlstmt->query, (int16)nparams, param_types, param_names); @@ -5083,7 +5085,7 @@ static int exec_stmt_null(PLpgSQL_execstate* estate, PLpgSQL_stmt* stmt) static int exec_stmt_commit(PLpgSQL_execstate* estate, PLpgSQL_stmt_commit* stmt) { if (estate->autonomous_session) { - if (sqlstmt) { + if (t_thrd.autonomous_cxt.sqlstmt) { int nparams = 0; int i; const char **param_names = NULL; @@ -5093,7 +5095,7 @@ static int exec_stmt_commit(PLpgSQL_execstate* estate, PLpgSQL_stmt_commit* stmt bool *nulls = NULL; AutonomousResult *aresult = NULL; ereport(LOG, (errmsg("query COMMIT"))); - build_symbol_table(estate, sqlstmt->ns, &nparams, ¶m_names, ¶m_types); + build_symbol_table(estate, t_thrd.autonomous_cxt.sqlstmt->ns, &nparams, ¶m_names, ¶m_types); astmt = AutonomousSessionPrepare(estate->autonomous_session, "COMMIT", (int16)nparams, param_types, param_names); values = (Datum *)palloc(nparams * sizeof(*values)); @@ -5104,12 +5106,11 @@ static int exec_stmt_commit(PLpgSQL_execstate* estate, PLpgSQL_stmt_commit* stmt } aresult = AutonomousSessionExecutePrepared(astmt, (int16)nparams, values, nulls); exec_set_found(estate, (list_length(aresult->tuples) != 0)); - sqlstmt = NULL; + t_thrd.autonomous_cxt.sqlstmt = NULL; return PLPGSQL_RC_OK; } else { ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), - errmsg("syntax error"), - errdetail("In antonomous transaction, commit/rollback must match start transaction"))); + errmsg("Syntax error: In antonomous transaction, commit/rollback must match start transaction"))); } } @@ -5176,7 +5177,7 @@ static int exec_stmt_commit(PLpgSQL_execstate* estate, PLpgSQL_stmt_commit* stmt static int exec_stmt_rollback(PLpgSQL_execstate* estate, PLpgSQL_stmt_rollback* stmt) { if (estate->autonomous_session) { - if (sqlstmt) { + if (t_thrd.autonomous_cxt.sqlstmt) { int nparams = 0; int i; const char **param_names = NULL; @@ -5186,7 +5187,7 @@ static int exec_stmt_rollback(PLpgSQL_execstate* estate, PLpgSQL_stmt_rollback* bool *nulls = NULL; AutonomousResult *aresult = NULL; ereport(LOG, (errmsg("query ROLLBACK"))); - build_symbol_table(estate, sqlstmt->ns, &nparams, ¶m_names, ¶m_types); + build_symbol_table(estate, t_thrd.autonomous_cxt.sqlstmt->ns, &nparams, ¶m_names, ¶m_types); astmt = AutonomousSessionPrepare(estate->autonomous_session, "ROLLBACK", (int16)nparams, param_types, param_names); values = (Datum *)palloc(nparams * sizeof(*values)); @@ -5197,13 +5198,12 @@ static int exec_stmt_rollback(PLpgSQL_execstate* estate, PLpgSQL_stmt_rollback* } aresult = AutonomousSessionExecutePrepared(astmt, (int16)nparams, values, nulls); exec_set_found(estate, (list_length(aresult->tuples) != 0)); - sqlstmt = NULL; + t_thrd.autonomous_cxt.sqlstmt = NULL; return PLPGSQL_RC_OK; } else { ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), - errmsg("syntax error"), - errdetail("In antonomous transaction, commit/rollback must match start transaction"))); - } + errmsg("Syntax error: In antonomous transaction, commit/rollback must match start transaction"))); + } } const char* PORTAL = "Portal"; diff --git a/src/gausskernel/process/tcop/autonomous.cpp b/src/gausskernel/process/tcop/autonomous.cpp index 44b25d1d5..e3f02bf6f 100644 --- a/src/gausskernel/process/tcop/autonomous.cpp +++ b/src/gausskernel/process/tcop/autonomous.cpp @@ -65,6 +65,7 @@ #include "utils/lsyscache.h" #include "utils/memutils.h" #include "utils/resowner.h" +#include "utils/ps_status.h" /* Table-of-contents constants for our dynamic shared memory segment. */ #define AUTONOMOUS_MAGIC 0x50674267 @@ -524,6 +525,8 @@ void autonomous_worker_main(Datum main_arg) (void)gspqsignal(SIGTERM, die); BackgroundWorkerUnblockSignals(); + t_thrd.autonomous_cxt.isnested = true; + /* Set up a memory context and resource owner. */ Assert(t_thrd.utils_cxt.CurrentResourceOwner == NULL); t_thrd.utils_cxt.CurrentResourceOwner = ResourceOwnerCreate(NULL, "autonomous"); @@ -533,7 +536,6 @@ void autonomous_worker_main(Datum main_arg) ALLOCSET_DEFAULT_INITSIZE, ALLOCSET_DEFAULT_MAXSIZE); - initStringInfo(&(*t_thrd.postgres_cxt.row_description_buf)); seg = (char *)DatumGetPointer(main_arg); if (seg == NULL) ereport(ERROR, @@ -586,9 +588,19 @@ void autonomous_worker_main(Datum main_arg) (void)MemoryContextSwitchTo(t_thrd.mem_cxt.msg_mem_cxt); MemoryContextResetAndDeleteChildren(t_thrd.mem_cxt.msg_mem_cxt); - ProcessCompletedNotifies(); - pgstat_report_stat(false); - pgstat_report_activity(STATE_IDLE, NULL); + if (IsAbortedTransactionBlockState()) { + set_ps_display("idle in transaction (aborted)", false); + pgstat_report_activity(STATE_IDLEINTRANSACTION_ABORTED, NULL); + } else if (IsTransactionOrTransactionBlock()) { + set_ps_display("idle in transaction", false); + pgstat_report_activity(STATE_IDLEINTRANSACTION, NULL); + } else { + ProcessCompletedNotifies(); + pgstat_report_stat(false); + + set_ps_display("idle", false); + pgstat_report_activity(STATE_IDLE, NULL); + } shm_mq_receive_stringinfo(command_qh, &msg); ereport(LOG, (errmsg("bgworker receive msg %s", msg.data))); diff --git a/src/gausskernel/process/threadpool/knl_thread.cpp b/src/gausskernel/process/threadpool/knl_thread.cpp index 1d0ca27a9..f5a026dd7 100755 --- a/src/gausskernel/process/threadpool/knl_thread.cpp +++ b/src/gausskernel/process/threadpool/knl_thread.cpp @@ -1381,6 +1381,12 @@ static void knl_t_heartbeat_init(knl_t_heartbeat_context* heartbeat_cxt) heartbeat_cxt->state = NULL; } +static void knl_t_autonomous_init(knl_t_autonomous_context* autonomous_cxt) +{ + autonomous_cxt->isnested = false; + autonomous_cxt->sqlstmt = NULL; +} + static void knl_t_mot_init(knl_t_mot_context* mot_cxt) { mot_cxt->last_error_code = 0; @@ -1498,6 +1504,7 @@ void knl_thread_init(knl_thread_role role) knl_t_heartbeat_init(&t_thrd.heartbeat_cxt); knl_t_poolcleaner_init(&t_thrd.poolcleaner_cxt); knl_t_mot_init(&t_thrd.mot_cxt); + knl_t_autonomous_init(&t_thrd.autonomous_cxt); } void knl_thread_set_name(const char* name) diff --git a/src/include/knl/knl_thread.h b/src/include/knl/knl_thread.h index 21a08dde1..a809352f2 100644 --- a/src/include/knl/knl_thread.h +++ b/src/include/knl/knl_thread.h @@ -2657,6 +2657,13 @@ typedef struct knl_t_heartbeat_context { struct heartbeat_state* state; } knl_t_heartbeat_context; +/* autonomous_transaction */ +struct PLpgSQL_expr; +typedef struct knl_t_autonomous_context { + PLpgSQL_expr* sqlstmt; + bool isnested; +} knl_t_autonomous_context; + /* MOT thread attributes */ #define MOT_MAX_ERROR_MESSAGE 256 #define MOT_MAX_ERROR_FRAMES 32 @@ -2731,6 +2738,7 @@ typedef struct knl_thrd_context { knl_t_arch_context arch; knl_t_async_context asy_cxt; knl_t_audit_context audit; + knl_t_autonomous_context autonomous_cxt; knl_t_autovacuum_context autovacuum_cxt; knl_t_basebackup_context basebackup_cxt; knl_t_bgwriter_context bgwriter_cxt;