forbidden nested autonomous transaction

This commit is contained in:
jiang_jianyu 2020-08-29 10:41:31 +08:00
parent c235237a4c
commit 9717117500
5 changed files with 51 additions and 17 deletions

View File

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

View File

@ -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, &param_names, &param_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, &param_names, &param_types);
build_symbol_table(estate, t_thrd.autonomous_cxt.sqlstmt->ns, &nparams, &param_names, &param_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, &param_names, &param_types);
build_symbol_table(estate, t_thrd.autonomous_cxt.sqlstmt->ns, &nparams, &param_names, &param_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";

View File

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

View File

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

View File

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