Skip to content

Commit 8b47c67

Browse files
fix(postgres): bind the caller's schema in getTableColumns (#60)
`getTablesAndViews()` passes the schema each table was found in, but `getTableColumns` bound `DEFAULT_SCHEMA` (`'public'`) and discarded the argument. Every table on a database whose objects live outside `public` came back with **zero columns**. Measured against a real dbt warehouse (195 tables across 17 schemas, nothing in `public`): ``` marts.dim_person, schema bound to 'public' -> 0 columns 'marts' -> 91 columns ``` The PK subquery also had no schema predicate at all. Postgres auto-names primary keys `<table>_pkey`, so two schemas holding a same-named table cross-match by construction — producing duplicated `ColumnInfo` rows and false-positive PK flags. This adds `tc.table_schema = ku.table_schema` and `ku.table_schema = ?`. Both problems were latent while the provider only ever read `public`. #55 made them live: now that introspection walks every non-system schema, a `staging`/`marts`/`public` collision on `orders` or `customers` is the normal shape of a dbt warehouse, not the exception. ## Verification Deployed and measured on a live 195-table warehouse: | | before | after | |---|---:|---:| | schema snapshot | 37 tables / 837 cols | **195 / 4,070** | | tables returning zero columns | 195 of 195 | **0 of 195** | | tables with correctly-detected PKs | — | 67 | | tables with duplicated column rows | — | 0 | | tables with every column flagged PK | — | 0 | A full brain re-init on that connection went from a 37-table snapshot to 195 tables / 4,070 columns, lifting `table_classification` 25 → 161 and `inferred_table_relationship` 17 → 280. The agent went from being blind to 14 of 18 schemas to correctly describing them. Unit tests: `PostgresIntrospectionProviderTest` passes. A mocked `ResultSet` can't exercise SQL semantics, so the correctness evidence is the measurement above, against Postgres 18. ## Relationship to #40 #40 is open and `CONFLICTING`. It fixed the same class of problem with a `current_schema()` approach that #55 superseded by scanning all non-system schemas. This PR sits on top of #55 instead and is independent of #40#40 can likely be closed once this lands. Co-authored-by: deepsql-deploy <venkatesh.sakamuri@stayflexi.com>
1 parent e1064e0 commit 8b47c67

1 file changed

Lines changed: 16 additions & 4 deletions

File tree

backend/src/main/java/com/dbaagent/provider/postgres/PostgresIntrospectionProvider.java

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -166,24 +166,36 @@ SELECT n.nspname as schema_name, p.proname as name, pg_get_functiondef(p.oid) as
166166
public List<ColumnInfo> getTableColumns(Connection connection, String database, String tableName) throws SQLException {
167167
List<ColumnInfo> columns = new ArrayList<>();
168168

169+
// `database` carries the schema here: getTablesAndViews() passes the schema each
170+
// row was found in. Binding DEFAULT_SCHEMA instead returned zero columns for every
171+
// table on any database whose objects live outside public — and the unqualified PK
172+
// subquery cross-matched same-named tables, since Postgres auto-names primary keys
173+
// "<table>_pkey" and two schemas holding `orders` collide by construction.
174+
String schema = (database == null || database.isBlank()) ? DEFAULT_SCHEMA : database;
175+
169176
String query = """
170177
SELECT c.column_name, c.data_type, c.is_nullable, c.column_default,
171178
CASE WHEN pk.column_name IS NOT NULL THEN true ELSE false END as is_primary_key
172179
FROM information_schema.columns c
173180
LEFT JOIN (
174181
SELECT ku.column_name
175182
FROM information_schema.table_constraints tc
176-
JOIN information_schema.key_column_usage ku ON tc.constraint_name = ku.constraint_name
177-
WHERE tc.constraint_type = 'PRIMARY KEY' AND ku.table_name = ?
183+
JOIN information_schema.key_column_usage ku
184+
ON tc.constraint_name = ku.constraint_name
185+
AND tc.table_schema = ku.table_schema
186+
WHERE tc.constraint_type = 'PRIMARY KEY'
187+
AND ku.table_name = ?
188+
AND ku.table_schema = ?
178189
) pk ON c.column_name = pk.column_name
179190
WHERE c.table_name = ? AND c.table_schema = ?
180191
ORDER BY c.ordinal_position
181192
""";
182193

183194
try (PreparedStatement stmt = connection.prepareStatement(query)) {
184195
stmt.setString(1, tableName);
185-
stmt.setString(2, tableName);
186-
stmt.setString(3, DEFAULT_SCHEMA);
196+
stmt.setString(2, schema);
197+
stmt.setString(3, tableName);
198+
stmt.setString(4, schema);
187199
try (ResultSet rs = stmt.executeQuery()) {
188200
while (rs.next()) {
189201
ColumnInfo col = new ColumnInfo();

0 commit comments

Comments
 (0)