Skip to content

Commit 03d71ae

Browse files
committed
Refactor sys.columns_internal to improve performance of sys.columns, sys.computed_columns, sys.identity_columns and sys.syscolumns
Signed-off-by: Rohit Bhagat <rohitbgt@amazon.com>
1 parent 6dd5375 commit 03d71ae

File tree

2 files changed

+526
-202
lines changed

2 files changed

+526
-202
lines changed

contrib/babelfishpg_tsql/sql/sys_views.sql

Lines changed: 156 additions & 202 deletions
Original file line numberDiff line numberDiff line change
@@ -462,204 +462,158 @@ and has_column_privilege(quote_ident(s.nspname) ||'.'||quote_ident(c.relname), a
462462
and a.attnum > 0;
463463
GRANT SELECT ON sys.all_columns TO PUBLIC;
464464

465-
-- internal function in order to workaround BABEL-1597
466-
CREATE OR REPLACE FUNCTION sys.columns_internal()
467-
RETURNS TABLE (
468-
out_object_id int,
469-
out_name sys.sysname,
470-
out_column_id int,
471-
out_system_type_id int,
472-
out_user_type_id int,
473-
out_max_length smallint,
474-
out_precision sys.tinyint,
475-
out_scale sys.tinyint,
476-
out_collation_name sys.sysname,
477-
out_collation_id int,
478-
out_offset smallint,
479-
out_is_nullable sys.bit,
480-
out_is_ansi_padded sys.bit,
481-
out_is_rowguidcol sys.bit,
482-
out_is_identity sys.bit,
483-
out_is_computed sys.bit,
484-
out_is_filestream sys.bit,
485-
out_is_replicated sys.bit,
486-
out_is_non_sql_subscribed sys.bit,
487-
out_is_merge_published sys.bit,
488-
out_is_dts_replicated sys.bit,
489-
out_is_xml_document sys.bit,
490-
out_xml_collection_id int,
491-
out_default_object_id int,
492-
out_rule_object_id int,
493-
out_is_sparse sys.bit,
494-
out_is_column_set sys.bit,
495-
out_generated_always_type sys.tinyint,
496-
out_generated_always_type_desc sys.nvarchar(60),
497-
out_encryption_type int,
498-
out_encryption_type_desc sys.nvarchar(64),
499-
out_encryption_algorithm_name sys.sysname,
500-
out_column_encryption_key_id int,
501-
out_column_encryption_key_database_name sys.sysname,
502-
out_is_hidden sys.bit,
503-
out_is_masked sys.bit,
504-
out_graph_type int,
505-
out_graph_type_desc sys.nvarchar(60)
506-
)
507-
AS
508-
$$
509-
BEGIN
510-
RETURN QUERY
511-
SELECT CAST(c.oid AS int),
512-
CAST(a.attname AS sys.sysname),
513-
CAST(a.attnum AS int),
514-
CASE
515-
WHEN tsql_type_name IS NOT NULL OR t.typbasetype = 0 THEN
516-
-- either tsql or PG base type
517-
CAST(a.atttypid AS int)
518-
ELSE
519-
CAST(t.typbasetype AS int)
520-
END,
521-
CAST(a.atttypid AS int),
522-
CASE
523-
WHEN a.atttypmod != -1 THEN
524-
sys.tsql_type_max_length_helper(coalesce(tsql_type_name, tsql_base_type_name), a.attlen, a.atttypmod)
525-
ELSE
526-
sys.tsql_type_max_length_helper(coalesce(tsql_type_name, tsql_base_type_name), a.attlen, t.typtypmod)
527-
END,
528-
CASE
529-
WHEN a.atttypmod != -1 THEN
530-
sys.tsql_type_precision_helper(coalesce(tsql_type_name, tsql_base_type_name), a.atttypmod)
531-
ELSE
532-
sys.tsql_type_precision_helper(coalesce(tsql_type_name, tsql_base_type_name), t.typtypmod)
533-
END,
534-
CASE
535-
WHEN a.atttypmod != -1 THEN
536-
sys.tsql_type_scale_helper(coalesce(tsql_type_name, tsql_base_type_name), a.atttypmod, false)
537-
ELSE
538-
sys.tsql_type_scale_helper(coalesce(tsql_type_name, tsql_base_type_name), t.typtypmod, false)
539-
END,
540-
CAST(coll.collname AS sys.sysname),
541-
CAST(a.attcollation AS int),
542-
CAST(a.attnum AS smallint),
543-
CAST(case when a.attnotnull then 0 else 1 end AS sys.bit),
544-
CAST(t.typname in ('bpchar', 'nchar', 'binary') AS sys.bit),
545-
CAST(0 AS sys.bit),
546-
CAST(a.attidentity <> ''::"char" AS sys.bit),
547-
CAST(a.attgenerated <> ''::"char" AS sys.bit),
548-
CAST(0 AS sys.bit),
549-
CAST(0 AS sys.bit),
550-
CAST(0 AS sys.bit),
551-
CAST(0 AS sys.bit),
552-
CAST(0 AS sys.bit),
553-
CAST(0 AS sys.bit),
554-
CAST(0 AS int),
555-
CAST(coalesce(d.oid, 0) AS int),
556-
CAST(coalesce((select oid from pg_constraint where conrelid = t.oid
557-
and contype = 'c' and a.attnum = any(conkey) limit 1), 0) AS int),
558-
CAST(0 AS sys.bit),
559-
CAST(0 AS sys.bit),
560-
CAST(0 AS sys.tinyint),
561-
CAST('NOT_APPLICABLE' AS sys.nvarchar(60)),
562-
CAST(null AS int),
563-
CAST(null AS sys.nvarchar(64)),
564-
CAST(null AS sys.sysname),
565-
CAST(null AS int),
566-
CAST(null AS sys.sysname),
567-
CAST(0 AS sys.bit),
568-
CAST(0 AS sys.bit),
569-
CAST(null AS int),
570-
CAST(null AS sys.nvarchar(60))
571-
FROM pg_attribute a
572-
INNER JOIN pg_class c ON c.oid = a.attrelid
573-
INNER JOIN pg_type t ON t.oid = a.atttypid
574-
INNER JOIN sys.schemas sch on c.relnamespace = sch.schema_id
575-
INNER JOIN sys.pg_namespace_ext ext on sch.schema_id = ext.oid
576-
LEFT JOIN pg_attrdef d ON c.oid = d.adrelid AND a.attnum = d.adnum
577-
LEFT JOIN pg_collation coll ON coll.oid = a.attcollation
578-
, sys.translate_pg_type_to_tsql(a.atttypid) AS tsql_type_name
579-
, sys.translate_pg_type_to_tsql(t.typbasetype) AS tsql_base_type_name
580-
WHERE NOT a.attisdropped
581-
AND a.attnum > 0
582-
-- r = ordinary table, i = index, S = sequence, t = TOAST table, v = view, m = materialized view, c = composite type, f = foreign table, p = partitioned table
583-
AND c.relkind IN ('r', 'v', 'm', 'f', 'p')
584-
AND c.relispartition = false
585-
AND has_column_privilege(a.attrelid, a.attname, 'SELECT,INSERT,UPDATE,REFERENCES')
586-
union all
587-
-- system tables information
588-
SELECT CAST(c.oid AS int),
589-
CAST(a.attname AS sys.sysname),
590-
CAST(a.attnum AS int),
591-
CASE
592-
WHEN tsql_type_name IS NOT NULL OR t.typbasetype = 0 THEN
593-
-- either tsql or PG base type
594-
CAST(a.atttypid AS int)
595-
ELSE
596-
CAST(t.typbasetype AS int)
597-
END,
598-
CAST(a.atttypid AS int),
599-
CASE
600-
WHEN a.atttypmod != -1 THEN
601-
sys.tsql_type_max_length_helper(coalesce(tsql_type_name, tsql_base_type_name), a.attlen, a.atttypmod)
602-
ELSE
603-
sys.tsql_type_max_length_helper(coalesce(tsql_type_name, tsql_base_type_name), a.attlen, t.typtypmod)
604-
END,
605-
CASE
606-
WHEN a.atttypmod != -1 THEN
607-
sys.tsql_type_precision_helper(coalesce(tsql_type_name, tsql_base_type_name), a.atttypmod)
608-
ELSE
609-
sys.tsql_type_precision_helper(coalesce(tsql_type_name, tsql_base_type_name), t.typtypmod)
610-
END,
611-
CASE
612-
WHEN a.atttypmod != -1 THEN
613-
sys.tsql_type_scale_helper(coalesce(tsql_type_name, tsql_base_type_name), a.atttypmod, false)
614-
ELSE
615-
sys.tsql_type_scale_helper(coalesce(tsql_type_name, tsql_base_type_name), t.typtypmod, false)
616-
END,
617-
CAST(coll.collname AS sys.sysname),
618-
CAST(a.attcollation AS int),
619-
CAST(a.attnum AS smallint),
620-
CAST(case when a.attnotnull then 0 else 1 end AS sys.bit),
621-
CAST(t.typname in ('bpchar', 'nchar', 'binary') AS sys.bit),
622-
CAST(0 AS sys.bit),
623-
CAST(a.attidentity <> ''::"char" AS sys.bit),
624-
CAST(a.attgenerated <> ''::"char" AS sys.bit),
625-
CAST(0 AS sys.bit),
626-
CAST(0 AS sys.bit),
627-
CAST(0 AS sys.bit),
628-
CAST(0 AS sys.bit),
629-
CAST(0 AS sys.bit),
630-
CAST(0 AS sys.bit),
631-
CAST(0 AS int),
632-
CAST(coalesce(d.oid, 0) AS int),
633-
CAST(coalesce((select oid from pg_constraint where conrelid = t.oid
634-
and contype = 'c' and a.attnum = any(conkey) limit 1), 0) AS int),
635-
CAST(0 AS sys.bit),
636-
CAST(0 AS sys.bit),
637-
CAST(0 AS sys.tinyint),
638-
CAST('NOT_APPLICABLE' AS sys.nvarchar(60)),
639-
CAST(null AS int),
640-
CAST(null AS sys.nvarchar(64)),
641-
CAST(null AS sys.sysname),
642-
CAST(null AS int),
643-
CAST(null AS sys.sysname),
644-
CAST(0 AS sys.bit),
645-
CAST(0 AS sys.bit),
646-
CAST(null AS int),
647-
CAST(null AS sys.nvarchar(60))
648-
FROM pg_attribute a
649-
INNER JOIN pg_class c ON c.oid = a.attrelid
650-
INNER JOIN pg_type t ON t.oid = a.atttypid
651-
INNER JOIN pg_namespace nsp ON (nsp.oid = c.relnamespace and nsp.nspname = 'sys')
652-
LEFT JOIN pg_attrdef d ON c.oid = d.adrelid AND a.attnum = d.adnum
653-
LEFT JOIN pg_collation coll ON coll.oid = a.attcollation
654-
, sys.translate_pg_type_to_tsql(a.atttypid) AS tsql_type_name
655-
, sys.translate_pg_type_to_tsql(t.typbasetype) AS tsql_base_type_name
656-
WHERE NOT a.attisdropped
657-
AND a.attnum > 0
658-
AND c.relkind = 'r'
659-
AND has_column_privilege(a.attrelid, a.attname, 'SELECT,INSERT,UPDATE,REFERENCES');
660-
END;
661-
$$
662-
language plpgsql STABLE;
465+
-- internal view (converted from function for better query optimization)
466+
CREATE OR REPLACE VIEW sys.columns_internal AS
467+
SELECT CAST(c.oid AS int) AS out_object_id,
468+
CAST(a.attname AS sys.sysname) AS out_name,
469+
CAST(a.attnum AS int) AS out_column_id,
470+
CASE
471+
WHEN tsql_type_name IS NOT NULL OR t.typbasetype = 0 THEN
472+
-- either tsql or PG base type
473+
CAST(a.atttypid AS int)
474+
ELSE
475+
CAST(t.typbasetype AS int)
476+
END AS out_system_type_id,
477+
CAST(a.atttypid AS int) AS out_user_type_id,
478+
CASE
479+
WHEN a.atttypmod != -1 THEN
480+
CAST(sys.tsql_type_max_length_helper(coalesce(tsql_type_name, tsql_base_type_name), a.attlen, a.atttypmod) AS smallint)
481+
ELSE
482+
CAST(sys.tsql_type_max_length_helper(coalesce(tsql_type_name, tsql_base_type_name), a.attlen, t.typtypmod) AS smallint)
483+
END AS out_max_length,
484+
CASE
485+
WHEN a.atttypmod != -1 THEN
486+
CAST(sys.tsql_type_precision_helper(coalesce(tsql_type_name, tsql_base_type_name), a.atttypmod) AS sys.tinyint)
487+
ELSE
488+
CAST(sys.tsql_type_precision_helper(coalesce(tsql_type_name, tsql_base_type_name), t.typtypmod) AS sys.tinyint)
489+
END AS out_precision,
490+
CASE
491+
WHEN a.atttypmod != -1 THEN
492+
CAST(sys.tsql_type_scale_helper(coalesce(tsql_type_name, tsql_base_type_name), a.atttypmod, false) AS sys.tinyint)
493+
ELSE
494+
CAST(sys.tsql_type_scale_helper(coalesce(tsql_type_name, tsql_base_type_name), t.typtypmod, false) AS sys.tinyint)
495+
END AS out_scale,
496+
CAST(coll.collname AS sys.sysname) AS out_collation_name,
497+
CAST(a.attcollation AS int) AS out_collation_id,
498+
CAST(a.attnum AS smallint) AS out_offset,
499+
CAST(case when a.attnotnull then 0 else 1 end AS sys.bit) AS out_is_nullable,
500+
CAST(t.typname in ('bpchar', 'nchar', 'binary') AS sys.bit) AS out_is_ansi_padded,
501+
CAST(0 AS sys.bit) AS out_is_rowguidcol,
502+
CAST(a.attidentity <> ''::"char" AS sys.bit) AS out_is_identity,
503+
CAST(a.attgenerated <> ''::"char" AS sys.bit) AS out_is_computed,
504+
CAST(0 AS sys.bit) AS out_is_filestream,
505+
CAST(0 AS sys.bit) AS out_is_replicated,
506+
CAST(0 AS sys.bit) AS out_is_non_sql_subscribed,
507+
CAST(0 AS sys.bit) AS out_is_merge_published,
508+
CAST(0 AS sys.bit) AS out_is_dts_replicated,
509+
CAST(0 AS sys.bit) AS out_is_xml_document,
510+
CAST(0 AS int) AS out_xml_collection_id,
511+
CAST(coalesce(d.oid, 0) AS int) AS out_default_object_id,
512+
CAST(coalesce((select oid from pg_constraint where conrelid = t.oid
513+
and contype = 'c' and a.attnum = any(conkey) limit 1), 0) AS int) AS out_rule_object_id,
514+
CAST(0 AS sys.bit) AS out_is_sparse,
515+
CAST(0 AS sys.bit) AS out_is_column_set,
516+
CAST(0 AS sys.tinyint) AS out_generated_always_type,
517+
CAST('NOT_APPLICABLE' AS sys.nvarchar) AS out_generated_always_type_desc,
518+
CAST(null AS int) AS out_encryption_type,
519+
CAST(null AS sys.nvarchar) AS out_encryption_type_desc,
520+
CAST(null AS sys.sysname) AS out_encryption_algorithm_name,
521+
CAST(null AS int) AS out_column_encryption_key_id,
522+
CAST(null AS sys.sysname) AS out_column_encryption_key_database_name,
523+
CAST(0 AS sys.bit) AS out_is_hidden,
524+
CAST(0 AS sys.bit) AS out_is_masked,
525+
CAST(null AS int) AS out_graph_type,
526+
CAST(null AS sys.nvarchar) AS out_graph_type_desc
527+
FROM pg_attribute a
528+
INNER JOIN pg_class c ON c.oid = a.attrelid
529+
INNER JOIN pg_type t ON t.oid = a.atttypid
530+
INNER JOIN sys.schemas sch on c.relnamespace = sch.schema_id
531+
INNER JOIN sys.pg_namespace_ext ext on sch.schema_id = ext.oid
532+
LEFT JOIN pg_attrdef d ON c.oid = d.adrelid AND a.attnum = d.adnum
533+
LEFT JOIN pg_collation coll ON coll.oid = a.attcollation
534+
, sys.translate_pg_type_to_tsql(a.atttypid) AS tsql_type_name
535+
, sys.translate_pg_type_to_tsql(t.typbasetype) AS tsql_base_type_name
536+
WHERE NOT a.attisdropped
537+
AND a.attnum > 0
538+
-- r = ordinary table, i = index, S = sequence, t = TOAST table, v = view, m = materialized view, c = composite type, f = foreign table, p = partitioned table
539+
AND c.relkind IN ('r', 'v', 'm', 'f', 'p')
540+
AND c.relispartition = false
541+
AND has_column_privilege(a.attrelid, a.attname, 'SELECT,INSERT,UPDATE,REFERENCES')
542+
union all
543+
-- system tables information
544+
SELECT CAST(c.oid AS int),
545+
CAST(a.attname AS sys.sysname),
546+
CAST(a.attnum AS int),
547+
CASE
548+
WHEN tsql_type_name IS NOT NULL OR t.typbasetype = 0 THEN
549+
-- either tsql or PG base type
550+
CAST(a.atttypid AS int)
551+
ELSE
552+
CAST(t.typbasetype AS int)
553+
END,
554+
CAST(a.atttypid AS int),
555+
CASE
556+
WHEN a.atttypmod != -1 THEN
557+
sys.tsql_type_max_length_helper(coalesce(tsql_type_name, tsql_base_type_name), a.attlen, a.atttypmod)
558+
ELSE
559+
sys.tsql_type_max_length_helper(coalesce(tsql_type_name, tsql_base_type_name), a.attlen, t.typtypmod)
560+
END,
561+
CASE
562+
WHEN a.atttypmod != -1 THEN
563+
sys.tsql_type_precision_helper(coalesce(tsql_type_name, tsql_base_type_name), a.atttypmod)
564+
ELSE
565+
sys.tsql_type_precision_helper(coalesce(tsql_type_name, tsql_base_type_name), t.typtypmod)
566+
END,
567+
CASE
568+
WHEN a.atttypmod != -1 THEN
569+
sys.tsql_type_scale_helper(coalesce(tsql_type_name, tsql_base_type_name), a.atttypmod, false)
570+
ELSE
571+
sys.tsql_type_scale_helper(coalesce(tsql_type_name, tsql_base_type_name), t.typtypmod, false)
572+
END,
573+
CAST(coll.collname AS sys.sysname),
574+
CAST(a.attcollation AS int),
575+
CAST(a.attnum AS smallint),
576+
CAST(case when a.attnotnull then 0 else 1 end AS sys.bit),
577+
CAST(t.typname in ('bpchar', 'nchar', 'binary') AS sys.bit),
578+
CAST(0 AS sys.bit),
579+
CAST(a.attidentity <> ''::"char" AS sys.bit),
580+
CAST(a.attgenerated <> ''::"char" AS sys.bit),
581+
CAST(0 AS sys.bit),
582+
CAST(0 AS sys.bit),
583+
CAST(0 AS sys.bit),
584+
CAST(0 AS sys.bit),
585+
CAST(0 AS sys.bit),
586+
CAST(0 AS sys.bit),
587+
CAST(0 AS int),
588+
CAST(coalesce(d.oid, 0) AS int),
589+
CAST(coalesce((select oid from pg_constraint where conrelid = t.oid
590+
and contype = 'c' and a.attnum = any(conkey) limit 1), 0) AS int),
591+
CAST(0 AS sys.bit),
592+
CAST(0 AS sys.bit),
593+
CAST(0 AS sys.tinyint),
594+
CAST('NOT_APPLICABLE' AS sys.nvarchar),
595+
CAST(null AS int),
596+
CAST(null AS sys.nvarchar),
597+
CAST(null AS sys.sysname),
598+
CAST(null AS int),
599+
CAST(null AS sys.sysname),
600+
CAST(0 AS sys.bit),
601+
CAST(0 AS sys.bit),
602+
CAST(null AS int),
603+
CAST(null AS sys.nvarchar)
604+
FROM pg_attribute a
605+
INNER JOIN pg_class c ON c.oid = a.attrelid
606+
INNER JOIN pg_type t ON t.oid = a.atttypid
607+
INNER JOIN pg_namespace nsp ON (nsp.oid = c.relnamespace and nsp.nspname = 'sys')
608+
LEFT JOIN pg_attrdef d ON c.oid = d.adrelid AND a.attnum = d.adnum
609+
LEFT JOIN pg_collation coll ON coll.oid = a.attcollation
610+
, sys.translate_pg_type_to_tsql(a.atttypid) AS tsql_type_name
611+
, sys.translate_pg_type_to_tsql(t.typbasetype) AS tsql_base_type_name
612+
WHERE NOT a.attisdropped
613+
AND a.attnum > 0
614+
AND c.relkind = 'r'
615+
AND has_column_privilege(a.attrelid, a.attname, 'SELECT,INSERT,UPDATE,REFERENCES');
616+
GRANT SELECT ON sys.columns_internal TO PUBLIC;
663617

664618
create or replace view sys.columns AS
665619
select out_object_id as object_id
@@ -698,7 +652,7 @@ select out_object_id as object_id
698652
, out_is_masked as is_masked
699653
, out_graph_type as graph_type
700654
, out_graph_type_desc as graph_type_desc
701-
from sys.columns_internal();
655+
from sys.columns_internal;
702656
GRANT SELECT ON sys.columns TO PUBLIC;
703657

704658
CREATE OR replace view sys.foreign_key_columns as
@@ -815,7 +769,7 @@ SELECT
815769
, CAST(sys.ident_incr(OBJECT_NAME(sc.out_object_id)) AS SQL_VARIANT) AS increment_value
816770
, CAST(sys.babelfish_get_sequence_value(pg_get_serial_sequence(quote_ident(ext.nspname)||'.'||quote_ident(c.relname), a.attname)) AS SQL_VARIANT) AS last_value
817771
, CAST(0 as sys.BIT) as is_not_for_replication
818-
FROM sys.columns_internal() sc
772+
FROM sys.columns_internal sc
819773
INNER JOIN pg_attribute a ON a.attrelid = sc.out_object_id AND sc.out_column_id = a.attnum
820774
INNER JOIN pg_class c ON c.oid = a.attrelid
821775
INNER JOIN sys.pg_namespace_ext ext ON ext.oid = c.relnamespace
@@ -2128,7 +2082,7 @@ SELECT out_object_id as object_id
21282082
, cast(tsql_get_expr(d.adbin, d.adrelid) AS sys.nvarchar) AS definition
21292083
, 1::sys.bit AS uses_database_collation
21302084
, 1::sys.bit AS is_persisted
2131-
FROM sys.columns_internal() sc
2085+
FROM sys.columns_internal sc
21322086
INNER JOIN pg_attribute a ON sc.out_object_id = a.attrelid AND sc.out_column_id = a.attnum
21332087
INNER JOIN pg_attrdef d ON d.adrelid = a.attrelid AND d.adnum = a.attnum
21342088
WHERE a.attgenerated = 's' AND sc.out_is_computed::integer = 1;
@@ -2304,7 +2258,7 @@ SELECT out_name as name
23042258
, 0::int as isoutparam
23052259
, out_is_nullable::int as isnullable
23062260
, out_collation_name::sys.sysname as collation
2307-
FROM sys.columns_internal()
2261+
FROM sys.columns_internal
23082262
union all
23092263
SELECT p.name
23102264
, p.id

0 commit comments

Comments
 (0)