mirror of
https://github.com/postgres/postgres.git
synced 2025-07-26 01:22:12 +03:00
Allow ALTER TYPE to update an existing type's typsubscript value.
This is essential if we'd like to allow existing extension data types to support subscripting in future, since dropping and recreating the type isn't a practical thing for an extension upgrade script, and direct manipulation of pg_type isn't a great answer either. There was some discussion about also allowing alteration of typelem, but it's less clear whether that's a good idea or not, so for now I forebore. Discussion: https://postgr.es/m/3724341.1607551174@sss.pgh.pa.us
This commit is contained in:
@ -194,6 +194,14 @@ ALTER TYPE <replaceable class="parameter">name</replaceable> SET ( <replaceable
|
|||||||
requires superuser privilege.
|
requires superuser privilege.
|
||||||
</para>
|
</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
<literal>SUBSCRIPT</literal> can be set to the name of a type-specific
|
||||||
|
subscripting handler function, or <literal>NONE</literal> to remove
|
||||||
|
the type's subscripting handler function. Using this option
|
||||||
|
requires superuser privilege.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
<listitem>
|
<listitem>
|
||||||
<para>
|
<para>
|
||||||
<literal>STORAGE</literal><indexterm>
|
<literal>STORAGE</literal><indexterm>
|
||||||
|
@ -94,6 +94,7 @@ typedef struct
|
|||||||
bool updateTypmodin;
|
bool updateTypmodin;
|
||||||
bool updateTypmodout;
|
bool updateTypmodout;
|
||||||
bool updateAnalyze;
|
bool updateAnalyze;
|
||||||
|
bool updateSubscript;
|
||||||
/* New values for relevant attributes */
|
/* New values for relevant attributes */
|
||||||
char storage;
|
char storage;
|
||||||
Oid receiveOid;
|
Oid receiveOid;
|
||||||
@ -101,6 +102,7 @@ typedef struct
|
|||||||
Oid typmodinOid;
|
Oid typmodinOid;
|
||||||
Oid typmodoutOid;
|
Oid typmodoutOid;
|
||||||
Oid analyzeOid;
|
Oid analyzeOid;
|
||||||
|
Oid subscriptOid;
|
||||||
} AlterTypeRecurseParams;
|
} AlterTypeRecurseParams;
|
||||||
|
|
||||||
/* Potentially set by pg_upgrade_support functions */
|
/* Potentially set by pg_upgrade_support functions */
|
||||||
@ -3885,6 +3887,18 @@ AlterType(AlterTypeStmt *stmt)
|
|||||||
/* Replacing an analyze function requires superuser. */
|
/* Replacing an analyze function requires superuser. */
|
||||||
requireSuper = true;
|
requireSuper = true;
|
||||||
}
|
}
|
||||||
|
else if (strcmp(defel->defname, "subscript") == 0)
|
||||||
|
{
|
||||||
|
if (defel->arg != NULL)
|
||||||
|
atparams.subscriptOid =
|
||||||
|
findTypeSubscriptingFunction(defGetQualifiedName(defel),
|
||||||
|
typeOid);
|
||||||
|
else
|
||||||
|
atparams.subscriptOid = InvalidOid; /* NONE, remove function */
|
||||||
|
atparams.updateSubscript = true;
|
||||||
|
/* Replacing a subscript function requires superuser. */
|
||||||
|
requireSuper = true;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The rest of the options that CREATE accepts cannot be changed.
|
* The rest of the options that CREATE accepts cannot be changed.
|
||||||
@ -4042,6 +4056,11 @@ AlterTypeRecurse(Oid typeOid, bool isImplicitArray,
|
|||||||
replaces[Anum_pg_type_typanalyze - 1] = true;
|
replaces[Anum_pg_type_typanalyze - 1] = true;
|
||||||
values[Anum_pg_type_typanalyze - 1] = ObjectIdGetDatum(atparams->analyzeOid);
|
values[Anum_pg_type_typanalyze - 1] = ObjectIdGetDatum(atparams->analyzeOid);
|
||||||
}
|
}
|
||||||
|
if (atparams->updateSubscript)
|
||||||
|
{
|
||||||
|
replaces[Anum_pg_type_typsubscript - 1] = true;
|
||||||
|
values[Anum_pg_type_typsubscript - 1] = ObjectIdGetDatum(atparams->subscriptOid);
|
||||||
|
}
|
||||||
|
|
||||||
newtup = heap_modify_tuple(tup, RelationGetDescr(catalog),
|
newtup = heap_modify_tuple(tup, RelationGetDescr(catalog),
|
||||||
values, nulls, replaces);
|
values, nulls, replaces);
|
||||||
@ -4098,6 +4117,7 @@ AlterTypeRecurse(Oid typeOid, bool isImplicitArray,
|
|||||||
atparams->updateReceive = false; /* domains use F_DOMAIN_RECV */
|
atparams->updateReceive = false; /* domains use F_DOMAIN_RECV */
|
||||||
atparams->updateTypmodin = false; /* domains don't have typmods */
|
atparams->updateTypmodin = false; /* domains don't have typmods */
|
||||||
atparams->updateTypmodout = false;
|
atparams->updateTypmodout = false;
|
||||||
|
atparams->updateSubscript = false; /* domains don't have subscriptors */
|
||||||
|
|
||||||
/* Skip the scan if nothing remains to be done */
|
/* Skip the scan if nothing remains to be done */
|
||||||
if (!(atparams->updateStorage ||
|
if (!(atparams->updateStorage ||
|
||||||
|
@ -260,38 +260,40 @@ ALTER TYPE myvarchar SET (
|
|||||||
receive = myvarcharrecv,
|
receive = myvarcharrecv,
|
||||||
typmod_in = varchartypmodin,
|
typmod_in = varchartypmodin,
|
||||||
typmod_out = varchartypmodout,
|
typmod_out = varchartypmodout,
|
||||||
analyze = array_typanalyze -- bogus, but it doesn't matter
|
-- these are bogus, but it's safe as long as we don't use the type:
|
||||||
|
analyze = ts_typanalyze,
|
||||||
|
subscript = raw_array_subscript_handler
|
||||||
);
|
);
|
||||||
SELECT typinput, typoutput, typreceive, typsend, typmodin, typmodout,
|
SELECT typinput, typoutput, typreceive, typsend, typmodin, typmodout,
|
||||||
typanalyze, typstorage
|
typanalyze, typsubscript, typstorage
|
||||||
FROM pg_type WHERE typname = 'myvarchar';
|
FROM pg_type WHERE typname = 'myvarchar';
|
||||||
typinput | typoutput | typreceive | typsend | typmodin | typmodout | typanalyze | typstorage
|
typinput | typoutput | typreceive | typsend | typmodin | typmodout | typanalyze | typsubscript | typstorage
|
||||||
-------------+--------------+---------------+---------------+-----------------+------------------+------------------+------------
|
-------------+--------------+---------------+---------------+-----------------+------------------+---------------+-----------------------------+------------
|
||||||
myvarcharin | myvarcharout | myvarcharrecv | myvarcharsend | varchartypmodin | varchartypmodout | array_typanalyze | x
|
myvarcharin | myvarcharout | myvarcharrecv | myvarcharsend | varchartypmodin | varchartypmodout | ts_typanalyze | raw_array_subscript_handler | x
|
||||||
(1 row)
|
(1 row)
|
||||||
|
|
||||||
SELECT typinput, typoutput, typreceive, typsend, typmodin, typmodout,
|
SELECT typinput, typoutput, typreceive, typsend, typmodin, typmodout,
|
||||||
typanalyze, typstorage
|
typanalyze, typsubscript, typstorage
|
||||||
FROM pg_type WHERE typname = '_myvarchar';
|
FROM pg_type WHERE typname = '_myvarchar';
|
||||||
typinput | typoutput | typreceive | typsend | typmodin | typmodout | typanalyze | typstorage
|
typinput | typoutput | typreceive | typsend | typmodin | typmodout | typanalyze | typsubscript | typstorage
|
||||||
----------+-----------+------------+------------+-----------------+------------------+------------------+------------
|
----------+-----------+------------+------------+-----------------+------------------+------------------+-------------------------+------------
|
||||||
array_in | array_out | array_recv | array_send | varchartypmodin | varchartypmodout | array_typanalyze | x
|
array_in | array_out | array_recv | array_send | varchartypmodin | varchartypmodout | array_typanalyze | array_subscript_handler | x
|
||||||
(1 row)
|
(1 row)
|
||||||
|
|
||||||
SELECT typinput, typoutput, typreceive, typsend, typmodin, typmodout,
|
SELECT typinput, typoutput, typreceive, typsend, typmodin, typmodout,
|
||||||
typanalyze, typstorage
|
typanalyze, typsubscript, typstorage
|
||||||
FROM pg_type WHERE typname = 'myvarchardom';
|
FROM pg_type WHERE typname = 'myvarchardom';
|
||||||
typinput | typoutput | typreceive | typsend | typmodin | typmodout | typanalyze | typstorage
|
typinput | typoutput | typreceive | typsend | typmodin | typmodout | typanalyze | typsubscript | typstorage
|
||||||
-----------+--------------+-------------+---------------+----------+-----------+------------------+------------
|
-----------+--------------+-------------+---------------+----------+-----------+---------------+--------------+------------
|
||||||
domain_in | myvarcharout | domain_recv | myvarcharsend | - | - | array_typanalyze | x
|
domain_in | myvarcharout | domain_recv | myvarcharsend | - | - | ts_typanalyze | - | x
|
||||||
(1 row)
|
(1 row)
|
||||||
|
|
||||||
SELECT typinput, typoutput, typreceive, typsend, typmodin, typmodout,
|
SELECT typinput, typoutput, typreceive, typsend, typmodin, typmodout,
|
||||||
typanalyze, typstorage
|
typanalyze, typsubscript, typstorage
|
||||||
FROM pg_type WHERE typname = '_myvarchardom';
|
FROM pg_type WHERE typname = '_myvarchardom';
|
||||||
typinput | typoutput | typreceive | typsend | typmodin | typmodout | typanalyze | typstorage
|
typinput | typoutput | typreceive | typsend | typmodin | typmodout | typanalyze | typsubscript | typstorage
|
||||||
----------+-----------+------------+------------+----------+-----------+------------------+------------
|
----------+-----------+------------+------------+----------+-----------+------------------+-------------------------+------------
|
||||||
array_in | array_out | array_recv | array_send | - | - | array_typanalyze | x
|
array_in | array_out | array_recv | array_send | - | - | array_typanalyze | array_subscript_handler | x
|
||||||
(1 row)
|
(1 row)
|
||||||
|
|
||||||
-- ensure dependencies are straight
|
-- ensure dependencies are straight
|
||||||
|
@ -207,23 +207,25 @@ ALTER TYPE myvarchar SET (
|
|||||||
receive = myvarcharrecv,
|
receive = myvarcharrecv,
|
||||||
typmod_in = varchartypmodin,
|
typmod_in = varchartypmodin,
|
||||||
typmod_out = varchartypmodout,
|
typmod_out = varchartypmodout,
|
||||||
analyze = array_typanalyze -- bogus, but it doesn't matter
|
-- these are bogus, but it's safe as long as we don't use the type:
|
||||||
|
analyze = ts_typanalyze,
|
||||||
|
subscript = raw_array_subscript_handler
|
||||||
);
|
);
|
||||||
|
|
||||||
SELECT typinput, typoutput, typreceive, typsend, typmodin, typmodout,
|
SELECT typinput, typoutput, typreceive, typsend, typmodin, typmodout,
|
||||||
typanalyze, typstorage
|
typanalyze, typsubscript, typstorage
|
||||||
FROM pg_type WHERE typname = 'myvarchar';
|
FROM pg_type WHERE typname = 'myvarchar';
|
||||||
|
|
||||||
SELECT typinput, typoutput, typreceive, typsend, typmodin, typmodout,
|
SELECT typinput, typoutput, typreceive, typsend, typmodin, typmodout,
|
||||||
typanalyze, typstorage
|
typanalyze, typsubscript, typstorage
|
||||||
FROM pg_type WHERE typname = '_myvarchar';
|
FROM pg_type WHERE typname = '_myvarchar';
|
||||||
|
|
||||||
SELECT typinput, typoutput, typreceive, typsend, typmodin, typmodout,
|
SELECT typinput, typoutput, typreceive, typsend, typmodin, typmodout,
|
||||||
typanalyze, typstorage
|
typanalyze, typsubscript, typstorage
|
||||||
FROM pg_type WHERE typname = 'myvarchardom';
|
FROM pg_type WHERE typname = 'myvarchardom';
|
||||||
|
|
||||||
SELECT typinput, typoutput, typreceive, typsend, typmodin, typmodout,
|
SELECT typinput, typoutput, typreceive, typsend, typmodin, typmodout,
|
||||||
typanalyze, typstorage
|
typanalyze, typsubscript, typstorage
|
||||||
FROM pg_type WHERE typname = '_myvarchardom';
|
FROM pg_type WHERE typname = '_myvarchardom';
|
||||||
|
|
||||||
-- ensure dependencies are straight
|
-- ensure dependencies are straight
|
||||||
|
Reference in New Issue
Block a user