mirror of
https://github.com/postgres/postgres.git
synced 2025-05-01 01:04:50 +03:00
Add pg_basetype() function to extract a domain's base type.
This SQL-callable function behaves much like our internal utility function getBaseType(), except it returns NULL rather than failing for an invalid type OID. (That behavior is modeled on our experience with other catalog-inquiry functions such as the ACL checking functions.) The key advantage over doing a join to pg_type is that it will loop as needed to find the bottom base type of a nest of domains. Steve Chavez, reviewed by jian he and others Discussion: https://postgr.es/m/CAGRrpzZSX8j=MQcbCSEisFA=ic=K3bknVfnFjAv1diVJxFHJvg@mail.gmail.com
This commit is contained in:
parent
ecf741cfae
commit
b154d8a6d0
@ -25129,6 +25129,30 @@ SELECT pg_type_is_visible('myschema.widget'::regtype);
|
||||
</para></entry>
|
||||
</row>
|
||||
|
||||
<row>
|
||||
<entry role="func_table_entry"><para role="func_signature">
|
||||
<indexterm>
|
||||
<primary>pg_basetype</primary>
|
||||
</indexterm>
|
||||
<function>pg_basetype</function> ( <type>regtype</type> )
|
||||
<returnvalue>regtype</returnvalue>
|
||||
</para>
|
||||
<para>
|
||||
Returns the OID of the base type of a domain identified by its
|
||||
type OID. If the argument is the OID of a non-domain type,
|
||||
returns the argument as-is. Returns NULL if the argument is
|
||||
not a valid type OID. If there's a chain of domain dependencies,
|
||||
it will recurse until finding the base type.
|
||||
</para>
|
||||
<para>
|
||||
Assuming <literal>CREATE DOMAIN mytext AS text</literal>:
|
||||
</para>
|
||||
<para>
|
||||
<literal>pg_basetype('mytext'::regtype)</literal>
|
||||
<returnvalue>text</returnvalue>
|
||||
</para></entry>
|
||||
</row>
|
||||
|
||||
<row>
|
||||
<entry id="pg-char-to-encoding" role="func_table_entry"><para role="func_signature">
|
||||
<indexterm>
|
||||
|
@ -44,6 +44,7 @@
|
||||
#include "utils/fmgroids.h"
|
||||
#include "utils/lsyscache.h"
|
||||
#include "utils/ruleutils.h"
|
||||
#include "utils/syscache.h"
|
||||
#include "utils/timestamp.h"
|
||||
|
||||
|
||||
@ -566,6 +567,50 @@ pg_typeof(PG_FUNCTION_ARGS)
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Return the base type of the argument.
|
||||
* If the given type is a domain, return its base type;
|
||||
* otherwise return the type's own OID.
|
||||
* Return NULL if the type OID doesn't exist or points to a
|
||||
* non-existent base type.
|
||||
*
|
||||
* This is a SQL-callable version of getBaseType(). Unlike that function,
|
||||
* we don't want to fail for a bogus type OID; this is helpful to keep race
|
||||
* conditions from turning into query failures when scanning the catalogs.
|
||||
* Hence we need our own implementation.
|
||||
*/
|
||||
Datum
|
||||
pg_basetype(PG_FUNCTION_ARGS)
|
||||
{
|
||||
Oid typid = PG_GETARG_OID(0);
|
||||
|
||||
/*
|
||||
* We loop to find the bottom base type in a stack of domains.
|
||||
*/
|
||||
for (;;)
|
||||
{
|
||||
HeapTuple tup;
|
||||
Form_pg_type typTup;
|
||||
|
||||
tup = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
|
||||
if (!HeapTupleIsValid(tup))
|
||||
PG_RETURN_NULL(); /* return NULL for bogus OID */
|
||||
typTup = (Form_pg_type) GETSTRUCT(tup);
|
||||
if (typTup->typtype != TYPTYPE_DOMAIN)
|
||||
{
|
||||
/* Not a domain, so done */
|
||||
ReleaseSysCache(tup);
|
||||
break;
|
||||
}
|
||||
|
||||
typid = typTup->typbasetype;
|
||||
ReleaseSysCache(tup);
|
||||
}
|
||||
|
||||
PG_RETURN_OID(typid);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Implementation of the COLLATE FOR expression; returns the collation
|
||||
* of the argument.
|
||||
|
@ -57,6 +57,6 @@
|
||||
*/
|
||||
|
||||
/* yyyymmddN */
|
||||
#define CATALOG_VERSION_NO 202403301
|
||||
#define CATALOG_VERSION_NO 202403302
|
||||
|
||||
#endif
|
||||
|
@ -3889,6 +3889,9 @@
|
||||
{ oid => '1619', descr => 'type of the argument',
|
||||
proname => 'pg_typeof', proisstrict => 'f', provolatile => 's',
|
||||
prorettype => 'regtype', proargtypes => 'any', prosrc => 'pg_typeof' },
|
||||
{ oid => '8312', descr => 'base type of a domain type',
|
||||
proname => 'pg_basetype', provolatile => 's', prorettype => 'regtype',
|
||||
proargtypes => 'regtype', prosrc => 'pg_basetype' },
|
||||
{ oid => '3162',
|
||||
descr => 'collation of the argument; implementation of the COLLATION FOR expression',
|
||||
proname => 'pg_collation_for', proisstrict => 'f', provolatile => 's',
|
||||
|
@ -1244,6 +1244,31 @@ alter domain testdomain1 rename constraint unsigned to unsigned_foo;
|
||||
alter domain testdomain1 drop constraint unsigned_foo;
|
||||
drop domain testdomain1;
|
||||
--
|
||||
-- Get the base type of a domain
|
||||
--
|
||||
create domain mytext as text;
|
||||
create domain mytext_child_1 as mytext;
|
||||
select pg_basetype('mytext'::regtype);
|
||||
pg_basetype
|
||||
-------------
|
||||
text
|
||||
(1 row)
|
||||
|
||||
select pg_basetype('mytext_child_1'::regtype);
|
||||
pg_basetype
|
||||
-------------
|
||||
text
|
||||
(1 row)
|
||||
|
||||
select pg_basetype(1); -- expect NULL not error
|
||||
pg_basetype
|
||||
-------------
|
||||
|
||||
(1 row)
|
||||
|
||||
drop domain mytext cascade;
|
||||
NOTICE: drop cascades to type mytext_child_1
|
||||
--
|
||||
-- Information schema
|
||||
--
|
||||
SELECT * FROM information_schema.column_domain_usage
|
||||
|
@ -839,6 +839,18 @@ alter domain testdomain1 rename constraint unsigned to unsigned_foo;
|
||||
alter domain testdomain1 drop constraint unsigned_foo;
|
||||
drop domain testdomain1;
|
||||
|
||||
--
|
||||
-- Get the base type of a domain
|
||||
--
|
||||
create domain mytext as text;
|
||||
create domain mytext_child_1 as mytext;
|
||||
|
||||
select pg_basetype('mytext'::regtype);
|
||||
select pg_basetype('mytext_child_1'::regtype);
|
||||
select pg_basetype(1); -- expect NULL not error
|
||||
|
||||
drop domain mytext cascade;
|
||||
|
||||
|
||||
--
|
||||
-- Information schema
|
||||
|
Loading…
x
Reference in New Issue
Block a user