*
*
* 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
/*
* 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)
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
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;
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,
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,
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,
if (con->contype == CONSTR_FOREIGN)
{
- FkConstraint *fkconstraint = (FkConstraint *) con->qual;
+ Constraint *fkconstraint = (Constraint *) con->qual;
Relation refrel;
if (rel == NULL)
*/
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);
}
}
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();
*/
static void
ATAddForeignKeyConstraint(AlteredTableInfo *tab, Relation rel,
- FkConstraint *fkconstraint)
+ Constraint *fkconstraint)
{
Relation pkrel;
int16 pkattnum[INDEX_MAX_KEYS];
(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)),
/*
* Record the FK constraint in pg_constraint.
*/
- constrOid = CreateConstraintEntry(fkconstraint->constr_name,
+ constrOid = CreateConstraintEntry(fkconstraint->conname,
RelationGetNamespace(rel),
CONSTRAINT_FOREIGN,
fkconstraint->deferrable,
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;
* Caller must have opened and locked both relations.
*/
static void
-validateForeignKeyConstraint(FkConstraint *fkconstraint,
+validateForeignKeyConstraint(Constraint *fkconstraint,
Relation rel,
Relation pkrel,
Oid pkindOid,
*/
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);
}
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;
* 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;
* 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;
* 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;
* 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 $
*
*-------------------------------------------------------------------------
*/
/* 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 */
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;
*
*
* 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
*/
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:
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:
/* 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));
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:
/*
* 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
/*
* 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 */
* 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 $
*
*-------------------------------------------------------------------------
*/
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)
{
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;
}
case T_CommonTableExpr:
retval = _copyCommonTableExpr(from);
break;
- case T_FkConstraint:
- retval = _copyFkConstraint(from);
- break;
case T_PrivGrantee:
retval = _copyPrivGrantee(from);
break;
* 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 $
*
*-------------------------------------------------------------------------
*/
_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;
}
}
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);
case T_CommonTableExpr:
retval = _equalCommonTableExpr(a, b);
break;
- case T_FkConstraint:
- retval = _equalFkConstraint(a, b);
- break;
case T_PrivGrantee:
retval = _equalPrivGrantee(a, b);
break;
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
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;
*
*
* 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*
{
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:
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;
+ }
}
case T_Constraint:
_outConstraint(str, obj);
break;
- case T_FkConstraint:
- _outFkConstraint(str, obj);
- break;
case T_FuncCall:
_outFuncCall(str, obj);
break;
*
*
* 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
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; }
{
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;
}
;
{
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;
}
;
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; }
;
{
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
{
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;
{
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;
| 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;
* 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 $
*
*-------------------------------------------------------------------------
*/
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);
(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);
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 */
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;
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)
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;
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;
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;
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:
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:
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);
}
}
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 */
{
foreach(fkclist, cxt->fkconstraints)
{
- FkConstraint *fkconstraint = (FkConstraint *) lfirst(fkclist);
+ Constraint *constraint = (Constraint *) lfirst(fkclist);
- fkconstraint->skip_validation = true;
+ constraint->skip_validation = true;
}
}
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);
}
* 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",
* 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;
}
}
}
* 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 $
*
*-------------------------------------------------------------------------
*/
T_RangeTblEntry,
T_SortGroupClause,
T_WindowClause,
- T_FkConstraint,
T_PrivGrantee,
T_FuncWithArgs,
T_AccessPriv,
* 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 $
*
*-------------------------------------------------------------------------
*/
/* ----------------------
* 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).
* ----------------------
*/
} 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.
* ----------
*/
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