OSDN Git Service

Merge the Constraint and FkConstraint node types into a single type.
authorTom Lane <tgl@sss.pgh.pa.us>
Thu, 30 Jul 2009 02:45:38 +0000 (02:45 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Thu, 30 Jul 2009 02:45:38 +0000 (02:45 +0000)
This was foreseen to be a good idea long ago, but nobody had got round
to doing it.  The recent patch for deferred unique constraints made
transformConstraintAttrs() ugly enough that I decided it was time.
This change will also greatly simplify parsing of deferred CHECK constraints,
if anyone ever gets around to implementing that.

While at it, add a location field to Constraint, and use that to provide
an error cursor for some of the constraint-related error messages.

12 files changed:
src/backend/catalog/heap.c
src/backend/commands/tablecmds.c
src/backend/commands/trigger.c
src/backend/commands/typecmds.c
src/backend/nodes/copyfuncs.c
src/backend/nodes/equalfuncs.c
src/backend/nodes/nodeFuncs.c
src/backend/nodes/outfuncs.c
src/backend/parser/gram.y
src/backend/parser/parse_utilcmd.c
src/include/nodes/nodes.h
src/include/nodes/parsenodes.h

index 588c26a..478583a 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/catalog/heap.c,v 1.355 2009/07/28 02:56:29 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/catalog/heap.c,v 1.356 2009/07/30 02:45:36 tgl Exp $
  *
  *
  * INTERFACE ROUTINES
@@ -1870,11 +1870,11 @@ AddRelationNewConstraints(Relation rel,
                /*
                 * Check name uniqueness, or generate a name if none was given.
                 */
-               if (cdef->name != NULL)
+               if (cdef->conname != NULL)
                {
                        ListCell   *cell2;
 
-                       ccname = cdef->name;
+                       ccname = cdef->conname;
                        /* Check against other new constraints */
                        /* Needed because we don't do CommandCounterIncrement in loop */
                        foreach(cell2, checknames)
index 0d3e3bc..53abfec 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/commands/tablecmds.c,v 1.293 2009/07/29 20:56:18 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/commands/tablecmds.c,v 1.294 2009/07/30 02:45:36 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -154,7 +154,7 @@ typedef struct NewConstraint
        Oid                     refrelid;               /* PK rel, if FOREIGN */
        Oid                     refindid;               /* OID of PK's index, if FOREIGN */
        Oid                     conid;                  /* OID of pg_constraint entry, if FOREIGN */
-       Node       *qual;                       /* Check expr or FkConstraint struct */
+       Node       *qual;                       /* Check expr or CONSTR_FOREIGN Constraint */
        List       *qualstate;          /* Execution state for CHECK */
 } NewConstraint;
 
@@ -247,10 +247,10 @@ static Oid transformFkeyCheckAttrs(Relation pkrel,
                                                int numattrs, int16 *attnums,
                                                Oid *opclasses);
 static void checkFkeyPermissions(Relation rel, int16 *attnums, int natts);
-static void validateForeignKeyConstraint(FkConstraint *fkconstraint,
+static void validateForeignKeyConstraint(Constraint *fkconstraint,
                                                         Relation rel, Relation pkrel,
                                                         Oid pkindOid, Oid constraintOid);
-static void createForeignKeyTriggers(Relation rel, FkConstraint *fkconstraint,
+static void createForeignKeyTriggers(Relation rel, Constraint *fkconstraint,
                                                 Oid constraintOid, Oid indexOid);
 static void ATController(Relation rel, List *cmds, bool recurse);
 static void ATPrepCmd(List **wqueue, Relation rel, AlterTableCmd *cmd,
@@ -293,13 +293,13 @@ static void ATExecAddIndex(AlteredTableInfo *tab, Relation rel,
                           IndexStmt *stmt, bool is_rebuild);
 static void ATExecAddConstraint(List **wqueue,
                                        AlteredTableInfo *tab, Relation rel,
-                                       Node *newConstraint, bool recurse);
+                                       Constraint *newConstraint, bool recurse);
 static void ATAddCheckConstraint(List **wqueue,
                                         AlteredTableInfo *tab, Relation rel,
                                         Constraint *constr,
                                         bool recurse, bool recursing);
 static void ATAddForeignKeyConstraint(AlteredTableInfo *tab, Relation rel,
-                                                 FkConstraint *fkconstraint);
+                                                 Constraint *fkconstraint);
 static void ATExecDropConstraint(Relation rel, const char *constrName,
                                                                 DropBehavior behavior,
                                                                 bool recurse, bool recursing,
@@ -2637,10 +2637,12 @@ ATExecCmd(List **wqueue, AlteredTableInfo *tab, Relation rel,
                        ATExecAddIndex(tab, rel, (IndexStmt *) cmd->def, true);
                        break;
                case AT_AddConstraint:  /* ADD CONSTRAINT */
-                       ATExecAddConstraint(wqueue, tab, rel, cmd->def, false);
+                       ATExecAddConstraint(wqueue, tab, rel, (Constraint *) cmd->def,
+                                                               false);
                        break;
                case AT_AddConstraintRecurse:   /* ADD CONSTRAINT with recursion */
-                       ATExecAddConstraint(wqueue, tab, rel, cmd->def, true);
+                       ATExecAddConstraint(wqueue, tab, rel, (Constraint *) cmd->def,
+                                                               true);
                        break;
                case AT_DropConstraint: /* DROP CONSTRAINT */
                        ATExecDropConstraint(rel, cmd->name, cmd->behavior,
@@ -2905,7 +2907,7 @@ ATRewriteTables(List **wqueue)
 
                        if (con->contype == CONSTR_FOREIGN)
                        {
-                               FkConstraint *fkconstraint = (FkConstraint *) con->qual;
+                               Constraint *fkconstraint = (Constraint *) con->qual;
                                Relation        refrel;
 
                                if (rel == NULL)
@@ -4405,69 +4407,55 @@ ATExecAddIndex(AlteredTableInfo *tab, Relation rel,
  */
 static void
 ATExecAddConstraint(List **wqueue, AlteredTableInfo *tab, Relation rel,
-                                       Node *newConstraint, bool recurse)
+                                       Constraint *newConstraint, bool recurse)
 {
-       switch (nodeTag(newConstraint))
+       Assert(IsA(newConstraint, Constraint));
+
+       /*
+        * Currently, we only expect to see CONSTR_CHECK and CONSTR_FOREIGN nodes
+        * arriving here (see the preprocessing done in parse_utilcmd.c).  Use a
+        * switch anyway to make it easier to add more code later.
+        */
+       switch (newConstraint->contype)
        {
-               case T_Constraint:
-                       {
-                               Constraint *constr = (Constraint *) newConstraint;
+               case CONSTR_CHECK:
+                       ATAddCheckConstraint(wqueue, tab, rel,
+                                                                newConstraint, recurse, false);
+                       break;
 
-                               /*
-                                * Currently, we only expect to see CONSTR_CHECK nodes
-                                * arriving here (see the preprocessing done in
-                                * parse_utilcmd.c).  Use a switch anyway to make it easier to
-                                * add more code later.
-                                */
-                               switch (constr->contype)
-                               {
-                                       case CONSTR_CHECK:
-                                               ATAddCheckConstraint(wqueue, tab, rel,
-                                                                                        constr, recurse, false);
-                                               break;
-                                       default:
-                                               elog(ERROR, "unrecognized constraint type: %d",
-                                                        (int) constr->contype);
-                               }
-                               break;
-                       }
-               case T_FkConstraint:
+               case CONSTR_FOREIGN:
+                       /*
+                        * Note that we currently never recurse for FK constraints, so
+                        * the "recurse" flag is silently ignored.
+                        *
+                        * Assign or validate constraint name
+                        */
+                       if (newConstraint->conname)
                        {
-                               FkConstraint *fkconstraint = (FkConstraint *) newConstraint;
-
-                               /*
-                                * Note that we currently never recurse for FK constraints, so
-                                * the "recurse" flag is silently ignored.
-                                *
-                                * Assign or validate constraint name
-                                */
-                               if (fkconstraint->constr_name)
-                               {
-                                       if (ConstraintNameIsUsed(CONSTRAINT_RELATION,
-                                                                                        RelationGetRelid(rel),
-                                                                                        RelationGetNamespace(rel),
-                                                                                        fkconstraint->constr_name))
-                                               ereport(ERROR,
-                                                               (errcode(ERRCODE_DUPLICATE_OBJECT),
-                                                                errmsg("constraint \"%s\" for relation \"%s\" already exists",
-                                                                               fkconstraint->constr_name,
-                                                                               RelationGetRelationName(rel))));
-                               }
-                               else
-                                       fkconstraint->constr_name =
-                                               ChooseConstraintName(RelationGetRelationName(rel),
-                                                                       strVal(linitial(fkconstraint->fk_attrs)),
-                                                                                        "fkey",
-                                                                                        RelationGetNamespace(rel),
-                                                                                        NIL);
-
-                               ATAddForeignKeyConstraint(tab, rel, fkconstraint);
-
-                               break;
+                               if (ConstraintNameIsUsed(CONSTRAINT_RELATION,
+                                                                                RelationGetRelid(rel),
+                                                                                RelationGetNamespace(rel),
+                                                                                newConstraint->conname))
+                                       ereport(ERROR,
+                                                       (errcode(ERRCODE_DUPLICATE_OBJECT),
+                                                        errmsg("constraint \"%s\" for relation \"%s\" already exists",
+                                                                       newConstraint->conname,
+                                                                       RelationGetRelationName(rel))));
                        }
+                       else
+                               newConstraint->conname =
+                                       ChooseConstraintName(RelationGetRelationName(rel),
+                                                                                strVal(linitial(newConstraint->fk_attrs)),
+                                                                                "fkey",
+                                                                                RelationGetNamespace(rel),
+                                                                                NIL);
+
+                       ATAddForeignKeyConstraint(tab, rel, newConstraint);
+                       break;
+
                default:
-                       elog(ERROR, "unrecognized node type: %d",
-                                (int) nodeTag(newConstraint));
+                       elog(ERROR, "unrecognized constraint type: %d",
+                                (int) newConstraint->contype);
        }
 }
 
@@ -4526,12 +4514,12 @@ ATAddCheckConstraint(List **wqueue, AlteredTableInfo *tab, Relation rel,
                tab->constraints = lappend(tab->constraints, newcon);
 
                /* Save the actually assigned name if it was defaulted */
-               if (constr->name == NULL)
-                       constr->name = ccon->name;
+               if (constr->conname == NULL)
+                       constr->conname = ccon->name;
        }
 
        /* At this point we must have a locked-down name to use */
-       Assert(constr->name != NULL);
+       Assert(constr->conname != NULL);
 
        /* Advance command counter in case same table is visited multiple times */
        CommandCounterIncrement();
@@ -4583,7 +4571,7 @@ ATAddCheckConstraint(List **wqueue, AlteredTableInfo *tab, Relation rel,
  */
 static void
 ATAddForeignKeyConstraint(AlteredTableInfo *tab, Relation rel,
-                                                 FkConstraint *fkconstraint)
+                                                 Constraint *fkconstraint)
 {
        Relation        pkrel;
        int16           pkattnum[INDEX_MAX_KEYS];
@@ -4798,7 +4786,7 @@ ATAddForeignKeyConstraint(AlteredTableInfo *tab, Relation rel,
                                        (errcode(ERRCODE_DATATYPE_MISMATCH),
                                         errmsg("foreign key constraint \"%s\" "
                                                        "cannot be implemented",
-                                                       fkconstraint->constr_name),
+                                                       fkconstraint->conname),
                                         errdetail("Key columns \"%s\" and \"%s\" "
                                                           "are of incompatible types: %s and %s.",
                                                           strVal(list_nth(fkconstraint->fk_attrs, i)),
@@ -4814,7 +4802,7 @@ ATAddForeignKeyConstraint(AlteredTableInfo *tab, Relation rel,
        /*
         * Record the FK constraint in pg_constraint.
         */
-       constrOid = CreateConstraintEntry(fkconstraint->constr_name,
+       constrOid = CreateConstraintEntry(fkconstraint->conname,
                                                                          RelationGetNamespace(rel),
                                                                          CONSTRAINT_FOREIGN,
                                                                          fkconstraint->deferrable,
@@ -4854,7 +4842,7 @@ ATAddForeignKeyConstraint(AlteredTableInfo *tab, Relation rel,
                NewConstraint *newcon;
 
                newcon = (NewConstraint *) palloc0(sizeof(NewConstraint));
-               newcon->name = fkconstraint->constr_name;
+               newcon->name = fkconstraint->conname;
                newcon->contype = CONSTR_FOREIGN;
                newcon->refrelid = RelationGetRelid(pkrel);
                newcon->refindid = indexOid;
@@ -5156,7 +5144,7 @@ checkFkeyPermissions(Relation rel, int16 *attnums, int natts)
  * Caller must have opened and locked both relations.
  */
 static void
-validateForeignKeyConstraint(FkConstraint *fkconstraint,
+validateForeignKeyConstraint(Constraint *fkconstraint,
                                                         Relation rel,
                                                         Relation pkrel,
                                                         Oid pkindOid,
@@ -5171,7 +5159,7 @@ validateForeignKeyConstraint(FkConstraint *fkconstraint,
         */
        MemSet(&trig, 0, sizeof(trig));
        trig.tgoid = InvalidOid;
-       trig.tgname = fkconstraint->constr_name;
+       trig.tgname = fkconstraint->conname;
        trig.tgenabled = TRIGGER_FIRES_ON_ORIGIN;
        trig.tgisconstraint = TRUE;
        trig.tgconstrrelid = RelationGetRelid(pkrel);
@@ -5228,13 +5216,13 @@ validateForeignKeyConstraint(FkConstraint *fkconstraint,
 }
 
 static void
-CreateFKCheckTrigger(RangeVar *myRel, FkConstraint *fkconstraint,
+CreateFKCheckTrigger(RangeVar *myRel, Constraint *fkconstraint,
                                         Oid constraintOid, Oid indexOid, bool on_insert)
 {
        CreateTrigStmt *fk_trigger;
 
        fk_trigger = makeNode(CreateTrigStmt);
-       fk_trigger->trigname = fkconstraint->constr_name;
+       fk_trigger->trigname = fkconstraint->conname;
        fk_trigger->relation = myRel;
        fk_trigger->before = false;
        fk_trigger->row = true;
@@ -5268,7 +5256,7 @@ CreateFKCheckTrigger(RangeVar *myRel, FkConstraint *fkconstraint,
  * Create the triggers that implement an FK constraint.
  */
 static void
-createForeignKeyTriggers(Relation rel, FkConstraint *fkconstraint,
+createForeignKeyTriggers(Relation rel, Constraint *fkconstraint,
                                                 Oid constraintOid, Oid indexOid)
 {
        RangeVar   *myRel;
@@ -5296,7 +5284,7 @@ createForeignKeyTriggers(Relation rel, FkConstraint *fkconstraint,
         * DELETE action on the referenced table.
         */
        fk_trigger = makeNode(CreateTrigStmt);
-       fk_trigger->trigname = fkconstraint->constr_name;
+       fk_trigger->trigname = fkconstraint->conname;
        fk_trigger->relation = fkconstraint->pktable;
        fk_trigger->before = false;
        fk_trigger->row = true;
@@ -5348,7 +5336,7 @@ createForeignKeyTriggers(Relation rel, FkConstraint *fkconstraint,
         * UPDATE action on the referenced table.
         */
        fk_trigger = makeNode(CreateTrigStmt);
-       fk_trigger->trigname = fkconstraint->constr_name;
+       fk_trigger->trigname = fkconstraint->conname;
        fk_trigger->relation = fkconstraint->pktable;
        fk_trigger->before = false;
        fk_trigger->row = true;
index b847311..7bc8212 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/commands/trigger.c,v 1.250 2009/07/29 20:56:18 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/commands/trigger.c,v 1.251 2009/07/30 02:45:36 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -607,12 +607,14 @@ ConvertTriggerToFK(CreateTrigStmt *stmt, Oid funcoid)
                /* OK, we have a set, so make the FK constraint ALTER TABLE cmd */
                AlterTableStmt *atstmt = makeNode(AlterTableStmt);
                AlterTableCmd *atcmd = makeNode(AlterTableCmd);
-               FkConstraint *fkcon = makeNode(FkConstraint);
+               Constraint *fkcon = makeNode(Constraint);
 
                ereport(NOTICE,
                                (errmsg("converting trigger group into constraint \"%s\" %s",
                                                constr_name, buf.data),
                                 errdetail("%s", _(funcdescr[funcnum]))));
+               fkcon->contype = CONSTR_FOREIGN;
+               fkcon->location = -1;
                if (funcnum == 2)
                {
                        /* This trigger is on the FK table */
@@ -642,9 +644,9 @@ ConvertTriggerToFK(CreateTrigStmt *stmt, Oid funcoid)
                atcmd->subtype = AT_AddConstraint;
                atcmd->def = (Node *) fkcon;
                if (strcmp(constr_name, "<unnamed>") == 0)
-                       fkcon->constr_name = NULL;
+                       fkcon->conname = NULL;
                else
-                       fkcon->constr_name = constr_name;
+                       fkcon->conname = constr_name;
                fkcon->fk_attrs = fk_attrs;
                fkcon->pk_attrs = pk_attrs;
                fkcon->fk_matchtype = fk_matchtype;
index 1d3077c..5fa2ac6 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/commands/typecmds.c,v 1.136 2009/07/28 02:56:30 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/commands/typecmds.c,v 1.137 2009/07/30 02:45:36 tgl Exp $
  *
  * DESCRIPTION
  *       The "DefineFoo" routines take the parse tree and pick out the
@@ -867,22 +867,11 @@ DefineDomain(CreateDomainStmt *stmt)
         */
        foreach(listptr, schema)
        {
-               Node       *newConstraint = lfirst(listptr);
-               Constraint *constr;
-
-               /* Check for unsupported constraint types */
-               if (IsA(newConstraint, FkConstraint))
-                       ereport(ERROR,
-                                       (errcode(ERRCODE_SYNTAX_ERROR),
-                               errmsg("foreign key constraints not possible for domains")));
+               Constraint *constr = lfirst(listptr);
 
-               /* otherwise it should be a plain Constraint */
-               if (!IsA(newConstraint, Constraint))
+               if (!IsA(constr, Constraint))
                        elog(ERROR, "unrecognized node type: %d",
-                                (int) nodeTag(newConstraint));
-
-               constr = (Constraint *) newConstraint;
-
+                                (int) nodeTag(constr));
                switch (constr->contype)
                {
                        case CONSTR_DEFAULT:
@@ -995,6 +984,12 @@ DefineDomain(CreateDomainStmt *stmt)
                                errmsg("primary key constraints not possible for domains")));
                                break;
 
+                       case CONSTR_FOREIGN:
+                               ereport(ERROR,
+                                               (errcode(ERRCODE_SYNTAX_ERROR),
+                               errmsg("foreign key constraints not possible for domains")));
+                               break;
+
                        case CONSTR_ATTR_DEFERRABLE:
                        case CONSTR_ATTR_NOT_DEFERRABLE:
                        case CONSTR_ATTR_DEFERRED:
@@ -1849,13 +1844,6 @@ AlterDomainAddConstraint(List *names, Node *newConstraint)
        /* Check it's a domain and check user has permission for ALTER DOMAIN */
        checkDomainOwner(tup, typename);
 
-       /* Check for unsupported constraint types */
-       if (IsA(newConstraint, FkConstraint))
-               ereport(ERROR,
-                               (errcode(ERRCODE_SYNTAX_ERROR),
-                                errmsg("foreign key constraints not possible for domains")));
-
-       /* otherwise it should be a plain Constraint */
        if (!IsA(newConstraint, Constraint))
                elog(ERROR, "unrecognized node type: %d",
                         (int) nodeTag(newConstraint));
@@ -1880,6 +1868,12 @@ AlterDomainAddConstraint(List *names, Node *newConstraint)
                                errmsg("primary key constraints not possible for domains")));
                        break;
 
+               case CONSTR_FOREIGN:
+                       ereport(ERROR,
+                                       (errcode(ERRCODE_SYNTAX_ERROR),
+                               errmsg("foreign key constraints not possible for domains")));
+                       break;
+
                case CONSTR_ATTR_DEFERRABLE:
                case CONSTR_ATTR_NOT_DEFERRABLE:
                case CONSTR_ATTR_DEFERRED:
@@ -2188,23 +2182,23 @@ domainAddConstraint(Oid domainOid, Oid domainNamespace, Oid baseTypeOid,
        /*
         * Assign or validate constraint name
         */
-       if (constr->name)
+       if (constr->conname)
        {
                if (ConstraintNameIsUsed(CONSTRAINT_DOMAIN,
                                                                 domainOid,
                                                                 domainNamespace,
-                                                                constr->name))
+                                                                constr->conname))
                        ereport(ERROR,
                                        (errcode(ERRCODE_DUPLICATE_OBJECT),
                                 errmsg("constraint \"%s\" for domain \"%s\" already exists",
-                                               constr->name, domainName)));
+                                               constr->conname, domainName)));
        }
        else
-               constr->name = ChooseConstraintName(domainName,
-                                                                                       NULL,
-                                                                                       "check",
-                                                                                       domainNamespace,
-                                                                                       NIL);
+               constr->conname = ChooseConstraintName(domainName,
+                                                                                          NULL,
+                                                                                          "check",
+                                                                                          domainNamespace,
+                                                                                          NIL);
 
        /*
         * Convert the A_EXPR in raw_expr into an EXPR
@@ -2284,7 +2278,7 @@ domainAddConstraint(Oid domainOid, Oid domainNamespace, Oid baseTypeOid,
        /*
         * Store the constraint in pg_constraint
         */
-       CreateConstraintEntry(constr->name, /* Constraint Name */
+       CreateConstraintEntry(constr->conname,          /* Constraint Name */
                                                  domainNamespace,              /* namespace */
                                                  CONSTRAINT_CHECK,             /* Constraint Type */
                                                  false,        /* Is Deferrable */
index d10a9eb..48039b8 100644 (file)
@@ -15,7 +15,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/nodes/copyfuncs.c,v 1.436 2009/07/29 20:56:19 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/nodes/copyfuncs.c,v 1.437 2009/07/30 02:45:37 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -1738,25 +1738,6 @@ _copyRangeTblEntry(RangeTblEntry *from)
        return newnode;
 }
 
-static FkConstraint *
-_copyFkConstraint(FkConstraint *from)
-{
-       FkConstraint *newnode = makeNode(FkConstraint);
-
-       COPY_STRING_FIELD(constr_name);
-       COPY_NODE_FIELD(pktable);
-       COPY_NODE_FIELD(fk_attrs);
-       COPY_NODE_FIELD(pk_attrs);
-       COPY_SCALAR_FIELD(fk_matchtype);
-       COPY_SCALAR_FIELD(fk_upd_action);
-       COPY_SCALAR_FIELD(fk_del_action);
-       COPY_SCALAR_FIELD(deferrable);
-       COPY_SCALAR_FIELD(initdeferred);
-       COPY_SCALAR_FIELD(skip_validation);
-
-       return newnode;
-}
-
 static SortGroupClause *
 _copySortGroupClause(SortGroupClause *from)
 {
@@ -2085,14 +2066,22 @@ _copyConstraint(Constraint *from)
        Constraint *newnode = makeNode(Constraint);
 
        COPY_SCALAR_FIELD(contype);
-       COPY_STRING_FIELD(name);
+       COPY_STRING_FIELD(conname);
+       COPY_SCALAR_FIELD(deferrable);
+       COPY_SCALAR_FIELD(initdeferred);
+       COPY_LOCATION_FIELD(location);
        COPY_NODE_FIELD(raw_expr);
        COPY_STRING_FIELD(cooked_expr);
        COPY_NODE_FIELD(keys);
        COPY_NODE_FIELD(options);
        COPY_STRING_FIELD(indexspace);
-       COPY_SCALAR_FIELD(deferrable);
-       COPY_SCALAR_FIELD(initdeferred);
+       COPY_NODE_FIELD(pktable);
+       COPY_NODE_FIELD(fk_attrs);
+       COPY_NODE_FIELD(pk_attrs);
+       COPY_SCALAR_FIELD(fk_matchtype);
+       COPY_SCALAR_FIELD(fk_upd_action);
+       COPY_SCALAR_FIELD(fk_del_action);
+       COPY_SCALAR_FIELD(skip_validation);
 
        return newnode;
 }
@@ -4082,9 +4071,6 @@ copyObject(void *from)
                case T_CommonTableExpr:
                        retval = _copyCommonTableExpr(from);
                        break;
-               case T_FkConstraint:
-                       retval = _copyFkConstraint(from);
-                       break;
                case T_PrivGrantee:
                        retval = _copyPrivGrantee(from);
                        break;
index 6fceab2..6c75f2e 100644 (file)
@@ -22,7 +22,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/nodes/equalfuncs.c,v 1.359 2009/07/29 20:56:19 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/nodes/equalfuncs.c,v 1.360 2009/07/30 02:45:37 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -2064,14 +2064,22 @@ static bool
 _equalConstraint(Constraint *a, Constraint *b)
 {
        COMPARE_SCALAR_FIELD(contype);
-       COMPARE_STRING_FIELD(name);
+       COMPARE_STRING_FIELD(conname);
+       COMPARE_SCALAR_FIELD(deferrable);
+       COMPARE_SCALAR_FIELD(initdeferred);
+       COMPARE_LOCATION_FIELD(location);
        COMPARE_NODE_FIELD(raw_expr);
        COMPARE_STRING_FIELD(cooked_expr);
        COMPARE_NODE_FIELD(keys);
        COMPARE_NODE_FIELD(options);
        COMPARE_STRING_FIELD(indexspace);
-       COMPARE_SCALAR_FIELD(deferrable);
-       COMPARE_SCALAR_FIELD(initdeferred);
+       COMPARE_NODE_FIELD(pktable);
+       COMPARE_NODE_FIELD(fk_attrs);
+       COMPARE_NODE_FIELD(pk_attrs);
+       COMPARE_SCALAR_FIELD(fk_matchtype);
+       COMPARE_SCALAR_FIELD(fk_upd_action);
+       COMPARE_SCALAR_FIELD(fk_del_action);
+       COMPARE_SCALAR_FIELD(skip_validation);
 
        return true;
 }
@@ -2190,23 +2198,6 @@ _equalCommonTableExpr(CommonTableExpr *a, CommonTableExpr *b)
 }
 
 static bool
-_equalFkConstraint(FkConstraint *a, FkConstraint *b)
-{
-       COMPARE_STRING_FIELD(constr_name);
-       COMPARE_NODE_FIELD(pktable);
-       COMPARE_NODE_FIELD(fk_attrs);
-       COMPARE_NODE_FIELD(pk_attrs);
-       COMPARE_SCALAR_FIELD(fk_matchtype);
-       COMPARE_SCALAR_FIELD(fk_upd_action);
-       COMPARE_SCALAR_FIELD(fk_del_action);
-       COMPARE_SCALAR_FIELD(deferrable);
-       COMPARE_SCALAR_FIELD(initdeferred);
-       COMPARE_SCALAR_FIELD(skip_validation);
-
-       return true;
-}
-
-static bool
 _equalXmlSerialize(XmlSerialize *a, XmlSerialize *b)
 {
        COMPARE_SCALAR_FIELD(xmloption);
@@ -2859,9 +2850,6 @@ equal(void *a, void *b)
                case T_CommonTableExpr:
                        retval = _equalCommonTableExpr(a, b);
                        break;
-               case T_FkConstraint:
-                       retval = _equalFkConstraint(a, b);
-                       break;
                case T_PrivGrantee:
                        retval = _equalPrivGrantee(a, b);
                        break;
index 4dc9bd4..61c0e21 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/nodes/nodeFuncs.c,v 1.41 2009/07/16 06:33:42 petere Exp $
+ *       $PostgreSQL: pgsql/src/backend/nodes/nodeFuncs.c,v 1.42 2009/07/30 02:45:37 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -903,6 +903,9 @@ exprLocation(Node *expr)
                case T_TypeName:
                        loc = ((TypeName *) expr)->location;
                        break;
+               case T_Constraint:
+                       loc = ((Constraint *) expr)->location;
+                       break;
                case T_XmlSerialize:
                        /* XMLSERIALIZE keyword should always be the first thing */
                        loc = ((XmlSerialize *) expr)->location;
index e4de1c5..454a8d0 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/nodes/outfuncs.c,v 1.362 2009/07/29 20:56:19 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/nodes/outfuncs.c,v 1.363 2009/07/30 02:45:37 tgl Exp $
  *
  * NOTES
  *       Every node type that can appear in stored rules' parsetrees *must*
@@ -2277,18 +2277,39 @@ _outConstraint(StringInfo str, Constraint *node)
 {
        WRITE_NODE_TYPE("CONSTRAINT");
 
-       WRITE_STRING_FIELD(name);
+       WRITE_STRING_FIELD(conname);
+       WRITE_BOOL_FIELD(deferrable);
+       WRITE_BOOL_FIELD(initdeferred);
+       WRITE_LOCATION_FIELD(location);
 
        appendStringInfo(str, " :contype ");
        switch (node->contype)
        {
+               case CONSTR_NULL:
+                       appendStringInfo(str, "NULL");
+                       break;
+
+               case CONSTR_NOTNULL:
+                       appendStringInfo(str, "NOT_NULL");
+                       break;
+
+               case CONSTR_DEFAULT:
+                       appendStringInfo(str, "DEFAULT");
+                       WRITE_NODE_FIELD(raw_expr);
+                       WRITE_STRING_FIELD(cooked_expr);
+                       break;
+
+               case CONSTR_CHECK:
+                       appendStringInfo(str, "CHECK");
+                       WRITE_NODE_FIELD(raw_expr);
+                       WRITE_STRING_FIELD(cooked_expr);
+                       break;
+
                case CONSTR_PRIMARY:
                        appendStringInfo(str, "PRIMARY_KEY");
                        WRITE_NODE_FIELD(keys);
                        WRITE_NODE_FIELD(options);
                        WRITE_STRING_FIELD(indexspace);
-                       WRITE_BOOL_FIELD(deferrable);
-                       WRITE_BOOL_FIELD(initdeferred);
                        break;
 
                case CONSTR_UNIQUE:
@@ -2296,47 +2317,40 @@ _outConstraint(StringInfo str, Constraint *node)
                        WRITE_NODE_FIELD(keys);
                        WRITE_NODE_FIELD(options);
                        WRITE_STRING_FIELD(indexspace);
-                       WRITE_BOOL_FIELD(deferrable);
-                       WRITE_BOOL_FIELD(initdeferred);
                        break;
 
-               case CONSTR_CHECK:
-                       appendStringInfo(str, "CHECK");
-                       WRITE_NODE_FIELD(raw_expr);
-                       WRITE_STRING_FIELD(cooked_expr);
+               case CONSTR_FOREIGN:
+                       appendStringInfo(str, "FOREIGN_KEY");
+                       WRITE_NODE_FIELD(pktable);
+                       WRITE_NODE_FIELD(fk_attrs);
+                       WRITE_NODE_FIELD(pk_attrs);
+                       WRITE_CHAR_FIELD(fk_matchtype);
+                       WRITE_CHAR_FIELD(fk_upd_action);
+                       WRITE_CHAR_FIELD(fk_del_action);
+                       WRITE_BOOL_FIELD(skip_validation);
                        break;
 
-               case CONSTR_DEFAULT:
-                       appendStringInfo(str, "DEFAULT");
-                       WRITE_NODE_FIELD(raw_expr);
-                       WRITE_STRING_FIELD(cooked_expr);
+               case CONSTR_ATTR_DEFERRABLE:
+                       appendStringInfo(str, "ATTR_DEFERRABLE");
                        break;
 
-               case CONSTR_NOTNULL:
-                       appendStringInfo(str, "NOT_NULL");
+               case CONSTR_ATTR_NOT_DEFERRABLE:
+                       appendStringInfo(str, "ATTR_NOT_DEFERRABLE");
                        break;
 
-               default:
-                       appendStringInfo(str, "<unrecognized_constraint>");
+               case CONSTR_ATTR_DEFERRED:
+                       appendStringInfo(str, "ATTR_DEFERRED");
                        break;
-       }
-}
 
-static void
-_outFkConstraint(StringInfo str, FkConstraint *node)
-{
-       WRITE_NODE_TYPE("FKCONSTRAINT");
+               case CONSTR_ATTR_IMMEDIATE:
+                       appendStringInfo(str, "ATTR_IMMEDIATE");
+                       break;
 
-       WRITE_STRING_FIELD(constr_name);
-       WRITE_NODE_FIELD(pktable);
-       WRITE_NODE_FIELD(fk_attrs);
-       WRITE_NODE_FIELD(pk_attrs);
-       WRITE_CHAR_FIELD(fk_matchtype);
-       WRITE_CHAR_FIELD(fk_upd_action);
-       WRITE_CHAR_FIELD(fk_del_action);
-       WRITE_BOOL_FIELD(deferrable);
-       WRITE_BOOL_FIELD(initdeferred);
-       WRITE_BOOL_FIELD(skip_validation);
+               default:
+                       appendStringInfo(str, "<unrecognized_constraint %d>",
+                                                        (int) node->contype);
+                       break;
+       }
 }
 
 
@@ -2765,9 +2779,6 @@ _outNode(StringInfo str, void *obj)
                        case T_Constraint:
                                _outConstraint(str, obj);
                                break;
-                       case T_FkConstraint:
-                               _outFkConstraint(str, obj);
-                               break;
                        case T_FuncCall:
                                _outFuncCall(str, obj);
                                break;
index 0547b64..543aea9 100644 (file)
@@ -11,7 +11,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/parser/gram.y,v 2.674 2009/07/29 20:56:19 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/parser/gram.y,v 2.675 2009/07/30 02:45:37 tgl Exp $
  *
  * HISTORY
  *       AUTHOR                        DATE                    MAJOR EVENT
@@ -2172,24 +2172,11 @@ ColQualList:
 ColConstraint:
                        CONSTRAINT name ColConstraintElem
                                {
-                                       switch (nodeTag($3))
-                                       {
-                                               case T_Constraint:
-                                                       {
-                                                               Constraint *n = (Constraint *)$3;
-                                                               n->name = $2;
-                                                       }
-                                                       break;
-                                               case T_FkConstraint:
-                                                       {
-                                                               FkConstraint *n = (FkConstraint *)$3;
-                                                               n->constr_name = $2;
-                                                       }
-                                                       break;
-                                               default:
-                                                       break;
-                                       }
-                                       $$ = $3;
+                                       Constraint *n = (Constraint *) $3;
+                                       Assert(IsA(n, Constraint));
+                                       n->conname = $2;
+                                       n->location = @1;
+                                       $$ = (Node *) n;
                                }
                        | ColConstraintElem                                             { $$ = $1; }
                        | ConstraintAttr                                                { $$ = $1; }
@@ -2215,94 +2202,66 @@ ColConstraintElem:
                                {
                                        Constraint *n = makeNode(Constraint);
                                        n->contype = CONSTR_NOTNULL;
-                                       n->name = NULL;
-                                       n->raw_expr = NULL;
-                                       n->cooked_expr = NULL;
-                                       n->keys = NULL;
-                                       n->indexspace = NULL;
-                                       n->deferrable = FALSE;
-                                       n->initdeferred = FALSE;
+                                       n->location = @1;
                                        $$ = (Node *)n;
                                }
                        | NULL_P
                                {
                                        Constraint *n = makeNode(Constraint);
                                        n->contype = CONSTR_NULL;
-                                       n->name = NULL;
-                                       n->raw_expr = NULL;
-                                       n->cooked_expr = NULL;
-                                       n->keys = NULL;
-                                       n->indexspace = NULL;
-                                       n->deferrable = FALSE;
-                                       n->initdeferred = FALSE;
+                                       n->location = @1;
                                        $$ = (Node *)n;
                                }
                        | UNIQUE opt_definition OptConsTableSpace
                                {
                                        Constraint *n = makeNode(Constraint);
                                        n->contype = CONSTR_UNIQUE;
-                                       n->name = NULL;
-                                       n->raw_expr = NULL;
-                                       n->cooked_expr = NULL;
+                                       n->location = @1;
                                        n->keys = NULL;
                                        n->options = $2;
                                        n->indexspace = $3;
-                                       n->deferrable = FALSE;
-                                       n->initdeferred = FALSE;
                                        $$ = (Node *)n;
                                }
                        | PRIMARY KEY opt_definition OptConsTableSpace
                                {
                                        Constraint *n = makeNode(Constraint);
                                        n->contype = CONSTR_PRIMARY;
-                                       n->name = NULL;
-                                       n->raw_expr = NULL;
-                                       n->cooked_expr = NULL;
+                                       n->location = @1;
                                        n->keys = NULL;
                                        n->options = $3;
                                        n->indexspace = $4;
-                                       n->deferrable = FALSE;
-                                       n->initdeferred = FALSE;
                                        $$ = (Node *)n;
                                }
                        | CHECK '(' a_expr ')'
                                {
                                        Constraint *n = makeNode(Constraint);
                                        n->contype = CONSTR_CHECK;
-                                       n->name = NULL;
+                                       n->location = @1;
                                        n->raw_expr = $3;
                                        n->cooked_expr = NULL;
-                                       n->keys = NULL;
-                                       n->indexspace = NULL;
-                                       n->deferrable = FALSE;
-                                       n->initdeferred = FALSE;
                                        $$ = (Node *)n;
                                }
                        | DEFAULT b_expr
                                {
                                        Constraint *n = makeNode(Constraint);
                                        n->contype = CONSTR_DEFAULT;
-                                       n->name = NULL;
+                                       n->location = @1;
                                        n->raw_expr = $2;
                                        n->cooked_expr = NULL;
-                                       n->keys = NULL;
-                                       n->indexspace = NULL;
-                                       n->deferrable = FALSE;
-                                       n->initdeferred = FALSE;
                                        $$ = (Node *)n;
                                }
                        | REFERENCES qualified_name opt_column_list key_match key_actions
                                {
-                                       FkConstraint *n = makeNode(FkConstraint);
-                                       n->constr_name          = NULL;
+                                       Constraint *n = makeNode(Constraint);
+                                       n->contype = CONSTR_FOREIGN;
+                                       n->location = @1;
                                        n->pktable                      = $2;
                                        n->fk_attrs                     = NIL;
                                        n->pk_attrs                     = $3;
                                        n->fk_matchtype         = $4;
                                        n->fk_upd_action        = (char) ($5 >> 8);
                                        n->fk_del_action        = (char) ($5 & 0xFF);
-                                       n->deferrable           = FALSE;
-                                       n->initdeferred         = FALSE;
+                                       n->skip_validation  = FALSE;
                                        $$ = (Node *)n;
                                }
                ;
@@ -2324,24 +2283,28 @@ ConstraintAttr:
                                {
                                        Constraint *n = makeNode(Constraint);
                                        n->contype = CONSTR_ATTR_DEFERRABLE;
+                                       n->location = @1;
                                        $$ = (Node *)n;
                                }
                        | NOT DEFERRABLE
                                {
                                        Constraint *n = makeNode(Constraint);
                                        n->contype = CONSTR_ATTR_NOT_DEFERRABLE;
+                                       n->location = @1;
                                        $$ = (Node *)n;
                                }
                        | INITIALLY DEFERRED
                                {
                                        Constraint *n = makeNode(Constraint);
                                        n->contype = CONSTR_ATTR_DEFERRED;
+                                       n->location = @1;
                                        $$ = (Node *)n;
                                }
                        | INITIALLY IMMEDIATE
                                {
                                        Constraint *n = makeNode(Constraint);
                                        n->contype = CONSTR_ATTR_IMMEDIATE;
+                                       n->location = @1;
                                        $$ = (Node *)n;
                                }
                ;
@@ -2387,24 +2350,11 @@ TableLikeOption:
 TableConstraint:
                        CONSTRAINT name ConstraintElem
                                {
-                                       switch (nodeTag($3))
-                                       {
-                                               case T_Constraint:
-                                                       {
-                                                               Constraint *n = (Constraint *)$3;
-                                                               n->name = $2;
-                                                       }
-                                                       break;
-                                               case T_FkConstraint:
-                                                       {
-                                                               FkConstraint *n = (FkConstraint *)$3;
-                                                               n->constr_name = $2;
-                                                       }
-                                                       break;
-                                               default:
-                                                       break;
-                                       }
-                                       $$ = $3;
+                                       Constraint *n = (Constraint *) $3;
+                                       Assert(IsA(n, Constraint));
+                                       n->conname = $2;
+                                       n->location = @1;
+                                       $$ = (Node *) n;
                                }
                        | ConstraintElem                                                { $$ = $1; }
                ;
@@ -2414,17 +2364,14 @@ ConstraintElem:
                                {
                                        Constraint *n = makeNode(Constraint);
                                        n->contype = CONSTR_CHECK;
-                                       n->name = NULL;
+                                       n->location = @1;
                                        n->raw_expr = $3;
                                        n->cooked_expr = NULL;
-                                       n->indexspace = NULL;
                                        if ($5 != 0)
                                                ereport(ERROR,
                                                                (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
                                                                 errmsg("CHECK constraints cannot be deferred"),
                                                                 parser_errposition(@5)));
-                                       n->deferrable = FALSE;
-                                       n->initdeferred = FALSE;
                                        $$ = (Node *)n;
                                }
                        | UNIQUE '(' columnList ')' opt_definition OptConsTableSpace
@@ -2432,9 +2379,7 @@ ConstraintElem:
                                {
                                        Constraint *n = makeNode(Constraint);
                                        n->contype = CONSTR_UNIQUE;
-                                       n->name = NULL;
-                                       n->raw_expr = NULL;
-                                       n->cooked_expr = NULL;
+                                       n->location = @1;
                                        n->keys = $3;
                                        n->options = $5;
                                        n->indexspace = $6;
@@ -2447,9 +2392,7 @@ ConstraintElem:
                                {
                                        Constraint *n = makeNode(Constraint);
                                        n->contype = CONSTR_PRIMARY;
-                                       n->name = NULL;
-                                       n->raw_expr = NULL;
-                                       n->cooked_expr = NULL;
+                                       n->location = @1;
                                        n->keys = $4;
                                        n->options = $6;
                                        n->indexspace = $7;
@@ -2460,14 +2403,16 @@ ConstraintElem:
                        | FOREIGN KEY '(' columnList ')' REFERENCES qualified_name
                                opt_column_list key_match key_actions ConstraintAttributeSpec
                                {
-                                       FkConstraint *n = makeNode(FkConstraint);
-                                       n->constr_name          = NULL;
+                                       Constraint *n = makeNode(Constraint);
+                                       n->contype = CONSTR_FOREIGN;
+                                       n->location = @1;
                                        n->pktable                      = $7;
                                        n->fk_attrs                     = $4;
                                        n->pk_attrs                     = $8;
                                        n->fk_matchtype         = $9;
                                        n->fk_upd_action        = (char) ($10 >> 8);
                                        n->fk_del_action        = (char) ($10 & 0xFF);
+                                       n->skip_validation  = FALSE;
                                        n->deferrable           = ($11 & 1) != 0;
                                        n->initdeferred         = ($11 & 2) != 0;
                                        $$ = (Node *)n;
index 94c8c59..7a11eb9 100644 (file)
@@ -19,7 +19,7 @@
  * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- *     $PostgreSQL: pgsql/src/backend/parser/parse_utilcmd.c,v 2.24 2009/07/29 20:56:19 tgl Exp $
+ *     $PostgreSQL: pgsql/src/backend/parser/parse_utilcmd.c,v 2.25 2009/07/30 02:45:37 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -112,7 +112,7 @@ static void transformFKConstraints(ParseState *pstate,
                                           CreateStmtContext *cxt,
                                           bool skipValidation,
                                           bool isAddConstraint);
-static void transformConstraintAttrs(List *constraintList);
+static void transformConstraintAttrs(ParseState *pstate, List *constraintList);
 static void transformColumnType(ParseState *pstate, ColumnDef *column);
 static void setSchemaName(char *context_schema, char **stmt_schema_name);
 
@@ -199,11 +199,6 @@ transformCreateStmt(CreateStmt *stmt, const char *queryString)
                                                                                 (Constraint *) element);
                                break;
 
-                       case T_FkConstraint:
-                               /* No pre-transformation needed */
-                               cxt.fkconstraints = lappend(cxt.fkconstraints, element);
-                               break;
-
                        case T_InhRelation:
                                transformInhRelation(pstate, &cxt,
                                                                         (InhRelation *) element);
@@ -295,7 +290,8 @@ transformColumnDefinition(ParseState *pstate, CreateStmtContext *cxt,
                if (is_serial && column->typeName->arrayBounds != NIL)
                        ereport(ERROR,
                                        (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
-                                        errmsg("array of serial is not implemented")));
+                                        errmsg("array of serial is not implemented"),
+                                        parser_errposition(pstate, column->typeName->location)));
        }
 
        /* Do necessary work on the column type declaration */
@@ -397,18 +393,19 @@ transformColumnDefinition(ParseState *pstate, CreateStmtContext *cxt,
 
                constraint = makeNode(Constraint);
                constraint->contype = CONSTR_DEFAULT;
+               constraint->location = -1;
                constraint->raw_expr = (Node *) funccallnode;
                constraint->cooked_expr = NULL;
-               constraint->keys = NIL;
                column->constraints = lappend(column->constraints, constraint);
 
                constraint = makeNode(Constraint);
                constraint->contype = CONSTR_NOTNULL;
+               constraint->location = -1;
                column->constraints = lappend(column->constraints, constraint);
        }
 
        /* Process column constraints, if any... */
-       transformConstraintAttrs(column->constraints);
+       transformConstraintAttrs(pstate, column->constraints);
 
        saw_nullable = false;
        saw_default = false;
@@ -416,21 +413,6 @@ transformColumnDefinition(ParseState *pstate, CreateStmtContext *cxt,
        foreach(clist, column->constraints)
        {
                constraint = lfirst(clist);
-
-               /*
-                * If this column constraint is a FOREIGN KEY constraint, then we fill
-                * in the current attribute's name and throw it into the list of FK
-                * constraints to be processed later.
-                */
-               if (IsA(constraint, FkConstraint))
-               {
-                       FkConstraint *fkconstraint = (FkConstraint *) constraint;
-
-                       fkconstraint->fk_attrs = list_make1(makeString(column->colname));
-                       cxt->fkconstraints = lappend(cxt->fkconstraints, fkconstraint);
-                       continue;
-               }
-
                Assert(IsA(constraint, Constraint));
 
                switch (constraint->contype)
@@ -440,7 +422,9 @@ transformColumnDefinition(ParseState *pstate, CreateStmtContext *cxt,
                                        ereport(ERROR,
                                                        (errcode(ERRCODE_SYNTAX_ERROR),
                                                         errmsg("conflicting NULL/NOT NULL declarations for column \"%s\" of table \"%s\"",
-                                                                 column->colname, cxt->relation->relname)));
+                                                                       column->colname, cxt->relation->relname),
+                                                        parser_errposition(pstate,
+                                                                                               constraint->location)));
                                column->is_not_null = FALSE;
                                saw_nullable = true;
                                break;
@@ -450,7 +434,9 @@ transformColumnDefinition(ParseState *pstate, CreateStmtContext *cxt,
                                        ereport(ERROR,
                                                        (errcode(ERRCODE_SYNTAX_ERROR),
                                                         errmsg("conflicting NULL/NOT NULL declarations for column \"%s\" of table \"%s\"",
-                                                                 column->colname, cxt->relation->relname)));
+                                                                       column->colname, cxt->relation->relname),
+                                                        parser_errposition(pstate,
+                                                                                               constraint->location)));
                                column->is_not_null = TRUE;
                                saw_nullable = true;
                                break;
@@ -460,7 +446,9 @@ transformColumnDefinition(ParseState *pstate, CreateStmtContext *cxt,
                                        ereport(ERROR,
                                                        (errcode(ERRCODE_SYNTAX_ERROR),
                                                         errmsg("multiple default values specified for column \"%s\" of table \"%s\"",
-                                                                 column->colname, cxt->relation->relname)));
+                                                                       column->colname, cxt->relation->relname),
+                                                        parser_errposition(pstate,
+                                                                                               constraint->location)));
                                column->raw_default = constraint->raw_expr;
                                Assert(constraint->cooked_expr == NULL);
                                saw_default = true;
@@ -477,6 +465,15 @@ transformColumnDefinition(ParseState *pstate, CreateStmtContext *cxt,
                                cxt->ckconstraints = lappend(cxt->ckconstraints, constraint);
                                break;
 
+                       case CONSTR_FOREIGN:
+                               /*
+                                * Fill in the current attribute's name and throw it into the
+                                * list of FK constraints to be processed later.
+                                */
+                               constraint->fk_attrs = list_make1(makeString(column->colname));
+                               cxt->fkconstraints = lappend(cxt->fkconstraints, constraint);
+                               break;
+
                        case CONSTR_ATTR_DEFERRABLE:
                        case CONSTR_ATTR_NOT_DEFERRABLE:
                        case CONSTR_ATTR_DEFERRED:
@@ -511,6 +508,10 @@ transformTableConstraint(ParseState *pstate, CreateStmtContext *cxt,
                        cxt->ckconstraints = lappend(cxt->ckconstraints, constraint);
                        break;
 
+               case CONSTR_FOREIGN:
+                       cxt->fkconstraints = lappend(cxt->fkconstraints, constraint);
+                       break;
+
                case CONSTR_NULL:
                case CONSTR_NOTNULL:
                case CONSTR_DEFAULT:
@@ -688,11 +689,11 @@ transformInhRelation(ParseState *pstate, CreateStmtContext *cxt,
                        change_varattnos_of_a_node(ccbin_node, attmap);
 
                        n->contype = CONSTR_CHECK;
-                       n->name = pstrdup(ccname);
+                       n->location = -1;
+                       n->conname = pstrdup(ccname);
                        n->raw_expr = NULL;
                        n->cooked_expr = nodeToString(ccbin_node);
-                       n->indexspace = NULL;
-                       cxt->ckconstraints = lappend(cxt->ckconstraints, (Node *) n);
+                       cxt->ckconstraints = lappend(cxt->ckconstraints, n);
                }
        }
 
@@ -1121,8 +1122,8 @@ transformIndexConstraint(Constraint *constraint, CreateStmtContext *cxt)
        index->deferrable = constraint->deferrable;
        index->initdeferred = constraint->initdeferred;
 
-       if (constraint->name != NULL)
-               index->idxname = pstrdup(constraint->name);
+       if (constraint->conname != NULL)
+               index->idxname = pstrdup(constraint->conname);
        else
                index->idxname = NULL;  /* DefineIndex will choose name */
 
@@ -1281,9 +1282,9 @@ transformFKConstraints(ParseState *pstate, CreateStmtContext *cxt,
        {
                foreach(fkclist, cxt->fkconstraints)
                {
-                       FkConstraint *fkconstraint = (FkConstraint *) lfirst(fkclist);
+                       Constraint *constraint = (Constraint *) lfirst(fkclist);
 
-                       fkconstraint->skip_validation = true;
+                       constraint->skip_validation = true;
                }
        }
 
@@ -1308,12 +1309,12 @@ transformFKConstraints(ParseState *pstate, CreateStmtContext *cxt,
 
                foreach(fkclist, cxt->fkconstraints)
                {
-                       FkConstraint *fkconstraint = (FkConstraint *) lfirst(fkclist);
+                       Constraint *constraint = (Constraint *) lfirst(fkclist);
                        AlterTableCmd *altercmd = makeNode(AlterTableCmd);
 
                        altercmd->subtype = AT_ProcessedConstraint;
                        altercmd->name = NULL;
-                       altercmd->def = (Node *) fkconstraint;
+                       altercmd->def = (Node *) constraint;
                        alterstmt->cmds = lappend(alterstmt->cmds, altercmd);
                }
 
@@ -1784,12 +1785,11 @@ transformAlterTableStmt(AlterTableStmt *stmt, const char *queryString)
                                 * The original AddConstraint cmd node doesn't go to newcmds
                                 */
                                if (IsA(cmd->def, Constraint))
+                               {
                                        transformTableConstraint(pstate, &cxt,
                                                                                         (Constraint *) cmd->def);
-                               else if (IsA(cmd->def, FkConstraint))
-                               {
-                                       cxt.fkconstraints = lappend(cxt.fkconstraints, cmd->def);
-                                       skipValidation = false;
+                                       if (((Constraint *) cmd->def)->contype == CONSTR_FOREIGN)
+                                               skipValidation = false;
                                }
                                else
                                        elog(ERROR, "unrecognized node type: %d",
@@ -1886,145 +1886,112 @@ transformAlterTableStmt(AlterTableStmt *stmt, const char *queryString)
  * for other constraint types.
  */
 static void
-transformConstraintAttrs(List *constraintList)
+transformConstraintAttrs(ParseState *pstate, List *constraintList)
 {
-       Node       *lastprimarynode = NULL;
+       Constraint *lastprimarycon = NULL;
        bool            saw_deferrability = false;
        bool            saw_initially = false;
        ListCell   *clist;
 
-#define SUPPORTS_ATTRS(node)                                                           \
-       ((node) != NULL &&                                                                              \
-        (IsA((node), FkConstraint) ||                                                  \
-         (IsA((node), Constraint) &&                                                   \
-          (((Constraint *) (node))->contype == CONSTR_PRIMARY || \
-               ((Constraint *) (node))->contype == CONSTR_UNIQUE))))
+#define SUPPORTS_ATTRS(node)                           \
+       ((node) != NULL &&                                              \
+        ((node)->contype == CONSTR_PRIMARY ||  \
+         (node)->contype == CONSTR_UNIQUE ||   \
+         (node)->contype == CONSTR_FOREIGN))
 
        foreach(clist, constraintList)
        {
-               Node       *node = lfirst(clist);
+               Constraint *con = (Constraint *) lfirst(clist);
 
-               if (!IsA(node, Constraint))
+               if (!IsA(con, Constraint))
+                       elog(ERROR, "unrecognized node type: %d",
+                                (int) nodeTag(con));
+               switch (con->contype)
                {
-                       lastprimarynode = node;
-                       /* reset flags for new primary node */
-                       saw_deferrability = false;
-                       saw_initially = false;
-               }
-               else
-               {
-                       Constraint *con = (Constraint *) node;
-
-                       switch (con->contype)
-                       {
-                               case CONSTR_ATTR_DEFERRABLE:
-                                       if (!SUPPORTS_ATTRS(lastprimarynode))
-                                               ereport(ERROR,
-                                                               (errcode(ERRCODE_SYNTAX_ERROR),
-                                                                errmsg("misplaced DEFERRABLE clause")));
-                                       if (saw_deferrability)
-                                               ereport(ERROR,
-                                                               (errcode(ERRCODE_SYNTAX_ERROR),
-                                                                errmsg("multiple DEFERRABLE/NOT DEFERRABLE clauses not allowed")));
-                                       saw_deferrability = true;
-                                       if (IsA(lastprimarynode, FkConstraint))
-                                               ((FkConstraint *) lastprimarynode)->deferrable = true;
-                                       else
-                                               ((Constraint *) lastprimarynode)->deferrable = true;
-                                       break;
+                       case CONSTR_ATTR_DEFERRABLE:
+                               if (!SUPPORTS_ATTRS(lastprimarycon))
+                                       ereport(ERROR,
+                                                       (errcode(ERRCODE_SYNTAX_ERROR),
+                                                        errmsg("misplaced DEFERRABLE clause"),
+                                                        parser_errposition(pstate, con->location)));
+                               if (saw_deferrability)
+                                       ereport(ERROR,
+                                                       (errcode(ERRCODE_SYNTAX_ERROR),
+                                                        errmsg("multiple DEFERRABLE/NOT DEFERRABLE clauses not allowed"),
+                                                        parser_errposition(pstate, con->location)));
+                               saw_deferrability = true;
+                               lastprimarycon->deferrable = true;
+                               break;
 
-                               case CONSTR_ATTR_NOT_DEFERRABLE:
-                                       if (!SUPPORTS_ATTRS(lastprimarynode))
-                                               ereport(ERROR,
-                                                               (errcode(ERRCODE_SYNTAX_ERROR),
-                                                                errmsg("misplaced NOT DEFERRABLE clause")));
-                                       if (saw_deferrability)
-                                               ereport(ERROR,
-                                                               (errcode(ERRCODE_SYNTAX_ERROR),
-                                                                errmsg("multiple DEFERRABLE/NOT DEFERRABLE clauses not allowed")));
-                                       saw_deferrability = true;
-                                       if (IsA(lastprimarynode, FkConstraint))
-                                       {
-                                               ((FkConstraint *) lastprimarynode)->deferrable = false;
-                                               if (saw_initially &&
-                                                       ((FkConstraint *) lastprimarynode)->initdeferred)
-                                                       ereport(ERROR,
-                                                                       (errcode(ERRCODE_SYNTAX_ERROR),
-                                                                        errmsg("constraint declared INITIALLY DEFERRED must be DEFERRABLE")));
-                                       }
-                                       else
-                                       {
-                                               ((Constraint *) lastprimarynode)->deferrable = false;
-                                               if (saw_initially &&
-                                                       ((Constraint *) lastprimarynode)->initdeferred)
-                                                       ereport(ERROR,
-                                                                       (errcode(ERRCODE_SYNTAX_ERROR),
-                                                                        errmsg("constraint declared INITIALLY DEFERRED must be DEFERRABLE")));
-                                       }
-                                       break;
+                       case CONSTR_ATTR_NOT_DEFERRABLE:
+                               if (!SUPPORTS_ATTRS(lastprimarycon))
+                                       ereport(ERROR,
+                                                       (errcode(ERRCODE_SYNTAX_ERROR),
+                                                        errmsg("misplaced NOT DEFERRABLE clause"),
+                                                        parser_errposition(pstate, con->location)));
+                               if (saw_deferrability)
+                                       ereport(ERROR,
+                                                       (errcode(ERRCODE_SYNTAX_ERROR),
+                                                        errmsg("multiple DEFERRABLE/NOT DEFERRABLE clauses not allowed"),
+                                                        parser_errposition(pstate, con->location)));
+                               saw_deferrability = true;
+                               lastprimarycon->deferrable = false;
+                               if (saw_initially &&
+                                       lastprimarycon->initdeferred)
+                                       ereport(ERROR,
+                                                       (errcode(ERRCODE_SYNTAX_ERROR),
+                                                        errmsg("constraint declared INITIALLY DEFERRED must be DEFERRABLE"),
+                                                        parser_errposition(pstate, con->location)));
+                               break;
 
-                               case CONSTR_ATTR_DEFERRED:
-                                       if (!SUPPORTS_ATTRS(lastprimarynode))
-                                               ereport(ERROR,
-                                                               (errcode(ERRCODE_SYNTAX_ERROR),
-                                                        errmsg("misplaced INITIALLY DEFERRED clause")));
-                                       if (saw_initially)
-                                               ereport(ERROR,
-                                                               (errcode(ERRCODE_SYNTAX_ERROR),
-                                                                errmsg("multiple INITIALLY IMMEDIATE/DEFERRED clauses not allowed")));
-                                       saw_initially = true;
+                       case CONSTR_ATTR_DEFERRED:
+                               if (!SUPPORTS_ATTRS(lastprimarycon))
+                                       ereport(ERROR,
+                                                       (errcode(ERRCODE_SYNTAX_ERROR),
+                                                        errmsg("misplaced INITIALLY DEFERRED clause"),
+                                                        parser_errposition(pstate, con->location)));
+                               if (saw_initially)
+                                       ereport(ERROR,
+                                                       (errcode(ERRCODE_SYNTAX_ERROR),
+                                                        errmsg("multiple INITIALLY IMMEDIATE/DEFERRED clauses not allowed"),
+                                                        parser_errposition(pstate, con->location)));
+                               saw_initially = true;
+                               lastprimarycon->initdeferred = true;
 
-                                       /*
-                                        * If only INITIALLY DEFERRED appears, assume DEFERRABLE
-                                        */
-                                       if (IsA(lastprimarynode, FkConstraint))
-                                       {
-                                               ((FkConstraint *) lastprimarynode)->initdeferred = true;
-
-                                               if (!saw_deferrability)
-                                                       ((FkConstraint *) lastprimarynode)->deferrable = true;
-                                               else if (!((FkConstraint *) lastprimarynode)->deferrable)
-                                                       ereport(ERROR,
-                                                                       (errcode(ERRCODE_SYNTAX_ERROR),
-                                                                        errmsg("constraint declared INITIALLY DEFERRED must be DEFERRABLE")));
-                                       }
-                                       else
-                                       {
-                                               ((Constraint *) lastprimarynode)->initdeferred = true;
-
-                                               if (!saw_deferrability)
-                                                       ((Constraint *) lastprimarynode)->deferrable = true;
-                                               else if (!((Constraint *) lastprimarynode)->deferrable)
-                                                       ereport(ERROR,
-                                                                       (errcode(ERRCODE_SYNTAX_ERROR),
-                                                                        errmsg("constraint declared INITIALLY DEFERRED must be DEFERRABLE")));
-                                       }
-                                       break;
+                               /*
+                                * If only INITIALLY DEFERRED appears, assume DEFERRABLE
+                                */
+                               if (!saw_deferrability)
+                                       lastprimarycon->deferrable = true;
+                               else if (!lastprimarycon->deferrable)
+                                       ereport(ERROR,
+                                                       (errcode(ERRCODE_SYNTAX_ERROR),
+                                                        errmsg("constraint declared INITIALLY DEFERRED must be DEFERRABLE"),
+                                                        parser_errposition(pstate, con->location)));
+                               break;
 
-                               case CONSTR_ATTR_IMMEDIATE:
-                                       if (!SUPPORTS_ATTRS(lastprimarynode))
-                                               ereport(ERROR,
-                                                               (errcode(ERRCODE_SYNTAX_ERROR),
-                                                       errmsg("misplaced INITIALLY IMMEDIATE clause")));
-                                       if (saw_initially)
-                                               ereport(ERROR,
-                                                               (errcode(ERRCODE_SYNTAX_ERROR),
-                                                                errmsg("multiple INITIALLY IMMEDIATE/DEFERRED clauses not allowed")));
-                                       saw_initially = true;
-                                       if (IsA(lastprimarynode, FkConstraint))
-                                               ((FkConstraint *) lastprimarynode)->initdeferred = false;
-                                       else
-                                               ((Constraint *) lastprimarynode)->initdeferred = false;
-                                       break;
+                       case CONSTR_ATTR_IMMEDIATE:
+                               if (!SUPPORTS_ATTRS(lastprimarycon))
+                                       ereport(ERROR,
+                                                       (errcode(ERRCODE_SYNTAX_ERROR),
+                                                        errmsg("misplaced INITIALLY IMMEDIATE clause"),
+                                                        parser_errposition(pstate, con->location)));
+                               if (saw_initially)
+                                       ereport(ERROR,
+                                                       (errcode(ERRCODE_SYNTAX_ERROR),
+                                                        errmsg("multiple INITIALLY IMMEDIATE/DEFERRED clauses not allowed"),
+                                                        parser_errposition(pstate, con->location)));
+                               saw_initially = true;
+                               lastprimarycon->initdeferred = false;
+                               break;
 
-                               default:
-                                       /* Otherwise it's not an attribute */
-                                       lastprimarynode = node;
-                                       /* reset flags for new primary node */
-                                       saw_deferrability = false;
-                                       saw_initially = false;
-                                       break;
-                       }
+                       default:
+                               /* Otherwise it's not an attribute */
+                               lastprimarycon = con;
+                               /* reset flags for new primary node */
+                               saw_deferrability = false;
+                               saw_initially = false;
+                               break;
                }
        }
 }
index f255c44..b29f720 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/nodes/nodes.h,v 1.223 2009/06/11 14:49:11 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/nodes/nodes.h,v 1.224 2009/07/30 02:45:37 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -364,7 +364,6 @@ typedef enum NodeTag
        T_RangeTblEntry,
        T_SortGroupClause,
        T_WindowClause,
-       T_FkConstraint,
        T_PrivGrantee,
        T_FuncWithArgs,
        T_AccessPriv,
index ae2f087..d057345 100644 (file)
@@ -13,7 +13,7 @@
  * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/nodes/parsenodes.h,v 1.399 2009/07/29 20:56:21 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/nodes/parsenodes.h,v 1.400 2009/07/30 02:45:38 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -1317,10 +1317,10 @@ typedef struct VariableShowStmt
 /* ----------------------
  *             Create Table Statement
  *
- * NOTE: in the raw gram.y output, ColumnDef, Constraint, and FkConstraint
- * nodes are intermixed in tableElts, and constraints is NIL.  After parse
- * analysis, tableElts contains just ColumnDefs, and constraints contains
- * just Constraint nodes (in fact, only CONSTR_CHECK nodes, in the present
+ * NOTE: in the raw gram.y output, ColumnDef and Constraint nodes are
+ * intermixed in tableElts, and constraints is NIL.  After parse analysis,
+ * tableElts contains just ColumnDefs, and constraints contains just
+ * Constraint nodes (in fact, only CONSTR_CHECK nodes, in the present
  * implementation).
  * ----------------------
  */
@@ -1339,23 +1339,32 @@ typedef struct CreateStmt
 } CreateStmt;
 
 /* ----------
- * Definitions for plain (non-FOREIGN KEY) constraints in CreateStmt
+ * Definitions for constraints in CreateStmt
  *
- * XXX probably these ought to be unified with FkConstraints at some point?
- * To this end we include CONSTR_FOREIGN in the ConstrType enum, even though
- * the parser does not generate it.
+ * Note that column defaults are treated as a type of constraint,
+ * even though that's a bit odd semantically.
  *
- * For constraints that use expressions (CONSTR_DEFAULT, CONSTR_CHECK)
+ * For constraints that use expressions (CONSTR_CHECK, CONSTR_DEFAULT)
  * we may have the expression in either "raw" form (an untransformed
  * parse tree) or "cooked" form (the nodeToString representation of
  * an executable expression tree), depending on how this Constraint
  * node was created (by parsing, or by inheritance from an existing
  * relation).  We should never have both in the same node!
  *
+ * FKCONSTR_ACTION_xxx values are stored into pg_constraint.confupdtype
+ * and pg_constraint.confdeltype columns; FKCONSTR_MATCH_xxx values are
+ * stored into pg_constraint.confmatchtype.  Changing the code values may
+ * require an initdb!
+ *
+ * If skip_validation is true then we skip checking that the existing rows
+ * in the table satisfy the constraint, and just install the catalog entries
+ * for the constraint. This is currently used only during CREATE TABLE
+ * (when we know the table must be empty).
+ *
  * Constraint attributes (DEFERRABLE etc) are initially represented as
  * separate Constraint nodes for simplicity of parsing.  parse_utilcmd.c makes
- * a pass through the constraints list to attach the info to the appropriate
- * Constraint and FkConstraint nodes.
+ * a pass through the constraints list to insert the info into the appropriate
+ * Constraint node.
  * ----------
  */
 
@@ -1365,69 +1374,56 @@ typedef enum ConstrType                 /* types of constraints */
        CONSTR_NOTNULL,
        CONSTR_DEFAULT,
        CONSTR_CHECK,
-       CONSTR_FOREIGN,
        CONSTR_PRIMARY,
        CONSTR_UNIQUE,
+       CONSTR_FOREIGN,
        CONSTR_ATTR_DEFERRABLE,         /* attributes for previous constraint node */
        CONSTR_ATTR_NOT_DEFERRABLE,
        CONSTR_ATTR_DEFERRED,
        CONSTR_ATTR_IMMEDIATE
 } ConstrType;
 
-typedef struct Constraint
-{
-       NodeTag         type;
-       ConstrType      contype;
-       char       *name;                       /* name, or NULL if unnamed */
-       Node       *raw_expr;           /* expr, as untransformed parse tree */
-       char       *cooked_expr;        /* expr, as nodeToString representation */
-       List       *keys;                       /* String nodes naming referenced column(s) */
-       List       *options;            /* options from WITH clause */
-       char       *indexspace;         /* index tablespace for PKEY/UNIQUE
-                                                                * constraints; NULL for default */
-       bool            deferrable;             /* DEFERRABLE */
-       bool            initdeferred;   /* INITIALLY DEFERRED */
-} Constraint;
-
-/* ----------
- * Definitions for FOREIGN KEY constraints in CreateStmt
- *
- * Note: FKCONSTR_ACTION_xxx values are stored into pg_constraint.confupdtype
- * and pg_constraint.confdeltype columns; FKCONSTR_MATCH_xxx values are
- * stored into pg_constraint.confmatchtype.  Changing the code values may
- * require an initdb!
- *
- * If skip_validation is true then we skip checking that the existing rows
- * in the table satisfy the constraint, and just install the catalog entries
- * for the constraint. This is currently used only during CREATE TABLE
- * (when we know the table must be empty).
- * ----------
- */
+/* Foreign key action codes */
 #define FKCONSTR_ACTION_NOACTION       'a'
 #define FKCONSTR_ACTION_RESTRICT       'r'
 #define FKCONSTR_ACTION_CASCADE                'c'
 #define FKCONSTR_ACTION_SETNULL                'n'
 #define FKCONSTR_ACTION_SETDEFAULT     'd'
 
+/* Foreign key matchtype codes */
 #define FKCONSTR_MATCH_FULL                    'f'
 #define FKCONSTR_MATCH_PARTIAL         'p'
 #define FKCONSTR_MATCH_UNSPECIFIED     'u'
 
-typedef struct FkConstraint
+typedef struct Constraint
 {
        NodeTag         type;
-       char       *constr_name;        /* Constraint name, or NULL if unnamed */
+       ConstrType      contype;                /* see above */
+
+       /* Fields used for most/all constraint types: */
+       char       *conname;            /* Constraint name, or NULL if unnamed */
+       bool            deferrable;             /* DEFERRABLE? */
+       bool            initdeferred;   /* INITIALLY DEFERRED? */
+       int                     location;               /* token location, or -1 if unknown */
+
+       /* Fields used for constraints with expressions (CHECK and DEFAULT): */
+       Node       *raw_expr;           /* expr, as untransformed parse tree */
+       char       *cooked_expr;        /* expr, as nodeToString representation */
+
+       /* Fields used for index constraints (UNIQUE and PRIMARY KEY): */
+       List       *keys;                       /* String nodes naming referenced column(s) */
+       List       *options;            /* options from WITH clause */
+       char       *indexspace;         /* index tablespace; NULL for default */
+
+       /* Fields used for FOREIGN KEY constraints: */
        RangeVar   *pktable;            /* Primary key table */
        List       *fk_attrs;           /* Attributes of foreign key */
        List       *pk_attrs;           /* Corresponding attrs in PK table */
        char            fk_matchtype;   /* FULL, PARTIAL, UNSPECIFIED */
        char            fk_upd_action;  /* ON UPDATE action */
        char            fk_del_action;  /* ON DELETE action */
-       bool            deferrable;             /* DEFERRABLE */
-       bool            initdeferred;   /* INITIALLY DEFERRED */
        bool            skip_validation;        /* skip validation of existing rows? */
-} FkConstraint;
-
+} Constraint;
 
 /* ----------------------
  *             Create/Drop Table Space Statements