Orafce and plpgsql_check are ready for PostgreSQL 10
Small note: All regress tests of https://github.com/orafce/orafce and https://github.com/okbob/plpgsql_check passed on PostgreSQL 10.
Some notes about PostgreSQL
Small note: All regress tests of https://github.com/orafce/orafce and https://github.com/okbob/plpgsql_check passed on PostgreSQL 10.
Often performance issue is missing index on foreign keys. With few queries is very simple to find foreign keys without index:
create table a(id serial primary key, v text); create table b(id serial primary key, id_a integer references a(id), v text);
-- returns a subset of column names specified by their nums in array create or replace function attnames(oid, smallint[]) returns name[] as $$ select array_agg(attname ) from (select attname from pg_attribute where attrelid = $1 and attnum = any($2) order by attnum) s $$ language sql; -- ensure safe quoting of column names for usage in SQL create or replace function qnames(name[]) returns text as $$ select string_agg(v, ',') from (select quote_ident(n) v from unnest($1) g(n)) s $$ language sql;
select conname, conrelid::regclass, attnames(conrelid, conkey) from pg_constraint where contype = 'f'; ┌─────────────┬──────────┬──────────┐ │ conname │ conrelid │ attnames │ ╞═════════════╪══════════╪══════════╡ │ b_id_a_fkey │ b │ {id_a} │ └─────────────┴──────────┴──────────┘ (1 row)
select conname, conrelid::regclass, attnames(conrelid, conkey) from pg_constraint where contype = 'f' and not exists (select * from pg_index where indrelid = conrelid and attnames(conrelid,conkey) = attnames(conrelid, indkey::smallint[])); -- list of foreign keys without index ┌─────────────┬──────────┬──────────┐ │ conname │ conrelid │ attnames │ ╞═════════════╪══════════╪══════════╡ │ b_id_a_fkey │ b │ {id_a} │ └─────────────┴──────────┴──────────┘ (1 row)
select format('create index on %s(%s)', conrelid::regclass, qnames(attnames(conrelid, conkey))) from pg_constraint where contype = 'f' and not exists (select * from pg_index where indrelid = conrelid and attnames(conrelid,conkey) = attnames(conrelid, indkey::smallint[])); ┌─────────────────────────┐ │ format │ ╞═════════════════════════╡ │ create index on b(id_a) │ └─────────────────────────┘ (1 row)
select format('(1):%I, (2):%s', 'BadTableName', 'BadTableName'); ┌──────────────────────────────────────┐ │ format │ ╞══════════════════════════════════════╡ │ (1):"BadTableName", (2):BadTableName │ └──────────────────────────────────────┘ (1 row)This case is exception, because I use casting from Oid to regclass, that enforce correct escaping. Two times escaping can produce wrong result. So %I cannot be used here.
create table "BadName"(a int); select '"BadName"'::regclass::oid; ┌───────┐ │ oid │ ╞═══════╡ │ 16419 │ └───────┘ (1 row) select 16419::regclass; ┌───────────┐ │ regclass │ ╞═══════════╡ │ "BadName" │ └───────────┘ (1 row) postgres=# select format('%I, %s', 16419::regclass, 16419::regclass); ┌──────────────────────────┐ │ format │ ╞══════════════════════════╡ │ """BadName""", "BadName" │ └──────────────────────────┘ (1 row)