Skip to content

Commit

Permalink
fix(client): Fix Postgres introspection subquery to only look at PK c…
Browse files Browse the repository at this point in the history
…onstraints (#1242)

Fixes #1238

Old subquery returns multiple rows when there was an index on other
columns. This one is limited to `contype = 'p'` for primary key
constraints.
  • Loading branch information
samwillis authored May 9, 2024
1 parent ebd2cb9 commit c4876dd
Show file tree
Hide file tree
Showing 2 changed files with 24 additions and 15 deletions.
5 changes: 5 additions & 0 deletions .changeset/breezy-meals-reflect.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"electric-sql": patch
---

Fix Postgres introspection subquery to only look at PK constraints
34 changes: 19 additions & 15 deletions clients/typescript/src/migrators/query-builder/pgBuilder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -96,21 +96,25 @@ class PgBuilder extends QueryBuilder {
ELSE 1
END AS notnull,
c.column_default AS dflt_value,
(
SELECT CASE
-- if the column is not part of the primary key
-- then return 0
WHEN NOT pg_attribute.attnum = ANY(pg_index.indkey) THEN 0
-- else, return the position of the column in the primary key
-- pg_index.indkey is indexed from 0 so we do + 1
ELSE array_position(pg_index.indkey, pg_attribute.attnum) + 1
END AS pk
FROM pg_class, pg_attribute, pg_index
WHERE pg_class.oid = pg_attribute.attrelid AND
pg_class.oid = pg_index.indrelid AND
pg_class.relname = $1 AND
pg_attribute.attname = c.column_name
)
COALESCE(
(
-- Subquery to determine if the column is part of the primary key and
-- its position. We +1 to the position as we return 0 if the column
-- is not part of the primary key.
SELECT array_position(ind.indkey, att.attnum) + 1
FROM pg_class cl
JOIN pg_attribute att ON cl.oid = att.attrelid
JOIN pg_index ind ON cl.oid = ind.indrelid
JOIN pg_constraint con ON con.conindid = ind.indexrelid
WHERE cl.relname = c.table_name -- Match the table name
AND att.attname = c.column_name -- Match the column name
AND cl.relnamespace = (
SELECT oid FROM pg_namespace WHERE nspname = c.table_schema
) -- Match the schema
AND con.contype = 'p' -- Only consider primary key constraints
),
0 -- If the column is not part of the primary key, return 0
) AS pk
FROM information_schema.columns AS c
WHERE
c.table_name = $1 AND
Expand Down

0 comments on commit c4876dd

Please sign in to comment.