From f15eaff05a2b134a9dddb0cf40a1388724990019 Mon Sep 17 00:00:00 2001 From: deepsql-deploy Date: Sat, 15 Aug 2026 16:09:30 +0000 Subject: [PATCH] fix(postgres): bind the caller's schema in getTableColumns getTablesAndViews() passes the schema each table was found in, but the method bound DEFAULT_SCHEMA ('public'), so every table on a database whose objects live outside public came back with zero columns. Measured on isha_data_clean: marts.dim_person returns 91 columns when bound to 'marts', 0 when bound to 'public'. The PK subquery also had no schema predicate at all. Postgres auto-names primary keys '_pkey', so two schemas holding a same-named table cross-match by construction. Adds tc.table_schema = ku.table_schema and ku.table_schema = ?. Local-only until PR #40 resolves its conflict with the multi-schema work in #55. --- .../PostgresIntrospectionProvider.java | 20 +++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/backend/src/main/java/com/dbaagent/provider/postgres/PostgresIntrospectionProvider.java b/backend/src/main/java/com/dbaagent/provider/postgres/PostgresIntrospectionProvider.java index 1d31aba..68eb646 100644 --- a/backend/src/main/java/com/dbaagent/provider/postgres/PostgresIntrospectionProvider.java +++ b/backend/src/main/java/com/dbaagent/provider/postgres/PostgresIntrospectionProvider.java @@ -166,6 +166,13 @@ SELECT n.nspname as schema_name, p.proname as name, pg_get_functiondef(p.oid) as public List getTableColumns(Connection connection, String database, String tableName) throws SQLException { List columns = new ArrayList<>(); + // `database` carries the schema here: getTablesAndViews() passes the schema each + // row was found in. Binding DEFAULT_SCHEMA instead returned zero columns for every + // table on any database whose objects live outside public — and the unqualified PK + // subquery cross-matched same-named tables, since Postgres auto-names primary keys + // "
_pkey" and two schemas holding `orders` collide by construction. + String schema = (database == null || database.isBlank()) ? DEFAULT_SCHEMA : database; + String query = """ SELECT c.column_name, c.data_type, c.is_nullable, c.column_default, CASE WHEN pk.column_name IS NOT NULL THEN true ELSE false END as is_primary_key @@ -173,8 +180,12 @@ public List getTableColumns(Connection connection, String database, LEFT JOIN ( SELECT ku.column_name FROM information_schema.table_constraints tc - JOIN information_schema.key_column_usage ku ON tc.constraint_name = ku.constraint_name - WHERE tc.constraint_type = 'PRIMARY KEY' AND ku.table_name = ? + JOIN information_schema.key_column_usage ku + ON tc.constraint_name = ku.constraint_name + AND tc.table_schema = ku.table_schema + WHERE tc.constraint_type = 'PRIMARY KEY' + AND ku.table_name = ? + AND ku.table_schema = ? ) pk ON c.column_name = pk.column_name WHERE c.table_name = ? AND c.table_schema = ? ORDER BY c.ordinal_position @@ -182,8 +193,9 @@ LEFT JOIN ( try (PreparedStatement stmt = connection.prepareStatement(query)) { stmt.setString(1, tableName); - stmt.setString(2, tableName); - stmt.setString(3, DEFAULT_SCHEMA); + stmt.setString(2, schema); + stmt.setString(3, tableName); + stmt.setString(4, schema); try (ResultSet rs = stmt.executeQuery()) { while (rs.next()) { ColumnInfo col = new ColumnInfo();