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);
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);
* 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
* 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];
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.
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,
if (domainForm->typtype != TYPTYPE_DOMAIN)
continue;
- AlterTypeRecurse(domainForm->oid, domainTup, catalog, atparams);
+ AlterTypeRecurse(domainForm->oid, false, domainTup, catalog, atparams);
}
systable_endscan(scan);
myvarcharin | myvarcharout | myvarcharrecv | myvarcharsend | varchartypmodin | varchartypmodout | array_typanalyze | x
(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,
typanalyze, typstorage
FROM pg_type WHERE typname = 'myvarchardom';
domain_in | myvarcharout | domain_recv | myvarcharsend | - | - | array_typanalyze | x
(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
DROP FUNCTION myvarcharsend(myvarchar); -- fail
ERROR: cannot drop function myvarcharsend(myvarchar) because other objects depend on it