Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixed wrong detection for columns with multiple constraints #17

Merged
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 12 additions & 4 deletions sql/non_primary_key_columns_with_serial_types.sql
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@
* Licensed under the Apache License 2.0
*/

-- Finds columns of serial types (smallserial/serial/bigserial) that are not primary keys.
-- Finds columns of serial types (smallserial/serial/bigserial)
-- that are not primary keys (or primary and foreign keys at the same time).
-- Based on https://dba.stackexchange.com/questions/90555/postgresql-select-primary-key-as-serial-or-bigserial/
select
col.attrelid::regclass::text as table_name,
Expand All @@ -21,14 +22,21 @@ from
join pg_catalog.pg_namespace nsp on nsp.oid = t.relnamespace
join pg_catalog.pg_attribute col on col.attrelid = t.oid
join pg_attrdef ad on ad.adrelid = col.attrelid and ad.adnum = col.attnum
left join pg_constraint c on c.conrelid = col.attrelid and c.conkey[1] = col.attnum
left join lateral (
select sum(case when c.contype = 'p' then +1 else -1 end) as res
from pg_constraint c
where
c.conrelid = col.attrelid and
c.conkey[1] = col.attnum and
c.contype in ('p', 'f') and /* primary or foreign key */
array_length(c.conkey, 1) = 1 /* single column */
group by c.conrelid, c.conkey[1]) c on true
where
t.relkind = 'r' and
col.attnum > 0 and /* to filter out system columns such as oid, ctid, xmin, xmax, etc. */
not col.attisdropped and
col.atttypid = any('{int,int8,int2}'::regtype[]) and
(c.contype is null or (c.contype != 'p' and /* not primary key */
array_length(c.conkey, 1) = 1)) and /* single column */
(c.res is null or c.res <= 0) and
/* column default value = nextval from owned sequence */
pg_get_expr(ad.adbin, ad.adrelid) = 'nextval(''' || (pg_get_serial_sequence(col.attrelid::regclass::text, col.attname))::regclass || '''::regclass)' and
nsp.nspname = :schema_name_param::text
Expand Down