aboutsummaryrefslogtreecommitdiff
path: root/src/backend/utils/adt/misc.c
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2024-03-30 13:57:19 -0400
committerTom Lane <tgl@sss.pgh.pa.us>2024-03-30 13:57:19 -0400
commitb154d8a6d0e52e5f6b09739639fdf55fa88bc6b8 (patch)
treefe758a1a6130bb68b0f3f93d05d1276ef0014a78 /src/backend/utils/adt/misc.c
parentecf741cfae0603d1df269d8b799455bbcaef86e7 (diff)
downloadpostgresql-b154d8a6d0e52e5f6b09739639fdf55fa88bc6b8.tar.gz
postgresql-b154d8a6d0e52e5f6b09739639fdf55fa88bc6b8.zip
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
Diffstat (limited to 'src/backend/utils/adt/misc.c')
-rw-r--r--src/backend/utils/adt/misc.c45
1 files changed, 45 insertions, 0 deletions
diff --git a/src/backend/utils/adt/misc.c b/src/backend/utils/adt/misc.c
index d4a92d0b3fa..0e6c45807a1 100644
--- a/src/backend/utils/adt/misc.c
+++ b/src/backend/utils/adt/misc.c
@@ -44,6 +44,7 @@
#include "utils/fmgroids.h"
#include "utils/lsyscache.h"
#include "utils/ruleutils.h"
+#include "utils/syscache.h"
#include "utils/timestamp.h"
@@ -567,6 +568,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.
*/