Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 5c439f1

Browse files
committed
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 fe30e7e. Back-patch to v13 where that came in.
1 parent 11dce63 commit 5c439f1

File tree

3 files changed

+76
-11
lines changed

3 files changed

+76
-11
lines changed

src/backend/commands/typecmds.c

Lines changed: 52 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,8 @@ static char *domainAddConstraint(Oid domainOid, Oid domainNamespace,
127127
const char *domainName, ObjectAddress *constrAddr);
128128
static Node *replace_domain_constraint_value(ParseState *pstate,
129129
ColumnRef *cref);
130-
static void AlterTypeRecurse(Oid typeOid, HeapTuple tup, Relation catalog,
130+
static void AlterTypeRecurse(Oid typeOid, bool isImplicitArray,
131+
HeapTuple tup, Relation catalog,
131132
AlterTypeRecurseParams *atparams);
132133

133134

@@ -3853,8 +3854,8 @@ AlterType(AlterTypeStmt *stmt)
38533854
errmsg("%s is not a base type",
38543855
format_type_be(typeOid))));
38553856

3856-
/* OK, recursively update this type and any domains over it */
3857-
AlterTypeRecurse(typeOid, tup, catalog, &atparams);
3857+
/* OK, recursively update this type and any arrays/domains over it */
3858+
AlterTypeRecurse(typeOid, false, tup, catalog, &atparams);
38583859

38593860
/* Clean up */
38603861
ReleaseSysCache(tup);
@@ -3870,13 +3871,15 @@ AlterType(AlterTypeStmt *stmt)
38703871
* AlterTypeRecurse: one recursion step for AlterType()
38713872
*
38723873
* Apply the changes specified by "atparams" to the type identified by
3873-
* "typeOid", whose existing pg_type tuple is "tup". Then search for any
3874-
* domains over this type, and recursively apply (most of) the same changes
3875-
* to those domains.
3874+
* "typeOid", whose existing pg_type tuple is "tup". If necessary,
3875+
* recursively update its array type as well. Then search for any domains
3876+
* over this type, and recursively apply (most of) the same changes to those
3877+
* domains.
38763878
*
38773879
* We need this because the system generally assumes that a domain inherits
38783880
* many properties from its base type. See DefineDomain() above for details
3879-
* of what is inherited.
3881+
* of what is inherited. Arrays inherit a smaller number of properties,
3882+
* but not none.
38803883
*
38813884
* There's a race condition here, in that some other transaction could
38823885
* concurrently add another domain atop this base type; we'd miss updating
@@ -3888,7 +3891,8 @@ AlterType(AlterTypeStmt *stmt)
38883891
* committed.
38893892
*/
38903893
static void
3891-
AlterTypeRecurse(Oid typeOid, HeapTuple tup, Relation catalog,
3894+
AlterTypeRecurse(Oid typeOid, bool isImplicitArray,
3895+
HeapTuple tup, Relation catalog,
38923896
AlterTypeRecurseParams *atparams)
38933897
{
38943898
Datum values[Natts_pg_type];
@@ -3949,12 +3953,43 @@ AlterTypeRecurse(Oid typeOid, HeapTuple tup, Relation catalog,
39493953
NULL, /* don't have defaultExpr handy */
39503954
NULL, /* don't have typacl handy */
39513955
0, /* we rejected composite types above */
3952-
false, /* and we rejected implicit arrays above */
3953-
false, /* so it can't be a dependent type */
3956+
isImplicitArray, /* it might be an array */
3957+
isImplicitArray, /* dependent iff it's array */
39543958
true);
39553959

39563960
InvokeObjectPostAlterHook(TypeRelationId, typeOid, 0);
39573961

3962+
/*
3963+
* Arrays inherit their base type's typmodin and typmodout, but none of
3964+
* the other properties we're concerned with here. Recurse to the array
3965+
* type if needed.
3966+
*/
3967+
if (!isImplicitArray &&
3968+
(atparams->updateTypmodin || atparams->updateTypmodout))
3969+
{
3970+
Oid arrtypoid = ((Form_pg_type) GETSTRUCT(newtup))->typarray;
3971+
3972+
if (OidIsValid(arrtypoid))
3973+
{
3974+
HeapTuple arrtup;
3975+
AlterTypeRecurseParams arrparams;
3976+
3977+
arrtup = SearchSysCache1(TYPEOID, ObjectIdGetDatum(arrtypoid));
3978+
if (!HeapTupleIsValid(arrtup))
3979+
elog(ERROR, "cache lookup failed for type %u", arrtypoid);
3980+
3981+
memset(&arrparams, 0, sizeof(arrparams));
3982+
arrparams.updateTypmodin = atparams->updateTypmodin;
3983+
arrparams.updateTypmodout = atparams->updateTypmodout;
3984+
arrparams.typmodinOid = atparams->typmodinOid;
3985+
arrparams.typmodoutOid = atparams->typmodoutOid;
3986+
3987+
AlterTypeRecurse(arrtypoid, true, arrtup, catalog, &arrparams);
3988+
3989+
ReleaseSysCache(arrtup);
3990+
}
3991+
}
3992+
39583993
/*
39593994
* Now we need to recurse to domains. However, some properties are not
39603995
* inherited by domains, so clear the update flags for those.
@@ -3963,6 +3998,12 @@ AlterTypeRecurse(Oid typeOid, HeapTuple tup, Relation catalog,
39633998
atparams->updateTypmodin = false; /* domains don't have typmods */
39643999
atparams->updateTypmodout = false;
39654000

4001+
/* Skip the scan if nothing remains to be done */
4002+
if (!(atparams->updateStorage ||
4003+
atparams->updateSend ||
4004+
atparams->updateAnalyze))
4005+
return;
4006+
39664007
/* Search pg_type for possible domains over this type */
39674008
ScanKeyInit(&key[0],
39684009
Anum_pg_type_typbasetype,
@@ -3983,7 +4024,7 @@ AlterTypeRecurse(Oid typeOid, HeapTuple tup, Relation catalog,
39834024
if (domainForm->typtype != TYPTYPE_DOMAIN)
39844025
continue;
39854026

3986-
AlterTypeRecurse(domainForm->oid, domainTup, catalog, atparams);
4027+
AlterTypeRecurse(domainForm->oid, false, domainTup, catalog, atparams);
39874028
}
39884029

39894030
systable_endscan(scan);

src/test/regress/expected/create_type.out

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -270,6 +270,14 @@ FROM pg_type WHERE typname = 'myvarchar';
270270
myvarcharin | myvarcharout | myvarcharrecv | myvarcharsend | varchartypmodin | varchartypmodout | array_typanalyze | x
271271
(1 row)
272272

273+
SELECT typinput, typoutput, typreceive, typsend, typmodin, typmodout,
274+
typanalyze, typstorage
275+
FROM pg_type WHERE typname = '_myvarchar';
276+
typinput | typoutput | typreceive | typsend | typmodin | typmodout | typanalyze | typstorage
277+
----------+-----------+------------+------------+-----------------+------------------+------------------+------------
278+
array_in | array_out | array_recv | array_send | varchartypmodin | varchartypmodout | array_typanalyze | x
279+
(1 row)
280+
273281
SELECT typinput, typoutput, typreceive, typsend, typmodin, typmodout,
274282
typanalyze, typstorage
275283
FROM pg_type WHERE typname = 'myvarchardom';
@@ -278,6 +286,14 @@ FROM pg_type WHERE typname = 'myvarchardom';
278286
domain_in | myvarcharout | domain_recv | myvarcharsend | - | - | array_typanalyze | x
279287
(1 row)
280288

289+
SELECT typinput, typoutput, typreceive, typsend, typmodin, typmodout,
290+
typanalyze, typstorage
291+
FROM pg_type WHERE typname = '_myvarchardom';
292+
typinput | typoutput | typreceive | typsend | typmodin | typmodout | typanalyze | typstorage
293+
----------+-----------+------------+------------+----------+-----------+------------------+------------
294+
array_in | array_out | array_recv | array_send | - | - | array_typanalyze | x
295+
(1 row)
296+
281297
-- ensure dependencies are straight
282298
DROP FUNCTION myvarcharsend(myvarchar); -- fail
283299
ERROR: cannot drop function myvarcharsend(myvarchar) because other objects depend on it

src/test/regress/sql/create_type.sql

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -214,10 +214,18 @@ SELECT typinput, typoutput, typreceive, typsend, typmodin, typmodout,
214214
typanalyze, typstorage
215215
FROM pg_type WHERE typname = 'myvarchar';
216216

217+
SELECT typinput, typoutput, typreceive, typsend, typmodin, typmodout,
218+
typanalyze, typstorage
219+
FROM pg_type WHERE typname = '_myvarchar';
220+
217221
SELECT typinput, typoutput, typreceive, typsend, typmodin, typmodout,
218222
typanalyze, typstorage
219223
FROM pg_type WHERE typname = 'myvarchardom';
220224

225+
SELECT typinput, typoutput, typreceive, typsend, typmodin, typmodout,
226+
typanalyze, typstorage
227+
FROM pg_type WHERE typname = '_myvarchardom';
228+
221229
-- ensure dependencies are straight
222230
DROP FUNCTION myvarcharsend(myvarchar); -- fail
223231
DROP TYPE myvarchar; -- fail

0 commit comments

Comments
 (0)