fix relation detection bug and allow offset on lower levels

This commit is contained in:
Ruslan Talpa
2016-10-05 11:34:07 +03:00
parent 980680f3d6
commit 211e3d4141
9 changed files with 169 additions and 98 deletions
+63 -63
View File
@@ -558,73 +558,73 @@ allSynonyms cols =
where
-- query explanation at https://gist.github.com/ruslantalpa/2eab8c930a65e8043d8f
sql = [q|
WITH view_columns AS (
SELECT
c.oid AS view_oid,
a.attname::information_schema.sql_identifier AS column_name
FROM pg_attribute a
JOIN pg_class c ON a.attrelid = c.oid
JOIN pg_namespace nc ON c.relnamespace = nc.oid
WHERE
NOT pg_is_other_temp_schema(nc.oid)
AND a.attnum > 0
AND NOT a.attisdropped
AND (c.relkind = 'v'::"char")
AND nc.nspname NOT IN ('information_schema', 'pg_catalog')
with view_columns as (
select
c.oid as view_oid,
a.attname::information_schema.sql_identifier as column_name
from pg_attribute a
join pg_class c on a.attrelid = c.oid
join pg_namespace nc on c.relnamespace = nc.oid
where
not pg_is_other_temp_schema(nc.oid)
and a.attnum > 0
and not a.attisdropped
and (c.relkind = 'v'::"char")
and nc.nspname not in ('information_schema', 'pg_catalog')
),
view_column_usage AS (
SELECT DISTINCT
v.oid as view_oid,
nv.nspname::information_schema.sql_identifier AS view_schema,
v.relname::information_schema.sql_identifier AS view_name,
nt.nspname::information_schema.sql_identifier AS table_schema,
t.relname::information_schema.sql_identifier AS table_name,
a.attname::information_schema.sql_identifier AS column_name,
pg_get_viewdef(v.oid)::information_schema.character_data AS view_definition
FROM pg_namespace nv
JOIN pg_class v ON nv.oid = v.relnamespace
JOIN pg_depend dv ON v.oid = dv.refobjid
JOIN pg_depend dt ON dv.objid = dt.objid
JOIN pg_class t ON dt.refobjid = t.oid
JOIN pg_namespace nt ON t.relnamespace = nt.oid
JOIN pg_attribute a ON t.oid = a.attrelid AND dt.refobjsubid = a.attnum
view_column_usage as (
select distinct
v.oid as view_oid,
nv.nspname::information_schema.sql_identifier as view_schema,
v.relname::information_schema.sql_identifier as view_name,
nt.nspname::information_schema.sql_identifier as table_schema,
t.relname::information_schema.sql_identifier as table_name,
a.attname::information_schema.sql_identifier as column_name,
pg_get_viewdef(v.oid)::information_schema.character_data as view_definition
from pg_namespace nv
join pg_class v on nv.oid = v.relnamespace
join pg_depend dv on v.oid = dv.refobjid
join pg_depend dt on dv.objid = dt.objid
join pg_class t on dt.refobjid = t.oid
join pg_namespace nt on t.relnamespace = nt.oid
join pg_attribute a on t.oid = a.attrelid and dt.refobjsubid = a.attnum
WHERE
nv.nspname not in ('information_schema', 'pg_catalog')
AND v.relkind = 'v'::"char"
AND dv.refclassid = 'pg_class'::regclass::oid
AND dv.classid = 'pg_rewrite'::regclass::oid
AND dv.deptype = 'i'::"char"
AND dv.refobjid <> dt.refobjid
AND dt.classid = 'pg_rewrite'::regclass::oid
AND dt.refclassid = 'pg_class'::regclass::oid
AND (t.relkind = ANY (ARRAY['r'::"char", 'v'::"char", 'f'::"char"]))
where
nv.nspname not in ('information_schema', 'pg_catalog')
and v.relkind = 'v'::"char"
and dv.refclassid = 'pg_class'::regclass::oid
and dv.classid = 'pg_rewrite'::regclass::oid
and dv.deptype = 'i'::"char"
and dv.refobjid <> dt.refobjid
and dt.classid = 'pg_rewrite'::regclass::oid
and dt.refclassid = 'pg_class'::regclass::oid
and (t.relkind = any (array['r'::"char", 'v'::"char", 'f'::"char"]))
),
candidates AS (
SELECT
vcu.*,
(
SELECT CASE WHEN match IS NOT NULL THEN coalesce(match[7], match[4]) END
FROM REGEXP_MATCHES(
CONCAT('SELECT ', SPLIT_PART(vcu.view_definition, 'SELECT', 2)),
CONCAT('SELECT.*?((',vcu.table_name,')|(\w+))\.(', vcu.column_name, ')(\sAS\s(")?([^"]+)\6)?.*?FROM.*?',vcu.table_schema,'\.(\2|',vcu.table_name,'\s+(AS\s)?\3)'),
'ns'
) match
) AS view_column_name
FROM view_column_usage AS vcu
candidates as (
select
vcu.*,
(
select case when match is not null then coalesce(match[8], match[7], match[4]) end
from regexp_matches(
CONCAT('SELECT ', SPLIT_PART(vcu.view_definition, 'SELECT', 2)),
CONCAT('SELECT.*?((',vcu.table_name,')|(\w+))\.(', vcu.column_name, ')(\s+AS\s+("([^"]+)"|([^, \n\t]+)))?.*?FROM.*?',vcu.table_schema,'\.(\2|',vcu.table_name,'\s+(as\s)?\3)'),
'nsi'
) match
) as view_column_name
from view_column_usage as vcu
)
SELECT
c.table_schema,
c.table_name,
c.column_name AS table_column_name,
c.view_schema,
c.view_name,
c.view_column_name
FROM view_columns AS vc, candidates AS c
WHERE
vc.view_oid = c.view_oid AND
vc.column_name = c.view_column_name
ORDER BY c.view_schema, c.view_name, c.table_name, c.view_column_name
select
c.table_schema,
c.table_name,
c.column_name as table_column_name,
c.view_schema,
c.view_name,
c.view_column_name
from view_columns as vc, candidates as c
where
vc.view_oid = c.view_oid
and vc.column_name = c.view_column_name
order by c.view_schema, c.view_name, c.table_name, c.view_column_name
|]
synonymFromRow :: [Column] -> (Text,Text,Text,Text,Text,Text) -> Maybe (Column,Column)