mirror of
https://github.com/postgres/postgres.git
synced 2025-05-29 16:21:20 +03:00
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.
This commit is contained in:
parent
11dce63d6c
commit
5c439f189b
@ -127,7 +127,8 @@ static char *domainAddConstraint(Oid domainOid, Oid domainNamespace,
|
|||||||
const char *domainName, ObjectAddress *constrAddr);
|
const char *domainName, ObjectAddress *constrAddr);
|
||||||
static Node *replace_domain_constraint_value(ParseState *pstate,
|
static Node *replace_domain_constraint_value(ParseState *pstate,
|
||||||
ColumnRef *cref);
|
ColumnRef *cref);
|
||||||
static void AlterTypeRecurse(Oid typeOid, HeapTuple tup, Relation catalog,
|
static void AlterTypeRecurse(Oid typeOid, bool isImplicitArray,
|
||||||
|
HeapTuple tup, Relation catalog,
|
||||||
AlterTypeRecurseParams *atparams);
|
AlterTypeRecurseParams *atparams);
|
||||||
|
|
||||||
|
|
||||||
@ -3853,8 +3854,8 @@ AlterType(AlterTypeStmt *stmt)
|
|||||||
errmsg("%s is not a base type",
|
errmsg("%s is not a base type",
|
||||||
format_type_be(typeOid))));
|
format_type_be(typeOid))));
|
||||||
|
|
||||||
/* OK, recursively update this type and any domains over it */
|
/* OK, recursively update this type and any arrays/domains over it */
|
||||||
AlterTypeRecurse(typeOid, tup, catalog, &atparams);
|
AlterTypeRecurse(typeOid, false, tup, catalog, &atparams);
|
||||||
|
|
||||||
/* Clean up */
|
/* Clean up */
|
||||||
ReleaseSysCache(tup);
|
ReleaseSysCache(tup);
|
||||||
@ -3870,13 +3871,15 @@ AlterType(AlterTypeStmt *stmt)
|
|||||||
* AlterTypeRecurse: one recursion step for AlterType()
|
* AlterTypeRecurse: one recursion step for AlterType()
|
||||||
*
|
*
|
||||||
* Apply the changes specified by "atparams" to the type identified by
|
* Apply the changes specified by "atparams" to the type identified by
|
||||||
* "typeOid", whose existing pg_type tuple is "tup". Then search for any
|
* "typeOid", whose existing pg_type tuple is "tup". If necessary,
|
||||||
* domains over this type, and recursively apply (most of) the same changes
|
* recursively update its array type as well. Then search for any domains
|
||||||
* to those 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
|
* We need this because the system generally assumes that a domain inherits
|
||||||
* many properties from its base type. See DefineDomain() above for details
|
* 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
|
* There's a race condition here, in that some other transaction could
|
||||||
* concurrently add another domain atop this base type; we'd miss updating
|
* concurrently add another domain atop this base type; we'd miss updating
|
||||||
@ -3888,7 +3891,8 @@ AlterType(AlterTypeStmt *stmt)
|
|||||||
* committed.
|
* committed.
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
AlterTypeRecurse(Oid typeOid, HeapTuple tup, Relation catalog,
|
AlterTypeRecurse(Oid typeOid, bool isImplicitArray,
|
||||||
|
HeapTuple tup, Relation catalog,
|
||||||
AlterTypeRecurseParams *atparams)
|
AlterTypeRecurseParams *atparams)
|
||||||
{
|
{
|
||||||
Datum values[Natts_pg_type];
|
Datum values[Natts_pg_type];
|
||||||
@ -3949,12 +3953,43 @@ AlterTypeRecurse(Oid typeOid, HeapTuple tup, Relation catalog,
|
|||||||
NULL, /* don't have defaultExpr handy */
|
NULL, /* don't have defaultExpr handy */
|
||||||
NULL, /* don't have typacl handy */
|
NULL, /* don't have typacl handy */
|
||||||
0, /* we rejected composite types above */
|
0, /* we rejected composite types above */
|
||||||
false, /* and we rejected implicit arrays above */
|
isImplicitArray, /* it might be an array */
|
||||||
false, /* so it can't be a dependent type */
|
isImplicitArray, /* dependent iff it's array */
|
||||||
true);
|
true);
|
||||||
|
|
||||||
InvokeObjectPostAlterHook(TypeRelationId, typeOid, 0);
|
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
|
* Now we need to recurse to domains. However, some properties are not
|
||||||
* inherited by domains, so clear the update flags for those.
|
* 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->updateTypmodin = false; /* domains don't have typmods */
|
||||||
atparams->updateTypmodout = false;
|
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 */
|
/* Search pg_type for possible domains over this type */
|
||||||
ScanKeyInit(&key[0],
|
ScanKeyInit(&key[0],
|
||||||
Anum_pg_type_typbasetype,
|
Anum_pg_type_typbasetype,
|
||||||
@ -3983,7 +4024,7 @@ AlterTypeRecurse(Oid typeOid, HeapTuple tup, Relation catalog,
|
|||||||
if (domainForm->typtype != TYPTYPE_DOMAIN)
|
if (domainForm->typtype != TYPTYPE_DOMAIN)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
AlterTypeRecurse(domainForm->oid, domainTup, catalog, atparams);
|
AlterTypeRecurse(domainForm->oid, false, domainTup, catalog, atparams);
|
||||||
}
|
}
|
||||||
|
|
||||||
systable_endscan(scan);
|
systable_endscan(scan);
|
||||||
|
@ -270,6 +270,14 @@ FROM pg_type WHERE typname = 'myvarchar';
|
|||||||
myvarcharin | myvarcharout | myvarcharrecv | myvarcharsend | varchartypmodin | varchartypmodout | array_typanalyze | x
|
myvarcharin | myvarcharout | myvarcharrecv | myvarcharsend | varchartypmodin | varchartypmodout | array_typanalyze | x
|
||||||
(1 row)
|
(1 row)
|
||||||
|
|
||||||
|
SELECT typinput, typoutput, typreceive, typsend, typmodin, typmodout,
|
||||||
|
typanalyze, typstorage
|
||||||
|
FROM pg_type WHERE typname = '_myvarchar';
|
||||||
|
typinput | typoutput | typreceive | typsend | typmodin | typmodout | typanalyze | typstorage
|
||||||
|
----------+-----------+------------+------------+-----------------+------------------+------------------+------------
|
||||||
|
array_in | array_out | array_recv | array_send | varchartypmodin | varchartypmodout | array_typanalyze | x
|
||||||
|
(1 row)
|
||||||
|
|
||||||
SELECT typinput, typoutput, typreceive, typsend, typmodin, typmodout,
|
SELECT typinput, typoutput, typreceive, typsend, typmodin, typmodout,
|
||||||
typanalyze, typstorage
|
typanalyze, typstorage
|
||||||
FROM pg_type WHERE typname = 'myvarchardom';
|
FROM pg_type WHERE typname = 'myvarchardom';
|
||||||
@ -278,6 +286,14 @@ FROM pg_type WHERE typname = 'myvarchardom';
|
|||||||
domain_in | myvarcharout | domain_recv | myvarcharsend | - | - | array_typanalyze | x
|
domain_in | myvarcharout | domain_recv | myvarcharsend | - | - | array_typanalyze | x
|
||||||
(1 row)
|
(1 row)
|
||||||
|
|
||||||
|
SELECT typinput, typoutput, typreceive, typsend, typmodin, typmodout,
|
||||||
|
typanalyze, typstorage
|
||||||
|
FROM pg_type WHERE typname = '_myvarchardom';
|
||||||
|
typinput | typoutput | typreceive | typsend | typmodin | typmodout | typanalyze | typstorage
|
||||||
|
----------+-----------+------------+------------+----------+-----------+------------------+------------
|
||||||
|
array_in | array_out | array_recv | array_send | - | - | array_typanalyze | x
|
||||||
|
(1 row)
|
||||||
|
|
||||||
-- ensure dependencies are straight
|
-- ensure dependencies are straight
|
||||||
DROP FUNCTION myvarcharsend(myvarchar); -- fail
|
DROP FUNCTION myvarcharsend(myvarchar); -- fail
|
||||||
ERROR: cannot drop function myvarcharsend(myvarchar) because other objects depend on it
|
ERROR: cannot drop function myvarcharsend(myvarchar) because other objects depend on it
|
||||||
|
@ -214,10 +214,18 @@ SELECT typinput, typoutput, typreceive, typsend, typmodin, typmodout,
|
|||||||
typanalyze, typstorage
|
typanalyze, typstorage
|
||||||
FROM pg_type WHERE typname = 'myvarchar';
|
FROM pg_type WHERE typname = 'myvarchar';
|
||||||
|
|
||||||
|
SELECT typinput, typoutput, typreceive, typsend, typmodin, typmodout,
|
||||||
|
typanalyze, typstorage
|
||||||
|
FROM pg_type WHERE typname = '_myvarchar';
|
||||||
|
|
||||||
SELECT typinput, typoutput, typreceive, typsend, typmodin, typmodout,
|
SELECT typinput, typoutput, typreceive, typsend, typmodin, typmodout,
|
||||||
typanalyze, typstorage
|
typanalyze, typstorage
|
||||||
FROM pg_type WHERE typname = 'myvarchardom';
|
FROM pg_type WHERE typname = 'myvarchardom';
|
||||||
|
|
||||||
|
SELECT typinput, typoutput, typreceive, typsend, typmodin, typmodout,
|
||||||
|
typanalyze, typstorage
|
||||||
|
FROM pg_type WHERE typname = '_myvarchardom';
|
||||||
|
|
||||||
-- ensure dependencies are straight
|
-- ensure dependencies are straight
|
||||||
DROP FUNCTION myvarcharsend(myvarchar); -- fail
|
DROP FUNCTION myvarcharsend(myvarchar); -- fail
|
||||||
DROP TYPE myvarchar; -- fail
|
DROP TYPE myvarchar; -- fail
|
||||||
|
Loading…
x
Reference in New Issue
Block a user