Commit 9a915e59 authored by Tom Lane's avatar Tom Lane

Improve the handling of SET CONSTRAINTS commands by having them search

pg_constraint before searching pg_trigger.  This allows saner handling of
corner cases; in particular we now say "constraint is not deferrable"
rather than "constraint does not exist" when the command is applied to
a constraint that's inherently non-deferrable.  Per a gripe several months
ago from hubert depesz lubaczewski.

To make this work without breaking user-defined constraint triggers,
we have to add entries for them to pg_constraint.  However, in return
we can remove the pgconstrname column from pg_constraint, which represents
a fairly sizable space savings.  I also replaced the tgisconstraint column
with tgisinternal; the old meaning of tgisconstraint can now be had by
testing for nonzero tgconstraint, while there is no other way to get
the old meaning of nonzero tgconstraint, namely that the trigger was
internally generated rather than being user-created.

In passing, fix an old misstatement in the docs and comments, namely that
pg_trigger.tgdeferrable is exactly redundant with pg_constraint.condeferrable.
Actually, we mark RI action triggers as nondeferrable even when they belong to
a nominally deferrable FK constraint.  The SET CONSTRAINTS code now relies on
that instead of hard-coding a list of exception OIDs.
parent ee3b4188
<!-- $PostgreSQL: pgsql/doc/src/sgml/catalogs.sgml,v 2.217 2010/01/10 01:23:08 rhaas Exp $ --> <!-- $PostgreSQL: pgsql/doc/src/sgml/catalogs.sgml,v 2.218 2010/01/17 22:56:21 tgl Exp $ -->
<!-- <!--
Documentation of the system catalogs, directed toward PostgreSQL developers Documentation of the system catalogs, directed toward PostgreSQL developers
--> -->
...@@ -1721,6 +1721,11 @@ ...@@ -1721,6 +1721,11 @@
catalog, not here. catalog, not here.
</para> </para>
<para>
User-defined constraint triggers (created with <command>CREATE CONSTRAINT
TRIGGER</>) also give rise to an entry in this table.
</para>
<para> <para>
Check constraints on domains are stored here, too. Check constraints on domains are stored here, too.
</para> </para>
...@@ -1764,6 +1769,7 @@ ...@@ -1764,6 +1769,7 @@
<literal>f</> = foreign key constraint, <literal>f</> = foreign key constraint,
<literal>p</> = primary key constraint, <literal>p</> = primary key constraint,
<literal>u</> = unique constraint, <literal>u</> = unique constraint,
<literal>t</> = constraint trigger,
<literal>x</> = exclusion constraint <literal>x</> = exclusion constraint
</entry> </entry>
</row> </row>
...@@ -1873,7 +1879,8 @@ ...@@ -1873,7 +1879,8 @@
<entry><structfield>conkey</structfield></entry> <entry><structfield>conkey</structfield></entry>
<entry><type>int2[]</type></entry> <entry><type>int2[]</type></entry>
<entry><literal><link linkend="catalog-pg-attribute"><structname>pg_attribute</structname></link>.attnum</></entry> <entry><literal><link linkend="catalog-pg-attribute"><structname>pg_attribute</structname></link>.attnum</></entry>
<entry>If a table constraint (including a foreign key), list of the constrained columns</entry> <entry>If a table constraint (including foreign keys, but not constraint
triggers), list of the constrained columns</entry>
</row> </row>
<row> <row>
...@@ -4826,17 +4833,11 @@ ...@@ -4826,17 +4833,11 @@
</row> </row>
<row> <row>
<entry><structfield>tgisconstraint</structfield></entry> <entry><structfield>tgisinternal</structfield></entry>
<entry><type>bool</type></entry> <entry><type>bool</type></entry>
<entry></entry> <entry></entry>
<entry>True if trigger is a <quote>constraint trigger</></entry> <entry>True if trigger is internally generated (usually, to enforce
</row> the constraint identified by <structfield>tgconstraint</>)</entry>
<row>
<entry><structfield>tgconstrname</structfield></entry>
<entry><type>name</type></entry>
<entry></entry>
<entry>Constraint name, if a constraint trigger</entry>
</row> </row>
<row> <row>
...@@ -4857,7 +4858,7 @@ ...@@ -4857,7 +4858,7 @@
<entry><structfield>tgconstraint</structfield></entry> <entry><structfield>tgconstraint</structfield></entry>
<entry><type>oid</type></entry> <entry><type>oid</type></entry>
<entry><literal><link linkend="catalog-pg-constraint"><structname>pg_constraint</structname></link>.oid</literal></entry> <entry><literal><link linkend="catalog-pg-constraint"><structname>pg_constraint</structname></link>.oid</literal></entry>
<entry>The <structname>pg_constraint</> entry owning the trigger, if any</entry> <entry>The <structname>pg_constraint</> entry associated with the trigger, if any</entry>
</row> </row>
<row> <row>
...@@ -4919,13 +4920,12 @@ ...@@ -4919,13 +4920,12 @@
<note> <note>
<para> <para>
When <structfield>tgconstraint</> is nonzero, When <structfield>tgconstraint</> is nonzero,
<structfield>tgisconstraint</> must be true, and <structfield>tgconstrrelid</>, <structfield>tgconstrindid</>,
<structfield>tgconstrname</>, <structfield>tgconstrrelid</>, <structfield>tgdeferrable</>, and <structfield>tginitdeferred</> are
<structfield>tgconstrindid</>, largely redundant with the referenced <structname>pg_constraint</> entry.
<structfield>tgdeferrable</>, <structfield>tginitdeferred</> are redundant However, it is possible for a non-deferrable trigger to be associated
with the referenced <structname>pg_constraint</> entry. The reason we with a deferrable constraint: foreign key constraints can have some
keep these fields is that we support <quote>stand-alone</> constraint deferrable and some non-deferrable triggers.
triggers with no corresponding <structname>pg_constraint</> entry.
</para> </para>
</note> </note>
......
<!-- $PostgreSQL: pgsql/doc/src/sgml/trigger.sgml,v 1.61 2009/11/23 21:41:20 petere Exp $ --> <!-- $PostgreSQL: pgsql/doc/src/sgml/trigger.sgml,v 1.62 2010/01/17 22:56:21 tgl Exp $ -->
<chapter id="triggers"> <chapter id="triggers">
<title>Triggers</title> <title>Triggers</title>
...@@ -506,7 +506,7 @@ typedef struct Trigger ...@@ -506,7 +506,7 @@ typedef struct Trigger
Oid tgfoid; Oid tgfoid;
int16 tgtype; int16 tgtype;
bool tgenabled; bool tgenabled;
bool tgisconstraint; bool tgisinternal;
Oid tgconstrrelid; Oid tgconstrrelid;
Oid tgconstrindid; Oid tgconstrindid;
Oid tgconstraint; Oid tgconstraint;
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/catalog/index.c,v 1.329 2010/01/06 03:03:58 momjian Exp $ * $PostgreSQL: pgsql/src/backend/catalog/index.c,v 1.330 2010/01/17 22:56:21 tgl Exp $
* *
* *
* INTERFACE ROUTINES * INTERFACE ROUTINES
...@@ -825,7 +825,8 @@ index_create(Oid heapRelationId, ...@@ -825,7 +825,8 @@ index_create(Oid heapRelationId,
-1); -1);
trigger = makeNode(CreateTrigStmt); trigger = makeNode(CreateTrigStmt);
trigger->trigname = pstrdup(indexRelationName); trigger->trigname = (isprimary ? "PK_ConstraintTrigger" :
"Unique_ConstraintTrigger");
trigger->relation = heapRel; trigger->relation = heapRel;
trigger->funcname = SystemFuncName("unique_key_recheck"); trigger->funcname = SystemFuncName("unique_key_recheck");
trigger->args = NIL; trigger->args = NIL;
...@@ -840,9 +841,7 @@ index_create(Oid heapRelationId, ...@@ -840,9 +841,7 @@ index_create(Oid heapRelationId,
trigger->constrrel = NULL; trigger->constrrel = NULL;
(void) CreateTrigger(trigger, NULL, conOid, indexRelationId, (void) CreateTrigger(trigger, NULL, conOid, indexRelationId,
isprimary ? "PK_ConstraintTrigger" : true);
"Unique_ConstraintTrigger",
false);
} }
} }
else else
......
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
* *
* Copyright (c) 2003-2010, PostgreSQL Global Development Group * Copyright (c) 2003-2010, PostgreSQL Global Development Group
* *
* $PostgreSQL: pgsql/src/backend/catalog/information_schema.sql,v 1.63 2010/01/02 16:57:36 momjian Exp $ * $PostgreSQL: pgsql/src/backend/catalog/information_schema.sql,v 1.64 2010/01/17 22:56:21 tgl Exp $
*/ */
/* /*
...@@ -1666,7 +1666,7 @@ CREATE VIEW table_constraints AS ...@@ -1666,7 +1666,7 @@ CREATE VIEW table_constraints AS
WHERE nc.oid = c.connamespace AND nr.oid = r.relnamespace WHERE nc.oid = c.connamespace AND nr.oid = r.relnamespace
AND c.conrelid = r.oid AND c.conrelid = r.oid
AND c.contype <> 'x' -- ignore nonstandard exclusion constraints AND c.contype NOT IN ('t', 'x') -- ignore nonstandard constraints
AND r.relkind = 'r' AND r.relkind = 'r'
AND (NOT pg_is_other_temp_schema(nr.oid)) AND (NOT pg_is_other_temp_schema(nr.oid))
AND (pg_has_role(r.relowner, 'USAGE') AND (pg_has_role(r.relowner, 'USAGE')
...@@ -1868,7 +1868,7 @@ CREATE VIEW triggered_update_columns AS ...@@ -1868,7 +1868,7 @@ CREATE VIEW triggered_update_columns AS
AND c.oid = t.tgrelid AND c.oid = t.tgrelid
AND t.oid = ta.tgoid AND t.oid = ta.tgoid
AND (a.attrelid, a.attnum) = (t.tgrelid, ta.tgattnum) AND (a.attrelid, a.attnum) = (t.tgrelid, ta.tgattnum)
AND NOT t.tgisconstraint AND NOT t.tgisinternal
AND (NOT pg_is_other_temp_schema(n.oid)) AND (NOT pg_is_other_temp_schema(n.oid))
AND (pg_has_role(c.relowner, 'USAGE') AND (pg_has_role(c.relowner, 'USAGE')
-- SELECT privilege omitted, per SQL standard -- SELECT privilege omitted, per SQL standard
...@@ -1953,7 +1953,7 @@ CREATE VIEW triggers AS ...@@ -1953,7 +1953,7 @@ CREATE VIEW triggers AS
WHERE n.oid = c.relnamespace WHERE n.oid = c.relnamespace
AND c.oid = t.tgrelid AND c.oid = t.tgrelid
AND t.tgtype & em.num <> 0 AND t.tgtype & em.num <> 0
AND NOT t.tgisconstraint AND NOT t.tgisinternal
AND (NOT pg_is_other_temp_schema(n.oid)) AND (NOT pg_is_other_temp_schema(n.oid))
AND (pg_has_role(c.relowner, 'USAGE') AND (pg_has_role(c.relowner, 'USAGE')
-- SELECT privilege omitted, per SQL standard -- SELECT privilege omitted, per SQL standard
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/commands/tablecmds.c,v 1.315 2010/01/15 09:19:01 heikki Exp $ * $PostgreSQL: pgsql/src/backend/commands/tablecmds.c,v 1.316 2010/01/17 22:56:21 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -5338,7 +5338,7 @@ validateForeignKeyConstraint(Constraint *fkconstraint, ...@@ -5338,7 +5338,7 @@ validateForeignKeyConstraint(Constraint *fkconstraint,
trig.tgoid = InvalidOid; trig.tgoid = InvalidOid;
trig.tgname = fkconstraint->conname; trig.tgname = fkconstraint->conname;
trig.tgenabled = TRIGGER_FIRES_ON_ORIGIN; trig.tgenabled = TRIGGER_FIRES_ON_ORIGIN;
trig.tgisconstraint = TRUE; trig.tgisinternal = TRUE;
trig.tgconstrrelid = RelationGetRelid(pkrel); trig.tgconstrrelid = RelationGetRelid(pkrel);
trig.tgconstrindid = pkindOid; trig.tgconstrindid = pkindOid;
trig.tgconstraint = constraintOid; trig.tgconstraint = constraintOid;
...@@ -5399,7 +5399,7 @@ CreateFKCheckTrigger(RangeVar *myRel, Constraint *fkconstraint, ...@@ -5399,7 +5399,7 @@ CreateFKCheckTrigger(RangeVar *myRel, Constraint *fkconstraint,
CreateTrigStmt *fk_trigger; CreateTrigStmt *fk_trigger;
fk_trigger = makeNode(CreateTrigStmt); fk_trigger = makeNode(CreateTrigStmt);
fk_trigger->trigname = fkconstraint->conname; fk_trigger->trigname = "RI_ConstraintTrigger";
fk_trigger->relation = myRel; fk_trigger->relation = myRel;
fk_trigger->before = false; fk_trigger->before = false;
fk_trigger->row = true; fk_trigger->row = true;
...@@ -5424,8 +5424,7 @@ CreateFKCheckTrigger(RangeVar *myRel, Constraint *fkconstraint, ...@@ -5424,8 +5424,7 @@ CreateFKCheckTrigger(RangeVar *myRel, Constraint *fkconstraint,
fk_trigger->constrrel = fkconstraint->pktable; fk_trigger->constrrel = fkconstraint->pktable;
fk_trigger->args = NIL; fk_trigger->args = NIL;
(void) CreateTrigger(fk_trigger, NULL, constraintOid, indexOid, (void) CreateTrigger(fk_trigger, NULL, constraintOid, indexOid, true);
"RI_ConstraintTrigger", false);
/* Make changes-so-far visible */ /* Make changes-so-far visible */
CommandCounterIncrement(); CommandCounterIncrement();
...@@ -5463,7 +5462,7 @@ createForeignKeyTriggers(Relation rel, Constraint *fkconstraint, ...@@ -5463,7 +5462,7 @@ createForeignKeyTriggers(Relation rel, Constraint *fkconstraint,
* DELETE action on the referenced table. * DELETE action on the referenced table.
*/ */
fk_trigger = makeNode(CreateTrigStmt); fk_trigger = makeNode(CreateTrigStmt);
fk_trigger->trigname = fkconstraint->conname; fk_trigger->trigname = "RI_ConstraintTrigger";
fk_trigger->relation = fkconstraint->pktable; fk_trigger->relation = fkconstraint->pktable;
fk_trigger->before = false; fk_trigger->before = false;
fk_trigger->row = true; fk_trigger->row = true;
...@@ -5506,8 +5505,7 @@ createForeignKeyTriggers(Relation rel, Constraint *fkconstraint, ...@@ -5506,8 +5505,7 @@ createForeignKeyTriggers(Relation rel, Constraint *fkconstraint,
} }
fk_trigger->args = NIL; fk_trigger->args = NIL;
(void) CreateTrigger(fk_trigger, NULL, constraintOid, indexOid, (void) CreateTrigger(fk_trigger, NULL, constraintOid, indexOid, true);
"RI_ConstraintTrigger", false);
/* Make changes-so-far visible */ /* Make changes-so-far visible */
CommandCounterIncrement(); CommandCounterIncrement();
...@@ -5517,7 +5515,7 @@ createForeignKeyTriggers(Relation rel, Constraint *fkconstraint, ...@@ -5517,7 +5515,7 @@ createForeignKeyTriggers(Relation rel, Constraint *fkconstraint,
* UPDATE action on the referenced table. * UPDATE action on the referenced table.
*/ */
fk_trigger = makeNode(CreateTrigStmt); fk_trigger = makeNode(CreateTrigStmt);
fk_trigger->trigname = fkconstraint->conname; fk_trigger->trigname = "RI_ConstraintTrigger";
fk_trigger->relation = fkconstraint->pktable; fk_trigger->relation = fkconstraint->pktable;
fk_trigger->before = false; fk_trigger->before = false;
fk_trigger->row = true; fk_trigger->row = true;
...@@ -5560,8 +5558,7 @@ createForeignKeyTriggers(Relation rel, Constraint *fkconstraint, ...@@ -5560,8 +5558,7 @@ createForeignKeyTriggers(Relation rel, Constraint *fkconstraint,
} }
fk_trigger->args = NIL; fk_trigger->args = NIL;
(void) CreateTrigger(fk_trigger, NULL, constraintOid, indexOid, (void) CreateTrigger(fk_trigger, NULL, constraintOid, indexOid, true);
"RI_ConstraintTrigger", false);
} }
/* /*
......
This diff is collapsed.
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/tcop/utility.c,v 1.329 2010/01/15 22:36:34 tgl Exp $ * $PostgreSQL: pgsql/src/backend/tcop/utility.c,v 1.330 2010/01/17 22:56:22 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -1001,8 +1001,8 @@ standard_ProcessUtility(Node *parsetree, ...@@ -1001,8 +1001,8 @@ standard_ProcessUtility(Node *parsetree,
break; break;
case T_CreateTrigStmt: case T_CreateTrigStmt:
CreateTrigger((CreateTrigStmt *) parsetree, queryString, (void) CreateTrigger((CreateTrigStmt *) parsetree, queryString,
InvalidOid, InvalidOid, NULL, true); InvalidOid, InvalidOid, false);
break; break;
case T_DropPropertyStmt: case T_DropPropertyStmt:
......
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/utils/adt/ruleutils.c,v 1.318 2010/01/02 16:57:55 momjian Exp $ * $PostgreSQL: pgsql/src/backend/utils/adt/ruleutils.c,v 1.319 2010/01/17 22:56:22 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -519,7 +519,7 @@ pg_get_triggerdef_worker(Oid trigid, bool pretty) ...@@ -519,7 +519,7 @@ pg_get_triggerdef_worker(Oid trigid, bool pretty)
tgname = NameStr(trigrec->tgname); tgname = NameStr(trigrec->tgname);
appendStringInfo(&buf, "CREATE %sTRIGGER %s", appendStringInfo(&buf, "CREATE %sTRIGGER %s",
trigrec->tgisconstraint ? "CONSTRAINT " : "", OidIsValid(trigrec->tgconstraint) ? "CONSTRAINT " : "",
quote_identifier(tgname)); quote_identifier(tgname));
appendStringInfoString(&buf, pretty ? "\n " : " "); appendStringInfoString(&buf, pretty ? "\n " : " ");
...@@ -577,7 +577,7 @@ pg_get_triggerdef_worker(Oid trigid, bool pretty) ...@@ -577,7 +577,7 @@ pg_get_triggerdef_worker(Oid trigid, bool pretty)
generate_relation_name(trigrec->tgrelid, NIL)); generate_relation_name(trigrec->tgrelid, NIL));
appendStringInfoString(&buf, pretty ? "\n " : " "); appendStringInfoString(&buf, pretty ? "\n " : " ");
if (trigrec->tgisconstraint) if (OidIsValid(trigrec->tgconstraint))
{ {
if (OidIsValid(trigrec->tgconstrrelid)) if (OidIsValid(trigrec->tgconstrrelid))
{ {
...@@ -1276,6 +1276,15 @@ pg_get_constraintdef_worker(Oid constraintId, bool fullCommand, ...@@ -1276,6 +1276,15 @@ pg_get_constraintdef_worker(Oid constraintId, bool fullCommand,
break; break;
} }
case CONSTRAINT_TRIGGER:
/*
* There isn't an ALTER TABLE syntax for creating a user-defined
* constraint trigger, but it seems better to print something
* than throw an error; if we throw error then this function
* couldn't safely be applied to all rows of pg_constraint.
*/
appendStringInfo(&buf, "TRIGGER");
break;
case CONSTRAINT_EXCLUSION: case CONSTRAINT_EXCLUSION:
{ {
Oid indexOid = conForm->conindid; Oid indexOid = conForm->conindid;
......
...@@ -12,7 +12,7 @@ ...@@ -12,7 +12,7 @@
* by PostgreSQL * by PostgreSQL
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/bin/pg_dump/pg_dump.c,v 1.566 2010/01/06 05:18:18 momjian Exp $ * $PostgreSQL: pgsql/src/bin/pg_dump/pg_dump.c,v 1.567 2010/01/17 22:56:22 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -4584,7 +4584,7 @@ getTriggers(TableInfo tblinfo[], int numTables) ...@@ -4584,7 +4584,7 @@ getTriggers(TableInfo tblinfo[], int numTables)
"tgenabled, tableoid, oid " "tgenabled, tableoid, oid "
"FROM pg_catalog.pg_trigger t " "FROM pg_catalog.pg_trigger t "
"WHERE tgrelid = '%u'::pg_catalog.oid " "WHERE tgrelid = '%u'::pg_catalog.oid "
"AND tgconstraint = 0", "AND NOT tgisinternal",
tbinfo->dobj.catId.oid); tbinfo->dobj.catId.oid);
} }
else if (g_fout->remoteVersion >= 80300) else if (g_fout->remoteVersion >= 80300)
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* Copyright (c) 2000-2010, PostgreSQL Global Development Group * Copyright (c) 2000-2010, PostgreSQL Global Development Group
* *
* $PostgreSQL: pgsql/src/bin/psql/describe.c,v 1.233 2010/01/02 16:57:59 momjian Exp $ * $PostgreSQL: pgsql/src/bin/psql/describe.c,v 1.234 2010/01/17 22:56:23 tgl Exp $
*/ */
#include "postgres_fe.h" #include "postgres_fe.h"
...@@ -1849,7 +1849,7 @@ describeOneTableDetails(const char *schemaname, ...@@ -1849,7 +1849,7 @@ describeOneTableDetails(const char *schemaname,
PQclear(result); PQclear(result);
} }
/* print triggers (but ignore RI and unique constraint triggers) */ /* print triggers (but only user-defined triggers) */
if (tableinfo.hastriggers) if (tableinfo.hastriggers)
{ {
printfPQExpBuffer(&buf, printfPQExpBuffer(&buf,
...@@ -1859,7 +1859,9 @@ describeOneTableDetails(const char *schemaname, ...@@ -1859,7 +1859,9 @@ describeOneTableDetails(const char *schemaname,
"FROM pg_catalog.pg_trigger t\n" "FROM pg_catalog.pg_trigger t\n"
"WHERE t.tgrelid = '%s' AND ", "WHERE t.tgrelid = '%s' AND ",
oid); oid);
if (pset.sversion >= 80300) if (pset.sversion >= 80500)
appendPQExpBuffer(&buf, "NOT t.tgisinternal");
else if (pset.sversion >= 80300)
appendPQExpBuffer(&buf, "t.tgconstraint = 0"); appendPQExpBuffer(&buf, "t.tgconstraint = 0");
else else
appendPQExpBuffer(&buf, appendPQExpBuffer(&buf,
......
...@@ -37,7 +37,7 @@ ...@@ -37,7 +37,7 @@
* Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.573 2010/01/15 09:19:07 heikki Exp $ * $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.574 2010/01/17 22:56:23 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -53,6 +53,6 @@ ...@@ -53,6 +53,6 @@
*/ */
/* yyyymmddN */ /* yyyymmddN */
#define CATALOG_VERSION_NO 201001151 #define CATALOG_VERSION_NO 201001171
#endif #endif
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $PostgreSQL: pgsql/src/include/catalog/indexing.h,v 1.115 2010/01/05 01:06:56 tgl Exp $ * $PostgreSQL: pgsql/src/include/catalog/indexing.h,v 1.116 2010/01/17 22:56:23 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -220,8 +220,8 @@ DECLARE_UNIQUE_INDEX(pg_tablespace_spcname_index, 2698, on pg_tablespace using b ...@@ -220,8 +220,8 @@ DECLARE_UNIQUE_INDEX(pg_tablespace_spcname_index, 2698, on pg_tablespace using b
#define TablespaceNameIndexId 2698 #define TablespaceNameIndexId 2698
/* This following index is not used for a cache and is not unique */ /* This following index is not used for a cache and is not unique */
DECLARE_INDEX(pg_trigger_tgconstrname_index, 2699, on pg_trigger using btree(tgconstrname name_ops)); DECLARE_INDEX(pg_trigger_tgconstraint_index, 2699, on pg_trigger using btree(tgconstraint oid_ops));
#define TriggerConstrNameIndexId 2699 #define TriggerConstraintIndexId 2699
DECLARE_UNIQUE_INDEX(pg_trigger_tgrelid_tgname_index, 2701, on pg_trigger using btree(tgrelid oid_ops, tgname name_ops)); DECLARE_UNIQUE_INDEX(pg_trigger_tgrelid_tgname_index, 2701, on pg_trigger using btree(tgrelid oid_ops, tgname name_ops));
#define TriggerRelidNameIndexId 2701 #define TriggerRelidNameIndexId 2701
DECLARE_UNIQUE_INDEX(pg_trigger_oid_index, 2702, on pg_trigger using btree(oid oid_ops)); DECLARE_UNIQUE_INDEX(pg_trigger_oid_index, 2702, on pg_trigger using btree(oid oid_ops));
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $PostgreSQL: pgsql/src/include/catalog/pg_constraint.h,v 1.36 2010/01/05 01:06:56 tgl Exp $ * $PostgreSQL: pgsql/src/include/catalog/pg_constraint.h,v 1.37 2010/01/17 22:56:23 tgl Exp $
* *
* NOTES * NOTES
* the genbki.pl script reads this file and generates .bki * the genbki.pl script reads this file and generates .bki
...@@ -38,7 +38,7 @@ CATALOG(pg_constraint,2606) ...@@ -38,7 +38,7 @@ CATALOG(pg_constraint,2606)
* Postgres practice, and partly because we don't want to have to obtain a * Postgres practice, and partly because we don't want to have to obtain a
* global lock to generate a globally unique name for a nameless * global lock to generate a globally unique name for a nameless
* constraint. We associate a namespace with constraint names only for * constraint. We associate a namespace with constraint names only for
* SQL92 compatibility. * SQL-spec compatibility.
*/ */
NameData conname; /* name of this constraint */ NameData conname; /* name of this constraint */
Oid connamespace; /* OID of namespace containing constraint */ Oid connamespace; /* OID of namespace containing constraint */
...@@ -92,7 +92,8 @@ CATALOG(pg_constraint,2606) ...@@ -92,7 +92,8 @@ CATALOG(pg_constraint,2606)
*/ */
/* /*
* Columns of conrelid that the constraint applies to * Columns of conrelid that the constraint applies to, if known
* (this is NULL for trigger constraints)
*/ */
int2 conkey[1]; int2 conkey[1];
...@@ -177,6 +178,7 @@ typedef FormData_pg_constraint *Form_pg_constraint; ...@@ -177,6 +178,7 @@ typedef FormData_pg_constraint *Form_pg_constraint;
#define CONSTRAINT_FOREIGN 'f' #define CONSTRAINT_FOREIGN 'f'
#define CONSTRAINT_PRIMARY 'p' #define CONSTRAINT_PRIMARY 'p'
#define CONSTRAINT_UNIQUE 'u' #define CONSTRAINT_UNIQUE 'u'
#define CONSTRAINT_TRIGGER 't'
#define CONSTRAINT_EXCLUSION 'x' #define CONSTRAINT_EXCLUSION 'x'
/* /*
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $PostgreSQL: pgsql/src/include/catalog/pg_trigger.h,v 1.38 2010/01/05 01:06:57 tgl Exp $ * $PostgreSQL: pgsql/src/include/catalog/pg_trigger.h,v 1.39 2010/01/17 22:56:23 tgl Exp $
* *
* NOTES * NOTES
* the genbki.pl script reads this file and generates .bki * the genbki.pl script reads this file and generates .bki
...@@ -25,11 +25,10 @@ ...@@ -25,11 +25,10 @@
* pg_trigger definition. cpp turns this into * pg_trigger definition. cpp turns this into
* typedef struct FormData_pg_trigger * typedef struct FormData_pg_trigger
* *
* Note: when tgconstraint is nonzero, tgisconstraint must be true, and * Note: when tgconstraint is nonzero, tgconstrrelid, tgconstrindid,
* tgconstrname, tgconstrrelid, tgconstrindid, tgdeferrable, tginitdeferred * tgdeferrable, and tginitdeferred are largely redundant with the referenced
* are redundant with the referenced pg_constraint entry. The reason we keep * pg_constraint entry. However, it is possible for a non-deferrable trigger
* these fields is that we support "stand-alone" constraint triggers with no * to be associated with a deferrable constraint.
* corresponding pg_constraint entry.
* ---------------- * ----------------
*/ */
#define TriggerRelationId 2620 #define TriggerRelationId 2620
...@@ -43,11 +42,10 @@ CATALOG(pg_trigger,2620) ...@@ -43,11 +42,10 @@ CATALOG(pg_trigger,2620)
* ROW/STATEMENT; see below */ * ROW/STATEMENT; see below */
char tgenabled; /* trigger's firing configuration WRT char tgenabled; /* trigger's firing configuration WRT
* session_replication_role */ * session_replication_role */
bool tgisconstraint; /* trigger is a constraint trigger */ bool tgisinternal; /* trigger is system-generated */
NameData tgconstrname; /* constraint name */
Oid tgconstrrelid; /* constraint's FROM table, if any */ Oid tgconstrrelid; /* constraint's FROM table, if any */
Oid tgconstrindid; /* constraint's supporting index, if any */ Oid tgconstrindid; /* constraint's supporting index, if any */
Oid tgconstraint; /* owning pg_constraint entry, if any */ Oid tgconstraint; /* associated pg_constraint entry, if any */
bool tgdeferrable; /* constraint trigger is deferrable */ bool tgdeferrable; /* constraint trigger is deferrable */
bool tginitdeferred; /* constraint trigger is deferred initially */ bool tginitdeferred; /* constraint trigger is deferred initially */
int2 tgnargs; /* # of extra arguments in tgargs */ int2 tgnargs; /* # of extra arguments in tgargs */
...@@ -69,23 +67,22 @@ typedef FormData_pg_trigger *Form_pg_trigger; ...@@ -69,23 +67,22 @@ typedef FormData_pg_trigger *Form_pg_trigger;
* compiler constants for pg_trigger * compiler constants for pg_trigger
* ---------------- * ----------------
*/ */
#define Natts_pg_trigger 16 #define Natts_pg_trigger 15
#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_tgenabled 5 #define Anum_pg_trigger_tgenabled 5
#define Anum_pg_trigger_tgisconstraint 6 #define Anum_pg_trigger_tgisinternal 6
#define Anum_pg_trigger_tgconstrname 7 #define Anum_pg_trigger_tgconstrrelid 7
#define Anum_pg_trigger_tgconstrrelid 8 #define Anum_pg_trigger_tgconstrindid 8
#define Anum_pg_trigger_tgconstrindid 9 #define Anum_pg_trigger_tgconstraint 9
#define Anum_pg_trigger_tgconstraint 10 #define Anum_pg_trigger_tgdeferrable 10
#define Anum_pg_trigger_tgdeferrable 11 #define Anum_pg_trigger_tginitdeferred 11
#define Anum_pg_trigger_tginitdeferred 12 #define Anum_pg_trigger_tgnargs 12
#define Anum_pg_trigger_tgnargs 13 #define Anum_pg_trigger_tgattr 13
#define Anum_pg_trigger_tgattr 14 #define Anum_pg_trigger_tgargs 14
#define Anum_pg_trigger_tgargs 15 #define Anum_pg_trigger_tgqual 15
#define Anum_pg_trigger_tgqual 16
/* Bits within tgtype */ /* Bits within tgtype */
#define TRIGGER_TYPE_ROW (1 << 0) #define TRIGGER_TYPE_ROW (1 << 0)
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
* Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $PostgreSQL: pgsql/src/include/commands/trigger.h,v 1.79 2010/01/02 16:58:03 momjian Exp $ * $PostgreSQL: pgsql/src/include/commands/trigger.h,v 1.80 2010/01/17 22:56:23 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -105,8 +105,8 @@ extern PGDLLIMPORT int SessionReplicationRole; ...@@ -105,8 +105,8 @@ extern PGDLLIMPORT int SessionReplicationRole;
#define TRIGGER_DISABLED 'D' #define TRIGGER_DISABLED 'D'
extern Oid CreateTrigger(CreateTrigStmt *stmt, const char *queryString, extern Oid CreateTrigger(CreateTrigStmt *stmt, const char *queryString,
Oid constraintOid, Oid indexOid, const char *prefix, Oid constraintOid, Oid indexOid,
bool checkPermissions); bool isInternal);
extern void DropTrigger(Oid relid, const char *trigname, extern void DropTrigger(Oid relid, const char *trigname,
DropBehavior behavior, bool missing_ok); DropBehavior behavior, bool missing_ok);
......
...@@ -13,7 +13,7 @@ ...@@ -13,7 +13,7 @@
* Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $PostgreSQL: pgsql/src/include/nodes/parsenodes.h,v 1.424 2010/01/15 22:36:35 tgl Exp $ * $PostgreSQL: pgsql/src/include/nodes/parsenodes.h,v 1.425 2010/01/17 22:56:23 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -1593,9 +1593,8 @@ typedef struct CreateTrigStmt ...@@ -1593,9 +1593,8 @@ typedef struct CreateTrigStmt
int16 events; /* INSERT/UPDATE/DELETE/TRUNCATE */ int16 events; /* INSERT/UPDATE/DELETE/TRUNCATE */
List *columns; /* column names, or NIL for all columns */ List *columns; /* column names, or NIL for all columns */
Node *whenClause; /* qual expression, or NULL if none */ Node *whenClause; /* qual expression, or NULL if none */
/* The following are used for constraint triggers (RI and unique checks) */
bool isconstraint; /* This is a constraint trigger */ bool isconstraint; /* This is a constraint trigger */
/* The remaining fields are only used for constraint triggers */
bool deferrable; /* [NOT] DEFERRABLE */ bool deferrable; /* [NOT] DEFERRABLE */
bool initdeferred; /* INITIALLY {DEFERRED|IMMEDIATE} */ bool initdeferred; /* INITIALLY {DEFERRED|IMMEDIATE} */
RangeVar *constrrel; /* opposite relation, if RI trigger */ RangeVar *constrrel; /* opposite relation, if RI trigger */
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $PostgreSQL: pgsql/src/include/utils/rel.h,v 1.119 2010/01/10 22:19:17 tgl Exp $ * $PostgreSQL: pgsql/src/include/utils/rel.h,v 1.120 2010/01/17 22:56:23 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -56,7 +56,7 @@ typedef struct Trigger ...@@ -56,7 +56,7 @@ typedef struct Trigger
Oid tgfoid; Oid tgfoid;
int16 tgtype; int16 tgtype;
char tgenabled; char tgenabled;
bool tgisconstraint; bool tgisinternal;
Oid tgconstrrelid; Oid tgconstrrelid;
Oid tgconstrindid; Oid tgconstrindid;
Oid tgconstraint; Oid tgconstraint;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment