diff options
Diffstat (limited to 'src/backend/catalog/heap.c')
| -rw-r--r-- | src/backend/catalog/heap.c | 147 |
1 files changed, 70 insertions, 77 deletions
diff --git a/src/backend/catalog/heap.c b/src/backend/catalog/heap.c index 718c3b9091..a4cc33d4c9 100644 --- a/src/backend/catalog/heap.c +++ b/src/backend/catalog/heap.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/catalog/heap.c,v 1.269 2004/06/06 20:30:07 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/catalog/heap.c,v 1.270 2004/06/10 17:55:53 tgl Exp $ * * * INTERFACE ROUTINES @@ -1488,7 +1488,7 @@ AddRelationRawConstraints(Relation rel, ParseState *pstate; RangeTblEntry *rte; int numchecks; - int constr_name_ctr = 0; + List *checknames; ListCell *cell; Node *expr; CookedConstraint *cooked; @@ -1547,6 +1547,7 @@ AddRelationRawConstraints(Relation rel, * Process constraint expressions. */ numchecks = numoldchecks; + checknames = NIL; foreach(cell, rawConstraints) { Constraint *cdef = (Constraint *) lfirst(cell); @@ -1556,81 +1557,6 @@ AddRelationRawConstraints(Relation rel, continue; Assert(cdef->cooked_expr == NULL); - /* Check name uniqueness, or generate a new name */ - if (cdef->name != NULL) - { - ListCell *cell2; - - ccname = cdef->name; - /* Check against pre-existing constraints */ - if (ConstraintNameIsUsed(CONSTRAINT_RELATION, - RelationGetRelid(rel), - RelationGetNamespace(rel), - ccname)) - ereport(ERROR, - (errcode(ERRCODE_DUPLICATE_OBJECT), - errmsg("constraint \"%s\" for relation \"%s\" already exists", - ccname, RelationGetRelationName(rel)))); - /* Check against other new constraints */ - /* Needed because we don't do CommandCounterIncrement in loop */ - foreach(cell2, rawConstraints) - { - Constraint *cdef2 = (Constraint *) lfirst(cell2); - - if (cdef2 == cdef || - cdef2->contype != CONSTR_CHECK || - cdef2->raw_expr == NULL || - cdef2->name == NULL) - continue; - if (strcmp(cdef2->name, ccname) == 0) - ereport(ERROR, - (errcode(ERRCODE_DUPLICATE_OBJECT), - errmsg("check constraint \"%s\" already exists", - ccname))); - } - } - else - { - bool success; - - do - { - ListCell *cell2; - - /* - * Generate a name that does not conflict with - * pre-existing constraints, nor with any auto-generated - * names so far. - */ - ccname = GenerateConstraintName(CONSTRAINT_RELATION, - RelationGetRelid(rel), - RelationGetNamespace(rel), - &constr_name_ctr); - - /* - * Check against other new constraints, in case the user - * has specified a name that looks like an auto-generated - * name. - */ - success = true; - foreach(cell2, rawConstraints) - { - Constraint *cdef2 = (Constraint *) lfirst(cell2); - - if (cdef2 == cdef || - cdef2->contype != CONSTR_CHECK || - cdef2->raw_expr == NULL || - cdef2->name == NULL) - continue; - if (strcmp(cdef2->name, ccname) == 0) - { - success = false; - break; - } - } - } while (!success); - } - /* * Transform raw parsetree to executable expression. */ @@ -1663,6 +1589,73 @@ AddRelationRawConstraints(Relation rel, errmsg("cannot use aggregate function in check constraint"))); /* + * Check name uniqueness, or generate a name if none was given. + */ + if (cdef->name != NULL) + { + ListCell *cell2; + + ccname = cdef->name; + /* Check against pre-existing constraints */ + if (ConstraintNameIsUsed(CONSTRAINT_RELATION, + RelationGetRelid(rel), + RelationGetNamespace(rel), + ccname)) + ereport(ERROR, + (errcode(ERRCODE_DUPLICATE_OBJECT), + errmsg("constraint \"%s\" for relation \"%s\" already exists", + ccname, RelationGetRelationName(rel)))); + /* Check against other new constraints */ + /* Needed because we don't do CommandCounterIncrement in loop */ + foreach(cell2, checknames) + { + if (strcmp((char *) lfirst(cell2), ccname) == 0) + ereport(ERROR, + (errcode(ERRCODE_DUPLICATE_OBJECT), + errmsg("check constraint \"%s\" already exists", + ccname))); + } + } + else + { + /* + * When generating a name, we want to create "tab_col_check" + * for a column constraint and "tab_check" for a table + * constraint. We no longer have any info about the + * syntactic positioning of the constraint phrase, so we + * approximate this by seeing whether the expression references + * more than one column. (If the user played by the rules, + * the result is the same...) + * + * Note: pull_var_clause() doesn't descend into sublinks, + * but we eliminated those above; and anyway this only needs + * to be an approximate answer. + */ + List *vars; + char *colname; + + vars = pull_var_clause(expr, false); + + /* eliminate duplicates */ + vars = list_union(NIL, vars); + + if (list_length(vars) == 1) + colname = get_attname(RelationGetRelid(rel), + ((Var *) linitial(vars))->varattno); + else + colname = NULL; + + ccname = ChooseConstraintName(RelationGetRelationName(rel), + colname, + "check", + RelationGetNamespace(rel), + checknames); + } + + /* save name for future checks */ + checknames = lappend(checknames, ccname); + + /* * OK, store it. */ StoreRelCheck(rel, ccname, nodeToString(expr)); |
