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.
This commit is contained in:
parent
78aef14c59
commit
060baf2784
|
@ -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)
|
||||
|
|
|
@ -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:
|
||||
case CONSTR_CHECK:
|
||||
ATAddCheckConstraint(wqueue, tab, rel,
|
||||
newConstraint, recurse, false);
|
||||
break;
|
||||
|
||||
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)
|
||||
{
|
||||
Constraint *constr = (Constraint *) newConstraint;
|
||||
|
||||
/*
|
||||
* 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;
|
||||
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))));
|
||||
}
|
||||
case T_FkConstraint:
|
||||
{
|
||||
FkConstraint *fkconstraint = (FkConstraint *) newConstraint;
|
||||
else
|
||||
newConstraint->conname =
|
||||
ChooseConstraintName(RelationGetRelationName(rel),
|
||||
strVal(linitial(newConstraint->fk_attrs)),
|
||||
"fkey",
|
||||
RelationGetNamespace(rel),
|
||||
NIL);
|
||||
|
||||
/*
|
||||
* 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, newConstraint);
|
||||
break;
|
||||
|
||||
ATAddForeignKeyConstraint(tab, rel, fkconstraint);
|
||||
|
||||
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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
Constraint *constr = lfirst(listptr);
|
||||
|
||||
/* 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(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 */
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
@ -2189,23 +2197,6 @@ _equalCommonTableExpr(CommonTableExpr *a, CommonTableExpr *b)
|
|||
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)
|
||||
{
|
||||
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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,33 +2277,20 @@ _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_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);
|
||||
case CONSTR_NULL:
|
||||
appendStringInfo(str, "NULL");
|
||||
break;
|
||||
|
||||
case CONSTR_UNIQUE:
|
||||
appendStringInfo(str, "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_NOTNULL:
|
||||
appendStringInfo(str, "NOT_NULL");
|
||||
break;
|
||||
|
||||
case CONSTR_DEFAULT:
|
||||
|
@ -2312,33 +2299,60 @@ _outConstraint(StringInfo str, Constraint *node)
|
|||
WRITE_STRING_FIELD(cooked_expr);
|
||||
break;
|
||||
|
||||
case CONSTR_NOTNULL:
|
||||
appendStringInfo(str, "NOT_NULL");
|
||||
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);
|
||||
break;
|
||||
|
||||
case CONSTR_UNIQUE:
|
||||
appendStringInfo(str, "UNIQUE");
|
||||
WRITE_NODE_FIELD(keys);
|
||||
WRITE_NODE_FIELD(options);
|
||||
WRITE_STRING_FIELD(indexspace);
|
||||
break;
|
||||
|
||||
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_ATTR_DEFERRABLE:
|
||||
appendStringInfo(str, "ATTR_DEFERRABLE");
|
||||
break;
|
||||
|
||||
case CONSTR_ATTR_NOT_DEFERRABLE:
|
||||
appendStringInfo(str, "ATTR_NOT_DEFERRABLE");
|
||||
break;
|
||||
|
||||
case CONSTR_ATTR_DEFERRED:
|
||||
appendStringInfo(str, "ATTR_DEFERRED");
|
||||
break;
|
||||
|
||||
case CONSTR_ATTR_IMMEDIATE:
|
||||
appendStringInfo(str, "ATTR_IMMEDIATE");
|
||||
break;
|
||||
|
||||
default:
|
||||
appendStringInfo(str, "<unrecognized_constraint>");
|
||||
appendStringInfo(str, "<unrecognized_constraint %d>",
|
||||
(int) node->contype);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
_outFkConstraint(StringInfo str, FkConstraint *node)
|
||||
{
|
||||
WRITE_NODE_TYPE("FKCONSTRAINT");
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* _outNode -
|
||||
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
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;
|
||||
|
||||
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_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_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_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;
|
||||
|
||||
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;
|
||||
/*
|
||||
* 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;
|
||||
|
||||
/*
|
||||
* If only INITIALLY DEFERRED appears, assume DEFERRABLE
|
||||
*/
|
||||
if (IsA(lastprimarynode, FkConstraint))
|
||||
{
|
||||
((FkConstraint *) lastprimarynode)->initdeferred = true;
|
||||
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;
|
||||
|
||||
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;
|
||||
|
||||
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;
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue