On Sun, Feb 18, 2024 at 7:29 AM Tomas Vondra <tomas.von...@enterprisedb.com> wrote: > > > Also, now that I looked at the v2 patch again, I see it only really > tweaked the pg_proc.dat entry, but the code still does PG_GETARG_OID (so > the "any" bit is not really correct). >
PG_GETARG_OID part indeed is wrong. so I change to following: +Datum +pg_basetype(PG_FUNCTION_ARGS) +{ + Oid oid; + + oid = get_fn_expr_argtype(fcinfo->flinfo, 0); + if (!SearchSysCacheExists1(TYPEOID, ObjectIdGetDatum(oid))) + PG_RETURN_NULL(); + + PG_RETURN_OID(getBaseType(oid)); +} I still name the function as pg_basetype, feel free to change it. + <row> + <entry role="func_table_entry"><para role="func_signature"> + <indexterm> + <primary>pg_basetype</primary> + </indexterm> + <function>pg_basetype</function> ( <type>"any"</type> ) + <returnvalue>regtype</returnvalue> + </para> + <para> + Returns the OID of the base type of a domain or if the argument is a basetype it returns the same type. + If there's a chain of domain dependencies, it will recurse until finding the base type. + </para> compared with pg_typeof's explanation, I feel like pg_basetype's explanation doesn't seem accurate. However, I don't know how to rephrase it.
From a06f2de575da6e5fa45919c792f3dab2470f4927 Mon Sep 17 00:00:00 2001 From: jian he <jian.universality@gmail.com> Date: Mon, 19 Feb 2024 15:01:19 +0800 Subject: [PATCH v3 1/1] Add pg_basetype("any") function Currently obtaining the base type of a domain involves a complex SQL query, this specially in the case of recursive domain types. To solve this, use the already available getBaseType() function, and expose it as the pg_basetype SQL function. if the argument is not a doamin type, return the type of the argument as is. if the argument is a type of doamin, pg_basetype will recurse the domain dependencies chain and return the real inner base type of the domain. discussion: https://postgr.es/m/CAGRrpzZSX8j=MQcbCSEisFA=ic=K3bknVfnFjAv1diVJxFHJvg@mail.gmail.com --- doc/src/sgml/func.sgml | 25 +++++++++++++++++++ src/backend/utils/adt/misc.c | 16 +++++++++++++ src/include/catalog/pg_proc.dat | 3 +++ src/test/regress/expected/domain.out | 36 ++++++++++++++++++++++++++++ src/test/regress/sql/domain.sql | 16 +++++++++++++ 5 files changed, 96 insertions(+) diff --git a/doc/src/sgml/func.sgml b/doc/src/sgml/func.sgml index cf3de803..5af0f4c6 100644 --- a/doc/src/sgml/func.sgml +++ b/doc/src/sgml/func.sgml @@ -24778,6 +24778,31 @@ 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>"any"</type> ) + <returnvalue>regtype</returnvalue> + </para> + <para> + Returns the OID of the base type of a domain or if the argument is a basetype it returns the same type. + If there's a chain of domain dependencies, it will recurse until finding the base type. + </para> + <para> + For example: +<programlisting> +CREATE DOMAIN mytext as text; + +SELECT pg_basetype('mytext'::mytext); + pg_basetype +----------- + text +</programlisting> + </para></entry> + </row> + <row> <entry id="pg-char-to-encoding" role="func_table_entry"><para role="func_signature"> <indexterm> diff --git a/src/backend/utils/adt/misc.c b/src/backend/utils/adt/misc.c index 2d7d7806..30f6a2e5 100644 --- a/src/backend/utils/adt/misc.c +++ b/src/backend/utils/adt/misc.c @@ -45,6 +45,7 @@ #include "utils/fmgroids.h" #include "utils/lsyscache.h" #include "utils/ruleutils.h" +#include "utils/syscache.h" #include "utils/timestamp.h" @@ -566,6 +567,21 @@ pg_typeof(PG_FUNCTION_ARGS) PG_RETURN_OID(get_fn_expr_argtype(fcinfo->flinfo, 0)); } +/* + * Return the base type of the argument. + * iff the argument is not a type of domain, return the argument's type as is. + */ +Datum +pg_basetype(PG_FUNCTION_ARGS) +{ + Oid oid; + + oid = get_fn_expr_argtype(fcinfo->flinfo, 0); + if (!SearchSysCacheExists1(TYPEOID, ObjectIdGetDatum(oid))) + PG_RETURN_NULL(); + + PG_RETURN_OID(getBaseType(oid)); +} /* * Implementation of the COLLATE FOR expression; returns the collation diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat index 9c120fc2..bbd6b411 100644 --- a/src/include/catalog/pg_proc.dat +++ b/src/include/catalog/pg_proc.dat @@ -3877,6 +3877,9 @@ { oid => '1619', descr => 'type of the argument', proname => 'pg_typeof', proisstrict => 'f', provolatile => 's', prorettype => 'regtype', proargtypes => 'any', prosrc => 'pg_typeof' }, +{ oid => '6312', descr => 'get the base type of a domain', + proname => 'pg_basetype', proisstrict => 'f', provolatile => 's', + prorettype => 'regtype', proargtypes => 'any', prosrc => 'pg_basetype' }, { oid => '3162', descr => 'collation of the argument; implementation of the COLLATION FOR expression', proname => 'pg_collation_for', proisstrict => 'f', provolatile => 's', diff --git a/src/test/regress/expected/domain.out b/src/test/regress/expected/domain.out index 6d94e844..13bf7877 100644 --- a/src/test/regress/expected/domain.out +++ b/src/test/regress/expected/domain.out @@ -1207,3 +1207,39 @@ create domain testdomain1 as int constraint unsigned check (value > 0); 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; +create domain mytext_child_2 as mytext_child_1; +select pg_basetype('mytext'::mytext); + pg_basetype +------------- + text +(1 row) + +-- gets base types recursively +select pg_basetype('mytext_child_1'::mytext_child_1); + pg_basetype +------------- + text +(1 row) + +select pg_basetype('mytext_child_2'::mytext_child_2); + pg_basetype +------------- + text +(1 row) + +-- if already a base type, get the same +select pg_basetype('text'::text); + pg_basetype +------------- + text +(1 row) + +drop domain mytext cascade; +NOTICE: drop cascades to 2 other objects +DETAIL: drop cascades to type mytext_child_1 +drop cascades to type mytext_child_2 diff --git a/src/test/regress/sql/domain.sql b/src/test/regress/sql/domain.sql index 745f5d5f..58540519 100644 --- a/src/test/regress/sql/domain.sql +++ b/src/test/regress/sql/domain.sql @@ -809,3 +809,19 @@ create domain testdomain1 as int constraint unsigned check (value > 0); 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; +create domain mytext_child_2 as mytext_child_1; + +select pg_basetype('mytext'::mytext); +-- gets base types recursively +select pg_basetype('mytext_child_1'::mytext_child_1); +select pg_basetype('mytext_child_2'::mytext_child_2); +-- if already a base type, get the same +select pg_basetype('text'::text); + +drop domain mytext cascade; \ No newline at end of file -- 2.34.1