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
|
||||
* $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
|
||||
* Transaction aborts can now occur two ways:
|
||||
@ -149,6 +149,7 @@
|
||||
#include "commands/async.h"
|
||||
#include "commands/sequence.h"
|
||||
#include "commands/vacuum.h"
|
||||
#include "commands/trigger.h"
|
||||
#include "libpq/be-fsstubs.h"
|
||||
#include "storage/proc.h"
|
||||
#include "storage/sinval.h"
|
||||
@ -865,6 +866,12 @@ StartTransaction()
|
||||
*/
|
||||
InitNoNameRelList();
|
||||
|
||||
/* ----------------
|
||||
* Tell the trigger manager to we're starting a transaction
|
||||
* ----------------
|
||||
*/
|
||||
DeferredTriggerBeginXact();
|
||||
|
||||
/* ----------------
|
||||
* done with start processing, set current transaction
|
||||
* state to "in progress"
|
||||
@ -904,6 +911,14 @@ CommitTransaction()
|
||||
if (s->state != TRANS_INPROGRESS)
|
||||
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
|
||||
* appropriately during the abort processing
|
||||
@ -992,6 +1007,13 @@ AbortTransaction()
|
||||
if (s->state != TRANS_INPROGRESS)
|
||||
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
|
||||
* appropriately during the abort processing
|
||||
|
@ -7,7 +7,7 @@
|
||||
*
|
||||
*
|
||||
* 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
|
||||
@ -1468,8 +1468,7 @@ heap_destroy_with_catalog(char *relname)
|
||||
RelationRemoveRules(rid);
|
||||
|
||||
/* triggers */
|
||||
if (rel->rd_rel->reltriggers > 0)
|
||||
RelationRemoveTriggers(rel);
|
||||
RelationRemoveTriggers(rel);
|
||||
|
||||
/* ----------------
|
||||
* delete attribute tuples
|
||||
|
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* 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_trigger_indices[Num_pg_trigger_indices] = {TriggerRelidIndex};
|
||||
char *Name_pg_trigger_indices[Num_pg_trigger_indices] = {TriggerRelidIndex,
|
||||
TriggerConstrNameIndex,
|
||||
TriggerConstrRelidIndex};
|
||||
|
||||
|
||||
static HeapTuple CatalogIndexFetchTuple(Relation heapRelation,
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -26,7 +26,7 @@
|
||||
*
|
||||
*
|
||||
* 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;
|
||||
|
||||
/* AFTER ROW INSERT Triggers */
|
||||
if (resultRelationDesc->trigdesc &&
|
||||
resultRelationDesc->trigdesc->n_after_row[TRIGGER_EVENT_INSERT] > 0)
|
||||
if (resultRelationDesc->trigdesc)
|
||||
ExecARInsertTriggers(resultRelationDesc, tuple);
|
||||
}
|
||||
|
||||
@ -1277,8 +1276,7 @@ ldelete:;
|
||||
*/
|
||||
|
||||
/* AFTER ROW DELETE Triggers */
|
||||
if (resultRelationDesc->trigdesc &&
|
||||
resultRelationDesc->trigdesc->n_after_row[TRIGGER_EVENT_DELETE] > 0)
|
||||
if (resultRelationDesc->trigdesc)
|
||||
ExecARDeleteTriggers(estate, tupleid);
|
||||
|
||||
}
|
||||
@ -1420,8 +1418,7 @@ lreplace:;
|
||||
ExecInsertIndexTuples(slot, &(tuple->t_self), estate, true);
|
||||
|
||||
/* AFTER ROW UPDATE Triggers */
|
||||
if (resultRelationDesc->trigdesc &&
|
||||
resultRelationDesc->trigdesc->n_after_row[TRIGGER_EVENT_UPDATE] > 0)
|
||||
if (resultRelationDesc->trigdesc)
|
||||
ExecARUpdateTriggers(estate, tupleid, tuple);
|
||||
}
|
||||
|
||||
|
@ -10,7 +10,7 @@
|
||||
*
|
||||
*
|
||||
* 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
|
||||
* AUTHOR DATE MAJOR EVENT
|
||||
@ -132,7 +132,8 @@ Oid param_type(int t); /* used in parse_expr.c */
|
||||
CreatedbStmt, DestroydbStmt, VacuumStmt, CursorStmt, SubSelect,
|
||||
UpdateStmt, InsertStmt, select_clause, SelectStmt, NotifyStmt, DeleteStmt,
|
||||
ClusterStmt, ExplainStmt, VariableSetStmt, VariableShowStmt, VariableResetStmt,
|
||||
CreateUserStmt, AlterUserStmt, DropUserStmt, RuleActionStmt
|
||||
CreateUserStmt, AlterUserStmt, DropUserStmt, RuleActionStmt,
|
||||
ConstraintsSetStmt,
|
||||
|
||||
%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 <ival> OptConstrTrigDeferrable, OptConstrTrigInitdeferred
|
||||
%type <str> OptConstrFromTable
|
||||
|
||||
%type <str> TriggerEvents, TriggerFuncArg
|
||||
|
||||
%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 <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:
|
||||
* - 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,
|
||||
CASCADE, CASE, CAST, CHAR, CHARACTER, CHECK, CLOSE,
|
||||
COALESCE, COLLATE, COLUMN, COMMIT,
|
||||
CONSTRAINT, CREATE, CROSS, CURRENT, CURRENT_DATE, CURRENT_TIME,
|
||||
CURRENT_TIMESTAMP, CURRENT_USER, CURSOR,
|
||||
CONSTRAINT, CONSTRAINTS, CREATE, CROSS, CURRENT, CURRENT_DATE,
|
||||
CURRENT_TIME, CURRENT_TIMESTAMP, CURRENT_USER, CURSOR,
|
||||
DAY_P, DECIMAL, DECLARE, DEFAULT, DELETE, DESC, DISTINCT, DOUBLE, DROP,
|
||||
ELSE, END_TRANS, EXCEPT, EXECUTE, EXISTS, EXTRACT,
|
||||
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
|
||||
|
||||
/* Keywords (in SQL3 reserved words) */
|
||||
%token TRIGGER
|
||||
%token DEFERRABLE, DEFERRED,
|
||||
IMMEDIATE, INITIALLY,
|
||||
PENDANT,
|
||||
RESTRICT,
|
||||
TRIGGER
|
||||
|
||||
/* Keywords (in SQL92 non-reserved words) */
|
||||
%token COMMITTED, SERIALIZABLE, TYPE_P
|
||||
@ -415,6 +427,7 @@ stmt : AddAttrStmt
|
||||
| VariableSetStmt
|
||||
| VariableShowStmt
|
||||
| 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 :
|
||||
@ -1434,6 +1490,54 @@ CreateTrigStmt: CREATE TRIGGER name TriggerActionTime TriggerEvents ON
|
||||
n->before = $4;
|
||||
n->row = $8;
|
||||
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;
|
||||
}
|
||||
;
|
||||
@ -1503,6 +1607,44 @@ TriggerFuncArg: ICONST
|
||||
| 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 *n = makeNode(DropTrigStmt);
|
||||
@ -5080,10 +5222,13 @@ ColId: IDENT { $$ = $1; }
|
||||
| BEFORE { $$ = "before"; }
|
||||
| CACHE { $$ = "cache"; }
|
||||
| COMMITTED { $$ = "committed"; }
|
||||
| CONSTRAINTS { $$ = "constraints"; }
|
||||
| CREATEDB { $$ = "createdb"; }
|
||||
| CREATEUSER { $$ = "createuser"; }
|
||||
| CYCLE { $$ = "cycle"; }
|
||||
| DATABASE { $$ = "database"; }
|
||||
| DEFERRABLE { $$ = "deferrable"; }
|
||||
| DEFERRED { $$ = "deferred"; }
|
||||
| DELIMITERS { $$ = "delimiters"; }
|
||||
| DOUBLE { $$ = "double"; }
|
||||
| EACH { $$ = "each"; }
|
||||
@ -5092,9 +5237,11 @@ ColId: IDENT { $$ = $1; }
|
||||
| FORWARD { $$ = "forward"; }
|
||||
| FUNCTION { $$ = "function"; }
|
||||
| HANDLER { $$ = "handler"; }
|
||||
| IMMEDIATE { $$ = "immediate"; }
|
||||
| INCREMENT { $$ = "increment"; }
|
||||
| INDEX { $$ = "index"; }
|
||||
| INHERITS { $$ = "inherits"; }
|
||||
| INITIALLY { $$ = "initially"; }
|
||||
| INSENSITIVE { $$ = "insensitive"; }
|
||||
| INSTEAD { $$ = "instead"; }
|
||||
| ISNULL { $$ = "isnull"; }
|
||||
@ -5119,12 +5266,14 @@ ColId: IDENT { $$ = $1; }
|
||||
| OPERATOR { $$ = "operator"; }
|
||||
| OPTION { $$ = "option"; }
|
||||
| PASSWORD { $$ = "password"; }
|
||||
| PENDANT { $$ = "pendant"; }
|
||||
| PRIOR { $$ = "prior"; }
|
||||
| PRIVILEGES { $$ = "privileges"; }
|
||||
| PROCEDURAL { $$ = "procedural"; }
|
||||
| READ { $$ = "read"; }
|
||||
| RELATIVE { $$ = "relative"; }
|
||||
| RENAME { $$ = "rename"; }
|
||||
| RESTRICT { $$ = "restrict"; }
|
||||
| RETURNS { $$ = "returns"; }
|
||||
| ROW { $$ = "row"; }
|
||||
| RULE { $$ = "rule"; }
|
||||
|
@ -7,7 +7,7 @@
|
||||
*
|
||||
*
|
||||
* 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},
|
||||
{"committed", COMMITTED},
|
||||
{"constraint", CONSTRAINT},
|
||||
{"constraints", CONSTRAINTS},
|
||||
{"copy", COPY},
|
||||
{"create", CREATE},
|
||||
{"createdb", CREATEDB},
|
||||
@ -79,6 +80,8 @@ static ScanKeyword ScanKeywords[] = {
|
||||
{"decimal", DECIMAL},
|
||||
{"declare", DECLARE},
|
||||
{"default", DEFAULT},
|
||||
{"deferrable", DEFERRABLE},
|
||||
{"deferred", DEFERRED},
|
||||
{"delete", DELETE},
|
||||
{"delimiters", DELIMITERS},
|
||||
{"desc", DESC},
|
||||
@ -112,10 +115,12 @@ static ScanKeyword ScanKeywords[] = {
|
||||
{"handler", HANDLER},
|
||||
{"having", HAVING},
|
||||
{"hour", HOUR_P},
|
||||
{"immediate", IMMEDIATE},
|
||||
{"in", IN},
|
||||
{"increment", INCREMENT},
|
||||
{"index", INDEX},
|
||||
{"inherits", INHERITS},
|
||||
{"initially", INITIALLY},
|
||||
{"inner", INNER_P},
|
||||
{"insensitive", INSENSITIVE},
|
||||
{"insert", INSERT},
|
||||
@ -177,6 +182,7 @@ static ScanKeyword ScanKeywords[] = {
|
||||
{"outer", OUTER_P},
|
||||
{"partial", PARTIAL},
|
||||
{"password", PASSWORD},
|
||||
{"pendant", PENDANT},
|
||||
{"position", POSITION},
|
||||
{"precision", PRECISION},
|
||||
{"primary", PRIMARY},
|
||||
@ -190,6 +196,7 @@ static ScanKeyword ScanKeywords[] = {
|
||||
{"relative", RELATIVE},
|
||||
{"rename", RENAME},
|
||||
{"reset", RESET},
|
||||
{"restrict", RESTRICT},
|
||||
{"returns", RETURNS},
|
||||
{"revoke", REVOKE},
|
||||
{"right", RIGHT},
|
||||
|
@ -7,7 +7,7 @@
|
||||
*
|
||||
*
|
||||
* 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
|
||||
* this is the "main" module of the postgres backend and
|
||||
@ -44,6 +44,7 @@
|
||||
#endif
|
||||
|
||||
#include "commands/async.h"
|
||||
#include "commands/trigger.h"
|
||||
#include "libpq/libpq.h"
|
||||
#include "libpq/pqformat.h"
|
||||
#include "libpq/pqsignal.h"
|
||||
@ -1484,9 +1485,16 @@ PostgresMain(int argc, char *argv[], int real_argc, char *real_argv[])
|
||||
if (!IsUnderPostmaster)
|
||||
{
|
||||
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
|
||||
*
|
||||
@ -1609,6 +1617,12 @@ PostgresMain(int argc, char *argv[], int real_argc, char *real_argv[])
|
||||
|
||||
pg_exec_query(parser_input->data);
|
||||
|
||||
/*
|
||||
* Invoke IMMEDIATE constraint triggers
|
||||
*
|
||||
*/
|
||||
DeferredTriggerEndQuery();
|
||||
|
||||
if (ShowStats)
|
||||
ShowUsage();
|
||||
}
|
||||
|
@ -9,7 +9,7 @@
|
||||
*
|
||||
*
|
||||
* 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);
|
||||
break;
|
||||
|
||||
case T_ConstraintsSetStmt:
|
||||
PS_SET_STATUS(commandTag = "SET CONSTRAINTS");
|
||||
CHECK_IF_ABORTED();
|
||||
|
||||
DeferredTriggerSetState((ConstraintsSetStmt *) parsetree);
|
||||
break;
|
||||
|
||||
|
||||
/*
|
||||
* ******************************** default ********************************
|
||||
|
@ -7,7 +7,7 @@
|
||||
*
|
||||
* 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_attrdef_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
|
||||
|
||||
|
||||
/*
|
||||
* Names of indices on system catalogs
|
||||
*/
|
||||
#define AttributeNameIndex "pg_attribute_relid_attnam_index"
|
||||
#define AttributeNumIndex "pg_attribute_relid_attnum_index"
|
||||
#define AttributeRelidIndex "pg_attribute_attrelid_index"
|
||||
#define ProcedureOidIndex "pg_proc_oid_index"
|
||||
#define ProcedureNameIndex "pg_proc_proname_narg_type_index"
|
||||
#define ProcedureSrcIndex "pg_proc_prosrc_index"
|
||||
#define TypeOidIndex "pg_type_oid_index"
|
||||
#define TypeNameIndex "pg_type_typname_index"
|
||||
#define ClassOidIndex "pg_class_oid_index"
|
||||
#define ClassNameIndex "pg_class_relname_index"
|
||||
#define AttrDefaultIndex "pg_attrdef_adrelid_index"
|
||||
#define RelCheckIndex "pg_relcheck_rcrelid_index"
|
||||
#define TriggerRelidIndex "pg_trigger_tgrelid_index"
|
||||
#define DescriptionObjIndex "pg_description_objoid_index"
|
||||
#define AttributeNameIndex "pg_attribute_relid_attnam_index"
|
||||
#define AttributeNumIndex "pg_attribute_relid_attnum_index"
|
||||
#define AttributeRelidIndex "pg_attribute_attrelid_index"
|
||||
#define ProcedureOidIndex "pg_proc_oid_index"
|
||||
#define ProcedureNameIndex "pg_proc_proname_narg_type_index"
|
||||
#define ProcedureSrcIndex "pg_proc_prosrc_index"
|
||||
#define TypeOidIndex "pg_type_oid_index"
|
||||
#define TypeNameIndex "pg_type_typname_index"
|
||||
#define ClassOidIndex "pg_class_oid_index"
|
||||
#define ClassNameIndex "pg_class_relname_index"
|
||||
#define AttrDefaultIndex "pg_attrdef_adrelid_index"
|
||||
#define RelCheckIndex "pg_relcheck_rcrelid_index"
|
||||
#define TriggerRelidIndex "pg_trigger_tgrelid_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_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_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));
|
||||
|
||||
|
@ -7,7 +7,7 @@
|
||||
*
|
||||
* 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
|
||||
* 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 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 tgnargs 21 0 2 5 0 -1 -1 t f s 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 tgargs 17 0 -1 7 0 -1 -1 f f i 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 tgisconstraint 16 0 1 6 0 -1 -1 t f c 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 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));
|
||||
|
@ -7,7 +7,7 @@
|
||||
*
|
||||
* 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
|
||||
* ``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("");
|
||||
DATA(insert OID = 1216 ( pg_relcheck 110 PGUID 0 0 0 t t r 4 0 0 0 0 0 f f _null_ ));
|
||||
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("");
|
||||
|
||||
#define RelOid_pg_type 1247
|
||||
|
@ -33,6 +33,13 @@ CATALOG(pg_trigger) BOOTSTRAP
|
||||
Oid tgfoid; /* OID of function to be called */
|
||||
int2 tgtype; /* BEFORE/AFTER UPDATE/DELETE/INSERT
|
||||
* 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 */
|
||||
int28 tgattr; /* UPDATE of attr1, attr2 ... (NI) */
|
||||
bytea tgargs; /* first\000second\000tgnargs\000 */
|
||||
@ -49,14 +56,20 @@ typedef FormData_pg_trigger *Form_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_tgname 2
|
||||
#define Anum_pg_trigger_tgfoid 3
|
||||
#define Anum_pg_trigger_tgtype 4
|
||||
#define Anum_pg_trigger_tgnargs 5
|
||||
#define Anum_pg_trigger_tgattr 6
|
||||
#define Anum_pg_trigger_tgargs 7
|
||||
#define Anum_pg_trigger_tgenabled 5
|
||||
#define Anum_pg_trigger_tgisconstraint 6
|
||||
#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_BEFORE (1 << 1)
|
||||
|
@ -32,6 +32,13 @@ extern DLLIMPORT TriggerData *CurrentTriggerData;
|
||||
#define TRIGGER_EVENT_ROW 0x00000004
|
||||
#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) \
|
||||
(((TriggerEvent) (event) & TRIGGER_EVENT_OPMASK) == \
|
||||
TRIGGER_EVENT_INSERT)
|
||||
@ -68,4 +75,46 @@ extern void ExecARDeleteTriggers(EState *estate, ItemPointer tupleid);
|
||||
extern HeapTuple ExecBRUpdateTriggers(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 */
|
||||
|
@ -6,7 +6,7 @@
|
||||
*
|
||||
* 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_DropUserStmt,
|
||||
T_LockStmt,
|
||||
T_ConstraintsSetStmt,
|
||||
|
||||
T_A_Expr = 700,
|
||||
T_Attr,
|
||||
|
@ -6,7 +6,7 @@
|
||||
*
|
||||
* 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' */
|
||||
List *attr; /* UPDATE OF a, b,... (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;
|
||||
|
||||
typedef struct DropTrigStmt
|
||||
@ -602,6 +609,19 @@ typedef struct LockStmt
|
||||
int mode; /* lock mode */
|
||||
} LockStmt;
|
||||
|
||||
|
||||
/* ----------------------
|
||||
* SET CONSTRAINTS Statement
|
||||
* ----------------------
|
||||
*/
|
||||
typedef struct ConstraintsSetStmt
|
||||
{
|
||||
NodeTag type;
|
||||
List *constraints;
|
||||
bool deferred;
|
||||
} ConstraintsSetStmt;
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
* Optimizable Statements
|
||||
*****************************************************************************/
|
||||
|
@ -6,7 +6,7 @@
|
||||
*
|
||||
* 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
|
||||
{
|
||||
Oid tgoid;
|
||||
char *tgname;
|
||||
Oid tgfoid;
|
||||
FmgrInfo tgfunc;
|
||||
int16 tgtype;
|
||||
bool tgenabled;
|
||||
bool tgisconstraint;
|
||||
bool tgdeferrable;
|
||||
bool tginitdeferred;
|
||||
int16 tgnargs;
|
||||
int16 tgattr[8];
|
||||
char **tgargs;
|
||||
|
@ -7,7 +7,7 @@
|
||||
*
|
||||
* 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 SnapshotSelf ((Snapshot) 0x1)
|
||||
#define SnapshotAny ((Snapshot) 0x2)
|
||||
|
||||
extern Snapshot SnapshotDirty;
|
||||
extern Snapshot QuerySnapshot;
|
||||
@ -37,6 +38,7 @@ extern Snapshot SerializableSnapshot;
|
||||
|
||||
#define IsSnapshotNow(snapshot) ((Snapshot) snapshot == SnapshotNow)
|
||||
#define IsSnapshotSelf(snapshot) ((Snapshot) snapshot == SnapshotSelf)
|
||||
#define IsSnapshotAny(snapshot) ((Snapshot) snapshot == SnapshotAny)
|
||||
#define IsSnapshotDirty(snapshot) ((Snapshot) snapshot == SnapshotDirty)
|
||||
|
||||
extern TransactionId HeapSpecialTransactionId;
|
||||
@ -55,18 +57,22 @@ extern CommandId HeapSpecialCommandId;
|
||||
false \
|
||||
: \
|
||||
( \
|
||||
(IsSnapshotSelf(snapshot) || heapisoverride()) ? \
|
||||
HeapTupleSatisfiesItself((tuple)->t_data) \
|
||||
(IsSnapshotAny(snapshot) || heapisoverride()) ? \
|
||||
true \
|
||||
: \
|
||||
((IsSnapshotDirty(snapshot)) ? \
|
||||
HeapTupleSatisfiesDirty((tuple)->t_data) \
|
||||
((IsSnapshotSelf(snapshot) || heapisoverride()) ? \
|
||||
HeapTupleSatisfiesItself((tuple)->t_data) \
|
||||
: \
|
||||
((IsSnapshotNow(snapshot)) ? \
|
||||
HeapTupleSatisfiesNow((tuple)->t_data) \
|
||||
((IsSnapshotDirty(snapshot)) ? \
|
||||
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 fkeys;
|
||||
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 table tttest (
|
||||
price_id int4,
|
||||
|
@ -88,34 +88,40 @@ DROP TABLE pkeys;
|
||||
DROP TABLE fkeys;
|
||||
DROP TABLE fkeys2;
|
||||
|
||||
create table dup17 (x int4);
|
||||
|
||||
create trigger dup17_before
|
||||
before insert on dup17
|
||||
for each row
|
||||
execute procedure
|
||||
funny_dup17 ()
|
||||
;
|
||||
|
||||
insert into dup17 values (17);
|
||||
select count(*) from dup17;
|
||||
insert into dup17 values (17);
|
||||
select count(*) from dup17;
|
||||
|
||||
drop trigger dup17_before on dup17;
|
||||
|
||||
create trigger dup17_after
|
||||
after insert on dup17
|
||||
for each row
|
||||
execute procedure
|
||||
funny_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;
|
||||
-- -- I've disabled the funny_dup17 test because the new semantics
|
||||
-- -- of AFTER ROW triggers, which get now fired at the end of a
|
||||
-- -- query allways, cause funny_dup17 to enter an endless loop.
|
||||
-- --
|
||||
-- -- Jan
|
||||
--
|
||||
-- create table dup17 (x int4);
|
||||
--
|
||||
-- create trigger dup17_before
|
||||
-- before insert on dup17
|
||||
-- for each row
|
||||
-- execute procedure
|
||||
-- funny_dup17 ()
|
||||
-- ;
|
||||
--
|
||||
-- insert into dup17 values (17);
|
||||
-- select count(*) from dup17;
|
||||
-- insert into dup17 values (17);
|
||||
-- select count(*) from dup17;
|
||||
--
|
||||
-- drop trigger dup17_before on dup17;
|
||||
--
|
||||
-- create trigger dup17_after
|
||||
-- after insert on dup17
|
||||
-- for each row
|
||||
-- execute procedure
|
||||
-- funny_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;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user