mirror of
https://github.com/postgres/postgres.git
synced 2025-04-22 23:02:54 +03:00
This is part #1 for of the DEFERRED CONSTRAINT TRIGGER support.
Implements the CREATE CONSTRAINT TRIGGER and SET CONSTRAINTS commands. TODO: Generic builtin trigger procedures Automatic execution of appropriate CREATE CONSTRAINT... at CREATE TABLE Support of new trigger type in pg_dump Swapping of huge # of events to disk Jan
This commit is contained in:
parent
d810338d29
commit
1547ee017c
@ -7,7 +7,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/access/transam/xact.c,v 1.54 1999/09/28 11:41:03 vadim Exp $
|
* $Header: /cvsroot/pgsql/src/backend/access/transam/xact.c,v 1.55 1999/09/29 16:05:55 wieck Exp $
|
||||||
*
|
*
|
||||||
* NOTES
|
* NOTES
|
||||||
* Transaction aborts can now occur two ways:
|
* Transaction aborts can now occur two ways:
|
||||||
@ -149,6 +149,7 @@
|
|||||||
#include "commands/async.h"
|
#include "commands/async.h"
|
||||||
#include "commands/sequence.h"
|
#include "commands/sequence.h"
|
||||||
#include "commands/vacuum.h"
|
#include "commands/vacuum.h"
|
||||||
|
#include "commands/trigger.h"
|
||||||
#include "libpq/be-fsstubs.h"
|
#include "libpq/be-fsstubs.h"
|
||||||
#include "storage/proc.h"
|
#include "storage/proc.h"
|
||||||
#include "storage/sinval.h"
|
#include "storage/sinval.h"
|
||||||
@ -865,6 +866,12 @@ StartTransaction()
|
|||||||
*/
|
*/
|
||||||
InitNoNameRelList();
|
InitNoNameRelList();
|
||||||
|
|
||||||
|
/* ----------------
|
||||||
|
* Tell the trigger manager to we're starting a transaction
|
||||||
|
* ----------------
|
||||||
|
*/
|
||||||
|
DeferredTriggerBeginXact();
|
||||||
|
|
||||||
/* ----------------
|
/* ----------------
|
||||||
* done with start processing, set current transaction
|
* done with start processing, set current transaction
|
||||||
* state to "in progress"
|
* state to "in progress"
|
||||||
@ -904,6 +911,14 @@ CommitTransaction()
|
|||||||
if (s->state != TRANS_INPROGRESS)
|
if (s->state != TRANS_INPROGRESS)
|
||||||
elog(NOTICE, "CommitTransaction and not in in-progress state ");
|
elog(NOTICE, "CommitTransaction and not in in-progress state ");
|
||||||
|
|
||||||
|
/* ----------------
|
||||||
|
* Tell the trigger manager that this transaction is about to be
|
||||||
|
* committed. He'll invoke all trigger deferred until XACT before
|
||||||
|
* we really start on committing the transaction.
|
||||||
|
* ----------------
|
||||||
|
*/
|
||||||
|
DeferredTriggerEndXact();
|
||||||
|
|
||||||
/* ----------------
|
/* ----------------
|
||||||
* set the current transaction state information
|
* set the current transaction state information
|
||||||
* appropriately during the abort processing
|
* appropriately during the abort processing
|
||||||
@ -992,6 +1007,13 @@ AbortTransaction()
|
|||||||
if (s->state != TRANS_INPROGRESS)
|
if (s->state != TRANS_INPROGRESS)
|
||||||
elog(NOTICE, "AbortTransaction and not in in-progress state ");
|
elog(NOTICE, "AbortTransaction and not in in-progress state ");
|
||||||
|
|
||||||
|
/* ----------------
|
||||||
|
* Tell the trigger manager that this transaction is about to be
|
||||||
|
* aborted.
|
||||||
|
* ----------------
|
||||||
|
*/
|
||||||
|
DeferredTriggerAbortXact();
|
||||||
|
|
||||||
/* ----------------
|
/* ----------------
|
||||||
* set the current transaction state information
|
* set the current transaction state information
|
||||||
* appropriately during the abort processing
|
* appropriately during the abort processing
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/catalog/heap.c,v 1.98 1999/09/24 00:24:11 tgl Exp $
|
* $Header: /cvsroot/pgsql/src/backend/catalog/heap.c,v 1.99 1999/09/29 16:05:56 wieck Exp $
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* INTERFACE ROUTINES
|
* INTERFACE ROUTINES
|
||||||
@ -1468,8 +1468,7 @@ heap_destroy_with_catalog(char *relname)
|
|||||||
RelationRemoveRules(rid);
|
RelationRemoveRules(rid);
|
||||||
|
|
||||||
/* triggers */
|
/* triggers */
|
||||||
if (rel->rd_rel->reltriggers > 0)
|
RelationRemoveTriggers(rel);
|
||||||
RelationRemoveTriggers(rel);
|
|
||||||
|
|
||||||
/* ----------------
|
/* ----------------
|
||||||
* delete attribute tuples
|
* delete attribute tuples
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/catalog/indexing.c,v 1.45 1999/09/18 19:06:33 tgl Exp $
|
* $Header: /cvsroot/pgsql/src/backend/catalog/indexing.c,v 1.46 1999/09/29 16:05:56 wieck Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -52,7 +52,9 @@ char *Name_pg_attrdef_indices[Num_pg_attrdef_indices] = {AttrDefaultIndex};
|
|||||||
|
|
||||||
char *Name_pg_relcheck_indices[Num_pg_relcheck_indices] = {RelCheckIndex};
|
char *Name_pg_relcheck_indices[Num_pg_relcheck_indices] = {RelCheckIndex};
|
||||||
|
|
||||||
char *Name_pg_trigger_indices[Num_pg_trigger_indices] = {TriggerRelidIndex};
|
char *Name_pg_trigger_indices[Num_pg_trigger_indices] = {TriggerRelidIndex,
|
||||||
|
TriggerConstrNameIndex,
|
||||||
|
TriggerConstrRelidIndex};
|
||||||
|
|
||||||
|
|
||||||
static HeapTuple CatalogIndexFetchTuple(Relation heapRelation,
|
static HeapTuple CatalogIndexFetchTuple(Relation heapRelation,
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -26,7 +26,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/executor/execMain.c,v 1.95 1999/09/24 00:24:23 tgl Exp $
|
* $Header: /cvsroot/pgsql/src/backend/executor/execMain.c,v 1.96 1999/09/29 16:06:02 wieck Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -1190,8 +1190,7 @@ ExecAppend(TupleTableSlot *slot,
|
|||||||
estate->es_lastoid = newId;
|
estate->es_lastoid = newId;
|
||||||
|
|
||||||
/* AFTER ROW INSERT Triggers */
|
/* AFTER ROW INSERT Triggers */
|
||||||
if (resultRelationDesc->trigdesc &&
|
if (resultRelationDesc->trigdesc)
|
||||||
resultRelationDesc->trigdesc->n_after_row[TRIGGER_EVENT_INSERT] > 0)
|
|
||||||
ExecARInsertTriggers(resultRelationDesc, tuple);
|
ExecARInsertTriggers(resultRelationDesc, tuple);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1277,8 +1276,7 @@ ldelete:;
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/* AFTER ROW DELETE Triggers */
|
/* AFTER ROW DELETE Triggers */
|
||||||
if (resultRelationDesc->trigdesc &&
|
if (resultRelationDesc->trigdesc)
|
||||||
resultRelationDesc->trigdesc->n_after_row[TRIGGER_EVENT_DELETE] > 0)
|
|
||||||
ExecARDeleteTriggers(estate, tupleid);
|
ExecARDeleteTriggers(estate, tupleid);
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -1420,8 +1418,7 @@ lreplace:;
|
|||||||
ExecInsertIndexTuples(slot, &(tuple->t_self), estate, true);
|
ExecInsertIndexTuples(slot, &(tuple->t_self), estate, true);
|
||||||
|
|
||||||
/* AFTER ROW UPDATE Triggers */
|
/* AFTER ROW UPDATE Triggers */
|
||||||
if (resultRelationDesc->trigdesc &&
|
if (resultRelationDesc->trigdesc)
|
||||||
resultRelationDesc->trigdesc->n_after_row[TRIGGER_EVENT_UPDATE] > 0)
|
|
||||||
ExecARUpdateTriggers(estate, tupleid, tuple);
|
ExecARUpdateTriggers(estate, tupleid, tuple);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.103 1999/09/28 14:49:36 momjian Exp $
|
* $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.104 1999/09/29 16:06:06 wieck Exp $
|
||||||
*
|
*
|
||||||
* HISTORY
|
* HISTORY
|
||||||
* AUTHOR DATE MAJOR EVENT
|
* AUTHOR DATE MAJOR EVENT
|
||||||
@ -132,7 +132,8 @@ Oid param_type(int t); /* used in parse_expr.c */
|
|||||||
CreatedbStmt, DestroydbStmt, VacuumStmt, CursorStmt, SubSelect,
|
CreatedbStmt, DestroydbStmt, VacuumStmt, CursorStmt, SubSelect,
|
||||||
UpdateStmt, InsertStmt, select_clause, SelectStmt, NotifyStmt, DeleteStmt,
|
UpdateStmt, InsertStmt, select_clause, SelectStmt, NotifyStmt, DeleteStmt,
|
||||||
ClusterStmt, ExplainStmt, VariableSetStmt, VariableShowStmt, VariableResetStmt,
|
ClusterStmt, ExplainStmt, VariableSetStmt, VariableShowStmt, VariableResetStmt,
|
||||||
CreateUserStmt, AlterUserStmt, DropUserStmt, RuleActionStmt
|
CreateUserStmt, AlterUserStmt, DropUserStmt, RuleActionStmt,
|
||||||
|
ConstraintsSetStmt,
|
||||||
|
|
||||||
%type <str> opt_database1, opt_database2, location, encoding
|
%type <str> opt_database1, opt_database2, location, encoding
|
||||||
|
|
||||||
@ -146,6 +147,9 @@ Oid param_type(int t); /* used in parse_expr.c */
|
|||||||
|
|
||||||
%type <boolean> TriggerActionTime, TriggerForSpec, PLangTrusted
|
%type <boolean> TriggerActionTime, TriggerForSpec, PLangTrusted
|
||||||
|
|
||||||
|
%type <ival> OptConstrTrigDeferrable, OptConstrTrigInitdeferred
|
||||||
|
%type <str> OptConstrFromTable
|
||||||
|
|
||||||
%type <str> TriggerEvents, TriggerFuncArg
|
%type <str> TriggerEvents, TriggerFuncArg
|
||||||
|
|
||||||
%type <str> relation_name, copy_file_name, copy_delimiter, def_name,
|
%type <str> relation_name, copy_file_name, copy_delimiter, def_name,
|
||||||
@ -254,6 +258,10 @@ Oid param_type(int t); /* used in parse_expr.c */
|
|||||||
%type <list> key_actions, key_action
|
%type <list> key_actions, key_action
|
||||||
%type <str> key_match, key_reference
|
%type <str> key_match, key_reference
|
||||||
|
|
||||||
|
%type <list> constraints_set_list
|
||||||
|
%type <list> constraints_set_namelist
|
||||||
|
%type <boolean> constraints_set_mode
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If you make any token changes, remember to:
|
* If you make any token changes, remember to:
|
||||||
* - use "yacc -d" and update parse.h
|
* - use "yacc -d" and update parse.h
|
||||||
@ -274,8 +282,8 @@ Oid param_type(int t); /* used in parse_expr.c */
|
|||||||
BEGIN_TRANS, BETWEEN, BOTH, BY,
|
BEGIN_TRANS, BETWEEN, BOTH, BY,
|
||||||
CASCADE, CASE, CAST, CHAR, CHARACTER, CHECK, CLOSE,
|
CASCADE, CASE, CAST, CHAR, CHARACTER, CHECK, CLOSE,
|
||||||
COALESCE, COLLATE, COLUMN, COMMIT,
|
COALESCE, COLLATE, COLUMN, COMMIT,
|
||||||
CONSTRAINT, CREATE, CROSS, CURRENT, CURRENT_DATE, CURRENT_TIME,
|
CONSTRAINT, CONSTRAINTS, CREATE, CROSS, CURRENT, CURRENT_DATE,
|
||||||
CURRENT_TIMESTAMP, CURRENT_USER, CURSOR,
|
CURRENT_TIME, CURRENT_TIMESTAMP, CURRENT_USER, CURSOR,
|
||||||
DAY_P, DECIMAL, DECLARE, DEFAULT, DELETE, DESC, DISTINCT, DOUBLE, DROP,
|
DAY_P, DECIMAL, DECLARE, DEFAULT, DELETE, DESC, DISTINCT, DOUBLE, DROP,
|
||||||
ELSE, END_TRANS, EXCEPT, EXECUTE, EXISTS, EXTRACT,
|
ELSE, END_TRANS, EXCEPT, EXECUTE, EXISTS, EXTRACT,
|
||||||
FALSE_P, FETCH, FLOAT, FOR, FOREIGN, FROM, FULL,
|
FALSE_P, FETCH, FLOAT, FOR, FOREIGN, FROM, FULL,
|
||||||
@ -295,7 +303,11 @@ Oid param_type(int t); /* used in parse_expr.c */
|
|||||||
WHEN, WHERE, WITH, WORK, YEAR_P, ZONE
|
WHEN, WHERE, WITH, WORK, YEAR_P, ZONE
|
||||||
|
|
||||||
/* Keywords (in SQL3 reserved words) */
|
/* Keywords (in SQL3 reserved words) */
|
||||||
%token TRIGGER
|
%token DEFERRABLE, DEFERRED,
|
||||||
|
IMMEDIATE, INITIALLY,
|
||||||
|
PENDANT,
|
||||||
|
RESTRICT,
|
||||||
|
TRIGGER
|
||||||
|
|
||||||
/* Keywords (in SQL92 non-reserved words) */
|
/* Keywords (in SQL92 non-reserved words) */
|
||||||
%token COMMITTED, SERIALIZABLE, TYPE_P
|
%token COMMITTED, SERIALIZABLE, TYPE_P
|
||||||
@ -415,6 +427,7 @@ stmt : AddAttrStmt
|
|||||||
| VariableSetStmt
|
| VariableSetStmt
|
||||||
| VariableShowStmt
|
| VariableShowStmt
|
||||||
| VariableResetStmt
|
| VariableResetStmt
|
||||||
|
| ConstraintsSetStmt
|
||||||
;
|
;
|
||||||
|
|
||||||
/*****************************************************************************
|
/*****************************************************************************
|
||||||
@ -630,6 +643,49 @@ VariableResetStmt: RESET ColId
|
|||||||
;
|
;
|
||||||
|
|
||||||
|
|
||||||
|
ConstraintsSetStmt: SET CONSTRAINTS constraints_set_list constraints_set_mode
|
||||||
|
{
|
||||||
|
ConstraintsSetStmt *n = makeNode(ConstraintsSetStmt);
|
||||||
|
n->constraints = $3;
|
||||||
|
n->deferred = $4;
|
||||||
|
$$ = (Node *) n;
|
||||||
|
}
|
||||||
|
;
|
||||||
|
|
||||||
|
|
||||||
|
constraints_set_list: ALL
|
||||||
|
{
|
||||||
|
$$ = NIL;
|
||||||
|
}
|
||||||
|
| constraints_set_namelist
|
||||||
|
{
|
||||||
|
$$ = $1;
|
||||||
|
}
|
||||||
|
;
|
||||||
|
|
||||||
|
|
||||||
|
constraints_set_namelist: IDENT
|
||||||
|
{
|
||||||
|
$$ = lappend(NIL, $1);
|
||||||
|
}
|
||||||
|
| constraints_set_namelist ',' IDENT
|
||||||
|
{
|
||||||
|
$$ = lappend($1, $3);
|
||||||
|
}
|
||||||
|
;
|
||||||
|
|
||||||
|
|
||||||
|
constraints_set_mode: DEFERRED
|
||||||
|
{
|
||||||
|
$$ = true;
|
||||||
|
}
|
||||||
|
| IMMEDIATE
|
||||||
|
{
|
||||||
|
$$ = false;
|
||||||
|
}
|
||||||
|
;
|
||||||
|
|
||||||
|
|
||||||
/*****************************************************************************
|
/*****************************************************************************
|
||||||
*
|
*
|
||||||
* QUERY :
|
* QUERY :
|
||||||
@ -1434,6 +1490,54 @@ CreateTrigStmt: CREATE TRIGGER name TriggerActionTime TriggerEvents ON
|
|||||||
n->before = $4;
|
n->before = $4;
|
||||||
n->row = $8;
|
n->row = $8;
|
||||||
memcpy (n->actions, $5, 4);
|
memcpy (n->actions, $5, 4);
|
||||||
|
n->lang = NULL; /* unused */
|
||||||
|
n->text = NULL; /* unused */
|
||||||
|
n->attr = NULL; /* unused */
|
||||||
|
n->when = NULL; /* unused */
|
||||||
|
|
||||||
|
n->isconstraint = false;
|
||||||
|
n->deferrable = false;
|
||||||
|
n->initdeferred = false;
|
||||||
|
n->constrrelname = NULL;
|
||||||
|
$$ = (Node *)n;
|
||||||
|
}
|
||||||
|
| CREATE CONSTRAINT TRIGGER name AFTER TriggerOneEvent ON
|
||||||
|
relation_name OptConstrFromTable
|
||||||
|
OptConstrTrigDeferrable OptConstrTrigInitdeferred
|
||||||
|
FOR EACH ROW EXECUTE PROCEDURE name '(' TriggerFuncArgs ')'
|
||||||
|
{
|
||||||
|
CreateTrigStmt *n = makeNode(CreateTrigStmt);
|
||||||
|
n->trigname = $4;
|
||||||
|
n->relname = $8;
|
||||||
|
n->funcname = $17;
|
||||||
|
n->args = $19;
|
||||||
|
n->before = false;
|
||||||
|
n->row = true;
|
||||||
|
n->actions[0] = $6;
|
||||||
|
n->actions[1] = '\0';
|
||||||
|
n->lang = NULL; /* unused */
|
||||||
|
n->text = NULL; /* unused */
|
||||||
|
n->attr = NULL; /* unused */
|
||||||
|
n->when = NULL; /* unused */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check that the DEFERRABLE and INITIALLY combination
|
||||||
|
* makes sense
|
||||||
|
*/
|
||||||
|
n->isconstraint = true;
|
||||||
|
if ($11 == 1)
|
||||||
|
{
|
||||||
|
if ($10 == 0)
|
||||||
|
elog(ERROR, "INITIALLY DEFERRED constraint "
|
||||||
|
"cannot be NOT DEFERRABLE");
|
||||||
|
n->deferrable = true;
|
||||||
|
n->initdeferred = true;
|
||||||
|
} else {
|
||||||
|
n->deferrable = ($10 == 1);
|
||||||
|
n->initdeferred = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
n->constrrelname = $9;
|
||||||
$$ = (Node *)n;
|
$$ = (Node *)n;
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
@ -1503,6 +1607,44 @@ TriggerFuncArg: ICONST
|
|||||||
| IDENT { $$ = $1; }
|
| IDENT { $$ = $1; }
|
||||||
;
|
;
|
||||||
|
|
||||||
|
OptConstrFromTable: /* Empty */
|
||||||
|
{
|
||||||
|
$$ = "";
|
||||||
|
}
|
||||||
|
| FROM relation_name
|
||||||
|
{
|
||||||
|
$$ = $2;
|
||||||
|
}
|
||||||
|
;
|
||||||
|
|
||||||
|
OptConstrTrigDeferrable: /* Empty */
|
||||||
|
{
|
||||||
|
$$ = -1;
|
||||||
|
}
|
||||||
|
| DEFERRABLE
|
||||||
|
{
|
||||||
|
$$ = 1;
|
||||||
|
}
|
||||||
|
| NOT DEFERRABLE
|
||||||
|
{
|
||||||
|
$$ = 0;
|
||||||
|
}
|
||||||
|
;
|
||||||
|
|
||||||
|
OptConstrTrigInitdeferred: /* Empty */
|
||||||
|
{
|
||||||
|
$$ = -1;
|
||||||
|
}
|
||||||
|
| INITIALLY DEFERRED
|
||||||
|
{
|
||||||
|
$$ = 1;
|
||||||
|
}
|
||||||
|
| INITIALLY IMMEDIATE
|
||||||
|
{
|
||||||
|
$$ = 0;
|
||||||
|
}
|
||||||
|
;
|
||||||
|
|
||||||
DropTrigStmt: DROP TRIGGER name ON relation_name
|
DropTrigStmt: DROP TRIGGER name ON relation_name
|
||||||
{
|
{
|
||||||
DropTrigStmt *n = makeNode(DropTrigStmt);
|
DropTrigStmt *n = makeNode(DropTrigStmt);
|
||||||
@ -5080,10 +5222,13 @@ ColId: IDENT { $$ = $1; }
|
|||||||
| BEFORE { $$ = "before"; }
|
| BEFORE { $$ = "before"; }
|
||||||
| CACHE { $$ = "cache"; }
|
| CACHE { $$ = "cache"; }
|
||||||
| COMMITTED { $$ = "committed"; }
|
| COMMITTED { $$ = "committed"; }
|
||||||
|
| CONSTRAINTS { $$ = "constraints"; }
|
||||||
| CREATEDB { $$ = "createdb"; }
|
| CREATEDB { $$ = "createdb"; }
|
||||||
| CREATEUSER { $$ = "createuser"; }
|
| CREATEUSER { $$ = "createuser"; }
|
||||||
| CYCLE { $$ = "cycle"; }
|
| CYCLE { $$ = "cycle"; }
|
||||||
| DATABASE { $$ = "database"; }
|
| DATABASE { $$ = "database"; }
|
||||||
|
| DEFERRABLE { $$ = "deferrable"; }
|
||||||
|
| DEFERRED { $$ = "deferred"; }
|
||||||
| DELIMITERS { $$ = "delimiters"; }
|
| DELIMITERS { $$ = "delimiters"; }
|
||||||
| DOUBLE { $$ = "double"; }
|
| DOUBLE { $$ = "double"; }
|
||||||
| EACH { $$ = "each"; }
|
| EACH { $$ = "each"; }
|
||||||
@ -5092,9 +5237,11 @@ ColId: IDENT { $$ = $1; }
|
|||||||
| FORWARD { $$ = "forward"; }
|
| FORWARD { $$ = "forward"; }
|
||||||
| FUNCTION { $$ = "function"; }
|
| FUNCTION { $$ = "function"; }
|
||||||
| HANDLER { $$ = "handler"; }
|
| HANDLER { $$ = "handler"; }
|
||||||
|
| IMMEDIATE { $$ = "immediate"; }
|
||||||
| INCREMENT { $$ = "increment"; }
|
| INCREMENT { $$ = "increment"; }
|
||||||
| INDEX { $$ = "index"; }
|
| INDEX { $$ = "index"; }
|
||||||
| INHERITS { $$ = "inherits"; }
|
| INHERITS { $$ = "inherits"; }
|
||||||
|
| INITIALLY { $$ = "initially"; }
|
||||||
| INSENSITIVE { $$ = "insensitive"; }
|
| INSENSITIVE { $$ = "insensitive"; }
|
||||||
| INSTEAD { $$ = "instead"; }
|
| INSTEAD { $$ = "instead"; }
|
||||||
| ISNULL { $$ = "isnull"; }
|
| ISNULL { $$ = "isnull"; }
|
||||||
@ -5119,12 +5266,14 @@ ColId: IDENT { $$ = $1; }
|
|||||||
| OPERATOR { $$ = "operator"; }
|
| OPERATOR { $$ = "operator"; }
|
||||||
| OPTION { $$ = "option"; }
|
| OPTION { $$ = "option"; }
|
||||||
| PASSWORD { $$ = "password"; }
|
| PASSWORD { $$ = "password"; }
|
||||||
|
| PENDANT { $$ = "pendant"; }
|
||||||
| PRIOR { $$ = "prior"; }
|
| PRIOR { $$ = "prior"; }
|
||||||
| PRIVILEGES { $$ = "privileges"; }
|
| PRIVILEGES { $$ = "privileges"; }
|
||||||
| PROCEDURAL { $$ = "procedural"; }
|
| PROCEDURAL { $$ = "procedural"; }
|
||||||
| READ { $$ = "read"; }
|
| READ { $$ = "read"; }
|
||||||
| RELATIVE { $$ = "relative"; }
|
| RELATIVE { $$ = "relative"; }
|
||||||
| RENAME { $$ = "rename"; }
|
| RENAME { $$ = "rename"; }
|
||||||
|
| RESTRICT { $$ = "restrict"; }
|
||||||
| RETURNS { $$ = "returns"; }
|
| RETURNS { $$ = "returns"; }
|
||||||
| ROW { $$ = "row"; }
|
| ROW { $$ = "row"; }
|
||||||
| RULE { $$ = "rule"; }
|
| RULE { $$ = "rule"; }
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/parser/keywords.c,v 1.61 1999/09/23 17:02:46 momjian Exp $
|
* $Header: /cvsroot/pgsql/src/backend/parser/keywords.c,v 1.62 1999/09/29 16:06:08 wieck Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -63,6 +63,7 @@ static ScanKeyword ScanKeywords[] = {
|
|||||||
{"commit", COMMIT},
|
{"commit", COMMIT},
|
||||||
{"committed", COMMITTED},
|
{"committed", COMMITTED},
|
||||||
{"constraint", CONSTRAINT},
|
{"constraint", CONSTRAINT},
|
||||||
|
{"constraints", CONSTRAINTS},
|
||||||
{"copy", COPY},
|
{"copy", COPY},
|
||||||
{"create", CREATE},
|
{"create", CREATE},
|
||||||
{"createdb", CREATEDB},
|
{"createdb", CREATEDB},
|
||||||
@ -79,6 +80,8 @@ static ScanKeyword ScanKeywords[] = {
|
|||||||
{"decimal", DECIMAL},
|
{"decimal", DECIMAL},
|
||||||
{"declare", DECLARE},
|
{"declare", DECLARE},
|
||||||
{"default", DEFAULT},
|
{"default", DEFAULT},
|
||||||
|
{"deferrable", DEFERRABLE},
|
||||||
|
{"deferred", DEFERRED},
|
||||||
{"delete", DELETE},
|
{"delete", DELETE},
|
||||||
{"delimiters", DELIMITERS},
|
{"delimiters", DELIMITERS},
|
||||||
{"desc", DESC},
|
{"desc", DESC},
|
||||||
@ -112,10 +115,12 @@ static ScanKeyword ScanKeywords[] = {
|
|||||||
{"handler", HANDLER},
|
{"handler", HANDLER},
|
||||||
{"having", HAVING},
|
{"having", HAVING},
|
||||||
{"hour", HOUR_P},
|
{"hour", HOUR_P},
|
||||||
|
{"immediate", IMMEDIATE},
|
||||||
{"in", IN},
|
{"in", IN},
|
||||||
{"increment", INCREMENT},
|
{"increment", INCREMENT},
|
||||||
{"index", INDEX},
|
{"index", INDEX},
|
||||||
{"inherits", INHERITS},
|
{"inherits", INHERITS},
|
||||||
|
{"initially", INITIALLY},
|
||||||
{"inner", INNER_P},
|
{"inner", INNER_P},
|
||||||
{"insensitive", INSENSITIVE},
|
{"insensitive", INSENSITIVE},
|
||||||
{"insert", INSERT},
|
{"insert", INSERT},
|
||||||
@ -177,6 +182,7 @@ static ScanKeyword ScanKeywords[] = {
|
|||||||
{"outer", OUTER_P},
|
{"outer", OUTER_P},
|
||||||
{"partial", PARTIAL},
|
{"partial", PARTIAL},
|
||||||
{"password", PASSWORD},
|
{"password", PASSWORD},
|
||||||
|
{"pendant", PENDANT},
|
||||||
{"position", POSITION},
|
{"position", POSITION},
|
||||||
{"precision", PRECISION},
|
{"precision", PRECISION},
|
||||||
{"primary", PRIMARY},
|
{"primary", PRIMARY},
|
||||||
@ -190,6 +196,7 @@ static ScanKeyword ScanKeywords[] = {
|
|||||||
{"relative", RELATIVE},
|
{"relative", RELATIVE},
|
||||||
{"rename", RENAME},
|
{"rename", RENAME},
|
||||||
{"reset", RESET},
|
{"reset", RESET},
|
||||||
|
{"restrict", RESTRICT},
|
||||||
{"returns", RETURNS},
|
{"returns", RETURNS},
|
||||||
{"revoke", REVOKE},
|
{"revoke", REVOKE},
|
||||||
{"right", RIGHT},
|
{"right", RIGHT},
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/tcop/postgres.c,v 1.129 1999/09/24 00:24:52 tgl Exp $
|
* $Header: /cvsroot/pgsql/src/backend/tcop/postgres.c,v 1.130 1999/09/29 16:06:10 wieck Exp $
|
||||||
*
|
*
|
||||||
* NOTES
|
* NOTES
|
||||||
* this is the "main" module of the postgres backend and
|
* this is the "main" module of the postgres backend and
|
||||||
@ -44,6 +44,7 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "commands/async.h"
|
#include "commands/async.h"
|
||||||
|
#include "commands/trigger.h"
|
||||||
#include "libpq/libpq.h"
|
#include "libpq/libpq.h"
|
||||||
#include "libpq/pqformat.h"
|
#include "libpq/pqformat.h"
|
||||||
#include "libpq/pqsignal.h"
|
#include "libpq/pqsignal.h"
|
||||||
@ -1484,9 +1485,16 @@ PostgresMain(int argc, char *argv[], int real_argc, char *real_argv[])
|
|||||||
if (!IsUnderPostmaster)
|
if (!IsUnderPostmaster)
|
||||||
{
|
{
|
||||||
puts("\nPOSTGRES backend interactive interface ");
|
puts("\nPOSTGRES backend interactive interface ");
|
||||||
puts("$Revision: 1.129 $ $Date: 1999/09/24 00:24:52 $\n");
|
puts("$Revision: 1.130 $ $Date: 1999/09/29 16:06:10 $\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ----------------
|
||||||
|
* Initialize the deferred trigger manager
|
||||||
|
* ----------------
|
||||||
|
*/
|
||||||
|
if (DeferredTriggerInit() != 0)
|
||||||
|
ExitPostgres(1);
|
||||||
|
|
||||||
/* ----------------
|
/* ----------------
|
||||||
* POSTGRES main processing loop begins here
|
* POSTGRES main processing loop begins here
|
||||||
*
|
*
|
||||||
@ -1609,6 +1617,12 @@ PostgresMain(int argc, char *argv[], int real_argc, char *real_argv[])
|
|||||||
|
|
||||||
pg_exec_query(parser_input->data);
|
pg_exec_query(parser_input->data);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Invoke IMMEDIATE constraint triggers
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
DeferredTriggerEndQuery();
|
||||||
|
|
||||||
if (ShowStats)
|
if (ShowStats)
|
||||||
ShowUsage();
|
ShowUsage();
|
||||||
}
|
}
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/tcop/utility.c,v 1.67 1999/09/27 15:47:54 vadim Exp $
|
* $Header: /cvsroot/pgsql/src/backend/tcop/utility.c,v 1.68 1999/09/29 16:06:11 wieck Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -785,6 +785,13 @@ ProcessUtility(Node *parsetree,
|
|||||||
LockTableCommand((LockStmt *) parsetree);
|
LockTableCommand((LockStmt *) parsetree);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case T_ConstraintsSetStmt:
|
||||||
|
PS_SET_STATUS(commandTag = "SET CONSTRAINTS");
|
||||||
|
CHECK_IF_ABORTED();
|
||||||
|
|
||||||
|
DeferredTriggerSetState((ConstraintsSetStmt *) parsetree);
|
||||||
|
break;
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ******************************** default ********************************
|
* ******************************** default ********************************
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
*
|
*
|
||||||
* Copyright (c) 1994, Regents of the University of California
|
* Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* $Id: indexing.h,v 1.23 1999/07/20 17:14:07 momjian Exp $
|
* $Id: indexing.h,v 1.24 1999/09/29 16:06:14 wieck Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -25,27 +25,29 @@
|
|||||||
#define Num_pg_class_indices 2
|
#define Num_pg_class_indices 2
|
||||||
#define Num_pg_attrdef_indices 1
|
#define Num_pg_attrdef_indices 1
|
||||||
#define Num_pg_relcheck_indices 1
|
#define Num_pg_relcheck_indices 1
|
||||||
#define Num_pg_trigger_indices 1
|
#define Num_pg_trigger_indices 3
|
||||||
#define Num_pg_description_indices 1
|
#define Num_pg_description_indices 1
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Names of indices on system catalogs
|
* Names of indices on system catalogs
|
||||||
*/
|
*/
|
||||||
#define AttributeNameIndex "pg_attribute_relid_attnam_index"
|
#define AttributeNameIndex "pg_attribute_relid_attnam_index"
|
||||||
#define AttributeNumIndex "pg_attribute_relid_attnum_index"
|
#define AttributeNumIndex "pg_attribute_relid_attnum_index"
|
||||||
#define AttributeRelidIndex "pg_attribute_attrelid_index"
|
#define AttributeRelidIndex "pg_attribute_attrelid_index"
|
||||||
#define ProcedureOidIndex "pg_proc_oid_index"
|
#define ProcedureOidIndex "pg_proc_oid_index"
|
||||||
#define ProcedureNameIndex "pg_proc_proname_narg_type_index"
|
#define ProcedureNameIndex "pg_proc_proname_narg_type_index"
|
||||||
#define ProcedureSrcIndex "pg_proc_prosrc_index"
|
#define ProcedureSrcIndex "pg_proc_prosrc_index"
|
||||||
#define TypeOidIndex "pg_type_oid_index"
|
#define TypeOidIndex "pg_type_oid_index"
|
||||||
#define TypeNameIndex "pg_type_typname_index"
|
#define TypeNameIndex "pg_type_typname_index"
|
||||||
#define ClassOidIndex "pg_class_oid_index"
|
#define ClassOidIndex "pg_class_oid_index"
|
||||||
#define ClassNameIndex "pg_class_relname_index"
|
#define ClassNameIndex "pg_class_relname_index"
|
||||||
#define AttrDefaultIndex "pg_attrdef_adrelid_index"
|
#define AttrDefaultIndex "pg_attrdef_adrelid_index"
|
||||||
#define RelCheckIndex "pg_relcheck_rcrelid_index"
|
#define RelCheckIndex "pg_relcheck_rcrelid_index"
|
||||||
#define TriggerRelidIndex "pg_trigger_tgrelid_index"
|
#define TriggerRelidIndex "pg_trigger_tgrelid_index"
|
||||||
#define DescriptionObjIndex "pg_description_objoid_index"
|
#define TriggerConstrNameIndex "pg_trigger_tgconstrname_index"
|
||||||
|
#define TriggerConstrRelidIndex "pg_trigger_tgconstrrelid_index"
|
||||||
|
#define DescriptionObjIndex "pg_description_objoid_index"
|
||||||
|
|
||||||
extern char *Name_pg_attr_indices[];
|
extern char *Name_pg_attr_indices[];
|
||||||
extern char *Name_pg_proc_indices[];
|
extern char *Name_pg_proc_indices[];
|
||||||
@ -114,6 +116,8 @@ DECLARE_INDEX(pg_attrdef_adrelid_index on pg_attrdef using btree(adrelid oid_ops
|
|||||||
DECLARE_INDEX(pg_relcheck_rcrelid_index on pg_relcheck using btree(rcrelid oid_ops));
|
DECLARE_INDEX(pg_relcheck_rcrelid_index on pg_relcheck using btree(rcrelid oid_ops));
|
||||||
|
|
||||||
DECLARE_INDEX(pg_trigger_tgrelid_index on pg_trigger using btree(tgrelid oid_ops));
|
DECLARE_INDEX(pg_trigger_tgrelid_index on pg_trigger using btree(tgrelid oid_ops));
|
||||||
|
DECLARE_INDEX(pg_trigger_tgconstrname_index on pg_trigger using btree(tgconstrname name_ops));
|
||||||
|
DECLARE_INDEX(pg_trigger_tgconstrrelid_index on pg_trigger using btree(tgconstrrelid oid_ops));
|
||||||
|
|
||||||
DECLARE_INDEX(pg_description_objoid_index on pg_description using btree(objoid oid_ops));
|
DECLARE_INDEX(pg_description_objoid_index on pg_description using btree(objoid oid_ops));
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
*
|
*
|
||||||
* Copyright (c) 1994, Regents of the University of California
|
* Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* $Id: pg_attribute.h,v 1.49 1999/08/09 02:45:56 tgl Exp $
|
* $Id: pg_attribute.h,v 1.50 1999/09/29 16:06:16 wieck Exp $
|
||||||
*
|
*
|
||||||
* NOTES
|
* NOTES
|
||||||
* the genbki.sh script reads this file and generates .bki
|
* the genbki.sh script reads this file and generates .bki
|
||||||
@ -447,9 +447,16 @@ DATA(insert OID = 0 ( 1219 tgrelid 26 0 4 1 0 -1 -1 t f i f f));
|
|||||||
DATA(insert OID = 0 ( 1219 tgname 19 0 NAMEDATALEN 2 0 -1 -1 f f i f f));
|
DATA(insert OID = 0 ( 1219 tgname 19 0 NAMEDATALEN 2 0 -1 -1 f f i f f));
|
||||||
DATA(insert OID = 0 ( 1219 tgfoid 26 0 4 3 0 -1 -1 t f i f f));
|
DATA(insert OID = 0 ( 1219 tgfoid 26 0 4 3 0 -1 -1 t f i f f));
|
||||||
DATA(insert OID = 0 ( 1219 tgtype 21 0 2 4 0 -1 -1 t f s f f));
|
DATA(insert OID = 0 ( 1219 tgtype 21 0 2 4 0 -1 -1 t f s f f));
|
||||||
DATA(insert OID = 0 ( 1219 tgnargs 21 0 2 5 0 -1 -1 t f s f f));
|
DATA(insert OID = 0 ( 1219 tgenabled 16 0 1 5 0 -1 -1 t f c f f));
|
||||||
DATA(insert OID = 0 ( 1219 tgattr 22 0 16 6 0 -1 -1 f f i f f));
|
DATA(insert OID = 0 ( 1219 tgisconstraint 16 0 1 6 0 -1 -1 t f c f f));
|
||||||
DATA(insert OID = 0 ( 1219 tgargs 17 0 -1 7 0 -1 -1 f f i f f));
|
DATA(insert OID = 0 ( 1219 tgconstrname 19 0 NAMEDATALEN 7 0 -1 -1 f f i f f));
|
||||||
|
DATA(insert OID = 0 ( 1219 tgconstrrelid 26 0 4 8 0 -1 -1 t f i f f));
|
||||||
|
|
||||||
|
DATA(insert OID = 0 ( 1219 tgdeferrable 16 0 1 9 0 -1 -1 t f c f f));
|
||||||
|
DATA(insert OID = 0 ( 1219 tginitdeferred 16 0 1 10 0 -1 -1 t f c f f));
|
||||||
|
DATA(insert OID = 0 ( 1219 tgnargs 21 0 2 11 0 -1 -1 t f s f f));
|
||||||
|
DATA(insert OID = 0 ( 1219 tgattr 22 0 16 12 0 -1 -1 f f i f f));
|
||||||
|
DATA(insert OID = 0 ( 1219 tgargs 17 0 -1 13 0 -1 -1 f f i f f));
|
||||||
DATA(insert OID = 0 ( 1219 ctid 27 0 6 -1 0 -1 -1 f f i f f));
|
DATA(insert OID = 0 ( 1219 ctid 27 0 6 -1 0 -1 -1 f f i f f));
|
||||||
DATA(insert OID = 0 ( 1219 oid 26 0 4 -2 0 -1 -1 t f i f f));
|
DATA(insert OID = 0 ( 1219 oid 26 0 4 -2 0 -1 -1 t f i f f));
|
||||||
DATA(insert OID = 0 ( 1219 xmin 28 0 4 -3 0 -1 -1 t f i f f));
|
DATA(insert OID = 0 ( 1219 xmin 28 0 4 -3 0 -1 -1 t f i f f));
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
*
|
*
|
||||||
* Copyright (c) 1994, Regents of the University of California
|
* Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* $Id: pg_class.h,v 1.29 1999/05/25 16:13:44 momjian Exp $
|
* $Id: pg_class.h,v 1.30 1999/09/29 16:06:16 wieck Exp $
|
||||||
*
|
*
|
||||||
* NOTES
|
* NOTES
|
||||||
* ``pg_relation'' is being replaced by ``pg_class''. currently
|
* ``pg_relation'' is being replaced by ``pg_class''. currently
|
||||||
@ -150,7 +150,7 @@ DATA(insert OID = 1215 ( pg_attrdef 109 PGUID 0 0 0 t t r 4 0 0 0 0 0 f f _n
|
|||||||
DESCR("");
|
DESCR("");
|
||||||
DATA(insert OID = 1216 ( pg_relcheck 110 PGUID 0 0 0 t t r 4 0 0 0 0 0 f f _null_ ));
|
DATA(insert OID = 1216 ( pg_relcheck 110 PGUID 0 0 0 t t r 4 0 0 0 0 0 f f _null_ ));
|
||||||
DESCR("");
|
DESCR("");
|
||||||
DATA(insert OID = 1219 ( pg_trigger 111 PGUID 0 0 0 t t r 7 0 0 0 0 0 f f _null_ ));
|
DATA(insert OID = 1219 ( pg_trigger 111 PGUID 0 0 0 t t r 13 0 0 0 0 0 f f _null_ ));
|
||||||
DESCR("");
|
DESCR("");
|
||||||
|
|
||||||
#define RelOid_pg_type 1247
|
#define RelOid_pg_type 1247
|
||||||
|
@ -33,6 +33,13 @@ CATALOG(pg_trigger) BOOTSTRAP
|
|||||||
Oid tgfoid; /* OID of function to be called */
|
Oid tgfoid; /* OID of function to be called */
|
||||||
int2 tgtype; /* BEFORE/AFTER UPDATE/DELETE/INSERT
|
int2 tgtype; /* BEFORE/AFTER UPDATE/DELETE/INSERT
|
||||||
* ROW/STATEMENT */
|
* ROW/STATEMENT */
|
||||||
|
bool tgenabled; /* trigger is enabled/disabled */
|
||||||
|
bool tgisconstraint; /* trigger is a RI constraint */
|
||||||
|
NameData tgconstrname; /* RI constraint name */
|
||||||
|
Oid tgconstrrelid; /* RI table of foreign key definition */
|
||||||
|
/* in the case of ON DELETE or ON UPDATE */
|
||||||
|
bool tgdeferrable; /* RI trigger is deferrable */
|
||||||
|
bool tginitdeferred; /* RI trigger is deferred initially */
|
||||||
int2 tgnargs; /* # of extra arguments in tgargs */
|
int2 tgnargs; /* # of extra arguments in tgargs */
|
||||||
int28 tgattr; /* UPDATE of attr1, attr2 ... (NI) */
|
int28 tgattr; /* UPDATE of attr1, attr2 ... (NI) */
|
||||||
bytea tgargs; /* first\000second\000tgnargs\000 */
|
bytea tgargs; /* first\000second\000tgnargs\000 */
|
||||||
@ -49,14 +56,20 @@ typedef FormData_pg_trigger *Form_pg_trigger;
|
|||||||
* compiler constants for pg_trigger
|
* compiler constants for pg_trigger
|
||||||
* ----------------
|
* ----------------
|
||||||
*/
|
*/
|
||||||
#define Natts_pg_trigger 7
|
#define Natts_pg_trigger 13
|
||||||
#define Anum_pg_trigger_tgrelid 1
|
#define Anum_pg_trigger_tgrelid 1
|
||||||
#define Anum_pg_trigger_tgname 2
|
#define Anum_pg_trigger_tgname 2
|
||||||
#define Anum_pg_trigger_tgfoid 3
|
#define Anum_pg_trigger_tgfoid 3
|
||||||
#define Anum_pg_trigger_tgtype 4
|
#define Anum_pg_trigger_tgtype 4
|
||||||
#define Anum_pg_trigger_tgnargs 5
|
#define Anum_pg_trigger_tgenabled 5
|
||||||
#define Anum_pg_trigger_tgattr 6
|
#define Anum_pg_trigger_tgisconstraint 6
|
||||||
#define Anum_pg_trigger_tgargs 7
|
#define Anum_pg_trigger_tgconstrname 7
|
||||||
|
#define Anum_pg_trigger_tgconstrrelid 8
|
||||||
|
#define Anum_pg_trigger_tgdeferrable 9
|
||||||
|
#define Anum_pg_trigger_tginitdeferred 10
|
||||||
|
#define Anum_pg_trigger_tgnargs 11
|
||||||
|
#define Anum_pg_trigger_tgattr 12
|
||||||
|
#define Anum_pg_trigger_tgargs 13
|
||||||
|
|
||||||
#define TRIGGER_TYPE_ROW (1 << 0)
|
#define TRIGGER_TYPE_ROW (1 << 0)
|
||||||
#define TRIGGER_TYPE_BEFORE (1 << 1)
|
#define TRIGGER_TYPE_BEFORE (1 << 1)
|
||||||
|
@ -32,6 +32,13 @@ extern DLLIMPORT TriggerData *CurrentTriggerData;
|
|||||||
#define TRIGGER_EVENT_ROW 0x00000004
|
#define TRIGGER_EVENT_ROW 0x00000004
|
||||||
#define TRIGGER_EVENT_BEFORE 0x00000008
|
#define TRIGGER_EVENT_BEFORE 0x00000008
|
||||||
|
|
||||||
|
#define TRIGGER_DEFERRED_DONE 0x00000010
|
||||||
|
#define TRIGGER_DEFERRED_CANCELED 0x00000020
|
||||||
|
#define TRIGGER_DEFERRED_DEFERRABLE 0x00000040
|
||||||
|
#define TRIGGER_DEFERRED_INITDEFERRED 0x00000080
|
||||||
|
#define TRIGGER_DEFERRED_HAS_BEFORE 0x00000100
|
||||||
|
#define TRIGGER_DEFERRED_MASK 0x000001F0
|
||||||
|
|
||||||
#define TRIGGER_FIRED_BY_INSERT(event) \
|
#define TRIGGER_FIRED_BY_INSERT(event) \
|
||||||
(((TriggerEvent) (event) & TRIGGER_EVENT_OPMASK) == \
|
(((TriggerEvent) (event) & TRIGGER_EVENT_OPMASK) == \
|
||||||
TRIGGER_EVENT_INSERT)
|
TRIGGER_EVENT_INSERT)
|
||||||
@ -68,4 +75,46 @@ extern void ExecARDeleteTriggers(EState *estate, ItemPointer tupleid);
|
|||||||
extern HeapTuple ExecBRUpdateTriggers(EState *estate, ItemPointer tupleid, HeapTuple tuple);
|
extern HeapTuple ExecBRUpdateTriggers(EState *estate, ItemPointer tupleid, HeapTuple tuple);
|
||||||
extern void ExecARUpdateTriggers(EState *estate, ItemPointer tupleid, HeapTuple tuple);
|
extern void ExecARUpdateTriggers(EState *estate, ItemPointer tupleid, HeapTuple tuple);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* ----------
|
||||||
|
* Deferred trigger stuff
|
||||||
|
* ----------
|
||||||
|
*/
|
||||||
|
typedef struct DeferredTriggerStatusData {
|
||||||
|
Oid dts_tgoid;
|
||||||
|
bool dts_tgisdeferred;
|
||||||
|
} DeferredTriggerStatusData;
|
||||||
|
typedef struct DeferredTriggerStatusData *DeferredTriggerStatus;
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct DeferredTriggerEventItem {
|
||||||
|
Oid dti_tgoid;
|
||||||
|
int32 dti_state;
|
||||||
|
} DeferredTriggerEventItem;
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct DeferredTriggerEventData {
|
||||||
|
int32 dte_event;
|
||||||
|
Oid dte_relid;
|
||||||
|
ItemPointerData dte_oldctid;
|
||||||
|
ItemPointerData dte_newctid;
|
||||||
|
int32 dte_n_items;
|
||||||
|
DeferredTriggerEventItem dte_item[1];
|
||||||
|
} DeferredTriggerEventData;
|
||||||
|
typedef struct DeferredTriggerEventData *DeferredTriggerEvent;
|
||||||
|
|
||||||
|
|
||||||
|
extern int DeferredTriggerInit(void);
|
||||||
|
extern void DeferredTriggerBeginXact(void);
|
||||||
|
extern void DeferredTriggerEndQuery(void);
|
||||||
|
extern void DeferredTriggerEndXact(void);
|
||||||
|
extern void DeferredTriggerAbortXact(void);
|
||||||
|
|
||||||
|
extern void DeferredTriggerSetState(ConstraintsSetStmt *stmt);
|
||||||
|
|
||||||
|
extern void DeferredTriggerSaveEvent(Relation rel, int event,
|
||||||
|
HeapTuple oldtup, HeapTuple newtup);
|
||||||
|
|
||||||
|
|
||||||
#endif /* TRIGGER_H */
|
#endif /* TRIGGER_H */
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
*
|
*
|
||||||
* Copyright (c) 1994, Regents of the University of California
|
* Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* $Id: nodes.h,v 1.52 1999/09/23 17:03:21 momjian Exp $
|
* $Id: nodes.h,v 1.53 1999/09/29 16:06:23 wieck Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -184,6 +184,7 @@ typedef enum NodeTag
|
|||||||
T_AlterUserStmt,
|
T_AlterUserStmt,
|
||||||
T_DropUserStmt,
|
T_DropUserStmt,
|
||||||
T_LockStmt,
|
T_LockStmt,
|
||||||
|
T_ConstraintsSetStmt,
|
||||||
|
|
||||||
T_A_Expr = 700,
|
T_A_Expr = 700,
|
||||||
T_Attr,
|
T_Attr,
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
*
|
*
|
||||||
* Copyright (c) 1994, Regents of the University of California
|
* Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* $Id: parsenodes.h,v 1.80 1999/09/28 04:34:50 momjian Exp $
|
* $Id: parsenodes.h,v 1.81 1999/09/29 16:06:23 wieck Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -180,6 +180,13 @@ typedef struct CreateTrigStmt
|
|||||||
char *text; /* AS 'text' */
|
char *text; /* AS 'text' */
|
||||||
List *attr; /* UPDATE OF a, b,... (NI) or NULL */
|
List *attr; /* UPDATE OF a, b,... (NI) or NULL */
|
||||||
char *when; /* WHEN 'a > 10 ...' (NI) or NULL */
|
char *when; /* WHEN 'a > 10 ...' (NI) or NULL */
|
||||||
|
|
||||||
|
/* The following are used for referential */
|
||||||
|
/* integrity constraint triggers */
|
||||||
|
bool isconstraint; /* This is an RI trigger */
|
||||||
|
bool deferrable; /* [NOT] DEFERRABLE */
|
||||||
|
bool initdeferred; /* INITIALLY {DEFERRED|IMMEDIATE} */
|
||||||
|
char *constrrelname; /* opposite relation */
|
||||||
} CreateTrigStmt;
|
} CreateTrigStmt;
|
||||||
|
|
||||||
typedef struct DropTrigStmt
|
typedef struct DropTrigStmt
|
||||||
@ -602,6 +609,19 @@ typedef struct LockStmt
|
|||||||
int mode; /* lock mode */
|
int mode; /* lock mode */
|
||||||
} LockStmt;
|
} LockStmt;
|
||||||
|
|
||||||
|
|
||||||
|
/* ----------------------
|
||||||
|
* SET CONSTRAINTS Statement
|
||||||
|
* ----------------------
|
||||||
|
*/
|
||||||
|
typedef struct ConstraintsSetStmt
|
||||||
|
{
|
||||||
|
NodeTag type;
|
||||||
|
List *constraints;
|
||||||
|
bool deferred;
|
||||||
|
} ConstraintsSetStmt;
|
||||||
|
|
||||||
|
|
||||||
/*****************************************************************************
|
/*****************************************************************************
|
||||||
* Optimizable Statements
|
* Optimizable Statements
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
*
|
*
|
||||||
* Copyright (c) 1994, Regents of the University of California
|
* Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* $Id: rel.h,v 1.26 1999/09/18 19:08:25 tgl Exp $
|
* $Id: rel.h,v 1.27 1999/09/29 16:06:28 wieck Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -42,10 +42,15 @@ typedef LockInfoData *LockInfo;
|
|||||||
|
|
||||||
typedef struct Trigger
|
typedef struct Trigger
|
||||||
{
|
{
|
||||||
|
Oid tgoid;
|
||||||
char *tgname;
|
char *tgname;
|
||||||
Oid tgfoid;
|
Oid tgfoid;
|
||||||
FmgrInfo tgfunc;
|
FmgrInfo tgfunc;
|
||||||
int16 tgtype;
|
int16 tgtype;
|
||||||
|
bool tgenabled;
|
||||||
|
bool tgisconstraint;
|
||||||
|
bool tgdeferrable;
|
||||||
|
bool tginitdeferred;
|
||||||
int16 tgnargs;
|
int16 tgnargs;
|
||||||
int16 tgattr[8];
|
int16 tgattr[8];
|
||||||
char **tgargs;
|
char **tgargs;
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
*
|
*
|
||||||
* Copyright (c) 1994, Regents of the University of California
|
* Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* $Id: tqual.h,v 1.24 1999/07/15 23:04:24 momjian Exp $
|
* $Id: tqual.h,v 1.25 1999/09/29 16:06:28 wieck Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -30,6 +30,7 @@ typedef SnapshotData *Snapshot;
|
|||||||
|
|
||||||
#define SnapshotNow ((Snapshot) 0x0)
|
#define SnapshotNow ((Snapshot) 0x0)
|
||||||
#define SnapshotSelf ((Snapshot) 0x1)
|
#define SnapshotSelf ((Snapshot) 0x1)
|
||||||
|
#define SnapshotAny ((Snapshot) 0x2)
|
||||||
|
|
||||||
extern Snapshot SnapshotDirty;
|
extern Snapshot SnapshotDirty;
|
||||||
extern Snapshot QuerySnapshot;
|
extern Snapshot QuerySnapshot;
|
||||||
@ -37,6 +38,7 @@ extern Snapshot SerializableSnapshot;
|
|||||||
|
|
||||||
#define IsSnapshotNow(snapshot) ((Snapshot) snapshot == SnapshotNow)
|
#define IsSnapshotNow(snapshot) ((Snapshot) snapshot == SnapshotNow)
|
||||||
#define IsSnapshotSelf(snapshot) ((Snapshot) snapshot == SnapshotSelf)
|
#define IsSnapshotSelf(snapshot) ((Snapshot) snapshot == SnapshotSelf)
|
||||||
|
#define IsSnapshotAny(snapshot) ((Snapshot) snapshot == SnapshotAny)
|
||||||
#define IsSnapshotDirty(snapshot) ((Snapshot) snapshot == SnapshotDirty)
|
#define IsSnapshotDirty(snapshot) ((Snapshot) snapshot == SnapshotDirty)
|
||||||
|
|
||||||
extern TransactionId HeapSpecialTransactionId;
|
extern TransactionId HeapSpecialTransactionId;
|
||||||
@ -55,18 +57,22 @@ extern CommandId HeapSpecialCommandId;
|
|||||||
false \
|
false \
|
||||||
: \
|
: \
|
||||||
( \
|
( \
|
||||||
(IsSnapshotSelf(snapshot) || heapisoverride()) ? \
|
(IsSnapshotAny(snapshot) || heapisoverride()) ? \
|
||||||
HeapTupleSatisfiesItself((tuple)->t_data) \
|
true \
|
||||||
: \
|
: \
|
||||||
((IsSnapshotDirty(snapshot)) ? \
|
((IsSnapshotSelf(snapshot) || heapisoverride()) ? \
|
||||||
HeapTupleSatisfiesDirty((tuple)->t_data) \
|
HeapTupleSatisfiesItself((tuple)->t_data) \
|
||||||
: \
|
: \
|
||||||
((IsSnapshotNow(snapshot)) ? \
|
((IsSnapshotDirty(snapshot)) ? \
|
||||||
HeapTupleSatisfiesNow((tuple)->t_data) \
|
HeapTupleSatisfiesDirty((tuple)->t_data) \
|
||||||
: \
|
: \
|
||||||
HeapTupleSatisfiesSnapshot((tuple)->t_data, snapshot) \
|
((IsSnapshotNow(snapshot)) ? \
|
||||||
) \
|
HeapTupleSatisfiesNow((tuple)->t_data) \
|
||||||
|
: \
|
||||||
|
HeapTupleSatisfiesSnapshot((tuple)->t_data, snapshot) \
|
||||||
|
) \
|
||||||
) \
|
) \
|
||||||
|
) \
|
||||||
) \
|
) \
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -64,101 +64,6 @@ NOTICE: check_pkeys_fkey_cascade: 1 tuple(s) of fkeys2 are deleted
|
|||||||
QUERY: DROP TABLE pkeys;
|
QUERY: DROP TABLE pkeys;
|
||||||
QUERY: DROP TABLE fkeys;
|
QUERY: DROP TABLE fkeys;
|
||||||
QUERY: DROP TABLE fkeys2;
|
QUERY: DROP TABLE fkeys2;
|
||||||
QUERY: create table dup17 (x int4);
|
|
||||||
QUERY: create trigger dup17_before
|
|
||||||
before insert on dup17
|
|
||||||
for each row
|
|
||||||
execute procedure
|
|
||||||
funny_dup17 ()
|
|
||||||
;
|
|
||||||
QUERY: insert into dup17 values (17);
|
|
||||||
NOTICE: funny_dup17 (fired BEFORE) on level 1: 0/0 tuples inserted/selected
|
|
||||||
QUERY: select count(*) from dup17;
|
|
||||||
count
|
|
||||||
-----
|
|
||||||
1
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
QUERY: insert into dup17 values (17);
|
|
||||||
NOTICE: funny_dup17 (fired BEFORE) on level 17: 1/2 tuples inserted/selected
|
|
||||||
NOTICE: funny_dup17 (fired BEFORE) on level 16: 1/3 tuples inserted/selected
|
|
||||||
NOTICE: funny_dup17 (fired BEFORE) on level 15: 1/4 tuples inserted/selected
|
|
||||||
NOTICE: funny_dup17 (fired BEFORE) on level 14: 1/5 tuples inserted/selected
|
|
||||||
NOTICE: funny_dup17 (fired BEFORE) on level 13: 1/6 tuples inserted/selected
|
|
||||||
NOTICE: funny_dup17 (fired BEFORE) on level 12: 1/7 tuples inserted/selected
|
|
||||||
NOTICE: funny_dup17 (fired BEFORE) on level 11: 1/8 tuples inserted/selected
|
|
||||||
NOTICE: funny_dup17 (fired BEFORE) on level 10: 1/9 tuples inserted/selected
|
|
||||||
NOTICE: funny_dup17 (fired BEFORE) on level 9: 1/10 tuples inserted/selected
|
|
||||||
NOTICE: funny_dup17 (fired BEFORE) on level 8: 1/11 tuples inserted/selected
|
|
||||||
NOTICE: funny_dup17 (fired BEFORE) on level 7: 1/12 tuples inserted/selected
|
|
||||||
NOTICE: funny_dup17 (fired BEFORE) on level 6: 1/13 tuples inserted/selected
|
|
||||||
NOTICE: funny_dup17 (fired BEFORE) on level 5: 1/14 tuples inserted/selected
|
|
||||||
NOTICE: funny_dup17 (fired BEFORE) on level 4: 1/15 tuples inserted/selected
|
|
||||||
NOTICE: funny_dup17 (fired BEFORE) on level 3: 1/16 tuples inserted/selected
|
|
||||||
NOTICE: funny_dup17 (fired BEFORE) on level 2: 1/17 tuples inserted/selected
|
|
||||||
NOTICE: funny_dup17 (fired BEFORE) on level 1: 1/18 tuples inserted/selected
|
|
||||||
QUERY: select count(*) from dup17;
|
|
||||||
count
|
|
||||||
-----
|
|
||||||
19
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
QUERY: drop trigger dup17_before on dup17;
|
|
||||||
QUERY: create trigger dup17_after
|
|
||||||
after insert on dup17
|
|
||||||
for each row
|
|
||||||
execute procedure
|
|
||||||
funny_dup17 ()
|
|
||||||
;
|
|
||||||
QUERY: insert into dup17 values (13);
|
|
||||||
NOTICE: funny_dup17 (fired AFTER ) on level 17: 17/34 tuples inserted/selected
|
|
||||||
NOTICE: funny_dup17 (fired AFTER ) on level 16: 16/49 tuples inserted/selected
|
|
||||||
NOTICE: funny_dup17 (fired AFTER ) on level 15: 15/63 tuples inserted/selected
|
|
||||||
NOTICE: funny_dup17 (fired AFTER ) on level 14: 14/76 tuples inserted/selected
|
|
||||||
NOTICE: funny_dup17 (fired AFTER ) on level 13: 13/88 tuples inserted/selected
|
|
||||||
NOTICE: funny_dup17 (fired AFTER ) on level 12: 12/99 tuples inserted/selected
|
|
||||||
NOTICE: funny_dup17 (fired AFTER ) on level 11: 11/109 tuples inserted/selected
|
|
||||||
NOTICE: funny_dup17 (fired AFTER ) on level 10: 10/118 tuples inserted/selected
|
|
||||||
NOTICE: funny_dup17 (fired AFTER ) on level 9: 9/126 tuples inserted/selected
|
|
||||||
NOTICE: funny_dup17 (fired AFTER ) on level 8: 8/133 tuples inserted/selected
|
|
||||||
NOTICE: funny_dup17 (fired AFTER ) on level 7: 7/139 tuples inserted/selected
|
|
||||||
NOTICE: funny_dup17 (fired AFTER ) on level 6: 6/144 tuples inserted/selected
|
|
||||||
NOTICE: funny_dup17 (fired AFTER ) on level 5: 5/148 tuples inserted/selected
|
|
||||||
NOTICE: funny_dup17 (fired AFTER ) on level 4: 4/151 tuples inserted/selected
|
|
||||||
NOTICE: funny_dup17 (fired AFTER ) on level 3: 3/153 tuples inserted/selected
|
|
||||||
NOTICE: funny_dup17 (fired AFTER ) on level 2: 2/154 tuples inserted/selected
|
|
||||||
NOTICE: funny_dup17 (fired AFTER ) on level 1: 1/154 tuples inserted/selected
|
|
||||||
QUERY: select count(*) from dup17 where x = 13;
|
|
||||||
count
|
|
||||||
-----
|
|
||||||
154
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
QUERY: insert into dup17 values (13);
|
|
||||||
NOTICE: funny_dup17 (fired AFTER ) on level 17: 171/342 tuples inserted/selected
|
|
||||||
NOTICE: funny_dup17 (fired AFTER ) on level 16: 170/511 tuples inserted/selected
|
|
||||||
NOTICE: funny_dup17 (fired AFTER ) on level 15: 169/679 tuples inserted/selected
|
|
||||||
NOTICE: funny_dup17 (fired AFTER ) on level 14: 168/846 tuples inserted/selected
|
|
||||||
NOTICE: funny_dup17 (fired AFTER ) on level 13: 167/1012 tuples inserted/selected
|
|
||||||
NOTICE: funny_dup17 (fired AFTER ) on level 12: 166/1177 tuples inserted/selected
|
|
||||||
NOTICE: funny_dup17 (fired AFTER ) on level 11: 165/1341 tuples inserted/selected
|
|
||||||
NOTICE: funny_dup17 (fired AFTER ) on level 10: 164/1504 tuples inserted/selected
|
|
||||||
NOTICE: funny_dup17 (fired AFTER ) on level 9: 163/1666 tuples inserted/selected
|
|
||||||
NOTICE: funny_dup17 (fired AFTER ) on level 8: 162/1827 tuples inserted/selected
|
|
||||||
NOTICE: funny_dup17 (fired AFTER ) on level 7: 161/1987 tuples inserted/selected
|
|
||||||
NOTICE: funny_dup17 (fired AFTER ) on level 6: 160/2146 tuples inserted/selected
|
|
||||||
NOTICE: funny_dup17 (fired AFTER ) on level 5: 159/2304 tuples inserted/selected
|
|
||||||
NOTICE: funny_dup17 (fired AFTER ) on level 4: 158/2461 tuples inserted/selected
|
|
||||||
NOTICE: funny_dup17 (fired AFTER ) on level 3: 157/2617 tuples inserted/selected
|
|
||||||
NOTICE: funny_dup17 (fired AFTER ) on level 2: 156/2772 tuples inserted/selected
|
|
||||||
NOTICE: funny_dup17 (fired AFTER ) on level 1: 155/2926 tuples inserted/selected
|
|
||||||
QUERY: select count(*) from dup17 where x = 13;
|
|
||||||
count
|
|
||||||
-----
|
|
||||||
2926
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
QUERY: DROP TABLE dup17;
|
|
||||||
QUERY: create sequence ttdummy_seq increment 10 start 0 minvalue 0;
|
QUERY: create sequence ttdummy_seq increment 10 start 0 minvalue 0;
|
||||||
QUERY: create table tttest (
|
QUERY: create table tttest (
|
||||||
price_id int4,
|
price_id int4,
|
||||||
|
@ -88,34 +88,40 @@ DROP TABLE pkeys;
|
|||||||
DROP TABLE fkeys;
|
DROP TABLE fkeys;
|
||||||
DROP TABLE fkeys2;
|
DROP TABLE fkeys2;
|
||||||
|
|
||||||
create table dup17 (x int4);
|
-- -- I've disabled the funny_dup17 test because the new semantics
|
||||||
|
-- -- of AFTER ROW triggers, which get now fired at the end of a
|
||||||
create trigger dup17_before
|
-- -- query allways, cause funny_dup17 to enter an endless loop.
|
||||||
before insert on dup17
|
-- --
|
||||||
for each row
|
-- -- Jan
|
||||||
execute procedure
|
--
|
||||||
funny_dup17 ()
|
-- create table dup17 (x int4);
|
||||||
;
|
--
|
||||||
|
-- create trigger dup17_before
|
||||||
insert into dup17 values (17);
|
-- before insert on dup17
|
||||||
select count(*) from dup17;
|
-- for each row
|
||||||
insert into dup17 values (17);
|
-- execute procedure
|
||||||
select count(*) from dup17;
|
-- funny_dup17 ()
|
||||||
|
-- ;
|
||||||
drop trigger dup17_before on dup17;
|
--
|
||||||
|
-- insert into dup17 values (17);
|
||||||
create trigger dup17_after
|
-- select count(*) from dup17;
|
||||||
after insert on dup17
|
-- insert into dup17 values (17);
|
||||||
for each row
|
-- select count(*) from dup17;
|
||||||
execute procedure
|
--
|
||||||
funny_dup17 ()
|
-- drop trigger dup17_before on dup17;
|
||||||
;
|
--
|
||||||
insert into dup17 values (13);
|
-- create trigger dup17_after
|
||||||
select count(*) from dup17 where x = 13;
|
-- after insert on dup17
|
||||||
insert into dup17 values (13);
|
-- for each row
|
||||||
select count(*) from dup17 where x = 13;
|
-- execute procedure
|
||||||
|
-- funny_dup17 ()
|
||||||
DROP TABLE dup17;
|
-- ;
|
||||||
|
-- insert into dup17 values (13);
|
||||||
|
-- select count(*) from dup17 where x = 13;
|
||||||
|
-- insert into dup17 values (13);
|
||||||
|
-- select count(*) from dup17 where x = 13;
|
||||||
|
--
|
||||||
|
-- DROP TABLE dup17;
|
||||||
|
|
||||||
create sequence ttdummy_seq increment 10 start 0 minvalue 0;
|
create sequence ttdummy_seq increment 10 start 0 minvalue 0;
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user