diff options
Diffstat (limited to 'src/backend/parser/parse_utilcmd.c')
-rw-r--r-- | src/backend/parser/parse_utilcmd.c | 297 |
1 files changed, 132 insertions, 165 deletions
diff --git a/src/backend/parser/parse_utilcmd.c b/src/backend/parser/parse_utilcmd.c index 94c8c5977bc..7a11eb96edd 100644 --- a/src/backend/parser/parse_utilcmd.c +++ b/src/backend/parser/parse_utilcmd.c @@ -19,7 +19,7 @@ * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/backend/parser/parse_utilcmd.c,v 2.24 2009/07/29 20:56:19 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/parser/parse_utilcmd.c,v 2.25 2009/07/30 02:45:37 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -112,7 +112,7 @@ static void transformFKConstraints(ParseState *pstate, CreateStmtContext *cxt, bool skipValidation, bool isAddConstraint); -static void transformConstraintAttrs(List *constraintList); +static void transformConstraintAttrs(ParseState *pstate, List *constraintList); static void transformColumnType(ParseState *pstate, ColumnDef *column); static void setSchemaName(char *context_schema, char **stmt_schema_name); @@ -199,11 +199,6 @@ transformCreateStmt(CreateStmt *stmt, const char *queryString) (Constraint *) element); break; - case T_FkConstraint: - /* No pre-transformation needed */ - cxt.fkconstraints = lappend(cxt.fkconstraints, element); - break; - case T_InhRelation: transformInhRelation(pstate, &cxt, (InhRelation *) element); @@ -295,7 +290,8 @@ transformColumnDefinition(ParseState *pstate, CreateStmtContext *cxt, if (is_serial && column->typeName->arrayBounds != NIL) ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), - errmsg("array of serial is not implemented"))); + errmsg("array of serial is not implemented"), + parser_errposition(pstate, column->typeName->location))); } /* Do necessary work on the column type declaration */ @@ -397,18 +393,19 @@ transformColumnDefinition(ParseState *pstate, CreateStmtContext *cxt, constraint = makeNode(Constraint); constraint->contype = CONSTR_DEFAULT; + constraint->location = -1; constraint->raw_expr = (Node *) funccallnode; constraint->cooked_expr = NULL; - constraint->keys = NIL; column->constraints = lappend(column->constraints, constraint); constraint = makeNode(Constraint); constraint->contype = CONSTR_NOTNULL; + constraint->location = -1; column->constraints = lappend(column->constraints, constraint); } /* Process column constraints, if any... */ - transformConstraintAttrs(column->constraints); + transformConstraintAttrs(pstate, column->constraints); saw_nullable = false; saw_default = false; @@ -416,21 +413,6 @@ transformColumnDefinition(ParseState *pstate, CreateStmtContext *cxt, foreach(clist, column->constraints) { constraint = lfirst(clist); - - /* - * If this column constraint is a FOREIGN KEY constraint, then we fill - * in the current attribute's name and throw it into the list of FK - * constraints to be processed later. - */ - if (IsA(constraint, FkConstraint)) - { - FkConstraint *fkconstraint = (FkConstraint *) constraint; - - fkconstraint->fk_attrs = list_make1(makeString(column->colname)); - cxt->fkconstraints = lappend(cxt->fkconstraints, fkconstraint); - continue; - } - Assert(IsA(constraint, Constraint)); switch (constraint->contype) @@ -440,7 +422,9 @@ transformColumnDefinition(ParseState *pstate, CreateStmtContext *cxt, ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("conflicting NULL/NOT NULL declarations for column \"%s\" of table \"%s\"", - column->colname, cxt->relation->relname))); + column->colname, cxt->relation->relname), + parser_errposition(pstate, + constraint->location))); column->is_not_null = FALSE; saw_nullable = true; break; @@ -450,7 +434,9 @@ transformColumnDefinition(ParseState *pstate, CreateStmtContext *cxt, ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("conflicting NULL/NOT NULL declarations for column \"%s\" of table \"%s\"", - column->colname, cxt->relation->relname))); + column->colname, cxt->relation->relname), + parser_errposition(pstate, + constraint->location))); column->is_not_null = TRUE; saw_nullable = true; break; @@ -460,7 +446,9 @@ transformColumnDefinition(ParseState *pstate, CreateStmtContext *cxt, ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("multiple default values specified for column \"%s\" of table \"%s\"", - column->colname, cxt->relation->relname))); + column->colname, cxt->relation->relname), + parser_errposition(pstate, + constraint->location))); column->raw_default = constraint->raw_expr; Assert(constraint->cooked_expr == NULL); saw_default = true; @@ -477,6 +465,15 @@ transformColumnDefinition(ParseState *pstate, CreateStmtContext *cxt, cxt->ckconstraints = lappend(cxt->ckconstraints, constraint); break; + case CONSTR_FOREIGN: + /* + * Fill in the current attribute's name and throw it into the + * list of FK constraints to be processed later. + */ + constraint->fk_attrs = list_make1(makeString(column->colname)); + cxt->fkconstraints = lappend(cxt->fkconstraints, constraint); + break; + case CONSTR_ATTR_DEFERRABLE: case CONSTR_ATTR_NOT_DEFERRABLE: case CONSTR_ATTR_DEFERRED: @@ -511,6 +508,10 @@ transformTableConstraint(ParseState *pstate, CreateStmtContext *cxt, cxt->ckconstraints = lappend(cxt->ckconstraints, constraint); break; + case CONSTR_FOREIGN: + cxt->fkconstraints = lappend(cxt->fkconstraints, constraint); + break; + case CONSTR_NULL: case CONSTR_NOTNULL: case CONSTR_DEFAULT: @@ -688,11 +689,11 @@ transformInhRelation(ParseState *pstate, CreateStmtContext *cxt, change_varattnos_of_a_node(ccbin_node, attmap); n->contype = CONSTR_CHECK; - n->name = pstrdup(ccname); + n->location = -1; + n->conname = pstrdup(ccname); n->raw_expr = NULL; n->cooked_expr = nodeToString(ccbin_node); - n->indexspace = NULL; - cxt->ckconstraints = lappend(cxt->ckconstraints, (Node *) n); + cxt->ckconstraints = lappend(cxt->ckconstraints, n); } } @@ -1121,8 +1122,8 @@ transformIndexConstraint(Constraint *constraint, CreateStmtContext *cxt) index->deferrable = constraint->deferrable; index->initdeferred = constraint->initdeferred; - if (constraint->name != NULL) - index->idxname = pstrdup(constraint->name); + if (constraint->conname != NULL) + index->idxname = pstrdup(constraint->conname); else index->idxname = NULL; /* DefineIndex will choose name */ @@ -1281,9 +1282,9 @@ transformFKConstraints(ParseState *pstate, CreateStmtContext *cxt, { foreach(fkclist, cxt->fkconstraints) { - FkConstraint *fkconstraint = (FkConstraint *) lfirst(fkclist); + Constraint *constraint = (Constraint *) lfirst(fkclist); - fkconstraint->skip_validation = true; + constraint->skip_validation = true; } } @@ -1308,12 +1309,12 @@ transformFKConstraints(ParseState *pstate, CreateStmtContext *cxt, foreach(fkclist, cxt->fkconstraints) { - FkConstraint *fkconstraint = (FkConstraint *) lfirst(fkclist); + Constraint *constraint = (Constraint *) lfirst(fkclist); AlterTableCmd *altercmd = makeNode(AlterTableCmd); altercmd->subtype = AT_ProcessedConstraint; altercmd->name = NULL; - altercmd->def = (Node *) fkconstraint; + altercmd->def = (Node *) constraint; alterstmt->cmds = lappend(alterstmt->cmds, altercmd); } @@ -1784,12 +1785,11 @@ transformAlterTableStmt(AlterTableStmt *stmt, const char *queryString) * The original AddConstraint cmd node doesn't go to newcmds */ if (IsA(cmd->def, Constraint)) + { transformTableConstraint(pstate, &cxt, (Constraint *) cmd->def); - else if (IsA(cmd->def, FkConstraint)) - { - cxt.fkconstraints = lappend(cxt.fkconstraints, cmd->def); - skipValidation = false; + if (((Constraint *) cmd->def)->contype == CONSTR_FOREIGN) + skipValidation = false; } else elog(ERROR, "unrecognized node type: %d", @@ -1886,145 +1886,112 @@ transformAlterTableStmt(AlterTableStmt *stmt, const char *queryString) * for other constraint types. */ static void -transformConstraintAttrs(List *constraintList) +transformConstraintAttrs(ParseState *pstate, List *constraintList) { - Node *lastprimarynode = NULL; + Constraint *lastprimarycon = NULL; bool saw_deferrability = false; bool saw_initially = false; ListCell *clist; -#define SUPPORTS_ATTRS(node) \ - ((node) != NULL && \ - (IsA((node), FkConstraint) || \ - (IsA((node), Constraint) && \ - (((Constraint *) (node))->contype == CONSTR_PRIMARY || \ - ((Constraint *) (node))->contype == CONSTR_UNIQUE)))) +#define SUPPORTS_ATTRS(node) \ + ((node) != NULL && \ + ((node)->contype == CONSTR_PRIMARY || \ + (node)->contype == CONSTR_UNIQUE || \ + (node)->contype == CONSTR_FOREIGN)) foreach(clist, constraintList) { - Node *node = lfirst(clist); + Constraint *con = (Constraint *) lfirst(clist); - if (!IsA(node, Constraint)) + if (!IsA(con, Constraint)) + elog(ERROR, "unrecognized node type: %d", + (int) nodeTag(con)); + switch (con->contype) { - lastprimarynode = node; - /* reset flags for new primary node */ - saw_deferrability = false; - saw_initially = false; - } - else - { - Constraint *con = (Constraint *) node; - - switch (con->contype) - { - case CONSTR_ATTR_DEFERRABLE: - if (!SUPPORTS_ATTRS(lastprimarynode)) - ereport(ERROR, - (errcode(ERRCODE_SYNTAX_ERROR), - errmsg("misplaced DEFERRABLE clause"))); - if (saw_deferrability) - ereport(ERROR, - (errcode(ERRCODE_SYNTAX_ERROR), - errmsg("multiple DEFERRABLE/NOT DEFERRABLE clauses not allowed"))); - saw_deferrability = true; - if (IsA(lastprimarynode, FkConstraint)) - ((FkConstraint *) lastprimarynode)->deferrable = true; - else - ((Constraint *) lastprimarynode)->deferrable = true; - break; + case CONSTR_ATTR_DEFERRABLE: + if (!SUPPORTS_ATTRS(lastprimarycon)) + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("misplaced DEFERRABLE clause"), + parser_errposition(pstate, con->location))); + if (saw_deferrability) + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("multiple DEFERRABLE/NOT DEFERRABLE clauses not allowed"), + parser_errposition(pstate, con->location))); + saw_deferrability = true; + lastprimarycon->deferrable = true; + break; - case CONSTR_ATTR_NOT_DEFERRABLE: - if (!SUPPORTS_ATTRS(lastprimarynode)) - ereport(ERROR, - (errcode(ERRCODE_SYNTAX_ERROR), - errmsg("misplaced NOT DEFERRABLE clause"))); - if (saw_deferrability) - ereport(ERROR, - (errcode(ERRCODE_SYNTAX_ERROR), - errmsg("multiple DEFERRABLE/NOT DEFERRABLE clauses not allowed"))); - saw_deferrability = true; - if (IsA(lastprimarynode, FkConstraint)) - { - ((FkConstraint *) lastprimarynode)->deferrable = false; - if (saw_initially && - ((FkConstraint *) lastprimarynode)->initdeferred) - ereport(ERROR, - (errcode(ERRCODE_SYNTAX_ERROR), - errmsg("constraint declared INITIALLY DEFERRED must be DEFERRABLE"))); - } - else - { - ((Constraint *) lastprimarynode)->deferrable = false; - if (saw_initially && - ((Constraint *) lastprimarynode)->initdeferred) - ereport(ERROR, - (errcode(ERRCODE_SYNTAX_ERROR), - errmsg("constraint declared INITIALLY DEFERRED must be DEFERRABLE"))); - } - break; + case CONSTR_ATTR_NOT_DEFERRABLE: + if (!SUPPORTS_ATTRS(lastprimarycon)) + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("misplaced NOT DEFERRABLE clause"), + parser_errposition(pstate, con->location))); + if (saw_deferrability) + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("multiple DEFERRABLE/NOT DEFERRABLE clauses not allowed"), + parser_errposition(pstate, con->location))); + saw_deferrability = true; + lastprimarycon->deferrable = false; + if (saw_initially && + lastprimarycon->initdeferred) + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("constraint declared INITIALLY DEFERRED must be DEFERRABLE"), + parser_errposition(pstate, con->location))); + break; - case CONSTR_ATTR_DEFERRED: - if (!SUPPORTS_ATTRS(lastprimarynode)) - ereport(ERROR, - (errcode(ERRCODE_SYNTAX_ERROR), - errmsg("misplaced INITIALLY DEFERRED clause"))); - if (saw_initially) - ereport(ERROR, - (errcode(ERRCODE_SYNTAX_ERROR), - errmsg("multiple INITIALLY IMMEDIATE/DEFERRED clauses not allowed"))); - saw_initially = true; + case CONSTR_ATTR_DEFERRED: + if (!SUPPORTS_ATTRS(lastprimarycon)) + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("misplaced INITIALLY DEFERRED clause"), + parser_errposition(pstate, con->location))); + if (saw_initially) + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("multiple INITIALLY IMMEDIATE/DEFERRED clauses not allowed"), + parser_errposition(pstate, con->location))); + saw_initially = true; + lastprimarycon->initdeferred = true; - /* - * If only INITIALLY DEFERRED appears, assume DEFERRABLE - */ - if (IsA(lastprimarynode, FkConstraint)) - { - ((FkConstraint *) lastprimarynode)->initdeferred = true; - - if (!saw_deferrability) - ((FkConstraint *) lastprimarynode)->deferrable = true; - else if (!((FkConstraint *) lastprimarynode)->deferrable) - ereport(ERROR, - (errcode(ERRCODE_SYNTAX_ERROR), - errmsg("constraint declared INITIALLY DEFERRED must be DEFERRABLE"))); - } - else - { - ((Constraint *) lastprimarynode)->initdeferred = true; - - if (!saw_deferrability) - ((Constraint *) lastprimarynode)->deferrable = true; - else if (!((Constraint *) lastprimarynode)->deferrable) - ereport(ERROR, - (errcode(ERRCODE_SYNTAX_ERROR), - errmsg("constraint declared INITIALLY DEFERRED must be DEFERRABLE"))); - } - break; + /* + * If only INITIALLY DEFERRED appears, assume DEFERRABLE + */ + if (!saw_deferrability) + lastprimarycon->deferrable = true; + else if (!lastprimarycon->deferrable) + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("constraint declared INITIALLY DEFERRED must be DEFERRABLE"), + parser_errposition(pstate, con->location))); + break; - case CONSTR_ATTR_IMMEDIATE: - if (!SUPPORTS_ATTRS(lastprimarynode)) - ereport(ERROR, - (errcode(ERRCODE_SYNTAX_ERROR), - errmsg("misplaced INITIALLY IMMEDIATE clause"))); - if (saw_initially) - ereport(ERROR, - (errcode(ERRCODE_SYNTAX_ERROR), - errmsg("multiple INITIALLY IMMEDIATE/DEFERRED clauses not allowed"))); - saw_initially = true; - if (IsA(lastprimarynode, FkConstraint)) - ((FkConstraint *) lastprimarynode)->initdeferred = false; - else - ((Constraint *) lastprimarynode)->initdeferred = false; - break; + case CONSTR_ATTR_IMMEDIATE: + if (!SUPPORTS_ATTRS(lastprimarycon)) + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("misplaced INITIALLY IMMEDIATE clause"), + parser_errposition(pstate, con->location))); + if (saw_initially) + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("multiple INITIALLY IMMEDIATE/DEFERRED clauses not allowed"), + parser_errposition(pstate, con->location))); + saw_initially = true; + lastprimarycon->initdeferred = false; + break; - default: - /* Otherwise it's not an attribute */ - lastprimarynode = node; - /* reset flags for new primary node */ - saw_deferrability = false; - saw_initially = false; - break; - } + default: + /* Otherwise it's not an attribute */ + lastprimarycon = con; + /* reset flags for new primary node */ + saw_deferrability = false; + saw_initially = false; + break; } } } |