From 28d2934f61f84d137ccd1b607fe1d7b0772fc1c9 Mon Sep 17 00:00:00 2001 From: Dmitry Patsura Date: Tue, 18 Aug 2026 13:20:59 +0200 Subject: [PATCH] perf(postgres-driver): build user defined types map in linear time MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `loadUserDefinedTypes` built its oid -> typname map with a reduce that spread the accumulator on every row, copying the whole map n times. That is quadratic and fully synchronous, so it blocks the event loop. This went unnoticed while the query only selected `typcategory in ('U', 'E')` (~20 rows on a stock Postgres). #11149 added `'A'` so that array-typed columns get mapped, and Postgres auto-creates an array type for every relation — the row count now scales with the number of tables in the database, not with the number of actual user defined types. Measured on postgres:16, `SELECT count(*) FROM pg_type WHERE typcategory in ('U', 'E', 'A')`: | tables in database | rows | spread reduce | in-place loop | | ------------------ | ---- | ------------- | ------------- | | 0 | 313 | 6.3 ms | 0.12 ms | | 5000 | 5313 | 2355 ms | 0.45 ms | | ~20000 | - | 35116 ms | 1.10 ms | Co-Authored-By: Claude Opus 5 (1M context) --- packages/cubejs-postgres-driver/src/PostgresDriver.ts | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/packages/cubejs-postgres-driver/src/PostgresDriver.ts b/packages/cubejs-postgres-driver/src/PostgresDriver.ts index e083b5d0104a4..37bdfd4db5d96 100644 --- a/packages/cubejs-postgres-driver/src/PostgresDriver.ts +++ b/packages/cubejs-postgres-driver/src/PostgresDriver.ts @@ -315,10 +315,13 @@ export class PostgresDriver ({ [current.oid]: current.typname, ...prev }), - {} - ); + const userDefinedTypes: Record = {}; + + for (const row of customTypes.rows) { + userDefinedTypes[row.oid] = row.typname; + } + + this.userDefinedTypes = userDefinedTypes; } }