From 1478d12eb352b1b7906ccfe3ab5eaafe60ffbe4f Mon Sep 17 00:00:00 2001 From: Ruben Fiszel Date: Fri, 24 Jul 2026 14:37:21 +0200 Subject: [PATCH] perf: optimize get_datatable_full_schema to avoid timeout on large catalogs (#10304) pg_get_full_schema built each column row with three per-column correlated subqueries (default value, primary-key EXISTS on pg_index, pk constraint name on pg_constraint). On large catalogs those run once per column and the introspection times out. Replace them with plain joins to pg_attrdef and the table's single primary-key constraint, so the planner does one hash/merge join instead of O(columns) index searches. Output is byte-for-byte identical. Fixes WIN-2239 Co-authored-by: Claude Opus 4.8 (1M context) --- backend/windmill-common/src/query_builders.rs | 22 ++++++++++--------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/backend/windmill-common/src/query_builders.rs b/backend/windmill-common/src/query_builders.rs index ce7dbc2533..063d3958de 100644 --- a/backend/windmill-common/src/query_builders.rs +++ b/backend/windmill-common/src/query_builders.rs @@ -4835,6 +4835,10 @@ fn pg_action_to_string(action: &str) -> String { pub async fn pg_get_full_schema( client: &tokio_postgres::Client, ) -> Result { + // Primary-key and default-value info are joined in (a table has at most one + // primary-key constraint, so `pkc` stays 1:1) rather than fetched via + // per-column correlated subqueries — on large catalogs those subqueries run + // once per column and make the introspection time out. let column_rows = client .query( "SELECT @@ -4842,19 +4846,17 @@ pub async fn pg_get_full_schema( c.relname AS table_name, a.attname AS column_name, pg_catalog.format_type(a.atttypid, a.atttypmod) AS datatype, - (SELECT substring(pg_catalog.pg_get_expr(d.adbin, d.adrelid, true) for 128) - FROM pg_catalog.pg_attrdef d - WHERE d.adrelid = a.attrelid AND d.adnum = a.attnum AND a.atthasdef) AS default_value, - CASE a.attnotnull WHEN false THEN true ELSE false END AS nullable, - EXISTS ( - SELECT 1 FROM pg_catalog.pg_index i - WHERE i.indrelid = c.oid AND i.indisprimary AND a.attnum = ANY(i.indkey) - ) AS is_primary_key, - (SELECT con.conname FROM pg_catalog.pg_constraint con - WHERE con.conrelid = c.oid AND con.contype = 'p' LIMIT 1) AS pk_constraint_name + substring(pg_catalog.pg_get_expr(ad.adbin, ad.adrelid, true) for 128) AS default_value, + NOT a.attnotnull AS nullable, + COALESCE(pkc.conkey @> ARRAY[a.attnum], false) AS is_primary_key, + pkc.conname AS pk_constraint_name FROM pg_catalog.pg_attribute a JOIN pg_catalog.pg_class c ON a.attrelid = c.oid JOIN pg_catalog.pg_namespace ns ON c.relnamespace = ns.oid + LEFT JOIN pg_catalog.pg_attrdef ad + ON ad.adrelid = a.attrelid AND ad.adnum = a.attnum AND a.atthasdef + LEFT JOIN pg_catalog.pg_constraint pkc + ON pkc.conrelid = c.oid AND pkc.contype = 'p' WHERE c.relkind = 'r' AND a.attnum > 0 AND NOT a.attisdropped