Skip to content

Conversation

@joelonsql
Copy link
Contributor

PostgreSQL 17 introduced pg_basetype() which natively resolves domain types to their base types. Use this instead of the recursive CTE when available, falling back to the recursive approach for older versions.

I've verified tests still works against PostgreSQL 16 and 17.

Note: I see an opportunity of reducing SQL code duplication between SchemaCache.hs and SqlFragment.hs, most of the big query is the same, with the below differences, however, if this is worth doing I'm not sure, and even if so, should probably be a separate commit anyway.

diff --git a/SqlFragment.sql b/SchemaCache.sql
index ffc24d78..db552451 100644
--- a/SqlFragment.sql
+++ b/SchemaCache.sql
@@ -42,8 +42,8 @@ WITH
     bt.oid <> bt.base_type as rettype_is_composite_alias,
     p.provolatile,
     p.provariadic > 0 as hasvariadic,
-    'ignored' AS transaction_isolation_level,
-    '{}'::text[] as kvs
+    lower((regexp_split_to_array((regexp_split_to_array(iso_config, '='))[2], ','))[1]) AS transaction_isolation_level,
+    coalesce(func_settings.kvs, '{}') as kvs
   FROM pg_proc p
   LEFT JOIN arguments a ON a.oid = p.oid
   JOIN pg_namespace pn ON pn.oid = p.pronamespace
@@ -52,6 +52,16 @@ WITH
   JOIN pg_namespace tn ON tn.oid = t.typnamespace
   LEFT JOIN pg_class comp ON comp.oid = t.typrelid
   LEFT JOIN pg_description as d ON d.objoid = p.oid AND d.classoid = 'pg_proc'::regclass
+  LEFT JOIN LATERAL unnest(proconfig) iso_config ON iso_config LIKE 'default_transaction_isolation%'
+  LEFT JOIN LATERAL (
+    SELECT
+      array_agg(row(
+        substr(setting, 1, strpos(setting, '=') - 1),
+        substr(setting, strpos(setting, '=') + 1)
+      )) as kvs
+    FROM unnest(proconfig) setting
+    WHERE setting ~ ANY($$2)
+  ) func_settings ON TRUE
   WHERE t.oid <> 'trigger'::regtype AND COALESCE(a.callable, true)
-  AND has_function_privilege(p.oid, 'execute')
   AND prokind = 'f'
+  AND p.pronamespace = ANY($$1::regnamespace[])

@joelonsql joelonsql force-pushed the use_pg_basetype branch 2 times, most recently from 1b831d7 to 2e1bf26 Compare December 17, 2025 12:29

### Added

- Use `pg_basetype()` for domain type resolution on PostgreSQL 17+ by @joelonsql in #XXXX
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's the observable effect, if any, for the user? Is this faster? If so, we should say that. I would not consider this a new "feature". It's likely either a performance improvement or a refactor. Although as a refactor it'd only increase complexity for now.

TLDR: If this doesn't make things faster, we should wait until we drop support for PG 16 - then this will make the code less complex.

Copy link
Contributor Author

@joelonsql joelonsql Dec 17, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

pg_basetype() is at least a new feature in PostgreSQL ;) I didn't think very much about it, but I see there is also a "refactor" on the list which probably makes more sense.

The pg_basetype() PostgreSQL feature was added by Steve Chavez, I just assumed there was a need to use this in PostgREST, since it seems to have been the reason for the pg_basetype() patch: https://www.postgresql.org/message-id/flat/CAGRrpzZSX8j%3DMQcbCSEisFA%3Dic%3DK3bknVfnFjAv1diVJxFHJvg%40mail.gmail.com

@joelonsql joelonsql changed the title feat: use pg_basetype() for domain type resolution on PG 17+ refactor: use pg_basetype() for domain type resolution on PG 17+ Dec 17, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

2 participants