Commit 060baf27 authored by Tom Lane's avatar Tom Lane

Merge the Constraint and FkConstraint node types into a single type.

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.
parent 78aef14c
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * 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 * INTERFACE ROUTINES
...@@ -1870,11 +1870,11 @@ AddRelationNewConstraints(Relation rel, ...@@ -1870,11 +1870,11 @@ AddRelationNewConstraints(Relation rel,
/* /*
* Check name uniqueness, or generate a name if none was given. * Check name uniqueness, or generate a name if none was given.
*/ */
if (cdef->name != NULL) if (cdef->conname != NULL)
{ {
ListCell *cell2; ListCell *cell2;
ccname = cdef->name; ccname = cdef->conname;
/* Check against other new constraints */ /* Check against other new constraints */
/* Needed because we don't do CommandCounterIncrement in loop */ /* Needed because we don't do CommandCounterIncrement in loop */
foreach(cell2, checknames) foreach(cell2, checknames)
......
This diff is collapsed.
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * 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) ...@@ -607,12 +607,14 @@ ConvertTriggerToFK(CreateTrigStmt *stmt, Oid funcoid)
/* OK, we have a set, so make the FK constraint ALTER TABLE cmd */ /* OK, we have a set, so make the FK constraint ALTER TABLE cmd */
AlterTableStmt *atstmt = makeNode(AlterTableStmt); AlterTableStmt *atstmt = makeNode(AlterTableStmt);
AlterTableCmd *atcmd = makeNode(AlterTableCmd); AlterTableCmd *atcmd = makeNode(AlterTableCmd);
FkConstraint *fkcon = makeNode(FkConstraint); Constraint *fkcon = makeNode(Constraint);
ereport(NOTICE, ereport(NOTICE,
(errmsg("converting trigger group into constraint \"%s\" %s", (errmsg("converting trigger group into constraint \"%s\" %s",
constr_name, buf.data), constr_name, buf.data),
errdetail("%s", _(funcdescr[funcnum])))); errdetail("%s", _(funcdescr[funcnum]))));
fkcon->contype = CONSTR_FOREIGN;
fkcon->location = -1;
if (funcnum == 2) if (funcnum == 2)
{ {
/* This trigger is on the FK table */ /* This trigger is on the FK table */
...@@ -642,9 +644,9 @@ ConvertTriggerToFK(CreateTrigStmt *stmt, Oid funcoid) ...@@ -642,9 +644,9 @@ ConvertTriggerToFK(CreateTrigStmt *stmt, Oid funcoid)
atcmd->subtype = AT_AddConstraint; atcmd->subtype = AT_AddConstraint;
atcmd->def = (Node *) fkcon; atcmd->def = (Node *) fkcon;
if (strcmp(constr_name, "<unnamed>") == 0) if (strcmp(constr_name, "<unnamed>") == 0)
fkcon->constr_name = NULL; fkcon->conname = NULL;
else else
fkcon->constr_name = constr_name; fkcon->conname = constr_name;
fkcon->fk_attrs = fk_attrs; fkcon->fk_attrs = fk_attrs;
fkcon->pk_attrs = pk_attrs; fkcon->pk_attrs = pk_attrs;
fkcon->fk_matchtype = fk_matchtype; fkcon->fk_matchtype = fk_matchtype;
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * 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 * DESCRIPTION
* The "DefineFoo" routines take the parse tree and pick out the * The "DefineFoo" routines take the parse tree and pick out the
...@@ -867,22 +867,11 @@ DefineDomain(CreateDomainStmt *stmt) ...@@ -867,22 +867,11 @@ DefineDomain(CreateDomainStmt *stmt)
*/ */
foreach(listptr, schema) foreach(listptr, schema)
{ {
Node *newConstraint = lfirst(listptr); Constraint *constr = 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")));
/* otherwise it should be a plain Constraint */ if (!IsA(constr, Constraint))
if (!IsA(newConstraint, Constraint))
elog(ERROR, "unrecognized node type: %d", elog(ERROR, "unrecognized node type: %d",
(int) nodeTag(newConstraint)); (int) nodeTag(constr));
constr = (Constraint *) newConstraint;
switch (constr->contype) switch (constr->contype)
{ {
case CONSTR_DEFAULT: case CONSTR_DEFAULT:
...@@ -995,6 +984,12 @@ DefineDomain(CreateDomainStmt *stmt) ...@@ -995,6 +984,12 @@ DefineDomain(CreateDomainStmt *stmt)
errmsg("primary key constraints not possible for domains"))); errmsg("primary key constraints not possible for domains")));
break; 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_DEFERRABLE:
case CONSTR_ATTR_NOT_DEFERRABLE: case CONSTR_ATTR_NOT_DEFERRABLE:
case CONSTR_ATTR_DEFERRED: case CONSTR_ATTR_DEFERRED:
...@@ -1849,13 +1844,6 @@ AlterDomainAddConstraint(List *names, Node *newConstraint) ...@@ -1849,13 +1844,6 @@ AlterDomainAddConstraint(List *names, Node *newConstraint)
/* Check it's a domain and check user has permission for ALTER DOMAIN */ /* Check it's a domain and check user has permission for ALTER DOMAIN */
checkDomainOwner(tup, typename); 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)) if (!IsA(newConstraint, Constraint))
elog(ERROR, "unrecognized node type: %d", elog(ERROR, "unrecognized node type: %d",
(int) nodeTag(newConstraint)); (int) nodeTag(newConstraint));
...@@ -1880,6 +1868,12 @@ AlterDomainAddConstraint(List *names, Node *newConstraint) ...@@ -1880,6 +1868,12 @@ AlterDomainAddConstraint(List *names, Node *newConstraint)
errmsg("primary key constraints not possible for domains"))); errmsg("primary key constraints not possible for domains")));
break; 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_DEFERRABLE:
case CONSTR_ATTR_NOT_DEFERRABLE: case CONSTR_ATTR_NOT_DEFERRABLE:
case CONSTR_ATTR_DEFERRED: case CONSTR_ATTR_DEFERRED:
...@@ -2188,23 +2182,23 @@ domainAddConstraint(Oid domainOid, Oid domainNamespace, Oid baseTypeOid, ...@@ -2188,23 +2182,23 @@ domainAddConstraint(Oid domainOid, Oid domainNamespace, Oid baseTypeOid,
/* /*
* Assign or validate constraint name * Assign or validate constraint name
*/ */
if (constr->name) if (constr->conname)
{ {
if (ConstraintNameIsUsed(CONSTRAINT_DOMAIN, if (ConstraintNameIsUsed(CONSTRAINT_DOMAIN,
domainOid, domainOid,
domainNamespace, domainNamespace,
constr->name)) constr->conname))
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_DUPLICATE_OBJECT), (errcode(ERRCODE_DUPLICATE_OBJECT),
errmsg("constraint \"%s\" for domain \"%s\" already exists", errmsg("constraint \"%s\" for domain \"%s\" already exists",
constr->name, domainName))); constr->conname, domainName)));
} }
else else
constr->name = ChooseConstraintName(domainName, constr->conname = ChooseConstraintName(domainName,
NULL, NULL,
"check", "check",
domainNamespace, domainNamespace,
NIL); NIL);
/* /*
* Convert the A_EXPR in raw_expr into an EXPR * Convert the A_EXPR in raw_expr into an EXPR
...@@ -2284,7 +2278,7 @@ domainAddConstraint(Oid domainOid, Oid domainNamespace, Oid baseTypeOid, ...@@ -2284,7 +2278,7 @@ domainAddConstraint(Oid domainOid, Oid domainNamespace, Oid baseTypeOid,
/* /*
* Store the constraint in pg_constraint * Store the constraint in pg_constraint
*/ */
CreateConstraintEntry(constr->name, /* Constraint Name */ CreateConstraintEntry(constr->conname, /* Constraint Name */
domainNamespace, /* namespace */ domainNamespace, /* namespace */
CONSTRAINT_CHECK, /* Constraint Type */ CONSTRAINT_CHECK, /* Constraint Type */
false, /* Is Deferrable */ false, /* Is Deferrable */
......
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * 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) ...@@ -1738,25 +1738,6 @@ _copyRangeTblEntry(RangeTblEntry *from)
return newnode; 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 * static SortGroupClause *
_copySortGroupClause(SortGroupClause *from) _copySortGroupClause(SortGroupClause *from)
{ {
...@@ -2085,14 +2066,22 @@ _copyConstraint(Constraint *from) ...@@ -2085,14 +2066,22 @@ _copyConstraint(Constraint *from)
Constraint *newnode = makeNode(Constraint); Constraint *newnode = makeNode(Constraint);
COPY_SCALAR_FIELD(contype); 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_NODE_FIELD(raw_expr);
COPY_STRING_FIELD(cooked_expr); COPY_STRING_FIELD(cooked_expr);
COPY_NODE_FIELD(keys); COPY_NODE_FIELD(keys);
COPY_NODE_FIELD(options); COPY_NODE_FIELD(options);
COPY_STRING_FIELD(indexspace); COPY_STRING_FIELD(indexspace);
COPY_SCALAR_FIELD(deferrable); COPY_NODE_FIELD(pktable);
COPY_SCALAR_FIELD(initdeferred); 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; return newnode;
} }
...@@ -4082,9 +4071,6 @@ copyObject(void *from) ...@@ -4082,9 +4071,6 @@ copyObject(void *from)
case T_CommonTableExpr: case T_CommonTableExpr:
retval = _copyCommonTableExpr(from); retval = _copyCommonTableExpr(from);
break; break;
case T_FkConstraint:
retval = _copyFkConstraint(from);
break;
case T_PrivGrantee: case T_PrivGrantee:
retval = _copyPrivGrantee(from); retval = _copyPrivGrantee(from);
break; break;
......
...@@ -22,7 +22,7 @@ ...@@ -22,7 +22,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * 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 ...@@ -2064,14 +2064,22 @@ static bool
_equalConstraint(Constraint *a, Constraint *b) _equalConstraint(Constraint *a, Constraint *b)
{ {
COMPARE_SCALAR_FIELD(contype); 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_NODE_FIELD(raw_expr);
COMPARE_STRING_FIELD(cooked_expr); COMPARE_STRING_FIELD(cooked_expr);
COMPARE_NODE_FIELD(keys); COMPARE_NODE_FIELD(keys);
COMPARE_NODE_FIELD(options); COMPARE_NODE_FIELD(options);
COMPARE_STRING_FIELD(indexspace); COMPARE_STRING_FIELD(indexspace);
COMPARE_SCALAR_FIELD(deferrable); COMPARE_NODE_FIELD(pktable);
COMPARE_SCALAR_FIELD(initdeferred); 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; return true;
} }
...@@ -2189,23 +2197,6 @@ _equalCommonTableExpr(CommonTableExpr *a, CommonTableExpr *b) ...@@ -2189,23 +2197,6 @@ _equalCommonTableExpr(CommonTableExpr *a, CommonTableExpr *b)
return true; 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 static bool
_equalXmlSerialize(XmlSerialize *a, XmlSerialize *b) _equalXmlSerialize(XmlSerialize *a, XmlSerialize *b)
{ {
...@@ -2859,9 +2850,6 @@ equal(void *a, void *b) ...@@ -2859,9 +2850,6 @@ equal(void *a, void *b)
case T_CommonTableExpr: case T_CommonTableExpr:
retval = _equalCommonTableExpr(a, b); retval = _equalCommonTableExpr(a, b);
break; break;
case T_FkConstraint:
retval = _equalFkConstraint(a, b);
break;
case T_PrivGrantee: case T_PrivGrantee:
retval = _equalPrivGrantee(a, b); retval = _equalPrivGrantee(a, b);
break; break;
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * 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) ...@@ -903,6 +903,9 @@ exprLocation(Node *expr)
case T_TypeName: case T_TypeName:
loc = ((TypeName *) expr)->location; loc = ((TypeName *) expr)->location;
break; break;
case T_Constraint:
loc = ((Constraint *) expr)->location;
break;
case T_XmlSerialize: case T_XmlSerialize:
/* XMLSERIALIZE keyword should always be the first thing */ /* XMLSERIALIZE keyword should always be the first thing */
loc = ((XmlSerialize *) expr)->location; loc = ((XmlSerialize *) expr)->location;
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * 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 * NOTES
* Every node type that can appear in stored rules' parsetrees *must* * Every node type that can appear in stored rules' parsetrees *must*
...@@ -2277,18 +2277,39 @@ _outConstraint(StringInfo str, Constraint *node) ...@@ -2277,18 +2277,39 @@ _outConstraint(StringInfo str, Constraint *node)
{ {
WRITE_NODE_TYPE("CONSTRAINT"); 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 "); appendStringInfo(str, " :contype ");
switch (node->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: case CONSTR_PRIMARY:
appendStringInfo(str, "PRIMARY_KEY"); appendStringInfo(str, "PRIMARY_KEY");
WRITE_NODE_FIELD(keys); WRITE_NODE_FIELD(keys);
WRITE_NODE_FIELD(options); WRITE_NODE_FIELD(options);
WRITE_STRING_FIELD(indexspace); WRITE_STRING_FIELD(indexspace);
WRITE_BOOL_FIELD(deferrable);
WRITE_BOOL_FIELD(initdeferred);
break; break;
case CONSTR_UNIQUE: case CONSTR_UNIQUE:
...@@ -2296,47 +2317,40 @@ _outConstraint(StringInfo str, Constraint *node) ...@@ -2296,47 +2317,40 @@ _outConstraint(StringInfo str, Constraint *node)
WRITE_NODE_FIELD(keys); WRITE_NODE_FIELD(keys);
WRITE_NODE_FIELD(options); WRITE_NODE_FIELD(options);
WRITE_STRING_FIELD(indexspace); WRITE_STRING_FIELD(indexspace);
WRITE_BOOL_FIELD(deferrable);
WRITE_BOOL_FIELD(initdeferred);
break; break;
case CONSTR_CHECK: case CONSTR_FOREIGN:
appendStringInfo(str, "CHECK"); appendStringInfo(str, "FOREIGN_KEY");
WRITE_NODE_FIELD(raw_expr); WRITE_NODE_FIELD(pktable);
WRITE_STRING_FIELD(cooked_expr); 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; break;
case CONSTR_DEFAULT: case CONSTR_ATTR_DEFERRABLE:
appendStringInfo(str, "DEFAULT"); appendStringInfo(str, "ATTR_DEFERRABLE");
WRITE_NODE_FIELD(raw_expr);
WRITE_STRING_FIELD(cooked_expr);
break; break;
case CONSTR_NOTNULL: case CONSTR_ATTR_NOT_DEFERRABLE:
appendStringInfo(str, "NOT_NULL"); appendStringInfo(str, "ATTR_NOT_DEFERRABLE");
break; break;
default: case CONSTR_ATTR_DEFERRED:
appendStringInfo(str, "<unrecognized_constraint>"); appendStringInfo(str, "ATTR_DEFERRED");
break; break;
}
}
static void case CONSTR_ATTR_IMMEDIATE:
_outFkConstraint(StringInfo str, FkConstraint *node) appendStringInfo(str, "ATTR_IMMEDIATE");
{ break;
WRITE_NODE_TYPE("FKCONSTRAINT");
WRITE_STRING_FIELD(constr_name); default:
WRITE_NODE_FIELD(pktable); appendStringInfo(str, "<unrecognized_constraint %d>",
WRITE_NODE_FIELD(fk_attrs); (int) node->contype);
WRITE_NODE_FIELD(pk_attrs); break;
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);
} }
...@@ -2765,9 +2779,6 @@ _outNode(StringInfo str, void *obj) ...@@ -2765,9 +2779,6 @@ _outNode(StringInfo str, void *obj)
case T_Constraint: case T_Constraint:
_outConstraint(str, obj); _outConstraint(str, obj);
break; break;
case T_FkConstraint:
_outFkConstraint(str, obj);
break;
case T_FuncCall: case T_FuncCall:
_outFuncCall(str, obj); _outFuncCall(str, obj);
break; break;
......
...@@ -11,7 +11,7 @@ ...@@ -11,7 +11,7 @@
* *
* *
* IDENTIFICATION * 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 * HISTORY
* AUTHOR DATE MAJOR EVENT * AUTHOR DATE MAJOR EVENT
...@@ -2172,24 +2172,11 @@ ColQualList: ...@@ -2172,24 +2172,11 @@ ColQualList:
ColConstraint: ColConstraint:
CONSTRAINT name ColConstraintElem CONSTRAINT name ColConstraintElem
{ {
switch (nodeTag($3)) Constraint *n = (Constraint *) $3;
{ Assert(IsA(n, Constraint));
case T_Constraint: n->conname = $2;
{ n->location = @1;
Constraint *n = (Constraint *)$3; $$ = (Node *) n;
n->name = $2;
}
break;
case T_FkConstraint:
{
FkConstraint *n = (FkConstraint *)$3;
n->constr_name = $2;
}
break;
default:
break;
}
$$ = $3;
} }
| ColConstraintElem { $$ = $1; } | ColConstraintElem { $$ = $1; }
| ConstraintAttr { $$ = $1; } | ConstraintAttr { $$ = $1; }
...@@ -2215,94 +2202,66 @@ ColConstraintElem: ...@@ -2215,94 +2202,66 @@ ColConstraintElem:
{ {
Constraint *n = makeNode(Constraint); Constraint *n = makeNode(Constraint);
n->contype = CONSTR_NOTNULL; n->contype = CONSTR_NOTNULL;
n->name = NULL; n->location = @1;
n->raw_expr = NULL;
n->cooked_expr = NULL;
n->keys = NULL;
n->indexspace = NULL;
n->deferrable = FALSE;
n->initdeferred = FALSE;
$$ = (Node *)n; $$ = (Node *)n;
} }
| NULL_P | NULL_P
{ {
Constraint *n = makeNode(Constraint); Constraint *n = makeNode(Constraint);
n->contype = CONSTR_NULL; n->contype = CONSTR_NULL;
n->name = NULL; n->location = @1;
n->raw_expr = NULL;
n->cooked_expr = NULL;
n->keys = NULL;
n->indexspace = NULL;
n->deferrable = FALSE;
n->initdeferred = FALSE;
$$ = (Node *)n; $$ = (Node *)n;
} }
| UNIQUE opt_definition OptConsTableSpace | UNIQUE opt_definition OptConsTableSpace
{ {
Constraint *n = makeNode(Constraint); Constraint *n = makeNode(Constraint);
n->contype = CONSTR_UNIQUE; n->contype = CONSTR_UNIQUE;
n->name = NULL; n->location = @1;
n->raw_expr = NULL;
n->cooked_expr = NULL;
n->keys = NULL; n->keys = NULL;
n->options = $2; n->options = $2;
n->indexspace = $3; n->indexspace = $3;
n->deferrable = FALSE;
n->initdeferred = FALSE;
$$ = (Node *)n; $$ = (Node *)n;
} }
| PRIMARY KEY opt_definition OptConsTableSpace | PRIMARY KEY opt_definition OptConsTableSpace
{ {
Constraint *n = makeNode(Constraint); Constraint *n = makeNode(Constraint);
n->contype = CONSTR_PRIMARY; n->contype = CONSTR_PRIMARY;
n->name = NULL; n->location = @1;
n->raw_expr = NULL;
n->cooked_expr = NULL;
n->keys = NULL; n->keys = NULL;
n->options = $3; n->options = $3;
n->indexspace = $4; n->indexspace = $4;
n->deferrable = FALSE;
n->initdeferred = FALSE;
$$ = (Node *)n; $$ = (Node *)n;
} }
| CHECK '(' a_expr ')' | CHECK '(' a_expr ')'
{ {
Constraint *n = makeNode(Constraint); Constraint *n = makeNode(Constraint);
n->contype = CONSTR_CHECK; n->contype = CONSTR_CHECK;
n->name = NULL; n->location = @1;
n->raw_expr = $3; n->raw_expr = $3;
n->cooked_expr = NULL; n->cooked_expr = NULL;
n->keys = NULL;
n->indexspace = NULL;
n->deferrable = FALSE;
n->initdeferred = FALSE;
$$ = (Node *)n; $$ = (Node *)n;
} }
| DEFAULT b_expr | DEFAULT b_expr
{ {
Constraint *n = makeNode(Constraint); Constraint *n = makeNode(Constraint);
n->contype = CONSTR_DEFAULT; n->contype = CONSTR_DEFAULT;
n->name = NULL; n->location = @1;
n->raw_expr = $2; n->raw_expr = $2;
n->cooked_expr = NULL; n->cooked_expr = NULL;
n->keys = NULL;
n->indexspace = NULL;
n->deferrable = FALSE;
n->initdeferred = FALSE;
$$ = (Node *)n; $$ = (Node *)n;
} }
| REFERENCES qualified_name opt_column_list key_match key_actions | REFERENCES qualified_name opt_column_list key_match key_actions
{ {
FkConstraint *n = makeNode(FkConstraint); Constraint *n = makeNode(Constraint);
n->constr_name = NULL; n->contype = CONSTR_FOREIGN;
n->location = @1;
n->pktable = $2; n->pktable = $2;
n->fk_attrs = NIL; n->fk_attrs = NIL;
n->pk_attrs = $3; n->pk_attrs = $3;
n->fk_matchtype = $4; n->fk_matchtype = $4;
n->fk_upd_action = (char) ($5 >> 8); n->fk_upd_action = (char) ($5 >> 8);
n->fk_del_action = (char) ($5 & 0xFF); n->fk_del_action = (char) ($5 & 0xFF);
n->deferrable = FALSE; n->skip_validation = FALSE;
n->initdeferred = FALSE;
$$ = (Node *)n; $$ = (Node *)n;
} }
; ;
...@@ -2324,24 +2283,28 @@ ConstraintAttr: ...@@ -2324,24 +2283,28 @@ ConstraintAttr:
{ {
Constraint *n = makeNode(Constraint); Constraint *n = makeNode(Constraint);
n->contype = CONSTR_ATTR_DEFERRABLE; n->contype = CONSTR_ATTR_DEFERRABLE;
n->location = @1;
$$ = (Node *)n; $$ = (Node *)n;
} }
| NOT DEFERRABLE | NOT DEFERRABLE
{ {
Constraint *n = makeNode(Constraint); Constraint *n = makeNode(Constraint);
n->contype = CONSTR_ATTR_NOT_DEFERRABLE; n->contype = CONSTR_ATTR_NOT_DEFERRABLE;
n->location = @1;
$$ = (Node *)n; $$ = (Node *)n;
} }
| INITIALLY DEFERRED | INITIALLY DEFERRED
{ {
Constraint *n = makeNode(Constraint); Constraint *n = makeNode(Constraint);
n->contype = CONSTR_ATTR_DEFERRED; n->contype = CONSTR_ATTR_DEFERRED;
n->location = @1;
$$ = (Node *)n; $$ = (Node *)n;
} }
| INITIALLY IMMEDIATE | INITIALLY IMMEDIATE
{ {
Constraint *n = makeNode(Constraint); Constraint *n = makeNode(Constraint);
n->contype = CONSTR_ATTR_IMMEDIATE; n->contype = CONSTR_ATTR_IMMEDIATE;
n->location = @1;
$$ = (Node *)n; $$ = (Node *)n;
} }
; ;
...@@ -2387,24 +2350,11 @@ TableLikeOption: ...@@ -2387,24 +2350,11 @@ TableLikeOption:
TableConstraint: TableConstraint:
CONSTRAINT name ConstraintElem CONSTRAINT name ConstraintElem
{ {
switch (nodeTag($3)) Constraint *n = (Constraint *) $3;
{ Assert(IsA(n, Constraint));
case T_Constraint: n->conname = $2;
{ n->location = @1;
Constraint *n = (Constraint *)$3; $$ = (Node *) n;
n->name = $2;
}
break;
case T_FkConstraint:
{
FkConstraint *n = (FkConstraint *)$3;
n->constr_name = $2;
}
break;
default:
break;
}
$$ = $3;
} }
| ConstraintElem { $$ = $1; } | ConstraintElem { $$ = $1; }
; ;
...@@ -2414,17 +2364,14 @@ ConstraintElem: ...@@ -2414,17 +2364,14 @@ ConstraintElem:
{ {
Constraint *n = makeNode(Constraint); Constraint *n = makeNode(Constraint);
n->contype = CONSTR_CHECK; n->contype = CONSTR_CHECK;
n->name = NULL; n->location = @1;
n->raw_expr = $3; n->raw_expr = $3;
n->cooked_expr = NULL; n->cooked_expr = NULL;
n->indexspace = NULL;
if ($5 != 0) if ($5 != 0)
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED), (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("CHECK constraints cannot be deferred"), errmsg("CHECK constraints cannot be deferred"),
parser_errposition(@5))); parser_errposition(@5)));
n->deferrable = FALSE;
n->initdeferred = FALSE;
$$ = (Node *)n; $$ = (Node *)n;
} }
| UNIQUE '(' columnList ')' opt_definition OptConsTableSpace | UNIQUE '(' columnList ')' opt_definition OptConsTableSpace
...@@ -2432,9 +2379,7 @@ ConstraintElem: ...@@ -2432,9 +2379,7 @@ ConstraintElem:
{ {
Constraint *n = makeNode(Constraint); Constraint *n = makeNode(Constraint);
n->contype = CONSTR_UNIQUE; n->contype = CONSTR_UNIQUE;
n->name = NULL; n->location = @1;
n->raw_expr = NULL;
n->cooked_expr = NULL;
n->keys = $3; n->keys = $3;
n->options = $5; n->options = $5;
n->indexspace = $6; n->indexspace = $6;
...@@ -2447,9 +2392,7 @@ ConstraintElem: ...@@ -2447,9 +2392,7 @@ ConstraintElem:
{ {
Constraint *n = makeNode(Constraint); Constraint *n = makeNode(Constraint);
n->contype = CONSTR_PRIMARY; n->contype = CONSTR_PRIMARY;
n->name = NULL; n->location = @1;
n->raw_expr = NULL;
n->cooked_expr = NULL;
n->keys = $4; n->keys = $4;
n->options = $6; n->options = $6;
n->indexspace = $7; n->indexspace = $7;
...@@ -2460,14 +2403,16 @@ ConstraintElem: ...@@ -2460,14 +2403,16 @@ ConstraintElem:
| FOREIGN KEY '(' columnList ')' REFERENCES qualified_name | FOREIGN KEY '(' columnList ')' REFERENCES qualified_name
opt_column_list key_match key_actions ConstraintAttributeSpec opt_column_list key_match key_actions ConstraintAttributeSpec
{ {
FkConstraint *n = makeNode(FkConstraint); Constraint *n = makeNode(Constraint);
n->constr_name = NULL; n->contype = CONSTR_FOREIGN;
n->location = @1;
n->pktable = $7; n->pktable = $7;
n->fk_attrs = $4; n->fk_attrs = $4;
n->pk_attrs = $8; n->pk_attrs = $8;
n->fk_matchtype = $9; n->fk_matchtype = $9;
n->fk_upd_action = (char) ($10 >> 8); n->fk_upd_action = (char) ($10 >> 8);
n->fk_del_action = (char) ($10 & 0xFF); n->fk_del_action = (char) ($10 & 0xFF);
n->skip_validation = FALSE;
n->deferrable = ($11 & 1) != 0; n->deferrable = ($11 & 1) != 0;
n->initdeferred = ($11 & 2) != 0; n->initdeferred = ($11 & 2) != 0;
$$ = (Node *)n; $$ = (Node *)n;
......
This diff is collapsed.
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $PostgreSQL: pgsql/src/include/nodes/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 ...@@ -364,7 +364,6 @@ typedef enum NodeTag
T_RangeTblEntry, T_RangeTblEntry,
T_SortGroupClause, T_SortGroupClause,
T_WindowClause, T_WindowClause,
T_FkConstraint,
T_PrivGrantee, T_PrivGrantee,
T_FuncWithArgs, T_FuncWithArgs,
T_AccessPriv, T_AccessPriv,
......
...@@ -13,7 +13,7 @@ ...@@ -13,7 +13,7 @@
* Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $PostgreSQL: pgsql/src/include/nodes/parsenodes.h,v 1.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 ...@@ -1317,10 +1317,10 @@ typedef struct VariableShowStmt
/* ---------------------- /* ----------------------
* Create Table Statement * Create Table Statement
* *
* NOTE: in the raw gram.y output, ColumnDef, Constraint, and FkConstraint * NOTE: in the raw gram.y output, ColumnDef and Constraint nodes are
* nodes are intermixed in tableElts, and constraints is NIL. After parse * intermixed in tableElts, and constraints is NIL. After parse analysis,
* analysis, tableElts contains just ColumnDefs, and constraints contains * tableElts contains just ColumnDefs, and constraints contains just
* just Constraint nodes (in fact, only CONSTR_CHECK nodes, in the present * Constraint nodes (in fact, only CONSTR_CHECK nodes, in the present
* implementation). * implementation).
* ---------------------- * ----------------------
*/ */
...@@ -1339,23 +1339,32 @@ typedef struct CreateStmt ...@@ -1339,23 +1339,32 @@ typedef struct CreateStmt
} 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? * Note that column defaults are treated as a type of constraint,
* To this end we include CONSTR_FOREIGN in the ConstrType enum, even though * even though that's a bit odd semantically.
* the parser does not generate it.
* *
* 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 * we may have the expression in either "raw" form (an untransformed
* parse tree) or "cooked" form (the nodeToString representation of * parse tree) or "cooked" form (the nodeToString representation of
* an executable expression tree), depending on how this Constraint * an executable expression tree), depending on how this Constraint
* node was created (by parsing, or by inheritance from an existing * node was created (by parsing, or by inheritance from an existing
* relation). We should never have both in the same node! * 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 * Constraint attributes (DEFERRABLE etc) are initially represented as
* separate Constraint nodes for simplicity of parsing. parse_utilcmd.c makes * separate Constraint nodes for simplicity of parsing. parse_utilcmd.c makes
* a pass through the constraints list to attach the info to the appropriate * a pass through the constraints list to insert the info into the appropriate
* Constraint and FkConstraint nodes. * Constraint node.
* ---------- * ----------
*/ */
...@@ -1365,69 +1374,56 @@ typedef enum ConstrType /* types of constraints */ ...@@ -1365,69 +1374,56 @@ typedef enum ConstrType /* types of constraints */
CONSTR_NOTNULL, CONSTR_NOTNULL,
CONSTR_DEFAULT, CONSTR_DEFAULT,
CONSTR_CHECK, CONSTR_CHECK,
CONSTR_FOREIGN,
CONSTR_PRIMARY, CONSTR_PRIMARY,
CONSTR_UNIQUE, CONSTR_UNIQUE,
CONSTR_FOREIGN,
CONSTR_ATTR_DEFERRABLE, /* attributes for previous constraint node */ CONSTR_ATTR_DEFERRABLE, /* attributes for previous constraint node */
CONSTR_ATTR_NOT_DEFERRABLE, CONSTR_ATTR_NOT_DEFERRABLE,
CONSTR_ATTR_DEFERRED, CONSTR_ATTR_DEFERRED,
CONSTR_ATTR_IMMEDIATE CONSTR_ATTR_IMMEDIATE
} ConstrType; } ConstrType;
typedef struct Constraint /* Foreign key action codes */
{
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).
* ----------
*/
#define FKCONSTR_ACTION_NOACTION 'a' #define FKCONSTR_ACTION_NOACTION 'a'
#define FKCONSTR_ACTION_RESTRICT 'r' #define FKCONSTR_ACTION_RESTRICT 'r'
#define FKCONSTR_ACTION_CASCADE 'c' #define FKCONSTR_ACTION_CASCADE 'c'
#define FKCONSTR_ACTION_SETNULL 'n' #define FKCONSTR_ACTION_SETNULL 'n'
#define FKCONSTR_ACTION_SETDEFAULT 'd' #define FKCONSTR_ACTION_SETDEFAULT 'd'
/* Foreign key matchtype codes */
#define FKCONSTR_MATCH_FULL 'f' #define FKCONSTR_MATCH_FULL 'f'
#define FKCONSTR_MATCH_PARTIAL 'p' #define FKCONSTR_MATCH_PARTIAL 'p'
#define FKCONSTR_MATCH_UNSPECIFIED 'u' #define FKCONSTR_MATCH_UNSPECIFIED 'u'
typedef struct FkConstraint typedef struct Constraint
{ {
NodeTag type; 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 */ RangeVar *pktable; /* Primary key table */
List *fk_attrs; /* Attributes of foreign key */ List *fk_attrs; /* Attributes of foreign key */
List *pk_attrs; /* Corresponding attrs in PK table */ List *pk_attrs; /* Corresponding attrs in PK table */
char fk_matchtype; /* FULL, PARTIAL, UNSPECIFIED */ char fk_matchtype; /* FULL, PARTIAL, UNSPECIFIED */
char fk_upd_action; /* ON UPDATE action */ char fk_upd_action; /* ON UPDATE action */
char fk_del_action; /* ON DELETE action */ char fk_del_action; /* ON DELETE action */
bool deferrable; /* DEFERRABLE */
bool initdeferred; /* INITIALLY DEFERRED */
bool skip_validation; /* skip validation of existing rows? */ bool skip_validation; /* skip validation of existing rows? */
} FkConstraint; } Constraint;
/* ---------------------- /* ----------------------
* Create/Drop Table Space Statements * Create/Drop Table Space Statements
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment