diff options
author | Kevin Grittner | 2011-01-28 21:15:48 +0000 |
---|---|---|
committer | Kevin Grittner | 2011-01-28 21:15:48 +0000 |
commit | df7a5756dbca0a755dd7397f49c273d66ce6afa8 (patch) | |
tree | 6f1c25310caf77042a0e942e11bf08da16433029 | |
parent | b2826ad52d72195317a13c2074a5cd002c98a338 (diff) |
Add support for TG_DEPTH to PL/pgSQL trigger functions.
-rw-r--r-- | src/backend/access/transam/xact.c | 7 | ||||
-rw-r--r-- | src/backend/commands/trigger.c | 8 | ||||
-rw-r--r-- | src/backend/tcop/pquery.c | 4 | ||||
-rw-r--r-- | src/include/commands/trigger.h | 2 | ||||
-rw-r--r-- | src/pl/plpgsql/src/pl_comp.c | 6 | ||||
-rw-r--r-- | src/pl/plpgsql/src/pl_exec.c | 5 | ||||
-rw-r--r-- | src/pl/plpgsql/src/plpgsql.h | 1 |
7 files changed, 32 insertions, 1 deletions
diff --git a/src/backend/access/transam/xact.c b/src/backend/access/transam/xact.c index 1e31e07ec9..ddfbd3a1fd 100644 --- a/src/backend/access/transam/xact.c +++ b/src/backend/access/transam/xact.c @@ -142,6 +142,7 @@ typedef struct TransactionStateData Oid prevUser; /* previous CurrentUserId setting */ int prevSecContext; /* previous SecurityRestrictionContext */ bool prevXactReadOnly; /* entry-time xact r/o state */ + int prevTgDepth; /* previous trigger depth */ bool startedInRecovery; /* did we start in recovery? */ struct TransactionStateData *parent; /* back link to parent */ } TransactionStateData; @@ -171,6 +172,7 @@ static TransactionStateData TopTransactionStateData = { InvalidOid, /* previous CurrentUserId setting */ 0, /* previous SecurityRestrictionContext */ false, /* entry-time xact r/o state */ + 0, /* previous trigger depth */ false, /* startedInRecovery */ NULL /* link to parent state block */ }; @@ -3996,6 +3998,8 @@ CommitSubTransaction(void) */ XactReadOnly = s->prevXactReadOnly; + tg_depth = s->prevTgDepth; + CurrentResourceOwner = s->parent->curTransactionOwner; CurTransactionResourceOwner = s->parent->curTransactionOwner; ResourceOwnerDelete(s->curTransactionOwner); @@ -4114,6 +4118,8 @@ AbortSubTransaction(void) */ XactReadOnly = s->prevXactReadOnly; + tg_depth = s->prevTgDepth; + RESUME_INTERRUPTS(); } @@ -4196,6 +4202,7 @@ PushTransaction(void) s->blockState = TBLOCK_SUBBEGIN; GetUserIdAndSecContext(&s->prevUser, &s->prevSecContext); s->prevXactReadOnly = XactReadOnly; + s->prevTgDepth = tg_depth; CurrentTransactionState = s; diff --git a/src/backend/commands/trigger.c b/src/backend/commands/trigger.c index 48021388fc..056b656fc2 100644 --- a/src/backend/commands/trigger.c +++ b/src/backend/commands/trigger.c @@ -55,10 +55,12 @@ #include "utils/tqual.h" +/* How many levels deep into trigger execution are we? */ +int tg_depth = 0; + /* GUC variables */ int SessionReplicationRole = SESSION_REPLICATION_ROLE_ORIGIN; - #define GetModifiedColumns(relinfo, estate) \ (rt_fetch((relinfo)->ri_RangeTableIndex, (estate)->es_range_table)->modifiedCols) @@ -1807,6 +1809,8 @@ ExecCallTriggerFunc(TriggerData *trigdata, if (instr) InstrStartNode(instr + tgindx); + tg_depth++; + /* * Do the function evaluation in the per-tuple memory context, so that * leaked memory will be reclaimed once per tuple. Note in particular that @@ -1828,6 +1832,8 @@ ExecCallTriggerFunc(TriggerData *trigdata, MemoryContextSwitchTo(oldContext); + tg_depth--; + /* * Trigger protocol allows function to return a null pointer, but NOT to * set the isnull result flag. diff --git a/src/backend/tcop/pquery.c b/src/backend/tcop/pquery.c index 0b108ac134..5b67346388 100644 --- a/src/backend/tcop/pquery.c +++ b/src/backend/tcop/pquery.c @@ -748,6 +748,8 @@ PortalRun(Portal portal, long count, bool isTopLevel, errmsg("portal \"%s\" cannot be run", portal->name))); portal->status = PORTAL_ACTIVE; + tg_depth = 0; + /* * Set up global portal context pointers. * @@ -1371,6 +1373,8 @@ PortalRunFetch(Portal portal, errmsg("portal \"%s\" cannot be run", portal->name))); portal->status = PORTAL_ACTIVE; + tg_depth = 0; + /* * Set up global portal context pointers. */ diff --git a/src/include/commands/trigger.h b/src/include/commands/trigger.h index c213ac7a4e..90a3ea7a61 100644 --- a/src/include/commands/trigger.h +++ b/src/include/commands/trigger.h @@ -108,6 +108,8 @@ extern PGDLLIMPORT int SessionReplicationRole; #define TRIGGER_FIRES_ON_REPLICA 'R' #define TRIGGER_DISABLED 'D' +extern int tg_depth; + extern Oid CreateTrigger(CreateTrigStmt *stmt, const char *queryString, Oid constraintOid, Oid indexOid, bool isInternal); diff --git a/src/pl/plpgsql/src/pl_comp.c b/src/pl/plpgsql/src/pl_comp.c index 41188a2369..175ad7ab85 100644 --- a/src/pl/plpgsql/src/pl_comp.c +++ b/src/pl/plpgsql/src/pl_comp.c @@ -633,6 +633,12 @@ do_compile(FunctionCallInfo fcinfo, true); function->tg_table_schema_varno = var->dno; + /* add the variable tg_depth */ + var = plpgsql_build_variable("tg_depth", 0, + plpgsql_build_datatype(INT4OID, -1), + true); + function->tg_depth_varno = var->dno; + /* Add the variable tg_nargs */ var = plpgsql_build_variable("tg_nargs", 0, plpgsql_build_datatype(INT4OID, -1), diff --git a/src/pl/plpgsql/src/pl_exec.c b/src/pl/plpgsql/src/pl_exec.c index 3e40945e35..82b73a0490 100644 --- a/src/pl/plpgsql/src/pl_exec.c +++ b/src/pl/plpgsql/src/pl_exec.c @@ -625,6 +625,11 @@ plpgsql_exec_trigger(PLpgSQL_function *func, var->isnull = false; var->freeval = true; + var = (PLpgSQL_var *) (estate.datums[func->tg_depth_varno]); + var->value = Int16GetDatum(tg_depth); + var->isnull = false; + var->freeval = false; + var = (PLpgSQL_var *) (estate.datums[func->tg_nargs_varno]); var->value = Int16GetDatum(trigdata->tg_trigger->tgnargs); var->isnull = false; diff --git a/src/pl/plpgsql/src/plpgsql.h b/src/pl/plpgsql/src/plpgsql.h index 0ad7e28136..2165526957 100644 --- a/src/pl/plpgsql/src/plpgsql.h +++ b/src/pl/plpgsql/src/plpgsql.h @@ -668,6 +668,7 @@ typedef struct PLpgSQL_function int tg_relname_varno; int tg_table_name_varno; int tg_table_schema_varno; + int tg_depth_varno; int tg_nargs_varno; int tg_argv_varno; |