diff options
Diffstat (limited to 'src/backend')
-rw-r--r-- | src/backend/commands/tablecmds.c | 37 | ||||
-rw-r--r-- | src/backend/utils/adt/ruleutils.c | 71 |
2 files changed, 71 insertions, 37 deletions
diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c index 75bdf7ba0c4..a7497e5c2a5 100644 --- a/src/backend/commands/tablecmds.c +++ b/src/backend/commands/tablecmds.c @@ -3390,7 +3390,7 @@ ATExecCmd(List **wqueue, AlteredTableInfo *tab, Relation rel, case AT_ReAddConstraint: /* Re-add pre-existing check * constraint */ ATExecAddConstraint(wqueue, tab, rel, (Constraint *) cmd->def, - false, true, lockmode); + true, true, lockmode); break; case AT_AddIndexConstraint: /* ADD CONSTRAINT USING INDEX */ ATExecAddIndexConstraint(tab, rel, (IndexStmt *) cmd->def, lockmode); @@ -5764,13 +5764,6 @@ ATExecAddConstraint(List **wqueue, AlteredTableInfo *tab, Relation rel, * AddRelationNewConstraints would normally assign different names to the * child constraints. To fix that, we must capture the name assigned at * the parent table and pass that down. - * - * When re-adding a previously existing constraint (during ALTER COLUMN TYPE), - * we don't need to recurse here, because recursion will be carried out at a - * higher level; the constraint name issue doesn't apply because the names - * have already been assigned and are just being re-used. We need a separate - * "is_readd" flag for that; just setting recurse=false would result in an - * error if there are child tables. */ static void ATAddCheckConstraint(List **wqueue, AlteredTableInfo *tab, Relation rel, @@ -5798,7 +5791,7 @@ ATAddCheckConstraint(List **wqueue, AlteredTableInfo *tab, Relation rel, */ newcons = AddRelationNewConstraints(rel, NIL, list_make1(copyObject(constr)), - recursing, /* allow_merge */ + recursing | is_readd, /* allow_merge */ !recursing, /* is_local */ is_readd); /* is_internal */ @@ -5842,10 +5835,8 @@ ATAddCheckConstraint(List **wqueue, AlteredTableInfo *tab, Relation rel, /* * If adding a NO INHERIT constraint, no need to find our children. - * Likewise, in a re-add operation, we don't need to recurse (that will be - * handled at higher levels). */ - if (constr->is_no_inherit || is_readd) + if (constr->is_no_inherit) return; /* @@ -8204,10 +8195,30 @@ ATPostAlterTypeCleanup(List **wqueue, AlteredTableInfo *tab, LOCKMODE lockmode) def_item, tab->changedConstraintDefs) { Oid oldId = lfirst_oid(oid_item); + HeapTuple tup; + Form_pg_constraint con; Oid relid; Oid confrelid; + bool conislocal; + + tup = SearchSysCache1(CONSTROID, ObjectIdGetDatum(oldId)); + if (!HeapTupleIsValid(tup)) /* should not happen */ + elog(ERROR, "cache lookup failed for constraint %u", oldId); + con = (Form_pg_constraint) GETSTRUCT(tup); + relid = con->conrelid; + confrelid = con->confrelid; + conislocal = con->conislocal; + ReleaseSysCache(tup); + + /* + * If the constraint is inherited (only), we don't want to inject a + * new definition here; it'll get recreated when ATAddCheckConstraint + * recurses from adding the parent table's constraint. But we had to + * carry the info this far so that we can drop the constraint below. + */ + if (!conislocal) + continue; - get_constraint_relation_oids(oldId, &relid, &confrelid); ATPostAlterTypeParse(oldId, relid, confrelid, (char *) lfirst(def_item), wqueue, lockmode, tab->rewrite); diff --git a/src/backend/utils/adt/ruleutils.c b/src/backend/utils/adt/ruleutils.c index f8bfb46eade..48c0bbc3994 100644 --- a/src/backend/utils/adt/ruleutils.c +++ b/src/backend/utils/adt/ruleutils.c @@ -420,6 +420,7 @@ static Node *processIndirection(Node *node, deparse_context *context, static void printSubscripts(ArrayRef *aref, deparse_context *context); static char *get_relation_name(Oid relid); static char *generate_relation_name(Oid relid, List *namespaces); +static char *generate_qualified_relation_name(Oid relid); static char *generate_function_name(Oid funcid, int nargs, List *argnames, Oid *argtypes, bool has_variadic, bool *use_variadic_p); @@ -1298,7 +1299,9 @@ pg_get_constraintdef_ext(PG_FUNCTION_ARGS) prettyFlags))); } -/* Internal version that returns a palloc'd C string; no pretty-printing */ +/* + * Internal version that returns a full ALTER TABLE ... ADD CONSTRAINT command + */ char * pg_get_constraintdef_string(Oid constraintId) { @@ -1347,10 +1350,16 @@ pg_get_constraintdef_worker(Oid constraintId, bool fullCommand, initStringInfo(&buf); - if (fullCommand && OidIsValid(conForm->conrelid)) + if (fullCommand) { - appendStringInfo(&buf, "ALTER TABLE ONLY %s ADD CONSTRAINT %s ", - generate_relation_name(conForm->conrelid, NIL), + /* + * Currently, callers want ALTER TABLE (without ONLY) for CHECK + * constraints, and other types of constraints don't inherit anyway so + * it doesn't matter whether we say ONLY or not. Someday we might + * need to let callers specify whether to put ONLY in the command. + */ + appendStringInfo(&buf, "ALTER TABLE %s ADD CONSTRAINT %s ", + generate_qualified_relation_name(conForm->conrelid), quote_identifier(NameStr(conForm->conname))); } @@ -1874,28 +1883,9 @@ pg_get_serial_sequence(PG_FUNCTION_ARGS) if (OidIsValid(sequenceId)) { - HeapTuple classtup; - Form_pg_class classtuple; - char *nspname; char *result; - /* Get the sequence's pg_class entry */ - classtup = SearchSysCache1(RELOID, ObjectIdGetDatum(sequenceId)); - if (!HeapTupleIsValid(classtup)) - elog(ERROR, "cache lookup failed for relation %u", sequenceId); - classtuple = (Form_pg_class) GETSTRUCT(classtup); - - /* Get the namespace */ - nspname = get_namespace_name(classtuple->relnamespace); - if (!nspname) - elog(ERROR, "cache lookup failed for namespace %u", - classtuple->relnamespace); - - /* And construct the result string */ - result = quote_qualified_identifier(nspname, - NameStr(classtuple->relname)); - - ReleaseSysCache(classtup); + result = generate_qualified_relation_name(sequenceId); PG_RETURN_TEXT_P(string_to_text(result)); } @@ -9139,6 +9129,39 @@ generate_relation_name(Oid relid, List *namespaces) } /* + * generate_qualified_relation_name + * Compute the name to display for a relation specified by OID + * + * As above, but unconditionally schema-qualify the name. + */ +static char * +generate_qualified_relation_name(Oid relid) +{ + HeapTuple tp; + Form_pg_class reltup; + char *relname; + char *nspname; + char *result; + + tp = SearchSysCache1(RELOID, ObjectIdGetDatum(relid)); + if (!HeapTupleIsValid(tp)) + elog(ERROR, "cache lookup failed for relation %u", relid); + reltup = (Form_pg_class) GETSTRUCT(tp); + relname = NameStr(reltup->relname); + + nspname = get_namespace_name(reltup->relnamespace); + if (!nspname) + elog(ERROR, "cache lookup failed for namespace %u", + reltup->relnamespace); + + result = quote_qualified_identifier(nspname, relname); + + ReleaseSysCache(tp); + + return result; +} + +/* * generate_function_name * Compute the name to display for a function specified by OID, * given that it is being called with the specified actual arg names and |