diff options
author | Tom Lane <tgl@sss.pgh.pa.us> | 2020-07-31 17:11:28 -0400 |
---|---|---|
committer | Tom Lane <tgl@sss.pgh.pa.us> | 2020-07-31 17:11:28 -0400 |
commit | 3d2376d55c6f2d364a6a1a95cc350c531f6d9423 (patch) | |
tree | 11fee97f3ce5a4d0ed613b7eed7fdb0e1e9e82e4 /src/backend/commands/typecmds.c | |
parent | 78e73e87548a1e0b71b6f2425f76ea6e9c85b2eb (diff) | |
download | postgresql-3d2376d55c6f2d364a6a1a95cc350c531f6d9423.tar.gz postgresql-3d2376d55c6f2d364a6a1a95cc350c531f6d9423.zip |
Fix oversight in ALTER TYPE: typmodin/typmodout must propagate to arrays.
If a base type supports typmods, its array type does too, with the
same interpretation. Hence changes in pg_type.typmodin/typmodout
must be propagated to the array type.
While here, improve AlterTypeRecurse to not recurse to domains if
there is nothing we'd need to change.
Oversight in fe30e7ebf. Back-patch to v13 where that came in.
Diffstat (limited to 'src/backend/commands/typecmds.c')
-rw-r--r-- | src/backend/commands/typecmds.c | 63 |
1 files changed, 52 insertions, 11 deletions
diff --git a/src/backend/commands/typecmds.c b/src/backend/commands/typecmds.c index 9e5938b10eb..2e107ace39b 100644 --- a/src/backend/commands/typecmds.c +++ b/src/backend/commands/typecmds.c @@ -127,7 +127,8 @@ static char *domainAddConstraint(Oid domainOid, Oid domainNamespace, const char *domainName, ObjectAddress *constrAddr); static Node *replace_domain_constraint_value(ParseState *pstate, ColumnRef *cref); -static void AlterTypeRecurse(Oid typeOid, HeapTuple tup, Relation catalog, +static void AlterTypeRecurse(Oid typeOid, bool isImplicitArray, + HeapTuple tup, Relation catalog, AlterTypeRecurseParams *atparams); @@ -3853,8 +3854,8 @@ AlterType(AlterTypeStmt *stmt) errmsg("%s is not a base type", format_type_be(typeOid)))); - /* OK, recursively update this type and any domains over it */ - AlterTypeRecurse(typeOid, tup, catalog, &atparams); + /* OK, recursively update this type and any arrays/domains over it */ + AlterTypeRecurse(typeOid, false, tup, catalog, &atparams); /* Clean up */ ReleaseSysCache(tup); @@ -3870,13 +3871,15 @@ AlterType(AlterTypeStmt *stmt) * AlterTypeRecurse: one recursion step for AlterType() * * Apply the changes specified by "atparams" to the type identified by - * "typeOid", whose existing pg_type tuple is "tup". Then search for any - * domains over this type, and recursively apply (most of) the same changes - * to those domains. + * "typeOid", whose existing pg_type tuple is "tup". If necessary, + * recursively update its array type as well. Then search for any domains + * over this type, and recursively apply (most of) the same changes to those + * domains. * * We need this because the system generally assumes that a domain inherits * many properties from its base type. See DefineDomain() above for details - * of what is inherited. + * of what is inherited. Arrays inherit a smaller number of properties, + * but not none. * * There's a race condition here, in that some other transaction could * concurrently add another domain atop this base type; we'd miss updating @@ -3888,7 +3891,8 @@ AlterType(AlterTypeStmt *stmt) * committed. */ static void -AlterTypeRecurse(Oid typeOid, HeapTuple tup, Relation catalog, +AlterTypeRecurse(Oid typeOid, bool isImplicitArray, + HeapTuple tup, Relation catalog, AlterTypeRecurseParams *atparams) { Datum values[Natts_pg_type]; @@ -3949,13 +3953,44 @@ AlterTypeRecurse(Oid typeOid, HeapTuple tup, Relation catalog, NULL, /* don't have defaultExpr handy */ NULL, /* don't have typacl handy */ 0, /* we rejected composite types above */ - false, /* and we rejected implicit arrays above */ - false, /* so it can't be a dependent type */ + isImplicitArray, /* it might be an array */ + isImplicitArray, /* dependent iff it's array */ true); InvokeObjectPostAlterHook(TypeRelationId, typeOid, 0); /* + * Arrays inherit their base type's typmodin and typmodout, but none of + * the other properties we're concerned with here. Recurse to the array + * type if needed. + */ + if (!isImplicitArray && + (atparams->updateTypmodin || atparams->updateTypmodout)) + { + Oid arrtypoid = ((Form_pg_type) GETSTRUCT(newtup))->typarray; + + if (OidIsValid(arrtypoid)) + { + HeapTuple arrtup; + AlterTypeRecurseParams arrparams; + + arrtup = SearchSysCache1(TYPEOID, ObjectIdGetDatum(arrtypoid)); + if (!HeapTupleIsValid(arrtup)) + elog(ERROR, "cache lookup failed for type %u", arrtypoid); + + memset(&arrparams, 0, sizeof(arrparams)); + arrparams.updateTypmodin = atparams->updateTypmodin; + arrparams.updateTypmodout = atparams->updateTypmodout; + arrparams.typmodinOid = atparams->typmodinOid; + arrparams.typmodoutOid = atparams->typmodoutOid; + + AlterTypeRecurse(arrtypoid, true, arrtup, catalog, &arrparams); + + ReleaseSysCache(arrtup); + } + } + + /* * Now we need to recurse to domains. However, some properties are not * inherited by domains, so clear the update flags for those. */ @@ -3963,6 +3998,12 @@ AlterTypeRecurse(Oid typeOid, HeapTuple tup, Relation catalog, atparams->updateTypmodin = false; /* domains don't have typmods */ atparams->updateTypmodout = false; + /* Skip the scan if nothing remains to be done */ + if (!(atparams->updateStorage || + atparams->updateSend || + atparams->updateAnalyze)) + return; + /* Search pg_type for possible domains over this type */ ScanKeyInit(&key[0], Anum_pg_type_typbasetype, @@ -3983,7 +4024,7 @@ AlterTypeRecurse(Oid typeOid, HeapTuple tup, Relation catalog, if (domainForm->typtype != TYPTYPE_DOMAIN) continue; - AlterTypeRecurse(domainForm->oid, domainTup, catalog, atparams); + AlterTypeRecurse(domainForm->oid, false, domainTup, catalog, atparams); } systable_endscan(scan); |