1
0
mirror of https://github.com/postgres/postgres.git synced 2025-11-01 21:31:19 +03:00

Implement syntax for transition tables in AFTER triggers.

This is infrastructure for the complete SQL standard feature.  No
support is included at this point for execution nodes or PLs.  The
intent is to add that soon.

As this patch leaves things, standard syntax can create tuplestores
to contain old and/or new versions of rows affected by a statement.
References to these tuplestores are in the TriggerData structure.
C triggers can access the tuplestores directly, so they are usable,
but they cannot yet be referenced within a SQL statement.
This commit is contained in:
Kevin Grittner
2016-11-04 10:49:50 -05:00
parent 69d590fffb
commit 8c48375e5f
16 changed files with 580 additions and 43 deletions

View File

@@ -310,6 +310,9 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query);
%type <list> TriggerEvents TriggerOneEvent
%type <value> TriggerFuncArg
%type <node> TriggerWhen
%type <str> TransitionRelName
%type <boolean> TransitionRowOrTable TransitionOldOrNew
%type <node> TriggerTransition
%type <list> event_trigger_when_list event_trigger_value_list
%type <defelt> event_trigger_when_item
@@ -374,6 +377,7 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query);
create_generic_options alter_generic_options
relation_expr_list dostmt_opt_list
transform_element_list transform_type_list
TriggerTransitions TriggerReferencing
%type <list> group_by_list
%type <node> group_by_item empty_grouping_set rollup_clause cube_clause
@@ -610,11 +614,11 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query);
MAPPING MATCH MATERIALIZED MAXVALUE METHOD MINUTE_P MINVALUE MODE MONTH_P MOVE
NAME_P NAMES NATIONAL NATURAL NCHAR NEXT NO NONE
NAME_P NAMES NATIONAL NATURAL NCHAR NEW NEXT NO NONE
NOT NOTHING NOTIFY NOTNULL NOWAIT NULL_P NULLIF
NULLS_P NUMERIC
OBJECT_P OF OFF OFFSET OIDS ON ONLY OPERATOR OPTION OPTIONS OR
OBJECT_P OF OFF OFFSET OIDS OLD ON ONLY OPERATOR OPTION OPTIONS OR
ORDER ORDINALITY OUT_P OUTER_P OVER OVERLAPS OVERLAY OWNED OWNER
PARALLEL PARSER PARTIAL PARTITION PASSING PASSWORD PLACING PLANS POLICY
@@ -623,8 +627,8 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query);
QUOTE
RANGE READ REAL REASSIGN RECHECK RECURSIVE REF REFERENCES REFRESH REINDEX
RELATIVE_P RELEASE RENAME REPEATABLE REPLACE REPLICA
RANGE READ REAL REASSIGN RECHECK RECURSIVE REF REFERENCES REFERENCING
REFRESH REINDEX RELATIVE_P RELEASE RENAME REPEATABLE REPLACE REPLICA
RESET RESTART RESTRICT RETURNING RETURNS REVOKE RIGHT ROLE ROLLBACK ROLLUP
ROW ROWS RULE
@@ -4748,19 +4752,20 @@ CreateAmStmt: CREATE ACCESS METHOD name TYPE_P INDEX HANDLER handler_name
CreateTrigStmt:
CREATE TRIGGER name TriggerActionTime TriggerEvents ON
qualified_name TriggerForSpec TriggerWhen
qualified_name TriggerReferencing TriggerForSpec TriggerWhen
EXECUTE PROCEDURE func_name '(' TriggerFuncArgs ')'
{
CreateTrigStmt *n = makeNode(CreateTrigStmt);
n->trigname = $3;
n->relation = $7;
n->funcname = $12;
n->args = $14;
n->row = $8;
n->funcname = $13;
n->args = $15;
n->row = $9;
n->timing = $4;
n->events = intVal(linitial($5));
n->columns = (List *) lsecond($5);
n->whenClause = $9;
n->whenClause = $10;
n->transitionRels = $8;
n->isconstraint = FALSE;
n->deferrable = FALSE;
n->initdeferred = FALSE;
@@ -4782,6 +4787,7 @@ CreateTrigStmt:
n->events = intVal(linitial($6));
n->columns = (List *) lsecond($6);
n->whenClause = $14;
n->transitionRels = NIL;
n->isconstraint = TRUE;
processCASbits($10, @10, "TRIGGER",
&n->deferrable, &n->initdeferred, NULL,
@@ -4834,6 +4840,49 @@ TriggerOneEvent:
{ $$ = list_make2(makeInteger(TRIGGER_TYPE_TRUNCATE), NIL); }
;
TriggerReferencing:
REFERENCING TriggerTransitions { $$ = $2; }
| /*EMPTY*/ { $$ = NIL; }
;
TriggerTransitions:
TriggerTransition { $$ = list_make1($1); }
| TriggerTransitions TriggerTransition { $$ = lappend($1, $2); }
;
TriggerTransition:
TransitionOldOrNew TransitionRowOrTable opt_as TransitionRelName
{
TriggerTransition *n = makeNode(TriggerTransition);
n->name = $4;
n->isNew = $1;
n->isTable = $2;
$$ = (Node *)n;
}
;
TransitionOldOrNew:
NEW { $$ = TRUE; }
| OLD { $$ = FALSE; }
;
TransitionRowOrTable:
TABLE { $$ = TRUE; }
/*
* According to the standard, lack of a keyword here implies ROW.
* Support for that would require prohibiting ROW entirely here,
* reserving the keyword ROW, and/or requiring AS (instead of
* allowing it to be optional, as the standard specifies) as the
* next token. Requiring ROW seems cleanest and easiest to
* explain.
*/
| ROW { $$ = FALSE; }
;
TransitionRelName:
ColId { $$ = $1; }
;
TriggerForSpec:
FOR TriggerForOptEach TriggerForType
{
@@ -13810,6 +13859,7 @@ unreserved_keyword:
| MOVE
| NAME_P
| NAMES
| NEW
| NEXT
| NO
| NOTHING
@@ -13820,6 +13870,7 @@ unreserved_keyword:
| OF
| OFF
| OIDS
| OLD
| OPERATOR
| OPTION
| OPTIONS
@@ -13851,6 +13902,7 @@ unreserved_keyword:
| RECHECK
| RECURSIVE
| REF
| REFERENCING
| REFRESH
| REINDEX
| RELATIVE_P