From 649f219568cd7b5809ff546e22cca276da8dd5e2 Mon Sep 17 00:00:00 2001 From: Marcus Gartner Date: Wed, 1 Feb 2023 17:58:10 -0500 Subject: [PATCH] builtins: mark some pg_.* builtins as strict Builtins defined using the UDF `Body` field will be wrapped in a `CASE` expression if they are strict, i.e., `CalledOnNullInput=false`. When the builtin is inlined, the `CASE` expression prevents decorrelation, leaving a slow apply-join in the query plan. This caused a significant regression of some ORM introspection queries. Some of these builtins have filters that cause the SQL body to return no rows if any of the arguments is NULL. In this case, the builtin will have the same behavior whether or not it is defined as being strict. We can safely optimize these builtins by setting `CalledOnNullInput=true`. The following conditions are sufficient to prove that `CalledOnNullInput` can be set for a builtin function with a SQL body: 1. The WHERE clause of the SQL query *null-rejects* every argument of the builtin. Operators like `=` and `<` *null-reject* their operands because they filter rows for which an operand is NULL. 2. The arguments are not used elsewhere in the query. This is not strictly necessary, but simplifies the proof because it ensures NULL arguments will not cause the builtin to error. Examples of SQL statements that would allow `CalledOnNullInput` to be set: ``` SELECT * FROM tab WHERE $1=1 AND $2='two'; SELECT * FROM tab WHERE $1 > 0; ``` Fixes #96218 Fixes #95569 Epic: None Release note: None --- .../testdata/benchmark_expectations | 4 +- .../opt/xform/testdata/external/activerecord | 173 ++++++------ pkg/sql/opt/xform/testdata/external/liquibase | 261 +++++++++--------- pkg/sql/opt/xform/testdata/external/navicat | 261 +++++++++--------- pkg/sql/opt/xform/testdata/external/pgjdbc | 18 +- pkg/sql/sem/builtins/builtins_test.go | 80 ++++++ pkg/sql/sem/builtins/pg_builtins.go | 70 +++-- 7 files changed, 481 insertions(+), 386 deletions(-) diff --git a/pkg/bench/rttanalysis/testdata/benchmark_expectations b/pkg/bench/rttanalysis/testdata/benchmark_expectations index ce8b91c7fe35..3baefa02d1aa 100644 --- a/pkg/bench/rttanalysis/testdata/benchmark_expectations +++ b/pkg/bench/rttanalysis/testdata/benchmark_expectations @@ -64,8 +64,8 @@ exp,benchmark 4,ORMQueries/django_column_introspection_1_table 4,ORMQueries/django_column_introspection_4_tables 4,ORMQueries/django_column_introspection_8_tables -3,ORMQueries/django_table_introspection_1_table -3,ORMQueries/django_table_introspection_8_tables +5,ORMQueries/django_table_introspection_1_table +5,ORMQueries/django_table_introspection_8_tables 0,ORMQueries/has_column_privilege_using_attnum 0,ORMQueries/has_column_privilege_using_column_name 0,ORMQueries/has_schema_privilege diff --git a/pkg/sql/opt/xform/testdata/external/activerecord b/pkg/sql/opt/xform/testdata/external/activerecord index 60f27c1ca974..af051a26e8af 100644 --- a/pkg/sql/opt/xform/testdata/external/activerecord +++ b/pkg/sql/opt/xform/testdata/external/activerecord @@ -118,98 +118,109 @@ sort ├── columns: attname:2!null format_type:75 pg_get_expr:76 attnotnull:13!null atttypid:3!null atttypmod:9!null collname:77 comment:85 [hidden: attnum:6!null] ├── stable ├── key: (6) - ├── fd: (6)-->(2,3,9,13,75-77,85), (2)-->(3,6,9,13,75-77), (3,9)-->(75) + ├── fd: (6)-->(2,3,9,13,75-77,85), (2)-->(3,6,9,13,75-77,85), (3,9)-->(75) ├── ordering: +6 └── project ├── columns: format_type:75 pg_get_expr:76 collname:77 comment:85 attname:2!null atttypid:3!null attnum:6!null atttypmod:9!null attnotnull:13!null ├── stable ├── key: (6) - ├── fd: (6)-->(2,3,9,13,75-77,85), (2)-->(3,6,9,13,75-77), (3,9)-->(75) - ├── right-join (hash) - │ ├── columns: attrelid:1!null attname:2!null atttypid:3!null attnum:6!null atttypmod:9!null attnotnull:13!null attisdropped:17!null attcollation:20!null adrelid:27 adnum:28 adbin:29 c.oid:33 c.collname:34 t.oid:42 typcollation:69 + ├── fd: (6)-->(2,3,9,13,75-77,85), (2)-->(3,6,9,13,75-77,85), (3,9)-->(75) + ├── distinct-on + │ ├── columns: attname:2!null atttypid:3!null attnum:6!null atttypmod:9!null attnotnull:13!null adrelid:27 adbin:29 c.collname:34 c.comment:84 + │ ├── grouping columns: attnum:6!null + │ ├── immutable │ ├── key: (6) - │ ├── fd: ()-->(1,17), (6)-->(2,3,9,13,20,27-29,33,34,42,69), (2)-->(3,6,9,13,20), (28)-->(29), (33)-->(34), (42)-->(69) - │ ├── inner-join (cross) - │ │ ├── columns: c.oid:33!null c.collname:34!null t.oid:42!null typcollation:69!null - │ │ ├── key: (33,42) - │ │ ├── fd: (33)-->(34), (42)-->(69) - │ │ ├── scan pg_collation@pg_collation_name_enc_nsp_index [as=c] - │ │ │ ├── columns: c.oid:33!null c.collname:34!null - │ │ │ ├── key: (33) - │ │ │ └── fd: (33)-->(34) - │ │ ├── scan pg_type [as=t] - │ │ │ ├── columns: t.oid:42!null typcollation:69!null - │ │ │ ├── key: (42) - │ │ │ └── fd: (42)-->(69) - │ │ └── filters - │ │ └── c.oid:33 != typcollation:69 [outer=(33,69), constraints=(/33: (/NULL - ]; /69: (/NULL - ])] - │ ├── left-join (lookup pg_attrdef [as=d]) - │ │ ├── columns: attrelid:1!null attname:2!null atttypid:3!null attnum:6!null atttypmod:9!null attnotnull:13!null attisdropped:17!null attcollation:20!null adrelid:27 adnum:28 adbin:29 - │ │ ├── key columns: [26] = [26] - │ │ ├── lookup columns are key - │ │ ├── key: (6) - │ │ ├── fd: ()-->(1,17), (6)-->(2,3,9,13,20,27-29), (2)-->(3,6,9,13,20), (28)-->(29) - │ │ ├── left-join (lookup pg_attrdef@pg_attrdef_adrelid_adnum_index [as=d]) - │ │ │ ├── columns: attrelid:1!null attname:2!null atttypid:3!null attnum:6!null atttypmod:9!null attnotnull:13!null attisdropped:17!null attcollation:20!null d.oid:26 adrelid:27 adnum:28 - │ │ │ ├── key columns: [1 6] = [27 28] - │ │ │ ├── lookup columns are key + │ ├── fd: (6)-->(2,3,9,13,27,29,34,84), (2)-->(3,6,9,13,27,29,34) + │ ├── right-join (hash) + │ │ ├── columns: attrelid:1!null attname:2!null atttypid:3!null attnum:6!null atttypmod:9!null attnotnull:13!null adrelid:27 adbin:29 c.collname:34 type:81 object_id:82 sub_id:83 c.comment:84 column86:86!null + │ │ ├── immutable + │ │ ├── fd: ()-->(1,86), (6)-->(2,3,9,13,27,29,34), (2)-->(3,6,9,13,27,29,34) + │ │ ├── select + │ │ │ ├── columns: type:81!null object_id:82!null sub_id:83!null c.comment:84!null + │ │ │ ├── fd: ()-->(81) + │ │ │ ├── scan comments [as=c] + │ │ │ │ └── columns: type:81!null object_id:82!null sub_id:83!null c.comment:84!null + │ │ │ └── filters + │ │ │ ├── type:81 = 2 [outer=(81), constraints=(/81: [/2 - /2]; tight), fd=()-->(81)] + │ │ │ └── sub_id:83 != 0 [outer=(83), constraints=(/83: (/NULL - /-1] [/1 - ]; tight)] + │ │ ├── project + │ │ │ ├── columns: column86:86!null attrelid:1!null attname:2!null atttypid:3!null attnum:6!null atttypmod:9!null attnotnull:13!null adrelid:27 adbin:29 c.collname:34 + │ │ │ ├── immutable │ │ │ ├── key: (6) - │ │ │ ├── fd: ()-->(1,17), (6)-->(2,3,9,13,20,26-28), (2)-->(3,6,9,13,20), (26)-->(27,28), (27,28)-->(26) - │ │ │ ├── select - │ │ │ │ ├── columns: attrelid:1!null attname:2!null atttypid:3!null attnum:6!null atttypmod:9!null attnotnull:13!null attisdropped:17!null attcollation:20!null + │ │ │ ├── fd: ()-->(1,86), (6)-->(2,3,9,13,27,29,34), (2)-->(3,6,9,13,27,29,34) + │ │ │ ├── right-join (hash) + │ │ │ │ ├── columns: attrelid:1!null attname:2!null atttypid:3!null attnum:6!null atttypmod:9!null attnotnull:13!null attisdropped:17!null attcollation:20!null adrelid:27 adnum:28 adbin:29 c.oid:33 c.collname:34 t.oid:42 typcollation:69 │ │ │ │ ├── key: (6) - │ │ │ │ ├── fd: ()-->(1,17), (6)-->(2,3,9,13,20), (2)-->(3,6,9,13,20) - │ │ │ │ ├── scan pg_attribute [as=a] - │ │ │ │ │ ├── columns: attrelid:1!null attname:2!null atttypid:3!null attnum:6!null atttypmod:9!null attnotnull:13!null attisdropped:17!null attcollation:20!null - │ │ │ │ │ ├── constraint: /1/6: [/numbers/1 - /numbers] + │ │ │ │ ├── fd: ()-->(1,17), (6)-->(2,3,9,13,20,27-29,33,34,42,69), (2)-->(3,6,9,13,20), (28)-->(29), (33)-->(34), (42)-->(69) + │ │ │ │ ├── inner-join (cross) + │ │ │ │ │ ├── columns: c.oid:33!null c.collname:34!null t.oid:42!null typcollation:69!null + │ │ │ │ │ ├── key: (33,42) + │ │ │ │ │ ├── fd: (33)-->(34), (42)-->(69) + │ │ │ │ │ ├── scan pg_collation@pg_collation_name_enc_nsp_index [as=c] + │ │ │ │ │ │ ├── columns: c.oid:33!null c.collname:34!null + │ │ │ │ │ │ ├── key: (33) + │ │ │ │ │ │ └── fd: (33)-->(34) + │ │ │ │ │ ├── scan pg_type [as=t] + │ │ │ │ │ │ ├── columns: t.oid:42!null typcollation:69!null + │ │ │ │ │ │ ├── key: (42) + │ │ │ │ │ │ └── fd: (42)-->(69) + │ │ │ │ │ └── filters + │ │ │ │ │ └── c.oid:33 != typcollation:69 [outer=(33,69), constraints=(/33: (/NULL - ]; /69: (/NULL - ])] + │ │ │ │ ├── left-join (lookup pg_attrdef [as=d]) + │ │ │ │ │ ├── columns: attrelid:1!null attname:2!null atttypid:3!null attnum:6!null atttypmod:9!null attnotnull:13!null attisdropped:17!null attcollation:20!null adrelid:27 adnum:28 adbin:29 + │ │ │ │ │ ├── key columns: [26] = [26] + │ │ │ │ │ ├── lookup columns are key │ │ │ │ │ ├── key: (6) - │ │ │ │ │ └── fd: ()-->(1), (6)-->(2,3,9,13,17,20), (2)-->(3,6,9,13,17,20) + │ │ │ │ │ ├── fd: ()-->(1,17), (6)-->(2,3,9,13,20,27-29), (2)-->(3,6,9,13,20), (28)-->(29) + │ │ │ │ │ ├── left-join (lookup pg_attrdef@pg_attrdef_adrelid_adnum_index [as=d]) + │ │ │ │ │ │ ├── columns: attrelid:1!null attname:2!null atttypid:3!null attnum:6!null atttypmod:9!null attnotnull:13!null attisdropped:17!null attcollation:20!null d.oid:26 adrelid:27 adnum:28 + │ │ │ │ │ │ ├── key columns: [1 6] = [27 28] + │ │ │ │ │ │ ├── lookup columns are key + │ │ │ │ │ │ ├── key: (6) + │ │ │ │ │ │ ├── fd: ()-->(1,17), (6)-->(2,3,9,13,20,26-28), (2)-->(3,6,9,13,20), (26)-->(27,28), (27,28)-->(26) + │ │ │ │ │ │ ├── select + │ │ │ │ │ │ │ ├── columns: attrelid:1!null attname:2!null atttypid:3!null attnum:6!null atttypmod:9!null attnotnull:13!null attisdropped:17!null attcollation:20!null + │ │ │ │ │ │ │ ├── key: (6) + │ │ │ │ │ │ │ ├── fd: ()-->(1,17), (6)-->(2,3,9,13,20), (2)-->(3,6,9,13,20) + │ │ │ │ │ │ │ ├── scan pg_attribute [as=a] + │ │ │ │ │ │ │ │ ├── columns: attrelid:1!null attname:2!null atttypid:3!null attnum:6!null atttypmod:9!null attnotnull:13!null attisdropped:17!null attcollation:20!null + │ │ │ │ │ │ │ │ ├── constraint: /1/6: [/numbers/1 - /numbers] + │ │ │ │ │ │ │ │ ├── key: (6) + │ │ │ │ │ │ │ │ └── fd: ()-->(1), (6)-->(2,3,9,13,17,20), (2)-->(3,6,9,13,17,20) + │ │ │ │ │ │ │ └── filters + │ │ │ │ │ │ │ └── NOT attisdropped:17 [outer=(17), constraints=(/17: [/false - /false]; tight), fd=()-->(17)] + │ │ │ │ │ │ └── filters + │ │ │ │ │ │ ├── adrelid:27 = numbers [outer=(27), constraints=(/27: [/numbers - /numbers]; tight), fd=()-->(27)] + │ │ │ │ │ │ └── adnum:28 > 0 [outer=(28), constraints=(/28: [/1 - ]; tight)] + │ │ │ │ │ └── filters (true) │ │ │ │ └── filters - │ │ │ │ └── NOT attisdropped:17 [outer=(17), constraints=(/17: [/false - /false]; tight), fd=()-->(17)] - │ │ │ └── filters - │ │ │ ├── adrelid:27 = numbers [outer=(27), constraints=(/27: [/numbers - /numbers]; tight), fd=()-->(27)] - │ │ │ └── adnum:28 > 0 [outer=(28), constraints=(/28: [/1 - ]; tight)] - │ │ └── filters (true) - │ └── filters - │ ├── c.oid:33 = attcollation:20 [outer=(20,33), constraints=(/20: (/NULL - ]; /33: (/NULL - ]), fd=(20)==(33), (33)==(20)] - │ └── t.oid:42 = atttypid:3 [outer=(3,42), constraints=(/3: (/NULL - ]; /42: (/NULL - ]), fd=(3)==(42), (42)==(3)] + │ │ │ │ ├── c.oid:33 = attcollation:20 [outer=(20,33), constraints=(/20: (/NULL - ]; /33: (/NULL - ]), fd=(20)==(33), (33)==(20)] + │ │ │ │ └── t.oid:42 = atttypid:3 [outer=(3,42), constraints=(/3: (/NULL - ]; /42: (/NULL - ]), fd=(3)==(42), (42)==(3)] + │ │ │ └── projections + │ │ │ └── attrelid:1::INT8 [as=column86:86, outer=(1), immutable] + │ │ └── filters + │ │ ├── column86:86 = object_id:82 [outer=(82,86), constraints=(/82: (/NULL - ]; /86: (/NULL - ]), fd=(82)==(86), (86)==(82)] + │ │ ├── sub_id:83 = attnum:6 [outer=(6,83), constraints=(/6: (/NULL - ]; /83: (/NULL - ]), fd=(6)==(83), (83)==(6)] + │ │ └── attrelid:1 < 4294966993 [outer=(1), constraints=(/1: (/NULL - /4294966992]; tight)] + │ └── aggregations + │ ├── const-agg [as=attname:2, outer=(2)] + │ │ └── attname:2 + │ ├── const-agg [as=atttypid:3, outer=(3)] + │ │ └── atttypid:3 + │ ├── const-agg [as=atttypmod:9, outer=(9)] + │ │ └── atttypmod:9 + │ ├── const-agg [as=attnotnull:13, outer=(13)] + │ │ └── attnotnull:13 + │ ├── const-agg [as=adrelid:27, outer=(27)] + │ │ └── adrelid:27 + │ ├── const-agg [as=adbin:29, outer=(29)] + │ │ └── adbin:29 + │ ├── const-agg [as=c.collname:34, outer=(34)] + │ │ └── c.collname:34 + │ └── first-agg [as=c.comment:84, outer=(84)] + │ └── c.comment:84 └── projections ├── format_type(atttypid:3, atttypmod:9) [as=format_type:75, outer=(3,9), stable] ├── pg_get_expr(adbin:29, adrelid:27) [as=pg_get_expr:76, outer=(27,29), stable] ├── c.collname:34 [as=collname:77, outer=(34)] - └── case [as=comment:85, outer=(1,6), immutable, correlated-subquery] - ├── true - ├── when - │ ├── (attnum:6 IS NULL) OR (attrelid:1 IS NULL) - │ └── CAST(NULL AS STRING) - └── subquery - └── project - ├── columns: c.comment:84!null - ├── outer: (1,6) - ├── cardinality: [0 - 1] - ├── immutable - ├── key: () - ├── fd: ()-->(84) - └── limit - ├── columns: type:81!null object_id:82!null sub_id:83!null c.comment:84!null - ├── outer: (1,6) - ├── cardinality: [0 - 1] - ├── immutable - ├── key: () - ├── fd: ()-->(81-84) - ├── select - │ ├── columns: type:81!null object_id:82!null sub_id:83!null c.comment:84!null - │ ├── outer: (1,6) - │ ├── immutable - │ ├── fd: ()-->(81-83) - │ ├── limit hint: 1.00 - │ ├── scan comments [as=c] - │ │ ├── columns: type:81!null object_id:82!null sub_id:83!null c.comment:84!null - │ │ └── limit hint: 300.00 - │ └── filters - │ ├── type:81 = 2 [outer=(81), constraints=(/81: [/2 - /2]; tight), fd=()-->(81)] - │ ├── object_id:82 = attrelid:1::INT8 [outer=(1,82), immutable, constraints=(/82: (/NULL - ]), fd=(1)-->(82)] - │ ├── sub_id:83 = attnum:6 [outer=(6,83), constraints=(/6: (/NULL - ]; /83: (/NULL - ]), fd=(6)==(83), (83)==(6)] - │ ├── attrelid:1 < 4294966993 [outer=(1), constraints=(/1: (/NULL - /4294966992]; tight)] - │ └── attnum:6 != 0 [outer=(6), constraints=(/6: (/NULL - /-1] [/1 - ]; tight)] - └── 1 + └── c.comment:84 [as=comment:85, outer=(84)] diff --git a/pkg/sql/opt/xform/testdata/external/liquibase b/pkg/sql/opt/xform/testdata/external/liquibase index 7585f0a05df3..45219961e5ba 100644 --- a/pkg/sql/opt/xform/testdata/external/liquibase +++ b/pkg/sql/opt/xform/testdata/external/liquibase @@ -165,117 +165,154 @@ project ├── immutable ├── fd: ()-->(31), (1)-->(2,10,13,15,17,20,22,23,26,27,37), (2)-->(1,10,13,15,17,20,22,23,26,27,37) ├── group-by (hash) - │ ├── columns: c.oid:1!null c.relname:2!null c.relowner:5!null c.reltuples:10!null c.relhasindex:13!null c.relpersistence:15!null c.relkind:17!null c.relhasoids:20!null c.relhasrules:22!null c.relhastriggers:23!null c.relacl:26 c.reloptions:27 n.nspname:31!null spcname:37 c2.relname:50 n2.nspname:79 ci.relname:106 ftoptions:136 srvname:140 count_rows:154!null pg_catalog.pg_description.description:179 rownum:182!null + │ ├── columns: c.oid:1!null c.relname:2!null c.reltuples:10!null c.relhasindex:13!null c.relpersistence:15!null c.relkind:17!null c.relhasoids:20!null c.relhasrules:22!null c.relhastriggers:23!null c.relacl:26 c.reloptions:27 n.nspname:31!null spcname:37 c2.relname:50 n2.nspname:79 ci.relname:106 ftoptions:136 srvname:140 count_rows:154!null column172:172 pg_catalog.pg_description.description:179 rownum:182!null │ ├── grouping columns: rownum:182!null + │ ├── immutable │ ├── key: (182) - │ ├── fd: ()-->(31), (1)-->(2,5,10,13,15,17,20,22,23,26,27,37), (2)-->(1,5,10,13,15,17,20,22,23,26,27,37), (182)-->(1,2,5,10,13,15,17,20,22,23,26,27,31,37,50,79,106,136,140,154,179) + │ ├── fd: ()-->(31), (1)-->(2,10,13,15,17,20,22,23,26,27,37), (2)-->(1,10,13,15,17,20,22,23,26,27,37), (182)-->(1,2,10,13,15,17,20,22,23,26,27,31,37,50,79,106,136,140,154,172,179) │ ├── right-join (hash) - │ │ ├── columns: c.oid:1!null c.relname:2!null c.relowner:5!null c.reltuples:10!null c.relhasindex:13!null c.relpersistence:15!null c.relkind:17!null c.relhasoids:20!null c.relhasrules:22!null c.relhastriggers:23!null c.relacl:26 c.reloptions:27 n.nspname:31!null spcname:37 c2.relname:50 n2.nspname:79 ci.relname:106 ftoptions:136 srvname:140 pg_inherits.inhparent:150 pg_catalog.pg_description.description:179 rownum:182!null - │ │ ├── fd: ()-->(31), (1)-->(2,5,10,13,15,17,20,22,23,26,27,37), (2)-->(1,5,10,13,15,17,20,22,23,26,27,37), (182)-->(1,2,5,10,13,15,17,20,22,23,26,27,37,50,79,106,136,140,179) + │ │ ├── columns: c.oid:1!null c.relname:2!null c.reltuples:10!null c.relhasindex:13!null c.relpersistence:15!null c.relkind:17!null c.relhasoids:20!null c.relhasrules:22!null c.relhastriggers:23!null c.relacl:26 c.reloptions:27 n.nspname:31!null spcname:37 c2.relname:50 n2.nspname:79 ci.relname:106 ftoptions:136 srvname:140 pg_inherits.inhparent:150 column172:172 pg_catalog.pg_description.description:179 rownum:182!null + │ │ ├── immutable + │ │ ├── fd: ()-->(31), (1)-->(2,10,13,15,17,20,22,23,26,27,37), (2)-->(1,10,13,15,17,20,22,23,26,27,37), (182)-->(1,2,10,13,15,17,20,22,23,26,27,37,50,79,106,136,140,172,179) │ │ ├── scan pg_inherits │ │ │ └── columns: pg_inherits.inhparent:150!null │ │ ├── distinct-on - │ │ │ ├── columns: c.oid:1!null c.relname:2!null c.relowner:5!null c.reltuples:10!null c.relhasindex:13!null c.relpersistence:15!null c.relkind:17!null c.relhasoids:20!null c.relhasrules:22!null c.relhastriggers:23!null c.relacl:26 c.reloptions:27 n.nspname:31!null spcname:37 c2.relname:50 n2.nspname:79 ci.relname:106 ftoptions:136 srvname:140 pg_catalog.pg_description.description:179 rownum:182!null + │ │ │ ├── columns: c.oid:1!null c.relname:2!null c.reltuples:10!null c.relhasindex:13!null c.relpersistence:15!null c.relkind:17!null c.relhasoids:20!null c.relhasrules:22!null c.relhastriggers:23!null c.relacl:26 c.reloptions:27 n.nspname:31!null spcname:37 c2.relname:50 n2.nspname:79 ci.relname:106 ftoptions:136 srvname:140 column172:172 pg_catalog.pg_description.description:179 rownum:182!null │ │ │ ├── grouping columns: rownum:182!null + │ │ │ ├── immutable │ │ │ ├── key: (182) - │ │ │ ├── fd: ()-->(31), (1)-->(2,5,10,13,15,17,20,22,23,26,27,37), (2)-->(1,5,10,13,15,17,20,22,23,26,27,37), (182)-->(1,2,5,10,13,15,17,20,22,23,26,27,31,37,50,79,106,136,140,179) + │ │ │ ├── fd: ()-->(31), (1)-->(2,10,13,15,17,20,22,23,26,27,37), (2)-->(1,10,13,15,17,20,22,23,26,27,37), (182)-->(1,2,10,13,15,17,20,22,23,26,27,31,37,50,79,106,136,140,172,179) │ │ │ ├── left-join (hash) - │ │ │ │ ├── columns: c.oid:1!null c.relname:2!null c.relnamespace:3!null c.relowner:5!null c.reltablespace:8!null c.reltuples:10!null c.relhasindex:13!null c.relpersistence:15!null c.relkind:17!null c.relhasoids:20!null c.relhasrules:22!null c.relhastriggers:23!null c.relacl:26 c.reloptions:27 n.oid:30!null n.nspname:31!null t.oid:36 spcname:37 i.inhrelid:44 i.inhparent:45 c2.oid:49 c2.relname:50 c2.relnamespace:51 n2.oid:78 n2.nspname:79 indexrelid:84 indrelid:85 indisclustered:91 ci.oid:105 ci.relname:106 ftrelid:134 ftserver:135 ftoptions:136 fs.oid:139 srvname:140 objoid:176 objsubid:178 pg_catalog.pg_description.description:179 rownum:182!null - │ │ │ │ ├── fd: ()-->(3,30,31), (1)-->(2,5,8,10,13,15,17,20,22,23,26,27,36,37), (2)-->(1,5,8,10,13,15,17,20,22,23,26,27), (3)==(30), (30)==(3), (36)-->(37), (37)-->(36), (49)-->(50,51), (50,51)-->(49), (45)==(49), (49)==(45), (78)~~>(79), (79)~~>(78), (84)-->(85), (105)-->(106), (134)-->(135,136), (139)-->(140), (140)-->(139), (182)-->(1,2,5,8,10,13,15,17,20,22,23,26,27,36,37,44,45,49-51,78,79,84,85,91,105,106,134-136,139,140) + │ │ │ │ ├── columns: c.oid:1!null c.relname:2!null c.reltuples:10!null c.relhasindex:13!null c.relpersistence:15!null c.relkind:17!null c.relhasoids:20!null c.relhasrules:22!null c.relhastriggers:23!null c.relacl:26 c.reloptions:27 n.nspname:31!null spcname:37 c2.relname:50 n2.nspname:79 ci.relname:106 ftoptions:136 srvname:140 column172:172 objoid:176 objsubid:178 pg_catalog.pg_description.description:179 rownum:182!null + │ │ │ │ ├── immutable + │ │ │ │ ├── fd: ()-->(31), (1)-->(2,10,13,15,17,20,22,23,26,27,37), (2)-->(1,10,13,15,17,20,22,23,26,27,37), (182)-->(1,2,10,13,15,17,20,22,23,26,27,37,50,79,106,136,140,172) │ │ │ │ ├── ordinality - │ │ │ │ │ ├── columns: c.oid:1!null c.relname:2!null c.relnamespace:3!null c.relowner:5!null c.reltablespace:8!null c.reltuples:10!null c.relhasindex:13!null c.relpersistence:15!null c.relkind:17!null c.relhasoids:20!null c.relhasrules:22!null c.relhastriggers:23!null c.relacl:26 c.reloptions:27 n.oid:30!null n.nspname:31!null t.oid:36 spcname:37 i.inhrelid:44 i.inhparent:45 c2.oid:49 c2.relname:50 c2.relnamespace:51 n2.oid:78 n2.nspname:79 indexrelid:84 indrelid:85 indisclustered:91 ci.oid:105 ci.relname:106 ftrelid:134 ftserver:135 ftoptions:136 fs.oid:139 srvname:140 rownum:182!null + │ │ │ │ │ ├── columns: c.oid:1!null c.relname:2!null c.reltuples:10!null c.relhasindex:13!null c.relpersistence:15!null c.relkind:17!null c.relhasoids:20!null c.relhasrules:22!null c.relhastriggers:23!null c.relacl:26 c.reloptions:27 n.nspname:31!null spcname:37 c2.relname:50 n2.nspname:79 ci.relname:106 ftoptions:136 srvname:140 column172:172 rownum:182!null + │ │ │ │ │ ├── immutable │ │ │ │ │ ├── key: (182) - │ │ │ │ │ ├── fd: ()-->(3,30,31), (1)-->(2,5,8,10,13,15,17,20,22,23,26,27,36,37), (2)-->(1,5,8,10,13,15,17,20,22,23,26,27), (3)==(30), (30)==(3), (36)-->(37), (37)-->(36), (49)-->(50,51), (50,51)-->(49), (45)==(49), (49)==(45), (78)~~>(79), (79)~~>(78), (84)-->(85), (105)-->(106), (134)-->(135,136), (139)-->(140), (140)-->(139), (182)-->(1-3,5,8,10,13,15,17,20,22,23,26,27,30,31,36,37,44,45,49-51,78,79,84,85,91,105,106,134-136,139,140) - │ │ │ │ │ └── left-join (lookup pg_namespace [as=n2]) - │ │ │ │ │ ├── columns: c.oid:1!null c.relname:2!null c.relnamespace:3!null c.relowner:5!null c.reltablespace:8!null c.reltuples:10!null c.relhasindex:13!null c.relpersistence:15!null c.relkind:17!null c.relhasoids:20!null c.relhasrules:22!null c.relhastriggers:23!null c.relacl:26 c.reloptions:27 n.oid:30!null n.nspname:31!null t.oid:36 spcname:37 i.inhrelid:44 i.inhparent:45 c2.oid:49 c2.relname:50 c2.relnamespace:51 n2.oid:78 n2.nspname:79 indexrelid:84 indrelid:85 indisclustered:91 ci.oid:105 ci.relname:106 ftrelid:134 ftserver:135 ftoptions:136 fs.oid:139 srvname:140 - │ │ │ │ │ ├── key columns: [51] = [78] - │ │ │ │ │ ├── lookup columns are key - │ │ │ │ │ ├── fd: ()-->(3,30,31), (1)-->(2,5,8,10,13,15,17,20,22,23,26,27,36,37), (2)-->(1,5,8,10,13,15,17,20,22,23,26,27), (3)==(30), (30)==(3), (36)-->(37), (37)-->(36), (49)-->(50,51), (50,51)-->(49), (45)==(49), (49)==(45), (78)~~>(79), (79)~~>(78), (84)-->(85), (105)-->(106), (134)-->(135,136), (139)-->(140), (140)-->(139) - │ │ │ │ │ ├── right-join (hash) - │ │ │ │ │ │ ├── columns: c.oid:1!null c.relname:2!null c.relnamespace:3!null c.relowner:5!null c.reltablespace:8!null c.reltuples:10!null c.relhasindex:13!null c.relpersistence:15!null c.relkind:17!null c.relhasoids:20!null c.relhasrules:22!null c.relhastriggers:23!null c.relacl:26 c.reloptions:27 n.oid:30!null n.nspname:31!null t.oid:36 spcname:37 i.inhrelid:44 i.inhparent:45 c2.oid:49 c2.relname:50 c2.relnamespace:51 indexrelid:84 indrelid:85 indisclustered:91 ci.oid:105 ci.relname:106 ftrelid:134 ftserver:135 ftoptions:136 fs.oid:139 srvname:140 - │ │ │ │ │ │ ├── fd: ()-->(3,30,31), (1)-->(2,5,8,10,13,15,17,20,22,23,26,27,134-136,139,140), (2)-->(1,5,8,10,13,15,17,20,22,23,26,27), (134)-->(135,136,139,140), (139)~~>(140), (140)~~>(139), (84)-->(85), (1,84)-->(91,105,106), (105)-->(106), (49)-->(50,51), (50,51)-->(49), (45)==(49), (49)==(45), (36)-->(37), (37)-->(36), (3)==(30), (30)==(3) - │ │ │ │ │ │ ├── inner-join (hash) - │ │ │ │ │ │ │ ├── columns: i.inhrelid:44!null i.inhparent:45!null c2.oid:49!null c2.relname:50!null c2.relnamespace:51!null - │ │ │ │ │ │ │ ├── multiplicity: left-rows(zero-or-one), right-rows(zero-or-more) - │ │ │ │ │ │ │ ├── fd: (49)-->(50,51), (50,51)-->(49), (45)==(49), (49)==(45) - │ │ │ │ │ │ │ ├── scan pg_inherits [as=i] - │ │ │ │ │ │ │ │ └── columns: i.inhrelid:44!null i.inhparent:45!null - │ │ │ │ │ │ │ ├── scan pg_class@pg_class_relname_nsp_index [as=c2] - │ │ │ │ │ │ │ │ ├── columns: c2.oid:49!null c2.relname:50!null c2.relnamespace:51!null - │ │ │ │ │ │ │ │ ├── key: (49) - │ │ │ │ │ │ │ │ └── fd: (49)-->(50,51), (50,51)-->(49) - │ │ │ │ │ │ │ └── filters - │ │ │ │ │ │ │ └── i.inhparent:45 = c2.oid:49 [outer=(45,49), constraints=(/45: (/NULL - ]; /49: (/NULL - ]), fd=(45)==(49), (49)==(45)] - │ │ │ │ │ │ ├── left-join (lookup pg_class [as=ci]) - │ │ │ │ │ │ │ ├── columns: c.oid:1!null c.relname:2!null c.relnamespace:3!null c.relowner:5!null c.reltablespace:8!null c.reltuples:10!null c.relhasindex:13!null c.relpersistence:15!null c.relkind:17!null c.relhasoids:20!null c.relhasrules:22!null c.relhastriggers:23!null c.relacl:26 c.reloptions:27 n.oid:30!null n.nspname:31!null t.oid:36 spcname:37 indexrelid:84 indrelid:85 indisclustered:91 ci.oid:105 ci.relname:106 ftrelid:134 ftserver:135 ftoptions:136 fs.oid:139 srvname:140 - │ │ │ │ │ │ │ ├── key columns: [84] = [105] - │ │ │ │ │ │ │ ├── lookup columns are key - │ │ │ │ │ │ │ ├── key: (1,84) - │ │ │ │ │ │ │ ├── fd: ()-->(3,30,31), (1)-->(2,5,8,10,13,15,17,20,22,23,26,27,134-136,139,140), (2)-->(1,5,8,10,13,15,17,20,22,23,26,27), (134)-->(135,136,139,140), (139)~~>(140), (140)~~>(139), (84)-->(85), (1,84)-->(36,37,91,105,106), (105)-->(106), (36)-->(37), (37)-->(36), (3)==(30), (30)==(3) - │ │ │ │ │ │ │ ├── left-join (lookup pg_index [as=ind]) - │ │ │ │ │ │ │ │ ├── columns: c.oid:1!null c.relname:2!null c.relnamespace:3!null c.relowner:5!null c.reltablespace:8!null c.reltuples:10!null c.relhasindex:13!null c.relpersistence:15!null c.relkind:17!null c.relhasoids:20!null c.relhasrules:22!null c.relhastriggers:23!null c.relacl:26 c.reloptions:27 n.oid:30!null n.nspname:31!null t.oid:36 spcname:37 indexrelid:84 indrelid:85 indisclustered:91 ftrelid:134 ftserver:135 ftoptions:136 fs.oid:139 srvname:140 - │ │ │ │ │ │ │ │ ├── key columns: [956] = [84] + │ │ │ │ │ ├── fd: ()-->(31), (1)-->(2,10,13,15,17,20,22,23,26,27,37), (2)-->(1,10,13,15,17,20,22,23,26,27,37), (182)-->(1,2,10,13,15,17,20,22,23,26,27,31,37,50,79,106,136,140,172) + │ │ │ │ │ └── project + │ │ │ │ │ ├── columns: column172:172 c.oid:1!null c.relname:2!null c.reltuples:10!null c.relhasindex:13!null c.relpersistence:15!null c.relkind:17!null c.relhasoids:20!null c.relhasrules:22!null c.relhastriggers:23!null c.relacl:26 c.reloptions:27 n.nspname:31!null spcname:37 c2.relname:50 n2.nspname:79 ci.relname:106 ftoptions:136 srvname:140 + │ │ │ │ │ ├── immutable + │ │ │ │ │ ├── fd: ()-->(31), (1)-->(2,10,13,15,17,20,22,23,26,27,37), (2)-->(1,10,13,15,17,20,22,23,26,27,37) + │ │ │ │ │ ├── left-join (lookup pg_namespace [as=n2]) + │ │ │ │ │ │ ├── columns: c.oid:1!null c.relname:2!null c.relnamespace:3!null c.relowner:5!null c.reltablespace:8!null c.reltuples:10!null c.relhasindex:13!null c.relpersistence:15!null c.relkind:17!null c.relhasoids:20!null c.relhasrules:22!null c.relhastriggers:23!null c.relacl:26 c.reloptions:27 n.oid:30!null n.nspname:31!null t.oid:36 spcname:37 i.inhrelid:44 i.inhparent:45 c2.oid:49 c2.relname:50 c2.relnamespace:51 n2.oid:78 n2.nspname:79 indexrelid:84 indrelid:85 indisclustered:91 ci.oid:105 ci.relname:106 ftrelid:134 ftserver:135 ftoptions:136 fs.oid:139 srvname:140 + │ │ │ │ │ │ ├── key columns: [51] = [78] + │ │ │ │ │ │ ├── lookup columns are key + │ │ │ │ │ │ ├── fd: ()-->(3,30,31), (1)-->(2,5,8,10,13,15,17,20,22,23,26,27,36,37), (2)-->(1,5,8,10,13,15,17,20,22,23,26,27), (3)==(30), (30)==(3), (36)-->(37), (37)-->(36), (49)-->(50,51), (50,51)-->(49), (45)==(49), (49)==(45), (78)~~>(79), (79)~~>(78), (84)-->(85), (105)-->(106), (134)-->(135,136), (139)-->(140), (140)-->(139) + │ │ │ │ │ │ ├── right-join (hash) + │ │ │ │ │ │ │ ├── columns: c.oid:1!null c.relname:2!null c.relnamespace:3!null c.relowner:5!null c.reltablespace:8!null c.reltuples:10!null c.relhasindex:13!null c.relpersistence:15!null c.relkind:17!null c.relhasoids:20!null c.relhasrules:22!null c.relhastriggers:23!null c.relacl:26 c.reloptions:27 n.oid:30!null n.nspname:31!null t.oid:36 spcname:37 i.inhrelid:44 i.inhparent:45 c2.oid:49 c2.relname:50 c2.relnamespace:51 indexrelid:84 indrelid:85 indisclustered:91 ci.oid:105 ci.relname:106 ftrelid:134 ftserver:135 ftoptions:136 fs.oid:139 srvname:140 + │ │ │ │ │ │ │ ├── fd: ()-->(3,30,31), (1)-->(2,5,8,10,13,15,17,20,22,23,26,27,134-136,139,140), (2)-->(1,5,8,10,13,15,17,20,22,23,26,27), (134)-->(135,136,139,140), (139)~~>(140), (140)~~>(139), (84)-->(85), (1,84)-->(91,105,106), (105)-->(106), (49)-->(50,51), (50,51)-->(49), (45)==(49), (49)==(45), (36)-->(37), (37)-->(36), (3)==(30), (30)==(3) + │ │ │ │ │ │ │ ├── inner-join (hash) + │ │ │ │ │ │ │ │ ├── columns: i.inhrelid:44!null i.inhparent:45!null c2.oid:49!null c2.relname:50!null c2.relnamespace:51!null + │ │ │ │ │ │ │ │ ├── multiplicity: left-rows(zero-or-one), right-rows(zero-or-more) + │ │ │ │ │ │ │ │ ├── fd: (49)-->(50,51), (50,51)-->(49), (45)==(49), (49)==(45) + │ │ │ │ │ │ │ │ ├── scan pg_inherits [as=i] + │ │ │ │ │ │ │ │ │ └── columns: i.inhrelid:44!null i.inhparent:45!null + │ │ │ │ │ │ │ │ ├── scan pg_class@pg_class_relname_nsp_index [as=c2] + │ │ │ │ │ │ │ │ │ ├── columns: c2.oid:49!null c2.relname:50!null c2.relnamespace:51!null + │ │ │ │ │ │ │ │ │ ├── key: (49) + │ │ │ │ │ │ │ │ │ └── fd: (49)-->(50,51), (50,51)-->(49) + │ │ │ │ │ │ │ │ └── filters + │ │ │ │ │ │ │ │ └── i.inhparent:45 = c2.oid:49 [outer=(45,49), constraints=(/45: (/NULL - ]; /49: (/NULL - ]), fd=(45)==(49), (49)==(45)] + │ │ │ │ │ │ │ ├── left-join (lookup pg_class [as=ci]) + │ │ │ │ │ │ │ │ ├── columns: c.oid:1!null c.relname:2!null c.relnamespace:3!null c.relowner:5!null c.reltablespace:8!null c.reltuples:10!null c.relhasindex:13!null c.relpersistence:15!null c.relkind:17!null c.relhasoids:20!null c.relhasrules:22!null c.relhastriggers:23!null c.relacl:26 c.reloptions:27 n.oid:30!null n.nspname:31!null t.oid:36 spcname:37 indexrelid:84 indrelid:85 indisclustered:91 ci.oid:105 ci.relname:106 ftrelid:134 ftserver:135 ftoptions:136 fs.oid:139 srvname:140 + │ │ │ │ │ │ │ │ ├── key columns: [84] = [105] │ │ │ │ │ │ │ │ ├── lookup columns are key - │ │ │ │ │ │ │ │ ├── second join in paired joiner │ │ │ │ │ │ │ │ ├── key: (1,84) - │ │ │ │ │ │ │ │ ├── fd: ()-->(3,30,31), (1)-->(2,5,8,10,13,15,17,20,22,23,26,27,134-136,139,140), (2)-->(1,5,8,10,13,15,17,20,22,23,26,27), (134)-->(135,136,139,140), (139)~~>(140), (140)~~>(139), (84)-->(85), (1,84)-->(36,37,91), (36)-->(37), (37)-->(36), (3)==(30), (30)==(3) - │ │ │ │ │ │ │ │ ├── left-join (lookup pg_index@pg_index_indrelid_index [as=ind]) - │ │ │ │ │ │ │ │ │ ├── columns: c.oid:1!null c.relname:2!null c.relnamespace:3!null c.relowner:5!null c.reltablespace:8!null c.reltuples:10!null c.relhasindex:13!null c.relpersistence:15!null c.relkind:17!null c.relhasoids:20!null c.relhasrules:22!null c.relhastriggers:23!null c.relacl:26 c.reloptions:27 n.oid:30!null n.nspname:31!null t.oid:36 spcname:37 ftrelid:134 ftserver:135 ftoptions:136 fs.oid:139 srvname:140 indexrelid:956 indrelid:957 continuation:977 - │ │ │ │ │ │ │ │ │ ├── key columns: [1] = [957] - │ │ │ │ │ │ │ │ │ ├── first join in paired joiner; continuation column: continuation:977 - │ │ │ │ │ │ │ │ │ ├── key: (1,956) - │ │ │ │ │ │ │ │ │ ├── fd: ()-->(3,30,31), (1)-->(2,5,8,10,13,15,17,20,22,23,26,27,36,37,134-136,139,140), (2)-->(1,5,8,10,13,15,17,20,22,23,26,27), (134)-->(135,136,139,140), (139)~~>(140), (140)~~>(139), (36)-->(37), (37)-->(36), (3)==(30), (30)==(3), (956)-->(957,977) - │ │ │ │ │ │ │ │ │ ├── left-join (lookup pg_tablespace [as=t]) - │ │ │ │ │ │ │ │ │ │ ├── columns: c.oid:1!null c.relname:2!null c.relnamespace:3!null c.relowner:5!null c.reltablespace:8!null c.reltuples:10!null c.relhasindex:13!null c.relpersistence:15!null c.relkind:17!null c.relhasoids:20!null c.relhasrules:22!null c.relhastriggers:23!null c.relacl:26 c.reloptions:27 n.oid:30!null n.nspname:31!null t.oid:36 spcname:37 ftrelid:134 ftserver:135 ftoptions:136 fs.oid:139 srvname:140 - │ │ │ │ │ │ │ │ │ │ ├── key columns: [8] = [36] - │ │ │ │ │ │ │ │ │ │ ├── lookup columns are key - │ │ │ │ │ │ │ │ │ │ ├── key: (1) - │ │ │ │ │ │ │ │ │ │ ├── fd: ()-->(3,30,31), (1)-->(2,5,8,10,13,15,17,20,22,23,26,27,36,37,134-136,139,140), (2)-->(1,5,8,10,13,15,17,20,22,23,26,27), (134)-->(135,136,139,140), (139)~~>(140), (140)~~>(139), (36)-->(37), (37)-->(36), (3)==(30), (30)==(3) - │ │ │ │ │ │ │ │ │ │ ├── left-join (lookup pg_foreign_server [as=fs]) - │ │ │ │ │ │ │ │ │ │ │ ├── columns: c.oid:1!null c.relname:2!null c.relnamespace:3!null c.relowner:5!null c.reltablespace:8!null c.reltuples:10!null c.relhasindex:13!null c.relpersistence:15!null c.relkind:17!null c.relhasoids:20!null c.relhasrules:22!null c.relhastriggers:23!null c.relacl:26 c.reloptions:27 n.oid:30!null n.nspname:31!null ftrelid:134 ftserver:135 ftoptions:136 fs.oid:139 srvname:140 - │ │ │ │ │ │ │ │ │ │ │ ├── key columns: [135] = [139] + │ │ │ │ │ │ │ │ ├── fd: ()-->(3,30,31), (1)-->(2,5,8,10,13,15,17,20,22,23,26,27,134-136,139,140), (2)-->(1,5,8,10,13,15,17,20,22,23,26,27), (134)-->(135,136,139,140), (139)~~>(140), (140)~~>(139), (84)-->(85), (1,84)-->(36,37,91,105,106), (105)-->(106), (36)-->(37), (37)-->(36), (3)==(30), (30)==(3) + │ │ │ │ │ │ │ │ ├── left-join (lookup pg_index [as=ind]) + │ │ │ │ │ │ │ │ │ ├── columns: c.oid:1!null c.relname:2!null c.relnamespace:3!null c.relowner:5!null c.reltablespace:8!null c.reltuples:10!null c.relhasindex:13!null c.relpersistence:15!null c.relkind:17!null c.relhasoids:20!null c.relhasrules:22!null c.relhastriggers:23!null c.relacl:26 c.reloptions:27 n.oid:30!null n.nspname:31!null t.oid:36 spcname:37 indexrelid:84 indrelid:85 indisclustered:91 ftrelid:134 ftserver:135 ftoptions:136 fs.oid:139 srvname:140 + │ │ │ │ │ │ │ │ │ ├── key columns: [956] = [84] + │ │ │ │ │ │ │ │ │ ├── lookup columns are key + │ │ │ │ │ │ │ │ │ ├── second join in paired joiner + │ │ │ │ │ │ │ │ │ ├── key: (1,84) + │ │ │ │ │ │ │ │ │ ├── fd: ()-->(3,30,31), (1)-->(2,5,8,10,13,15,17,20,22,23,26,27,134-136,139,140), (2)-->(1,5,8,10,13,15,17,20,22,23,26,27), (134)-->(135,136,139,140), (139)~~>(140), (140)~~>(139), (84)-->(85), (1,84)-->(36,37,91), (36)-->(37), (37)-->(36), (3)==(30), (30)==(3) + │ │ │ │ │ │ │ │ │ ├── left-join (lookup pg_index@pg_index_indrelid_index [as=ind]) + │ │ │ │ │ │ │ │ │ │ ├── columns: c.oid:1!null c.relname:2!null c.relnamespace:3!null c.relowner:5!null c.reltablespace:8!null c.reltuples:10!null c.relhasindex:13!null c.relpersistence:15!null c.relkind:17!null c.relhasoids:20!null c.relhasrules:22!null c.relhastriggers:23!null c.relacl:26 c.reloptions:27 n.oid:30!null n.nspname:31!null t.oid:36 spcname:37 ftrelid:134 ftserver:135 ftoptions:136 fs.oid:139 srvname:140 indexrelid:956 indrelid:957 continuation:977 + │ │ │ │ │ │ │ │ │ │ ├── key columns: [1] = [957] + │ │ │ │ │ │ │ │ │ │ ├── first join in paired joiner; continuation column: continuation:977 + │ │ │ │ │ │ │ │ │ │ ├── key: (1,956) + │ │ │ │ │ │ │ │ │ │ ├── fd: ()-->(3,30,31), (1)-->(2,5,8,10,13,15,17,20,22,23,26,27,36,37,134-136,139,140), (2)-->(1,5,8,10,13,15,17,20,22,23,26,27), (134)-->(135,136,139,140), (139)~~>(140), (140)~~>(139), (36)-->(37), (37)-->(36), (3)==(30), (30)==(3), (956)-->(957,977) + │ │ │ │ │ │ │ │ │ │ ├── left-join (lookup pg_tablespace [as=t]) + │ │ │ │ │ │ │ │ │ │ │ ├── columns: c.oid:1!null c.relname:2!null c.relnamespace:3!null c.relowner:5!null c.reltablespace:8!null c.reltuples:10!null c.relhasindex:13!null c.relpersistence:15!null c.relkind:17!null c.relhasoids:20!null c.relhasrules:22!null c.relhastriggers:23!null c.relacl:26 c.reloptions:27 n.oid:30!null n.nspname:31!null t.oid:36 spcname:37 ftrelid:134 ftserver:135 ftoptions:136 fs.oid:139 srvname:140 + │ │ │ │ │ │ │ │ │ │ │ ├── key columns: [8] = [36] │ │ │ │ │ │ │ │ │ │ │ ├── lookup columns are key │ │ │ │ │ │ │ │ │ │ │ ├── key: (1) - │ │ │ │ │ │ │ │ │ │ │ ├── fd: ()-->(3,30,31), (1)-->(2,5,8,10,13,15,17,20,22,23,26,27,134-136,139,140), (2)-->(1,5,8,10,13,15,17,20,22,23,26,27), (134)-->(135,136,139,140), (139)~~>(140), (140)~~>(139), (3)==(30), (30)==(3) - │ │ │ │ │ │ │ │ │ │ │ ├── left-join (lookup pg_foreign_table [as=ft]) - │ │ │ │ │ │ │ │ │ │ │ │ ├── columns: c.oid:1!null c.relname:2!null c.relnamespace:3!null c.relowner:5!null c.reltablespace:8!null c.reltuples:10!null c.relhasindex:13!null c.relpersistence:15!null c.relkind:17!null c.relhasoids:20!null c.relhasrules:22!null c.relhastriggers:23!null c.relacl:26 c.reloptions:27 n.oid:30!null n.nspname:31!null ftrelid:134 ftserver:135 ftoptions:136 - │ │ │ │ │ │ │ │ │ │ │ │ ├── key columns: [1] = [134] + │ │ │ │ │ │ │ │ │ │ │ ├── fd: ()-->(3,30,31), (1)-->(2,5,8,10,13,15,17,20,22,23,26,27,36,37,134-136,139,140), (2)-->(1,5,8,10,13,15,17,20,22,23,26,27), (134)-->(135,136,139,140), (139)~~>(140), (140)~~>(139), (36)-->(37), (37)-->(36), (3)==(30), (30)==(3) + │ │ │ │ │ │ │ │ │ │ │ ├── left-join (lookup pg_foreign_server [as=fs]) + │ │ │ │ │ │ │ │ │ │ │ │ ├── columns: c.oid:1!null c.relname:2!null c.relnamespace:3!null c.relowner:5!null c.reltablespace:8!null c.reltuples:10!null c.relhasindex:13!null c.relpersistence:15!null c.relkind:17!null c.relhasoids:20!null c.relhasrules:22!null c.relhastriggers:23!null c.relacl:26 c.reloptions:27 n.oid:30!null n.nspname:31!null ftrelid:134 ftserver:135 ftoptions:136 fs.oid:139 srvname:140 + │ │ │ │ │ │ │ │ │ │ │ │ ├── key columns: [135] = [139] │ │ │ │ │ │ │ │ │ │ │ │ ├── lookup columns are key │ │ │ │ │ │ │ │ │ │ │ │ ├── key: (1) - │ │ │ │ │ │ │ │ │ │ │ │ ├── fd: ()-->(3,30,31), (1)-->(2,5,8,10,13,15,17,20,22,23,26,27,134-136), (2)-->(1,5,8,10,13,15,17,20,22,23,26,27), (134)-->(135,136), (3)==(30), (30)==(3) - │ │ │ │ │ │ │ │ │ │ │ │ ├── inner-join (hash) - │ │ │ │ │ │ │ │ │ │ │ │ │ ├── columns: c.oid:1!null c.relname:2!null c.relnamespace:3!null c.relowner:5!null c.reltablespace:8!null c.reltuples:10!null c.relhasindex:13!null c.relpersistence:15!null c.relkind:17!null c.relhasoids:20!null c.relhasrules:22!null c.relhastriggers:23!null c.relacl:26 c.reloptions:27 n.oid:30!null n.nspname:31!null - │ │ │ │ │ │ │ │ │ │ │ │ │ ├── multiplicity: left-rows(zero-or-one), right-rows(zero-or-more) + │ │ │ │ │ │ │ │ │ │ │ │ ├── fd: ()-->(3,30,31), (1)-->(2,5,8,10,13,15,17,20,22,23,26,27,134-136,139,140), (2)-->(1,5,8,10,13,15,17,20,22,23,26,27), (134)-->(135,136,139,140), (139)~~>(140), (140)~~>(139), (3)==(30), (30)==(3) + │ │ │ │ │ │ │ │ │ │ │ │ ├── left-join (lookup pg_foreign_table [as=ft]) + │ │ │ │ │ │ │ │ │ │ │ │ │ ├── columns: c.oid:1!null c.relname:2!null c.relnamespace:3!null c.relowner:5!null c.reltablespace:8!null c.reltuples:10!null c.relhasindex:13!null c.relpersistence:15!null c.relkind:17!null c.relhasoids:20!null c.relhasrules:22!null c.relhastriggers:23!null c.relacl:26 c.reloptions:27 n.oid:30!null n.nspname:31!null ftrelid:134 ftserver:135 ftoptions:136 + │ │ │ │ │ │ │ │ │ │ │ │ │ ├── key columns: [1] = [134] + │ │ │ │ │ │ │ │ │ │ │ │ │ ├── lookup columns are key │ │ │ │ │ │ │ │ │ │ │ │ │ ├── key: (1) - │ │ │ │ │ │ │ │ │ │ │ │ │ ├── fd: ()-->(3,30,31), (1)-->(2,5,8,10,13,15,17,20,22,23,26,27), (2)-->(1,5,8,10,13,15,17,20,22,23,26,27), (3)==(30), (30)==(3) - │ │ │ │ │ │ │ │ │ │ │ │ │ ├── select - │ │ │ │ │ │ │ │ │ │ │ │ │ │ ├── columns: c.oid:1!null c.relname:2!null c.relnamespace:3!null c.relowner:5!null c.reltablespace:8!null c.reltuples:10!null c.relhasindex:13!null c.relpersistence:15!null c.relkind:17!null c.relhasoids:20!null c.relhasrules:22!null c.relhastriggers:23!null c.relacl:26 c.reloptions:27 + │ │ │ │ │ │ │ │ │ │ │ │ │ ├── fd: ()-->(3,30,31), (1)-->(2,5,8,10,13,15,17,20,22,23,26,27,134-136), (2)-->(1,5,8,10,13,15,17,20,22,23,26,27), (134)-->(135,136), (3)==(30), (30)==(3) + │ │ │ │ │ │ │ │ │ │ │ │ │ ├── inner-join (hash) + │ │ │ │ │ │ │ │ │ │ │ │ │ │ ├── columns: c.oid:1!null c.relname:2!null c.relnamespace:3!null c.relowner:5!null c.reltablespace:8!null c.reltuples:10!null c.relhasindex:13!null c.relpersistence:15!null c.relkind:17!null c.relhasoids:20!null c.relhasrules:22!null c.relhastriggers:23!null c.relacl:26 c.reloptions:27 n.oid:30!null n.nspname:31!null + │ │ │ │ │ │ │ │ │ │ │ │ │ │ ├── multiplicity: left-rows(zero-or-one), right-rows(zero-or-more) │ │ │ │ │ │ │ │ │ │ │ │ │ │ ├── key: (1) - │ │ │ │ │ │ │ │ │ │ │ │ │ │ ├── fd: (1)-->(2,3,5,8,10,13,15,17,20,22,23,26,27), (2,3)-->(1,5,8,10,13,15,17,20,22,23,26,27) - │ │ │ │ │ │ │ │ │ │ │ │ │ │ ├── scan pg_class [as=c] + │ │ │ │ │ │ │ │ │ │ │ │ │ │ ├── fd: ()-->(3,30,31), (1)-->(2,5,8,10,13,15,17,20,22,23,26,27), (2)-->(1,5,8,10,13,15,17,20,22,23,26,27), (3)==(30), (30)==(3) + │ │ │ │ │ │ │ │ │ │ │ │ │ │ ├── select │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ ├── columns: c.oid:1!null c.relname:2!null c.relnamespace:3!null c.relowner:5!null c.reltablespace:8!null c.reltuples:10!null c.relhasindex:13!null c.relpersistence:15!null c.relkind:17!null c.relhasoids:20!null c.relhasrules:22!null c.relhastriggers:23!null c.relacl:26 c.reloptions:27 │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ ├── key: (1) - │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ └── fd: (1)-->(2,3,5,8,10,13,15,17,20,22,23,26,27), (2,3)-->(1,5,8,10,13,15,17,20,22,23,26,27) + │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ ├── fd: (1)-->(2,3,5,8,10,13,15,17,20,22,23,26,27), (2,3)-->(1,5,8,10,13,15,17,20,22,23,26,27) + │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ ├── scan pg_class [as=c] + │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ ├── columns: c.oid:1!null c.relname:2!null c.relnamespace:3!null c.relowner:5!null c.reltablespace:8!null c.reltuples:10!null c.relhasindex:13!null c.relpersistence:15!null c.relkind:17!null c.relhasoids:20!null c.relhasrules:22!null c.relhastriggers:23!null c.relacl:26 c.reloptions:27 + │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ ├── key: (1) + │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ └── fd: (1)-->(2,3,5,8,10,13,15,17,20,22,23,26,27), (2,3)-->(1,5,8,10,13,15,17,20,22,23,26,27) + │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ └── filters + │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ └── (c.relkind:17 = 'r') OR (c.relkind:17 = 'f') [outer=(17), constraints=(/17: [/'f' - /'f'] [/'r' - /'r']; tight)] + │ │ │ │ │ │ │ │ │ │ │ │ │ │ ├── scan pg_namespace@pg_namespace_nspname_index [as=n] + │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ ├── columns: n.oid:30!null n.nspname:31!null + │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ ├── constraint: /31: [/'public' - /'public'] + │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ ├── cardinality: [0 - 1] + │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ ├── key: () + │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ └── fd: ()-->(30,31) │ │ │ │ │ │ │ │ │ │ │ │ │ │ └── filters - │ │ │ │ │ │ │ │ │ │ │ │ │ │ └── (c.relkind:17 = 'r') OR (c.relkind:17 = 'f') [outer=(17), constraints=(/17: [/'f' - /'f'] [/'r' - /'r']; tight)] - │ │ │ │ │ │ │ │ │ │ │ │ │ ├── scan pg_namespace@pg_namespace_nspname_index [as=n] - │ │ │ │ │ │ │ │ │ │ │ │ │ │ ├── columns: n.oid:30!null n.nspname:31!null - │ │ │ │ │ │ │ │ │ │ │ │ │ │ ├── constraint: /31: [/'public' - /'public'] - │ │ │ │ │ │ │ │ │ │ │ │ │ │ ├── cardinality: [0 - 1] - │ │ │ │ │ │ │ │ │ │ │ │ │ │ ├── key: () - │ │ │ │ │ │ │ │ │ │ │ │ │ │ └── fd: ()-->(30,31) - │ │ │ │ │ │ │ │ │ │ │ │ │ └── filters - │ │ │ │ │ │ │ │ │ │ │ │ │ └── n.oid:30 = c.relnamespace:3 [outer=(3,30), constraints=(/3: (/NULL - ]; /30: (/NULL - ]), fd=(3)==(30), (30)==(3)] + │ │ │ │ │ │ │ │ │ │ │ │ │ │ └── n.oid:30 = c.relnamespace:3 [outer=(3,30), constraints=(/3: (/NULL - ]; /30: (/NULL - ]), fd=(3)==(30), (30)==(3)] + │ │ │ │ │ │ │ │ │ │ │ │ │ └── filters (true) │ │ │ │ │ │ │ │ │ │ │ │ └── filters (true) │ │ │ │ │ │ │ │ │ │ │ └── filters (true) │ │ │ │ │ │ │ │ │ │ └── filters (true) - │ │ │ │ │ │ │ │ │ └── filters (true) - │ │ │ │ │ │ │ │ └── filters - │ │ │ │ │ │ │ │ └── indisclustered:91 [outer=(91), constraints=(/91: [/true - /true]; tight), fd=()-->(91)] - │ │ │ │ │ │ │ └── filters (true) - │ │ │ │ │ │ └── filters - │ │ │ │ │ │ └── i.inhrelid:44 = c.oid:1 [outer=(1,44), constraints=(/1: (/NULL - ]; /44: (/NULL - ]), fd=(1)==(44), (44)==(1)] - │ │ │ │ │ └── filters (true) + │ │ │ │ │ │ │ │ │ └── filters + │ │ │ │ │ │ │ │ │ └── indisclustered:91 [outer=(91), constraints=(/91: [/true - /true]; tight), fd=()-->(91)] + │ │ │ │ │ │ │ │ └── filters (true) + │ │ │ │ │ │ │ └── filters + │ │ │ │ │ │ │ └── i.inhrelid:44 = c.oid:1 [outer=(1,44), constraints=(/1: (/NULL - ]; /44: (/NULL - ]), fd=(1)==(44), (44)==(1)] + │ │ │ │ │ │ └── filters (true) + │ │ │ │ │ └── projections + │ │ │ │ │ └── assignment-cast: STRING [as=column172:172, outer=(5), immutable, correlated-subquery] + │ │ │ │ │ └── coalesce + │ │ │ │ │ ├── subquery + │ │ │ │ │ │ └── project + │ │ │ │ │ │ ├── columns: rolname:158 + │ │ │ │ │ │ ├── outer: (5) + │ │ │ │ │ │ ├── cardinality: [0 - 1] + │ │ │ │ │ │ ├── key: () + │ │ │ │ │ │ ├── fd: ()-->(158) + │ │ │ │ │ │ └── limit + │ │ │ │ │ │ ├── columns: pg_catalog.pg_roles.oid:157!null rolname:158 + │ │ │ │ │ │ ├── outer: (5) + │ │ │ │ │ │ ├── cardinality: [0 - 1] + │ │ │ │ │ │ ├── key: () + │ │ │ │ │ │ ├── fd: ()-->(157,158) + │ │ │ │ │ │ ├── select + │ │ │ │ │ │ │ ├── columns: pg_catalog.pg_roles.oid:157!null rolname:158 + │ │ │ │ │ │ │ ├── outer: (5) + │ │ │ │ │ │ │ ├── fd: ()-->(157) + │ │ │ │ │ │ │ ├── limit hint: 1.00 + │ │ │ │ │ │ │ ├── scan pg_roles + │ │ │ │ │ │ │ │ ├── columns: pg_catalog.pg_roles.oid:157 rolname:158 + │ │ │ │ │ │ │ │ └── limit hint: 1.01 + │ │ │ │ │ │ │ └── filters + │ │ │ │ │ │ │ └── pg_catalog.pg_roles.oid:157 = c.relowner:5 [outer=(5,157), constraints=(/5: (/NULL - ]; /157: (/NULL - ]), fd=(5)==(157), (157)==(5)] + │ │ │ │ │ │ └── 1 + │ │ │ │ │ └── (('unknown (OID=' || c.relowner:5) || ')')::NAME │ │ │ │ ├── select │ │ │ │ │ ├── columns: objoid:176 objsubid:178!null pg_catalog.pg_description.description:179 │ │ │ │ │ ├── fd: ()-->(178) @@ -290,8 +327,6 @@ project │ │ │ │ └── c.oid:1 │ │ │ ├── const-agg [as=c.relname:2, outer=(2)] │ │ │ │ └── c.relname:2 - │ │ │ ├── const-agg [as=c.relowner:5, outer=(5)] - │ │ │ │ └── c.relowner:5 │ │ │ ├── const-agg [as=c.reltuples:10, outer=(10)] │ │ │ │ └── c.reltuples:10 │ │ │ ├── const-agg [as=c.relhasindex:13, outer=(13)] @@ -324,6 +359,8 @@ project │ │ │ │ └── ftoptions:136 │ │ │ ├── const-agg [as=srvname:140, outer=(140)] │ │ │ │ └── srvname:140 + │ │ │ ├── const-agg [as=column172:172, outer=(172)] + │ │ │ │ └── column172:172 │ │ │ └── first-agg [as=pg_catalog.pg_description.description:179, outer=(179)] │ │ │ └── pg_catalog.pg_description.description:179 │ │ └── filters @@ -335,8 +372,6 @@ project │ │ └── c.oid:1 │ ├── const-agg [as=c.relname:2, outer=(2)] │ │ └── c.relname:2 - │ ├── const-agg [as=c.relowner:5, outer=(5)] - │ │ └── c.relowner:5 │ ├── const-agg [as=c.reltuples:10, outer=(10)] │ │ └── c.reltuples:10 │ ├── const-agg [as=c.relhasindex:13, outer=(13)] @@ -369,49 +404,11 @@ project │ │ └── ftoptions:136 │ ├── const-agg [as=srvname:140, outer=(140)] │ │ └── srvname:140 + │ ├── const-agg [as=column172:172, outer=(172)] + │ │ └── column172:172 │ └── const-agg [as=pg_catalog.pg_description.description:179, outer=(179)] │ └── pg_catalog.pg_description.description:179 └── projections - ├── case [as=tableowner:173, outer=(5), immutable, correlated-subquery] - │ ├── true - │ ├── when - │ │ ├── c.relowner:5 IS NULL - │ │ └── CAST(NULL AS STRING) - │ └── subquery - │ └── values - │ ├── columns: column172:172 - │ ├── outer: (5) - │ ├── cardinality: [1 - 1] - │ ├── immutable - │ ├── key: () - │ ├── fd: ()-->(172) - │ └── tuple - │ └── assignment-cast: STRING - │ └── coalesce - │ ├── subquery - │ │ └── project - │ │ ├── columns: rolname:158 - │ │ ├── outer: (5) - │ │ ├── cardinality: [0 - 1] - │ │ ├── key: () - │ │ ├── fd: ()-->(158) - │ │ └── limit - │ │ ├── columns: pg_catalog.pg_roles.oid:157!null rolname:158 - │ │ ├── outer: (5) - │ │ ├── cardinality: [0 - 1] - │ │ ├── key: () - │ │ ├── fd: ()-->(157,158) - │ │ ├── select - │ │ │ ├── columns: pg_catalog.pg_roles.oid:157!null rolname:158 - │ │ │ ├── outer: (5) - │ │ │ ├── fd: ()-->(157) - │ │ │ ├── limit hint: 1.00 - │ │ │ ├── scan pg_roles - │ │ │ │ ├── columns: pg_catalog.pg_roles.oid:157 rolname:158 - │ │ │ │ └── limit hint: 1.01 - │ │ │ └── filters - │ │ │ └── pg_catalog.pg_roles.oid:157 = c.relowner:5 [outer=(5,157), constraints=(/5: (/NULL - ]; /157: (/NULL - ]), fd=(5)==(157), (157)==(5)] - │ │ └── 1 - │ └── (('unknown (OID=' || c.relowner:5) || ')')::NAME - ├── CASE WHEN c.oid:1 IS NULL THEN CAST(NULL AS STRING) ELSE pg_catalog.pg_description.description:179 END [as=description:180, outer=(1,179)] + ├── column172:172 [as=tableowner:173, outer=(172)] + ├── pg_catalog.pg_description.description:179 [as=description:180, outer=(179)] └── count_rows:154 > 0 [as=inhtable:181, outer=(154)] diff --git a/pkg/sql/opt/xform/testdata/external/navicat b/pkg/sql/opt/xform/testdata/external/navicat index 69ef0dcfe7fb..b979ade646d7 100644 --- a/pkg/sql/opt/xform/testdata/external/navicat +++ b/pkg/sql/opt/xform/testdata/external/navicat @@ -169,117 +169,154 @@ sort ├── immutable ├── fd: ()-->(31), (1)-->(2,10,13,15,17,20,22,23,26,27,37), (2)-->(1,10,13,15,17,20,22,23,26,27,37) ├── group-by (hash) - │ ├── columns: c.oid:1!null c.relname:2!null c.relowner:5!null c.reltuples:10!null c.relhasindex:13!null c.relpersistence:15!null c.relkind:17!null c.relhasoids:20!null c.relhasrules:22!null c.relhastriggers:23!null c.relacl:26 c.reloptions:27 n.nspname:31!null spcname:37 c2.relname:50 n2.nspname:79 ci.relname:106 ftoptions:136 srvname:140 count_rows:154!null pg_catalog.pg_description.description:179 rownum:182!null + │ ├── columns: c.oid:1!null c.relname:2!null c.reltuples:10!null c.relhasindex:13!null c.relpersistence:15!null c.relkind:17!null c.relhasoids:20!null c.relhasrules:22!null c.relhastriggers:23!null c.relacl:26 c.reloptions:27 n.nspname:31!null spcname:37 c2.relname:50 n2.nspname:79 ci.relname:106 ftoptions:136 srvname:140 count_rows:154!null column172:172 pg_catalog.pg_description.description:179 rownum:182!null │ ├── grouping columns: rownum:182!null + │ ├── immutable │ ├── key: (182) - │ ├── fd: ()-->(31), (1)-->(2,5,10,13,15,17,20,22,23,26,27,37), (2)-->(1,5,10,13,15,17,20,22,23,26,27,37), (182)-->(1,2,5,10,13,15,17,20,22,23,26,27,31,37,50,79,106,136,140,154,179) + │ ├── fd: ()-->(31), (1)-->(2,10,13,15,17,20,22,23,26,27,37), (2)-->(1,10,13,15,17,20,22,23,26,27,37), (182)-->(1,2,10,13,15,17,20,22,23,26,27,31,37,50,79,106,136,140,154,172,179) │ ├── right-join (hash) - │ │ ├── columns: c.oid:1!null c.relname:2!null c.relowner:5!null c.reltuples:10!null c.relhasindex:13!null c.relpersistence:15!null c.relkind:17!null c.relhasoids:20!null c.relhasrules:22!null c.relhastriggers:23!null c.relacl:26 c.reloptions:27 n.nspname:31!null spcname:37 c2.relname:50 n2.nspname:79 ci.relname:106 ftoptions:136 srvname:140 pg_inherits.inhparent:150 pg_catalog.pg_description.description:179 rownum:182!null - │ │ ├── fd: ()-->(31), (1)-->(2,5,10,13,15,17,20,22,23,26,27,37), (2)-->(1,5,10,13,15,17,20,22,23,26,27,37), (182)-->(1,2,5,10,13,15,17,20,22,23,26,27,37,50,79,106,136,140,179) + │ │ ├── columns: c.oid:1!null c.relname:2!null c.reltuples:10!null c.relhasindex:13!null c.relpersistence:15!null c.relkind:17!null c.relhasoids:20!null c.relhasrules:22!null c.relhastriggers:23!null c.relacl:26 c.reloptions:27 n.nspname:31!null spcname:37 c2.relname:50 n2.nspname:79 ci.relname:106 ftoptions:136 srvname:140 pg_inherits.inhparent:150 column172:172 pg_catalog.pg_description.description:179 rownum:182!null + │ │ ├── immutable + │ │ ├── fd: ()-->(31), (1)-->(2,10,13,15,17,20,22,23,26,27,37), (2)-->(1,10,13,15,17,20,22,23,26,27,37), (182)-->(1,2,10,13,15,17,20,22,23,26,27,37,50,79,106,136,140,172,179) │ │ ├── scan pg_inherits │ │ │ └── columns: pg_inherits.inhparent:150!null │ │ ├── distinct-on - │ │ │ ├── columns: c.oid:1!null c.relname:2!null c.relowner:5!null c.reltuples:10!null c.relhasindex:13!null c.relpersistence:15!null c.relkind:17!null c.relhasoids:20!null c.relhasrules:22!null c.relhastriggers:23!null c.relacl:26 c.reloptions:27 n.nspname:31!null spcname:37 c2.relname:50 n2.nspname:79 ci.relname:106 ftoptions:136 srvname:140 pg_catalog.pg_description.description:179 rownum:182!null + │ │ │ ├── columns: c.oid:1!null c.relname:2!null c.reltuples:10!null c.relhasindex:13!null c.relpersistence:15!null c.relkind:17!null c.relhasoids:20!null c.relhasrules:22!null c.relhastriggers:23!null c.relacl:26 c.reloptions:27 n.nspname:31!null spcname:37 c2.relname:50 n2.nspname:79 ci.relname:106 ftoptions:136 srvname:140 column172:172 pg_catalog.pg_description.description:179 rownum:182!null │ │ │ ├── grouping columns: rownum:182!null + │ │ │ ├── immutable │ │ │ ├── key: (182) - │ │ │ ├── fd: ()-->(31), (1)-->(2,5,10,13,15,17,20,22,23,26,27,37), (2)-->(1,5,10,13,15,17,20,22,23,26,27,37), (182)-->(1,2,5,10,13,15,17,20,22,23,26,27,31,37,50,79,106,136,140,179) + │ │ │ ├── fd: ()-->(31), (1)-->(2,10,13,15,17,20,22,23,26,27,37), (2)-->(1,10,13,15,17,20,22,23,26,27,37), (182)-->(1,2,10,13,15,17,20,22,23,26,27,31,37,50,79,106,136,140,172,179) │ │ │ ├── left-join (hash) - │ │ │ │ ├── columns: c.oid:1!null c.relname:2!null c.relnamespace:3!null c.relowner:5!null c.reltablespace:8!null c.reltuples:10!null c.relhasindex:13!null c.relpersistence:15!null c.relkind:17!null c.relhasoids:20!null c.relhasrules:22!null c.relhastriggers:23!null c.relacl:26 c.reloptions:27 n.oid:30!null n.nspname:31!null t.oid:36 spcname:37 i.inhrelid:44 i.inhparent:45 c2.oid:49 c2.relname:50 c2.relnamespace:51 n2.oid:78 n2.nspname:79 indexrelid:84 indrelid:85 indisclustered:91 ci.oid:105 ci.relname:106 ftrelid:134 ftserver:135 ftoptions:136 fs.oid:139 srvname:140 objoid:176 objsubid:178 pg_catalog.pg_description.description:179 rownum:182!null - │ │ │ │ ├── fd: ()-->(3,30,31), (1)-->(2,5,8,10,13,15,17,20,22,23,26,27,36,37), (2)-->(1,5,8,10,13,15,17,20,22,23,26,27), (3)==(30), (30)==(3), (36)-->(37), (37)-->(36), (49)-->(50,51), (50,51)-->(49), (45)==(49), (49)==(45), (78)~~>(79), (79)~~>(78), (84)-->(85), (105)-->(106), (134)-->(135,136), (139)-->(140), (140)-->(139), (182)-->(1,2,5,8,10,13,15,17,20,22,23,26,27,36,37,44,45,49-51,78,79,84,85,91,105,106,134-136,139,140) + │ │ │ │ ├── columns: c.oid:1!null c.relname:2!null c.reltuples:10!null c.relhasindex:13!null c.relpersistence:15!null c.relkind:17!null c.relhasoids:20!null c.relhasrules:22!null c.relhastriggers:23!null c.relacl:26 c.reloptions:27 n.nspname:31!null spcname:37 c2.relname:50 n2.nspname:79 ci.relname:106 ftoptions:136 srvname:140 column172:172 objoid:176 objsubid:178 pg_catalog.pg_description.description:179 rownum:182!null + │ │ │ │ ├── immutable + │ │ │ │ ├── fd: ()-->(31), (1)-->(2,10,13,15,17,20,22,23,26,27,37), (2)-->(1,10,13,15,17,20,22,23,26,27,37), (182)-->(1,2,10,13,15,17,20,22,23,26,27,37,50,79,106,136,140,172) │ │ │ │ ├── ordinality - │ │ │ │ │ ├── columns: c.oid:1!null c.relname:2!null c.relnamespace:3!null c.relowner:5!null c.reltablespace:8!null c.reltuples:10!null c.relhasindex:13!null c.relpersistence:15!null c.relkind:17!null c.relhasoids:20!null c.relhasrules:22!null c.relhastriggers:23!null c.relacl:26 c.reloptions:27 n.oid:30!null n.nspname:31!null t.oid:36 spcname:37 i.inhrelid:44 i.inhparent:45 c2.oid:49 c2.relname:50 c2.relnamespace:51 n2.oid:78 n2.nspname:79 indexrelid:84 indrelid:85 indisclustered:91 ci.oid:105 ci.relname:106 ftrelid:134 ftserver:135 ftoptions:136 fs.oid:139 srvname:140 rownum:182!null + │ │ │ │ │ ├── columns: c.oid:1!null c.relname:2!null c.reltuples:10!null c.relhasindex:13!null c.relpersistence:15!null c.relkind:17!null c.relhasoids:20!null c.relhasrules:22!null c.relhastriggers:23!null c.relacl:26 c.reloptions:27 n.nspname:31!null spcname:37 c2.relname:50 n2.nspname:79 ci.relname:106 ftoptions:136 srvname:140 column172:172 rownum:182!null + │ │ │ │ │ ├── immutable │ │ │ │ │ ├── key: (182) - │ │ │ │ │ ├── fd: ()-->(3,30,31), (1)-->(2,5,8,10,13,15,17,20,22,23,26,27,36,37), (2)-->(1,5,8,10,13,15,17,20,22,23,26,27), (3)==(30), (30)==(3), (36)-->(37), (37)-->(36), (49)-->(50,51), (50,51)-->(49), (45)==(49), (49)==(45), (78)~~>(79), (79)~~>(78), (84)-->(85), (105)-->(106), (134)-->(135,136), (139)-->(140), (140)-->(139), (182)-->(1-3,5,8,10,13,15,17,20,22,23,26,27,30,31,36,37,44,45,49-51,78,79,84,85,91,105,106,134-136,139,140) - │ │ │ │ │ └── left-join (lookup pg_namespace [as=n2]) - │ │ │ │ │ ├── columns: c.oid:1!null c.relname:2!null c.relnamespace:3!null c.relowner:5!null c.reltablespace:8!null c.reltuples:10!null c.relhasindex:13!null c.relpersistence:15!null c.relkind:17!null c.relhasoids:20!null c.relhasrules:22!null c.relhastriggers:23!null c.relacl:26 c.reloptions:27 n.oid:30!null n.nspname:31!null t.oid:36 spcname:37 i.inhrelid:44 i.inhparent:45 c2.oid:49 c2.relname:50 c2.relnamespace:51 n2.oid:78 n2.nspname:79 indexrelid:84 indrelid:85 indisclustered:91 ci.oid:105 ci.relname:106 ftrelid:134 ftserver:135 ftoptions:136 fs.oid:139 srvname:140 - │ │ │ │ │ ├── key columns: [51] = [78] - │ │ │ │ │ ├── lookup columns are key - │ │ │ │ │ ├── fd: ()-->(3,30,31), (1)-->(2,5,8,10,13,15,17,20,22,23,26,27,36,37), (2)-->(1,5,8,10,13,15,17,20,22,23,26,27), (3)==(30), (30)==(3), (36)-->(37), (37)-->(36), (49)-->(50,51), (50,51)-->(49), (45)==(49), (49)==(45), (78)~~>(79), (79)~~>(78), (84)-->(85), (105)-->(106), (134)-->(135,136), (139)-->(140), (140)-->(139) - │ │ │ │ │ ├── right-join (hash) - │ │ │ │ │ │ ├── columns: c.oid:1!null c.relname:2!null c.relnamespace:3!null c.relowner:5!null c.reltablespace:8!null c.reltuples:10!null c.relhasindex:13!null c.relpersistence:15!null c.relkind:17!null c.relhasoids:20!null c.relhasrules:22!null c.relhastriggers:23!null c.relacl:26 c.reloptions:27 n.oid:30!null n.nspname:31!null t.oid:36 spcname:37 i.inhrelid:44 i.inhparent:45 c2.oid:49 c2.relname:50 c2.relnamespace:51 indexrelid:84 indrelid:85 indisclustered:91 ci.oid:105 ci.relname:106 ftrelid:134 ftserver:135 ftoptions:136 fs.oid:139 srvname:140 - │ │ │ │ │ │ ├── fd: ()-->(3,30,31), (1)-->(2,5,8,10,13,15,17,20,22,23,26,27,134-136,139,140), (2)-->(1,5,8,10,13,15,17,20,22,23,26,27), (134)-->(135,136,139,140), (139)~~>(140), (140)~~>(139), (84)-->(85), (1,84)-->(91,105,106), (105)-->(106), (49)-->(50,51), (50,51)-->(49), (45)==(49), (49)==(45), (36)-->(37), (37)-->(36), (3)==(30), (30)==(3) - │ │ │ │ │ │ ├── inner-join (hash) - │ │ │ │ │ │ │ ├── columns: i.inhrelid:44!null i.inhparent:45!null c2.oid:49!null c2.relname:50!null c2.relnamespace:51!null - │ │ │ │ │ │ │ ├── multiplicity: left-rows(zero-or-one), right-rows(zero-or-more) - │ │ │ │ │ │ │ ├── fd: (49)-->(50,51), (50,51)-->(49), (45)==(49), (49)==(45) - │ │ │ │ │ │ │ ├── scan pg_inherits [as=i] - │ │ │ │ │ │ │ │ └── columns: i.inhrelid:44!null i.inhparent:45!null - │ │ │ │ │ │ │ ├── scan pg_class@pg_class_relname_nsp_index [as=c2] - │ │ │ │ │ │ │ │ ├── columns: c2.oid:49!null c2.relname:50!null c2.relnamespace:51!null - │ │ │ │ │ │ │ │ ├── key: (49) - │ │ │ │ │ │ │ │ └── fd: (49)-->(50,51), (50,51)-->(49) - │ │ │ │ │ │ │ └── filters - │ │ │ │ │ │ │ └── i.inhparent:45 = c2.oid:49 [outer=(45,49), constraints=(/45: (/NULL - ]; /49: (/NULL - ]), fd=(45)==(49), (49)==(45)] - │ │ │ │ │ │ ├── left-join (lookup pg_class [as=ci]) - │ │ │ │ │ │ │ ├── columns: c.oid:1!null c.relname:2!null c.relnamespace:3!null c.relowner:5!null c.reltablespace:8!null c.reltuples:10!null c.relhasindex:13!null c.relpersistence:15!null c.relkind:17!null c.relhasoids:20!null c.relhasrules:22!null c.relhastriggers:23!null c.relacl:26 c.reloptions:27 n.oid:30!null n.nspname:31!null t.oid:36 spcname:37 indexrelid:84 indrelid:85 indisclustered:91 ci.oid:105 ci.relname:106 ftrelid:134 ftserver:135 ftoptions:136 fs.oid:139 srvname:140 - │ │ │ │ │ │ │ ├── key columns: [84] = [105] - │ │ │ │ │ │ │ ├── lookup columns are key - │ │ │ │ │ │ │ ├── key: (1,84) - │ │ │ │ │ │ │ ├── fd: ()-->(3,30,31), (1)-->(2,5,8,10,13,15,17,20,22,23,26,27,134-136,139,140), (2)-->(1,5,8,10,13,15,17,20,22,23,26,27), (134)-->(135,136,139,140), (139)~~>(140), (140)~~>(139), (84)-->(85), (1,84)-->(36,37,91,105,106), (105)-->(106), (36)-->(37), (37)-->(36), (3)==(30), (30)==(3) - │ │ │ │ │ │ │ ├── left-join (lookup pg_index [as=ind]) - │ │ │ │ │ │ │ │ ├── columns: c.oid:1!null c.relname:2!null c.relnamespace:3!null c.relowner:5!null c.reltablespace:8!null c.reltuples:10!null c.relhasindex:13!null c.relpersistence:15!null c.relkind:17!null c.relhasoids:20!null c.relhasrules:22!null c.relhastriggers:23!null c.relacl:26 c.reloptions:27 n.oid:30!null n.nspname:31!null t.oid:36 spcname:37 indexrelid:84 indrelid:85 indisclustered:91 ftrelid:134 ftserver:135 ftoptions:136 fs.oid:139 srvname:140 - │ │ │ │ │ │ │ │ ├── key columns: [956] = [84] + │ │ │ │ │ ├── fd: ()-->(31), (1)-->(2,10,13,15,17,20,22,23,26,27,37), (2)-->(1,10,13,15,17,20,22,23,26,27,37), (182)-->(1,2,10,13,15,17,20,22,23,26,27,31,37,50,79,106,136,140,172) + │ │ │ │ │ └── project + │ │ │ │ │ ├── columns: column172:172 c.oid:1!null c.relname:2!null c.reltuples:10!null c.relhasindex:13!null c.relpersistence:15!null c.relkind:17!null c.relhasoids:20!null c.relhasrules:22!null c.relhastriggers:23!null c.relacl:26 c.reloptions:27 n.nspname:31!null spcname:37 c2.relname:50 n2.nspname:79 ci.relname:106 ftoptions:136 srvname:140 + │ │ │ │ │ ├── immutable + │ │ │ │ │ ├── fd: ()-->(31), (1)-->(2,10,13,15,17,20,22,23,26,27,37), (2)-->(1,10,13,15,17,20,22,23,26,27,37) + │ │ │ │ │ ├── left-join (lookup pg_namespace [as=n2]) + │ │ │ │ │ │ ├── columns: c.oid:1!null c.relname:2!null c.relnamespace:3!null c.relowner:5!null c.reltablespace:8!null c.reltuples:10!null c.relhasindex:13!null c.relpersistence:15!null c.relkind:17!null c.relhasoids:20!null c.relhasrules:22!null c.relhastriggers:23!null c.relacl:26 c.reloptions:27 n.oid:30!null n.nspname:31!null t.oid:36 spcname:37 i.inhrelid:44 i.inhparent:45 c2.oid:49 c2.relname:50 c2.relnamespace:51 n2.oid:78 n2.nspname:79 indexrelid:84 indrelid:85 indisclustered:91 ci.oid:105 ci.relname:106 ftrelid:134 ftserver:135 ftoptions:136 fs.oid:139 srvname:140 + │ │ │ │ │ │ ├── key columns: [51] = [78] + │ │ │ │ │ │ ├── lookup columns are key + │ │ │ │ │ │ ├── fd: ()-->(3,30,31), (1)-->(2,5,8,10,13,15,17,20,22,23,26,27,36,37), (2)-->(1,5,8,10,13,15,17,20,22,23,26,27), (3)==(30), (30)==(3), (36)-->(37), (37)-->(36), (49)-->(50,51), (50,51)-->(49), (45)==(49), (49)==(45), (78)~~>(79), (79)~~>(78), (84)-->(85), (105)-->(106), (134)-->(135,136), (139)-->(140), (140)-->(139) + │ │ │ │ │ │ ├── right-join (hash) + │ │ │ │ │ │ │ ├── columns: c.oid:1!null c.relname:2!null c.relnamespace:3!null c.relowner:5!null c.reltablespace:8!null c.reltuples:10!null c.relhasindex:13!null c.relpersistence:15!null c.relkind:17!null c.relhasoids:20!null c.relhasrules:22!null c.relhastriggers:23!null c.relacl:26 c.reloptions:27 n.oid:30!null n.nspname:31!null t.oid:36 spcname:37 i.inhrelid:44 i.inhparent:45 c2.oid:49 c2.relname:50 c2.relnamespace:51 indexrelid:84 indrelid:85 indisclustered:91 ci.oid:105 ci.relname:106 ftrelid:134 ftserver:135 ftoptions:136 fs.oid:139 srvname:140 + │ │ │ │ │ │ │ ├── fd: ()-->(3,30,31), (1)-->(2,5,8,10,13,15,17,20,22,23,26,27,134-136,139,140), (2)-->(1,5,8,10,13,15,17,20,22,23,26,27), (134)-->(135,136,139,140), (139)~~>(140), (140)~~>(139), (84)-->(85), (1,84)-->(91,105,106), (105)-->(106), (49)-->(50,51), (50,51)-->(49), (45)==(49), (49)==(45), (36)-->(37), (37)-->(36), (3)==(30), (30)==(3) + │ │ │ │ │ │ │ ├── inner-join (hash) + │ │ │ │ │ │ │ │ ├── columns: i.inhrelid:44!null i.inhparent:45!null c2.oid:49!null c2.relname:50!null c2.relnamespace:51!null + │ │ │ │ │ │ │ │ ├── multiplicity: left-rows(zero-or-one), right-rows(zero-or-more) + │ │ │ │ │ │ │ │ ├── fd: (49)-->(50,51), (50,51)-->(49), (45)==(49), (49)==(45) + │ │ │ │ │ │ │ │ ├── scan pg_inherits [as=i] + │ │ │ │ │ │ │ │ │ └── columns: i.inhrelid:44!null i.inhparent:45!null + │ │ │ │ │ │ │ │ ├── scan pg_class@pg_class_relname_nsp_index [as=c2] + │ │ │ │ │ │ │ │ │ ├── columns: c2.oid:49!null c2.relname:50!null c2.relnamespace:51!null + │ │ │ │ │ │ │ │ │ ├── key: (49) + │ │ │ │ │ │ │ │ │ └── fd: (49)-->(50,51), (50,51)-->(49) + │ │ │ │ │ │ │ │ └── filters + │ │ │ │ │ │ │ │ └── i.inhparent:45 = c2.oid:49 [outer=(45,49), constraints=(/45: (/NULL - ]; /49: (/NULL - ]), fd=(45)==(49), (49)==(45)] + │ │ │ │ │ │ │ ├── left-join (lookup pg_class [as=ci]) + │ │ │ │ │ │ │ │ ├── columns: c.oid:1!null c.relname:2!null c.relnamespace:3!null c.relowner:5!null c.reltablespace:8!null c.reltuples:10!null c.relhasindex:13!null c.relpersistence:15!null c.relkind:17!null c.relhasoids:20!null c.relhasrules:22!null c.relhastriggers:23!null c.relacl:26 c.reloptions:27 n.oid:30!null n.nspname:31!null t.oid:36 spcname:37 indexrelid:84 indrelid:85 indisclustered:91 ci.oid:105 ci.relname:106 ftrelid:134 ftserver:135 ftoptions:136 fs.oid:139 srvname:140 + │ │ │ │ │ │ │ │ ├── key columns: [84] = [105] │ │ │ │ │ │ │ │ ├── lookup columns are key - │ │ │ │ │ │ │ │ ├── second join in paired joiner │ │ │ │ │ │ │ │ ├── key: (1,84) - │ │ │ │ │ │ │ │ ├── fd: ()-->(3,30,31), (1)-->(2,5,8,10,13,15,17,20,22,23,26,27,134-136,139,140), (2)-->(1,5,8,10,13,15,17,20,22,23,26,27), (134)-->(135,136,139,140), (139)~~>(140), (140)~~>(139), (84)-->(85), (1,84)-->(36,37,91), (36)-->(37), (37)-->(36), (3)==(30), (30)==(3) - │ │ │ │ │ │ │ │ ├── left-join (lookup pg_index@pg_index_indrelid_index [as=ind]) - │ │ │ │ │ │ │ │ │ ├── columns: c.oid:1!null c.relname:2!null c.relnamespace:3!null c.relowner:5!null c.reltablespace:8!null c.reltuples:10!null c.relhasindex:13!null c.relpersistence:15!null c.relkind:17!null c.relhasoids:20!null c.relhasrules:22!null c.relhastriggers:23!null c.relacl:26 c.reloptions:27 n.oid:30!null n.nspname:31!null t.oid:36 spcname:37 ftrelid:134 ftserver:135 ftoptions:136 fs.oid:139 srvname:140 indexrelid:956 indrelid:957 continuation:977 - │ │ │ │ │ │ │ │ │ ├── key columns: [1] = [957] - │ │ │ │ │ │ │ │ │ ├── first join in paired joiner; continuation column: continuation:977 - │ │ │ │ │ │ │ │ │ ├── key: (1,956) - │ │ │ │ │ │ │ │ │ ├── fd: ()-->(3,30,31), (1)-->(2,5,8,10,13,15,17,20,22,23,26,27,36,37,134-136,139,140), (2)-->(1,5,8,10,13,15,17,20,22,23,26,27), (134)-->(135,136,139,140), (139)~~>(140), (140)~~>(139), (36)-->(37), (37)-->(36), (3)==(30), (30)==(3), (956)-->(957,977) - │ │ │ │ │ │ │ │ │ ├── left-join (lookup pg_tablespace [as=t]) - │ │ │ │ │ │ │ │ │ │ ├── columns: c.oid:1!null c.relname:2!null c.relnamespace:3!null c.relowner:5!null c.reltablespace:8!null c.reltuples:10!null c.relhasindex:13!null c.relpersistence:15!null c.relkind:17!null c.relhasoids:20!null c.relhasrules:22!null c.relhastriggers:23!null c.relacl:26 c.reloptions:27 n.oid:30!null n.nspname:31!null t.oid:36 spcname:37 ftrelid:134 ftserver:135 ftoptions:136 fs.oid:139 srvname:140 - │ │ │ │ │ │ │ │ │ │ ├── key columns: [8] = [36] - │ │ │ │ │ │ │ │ │ │ ├── lookup columns are key - │ │ │ │ │ │ │ │ │ │ ├── key: (1) - │ │ │ │ │ │ │ │ │ │ ├── fd: ()-->(3,30,31), (1)-->(2,5,8,10,13,15,17,20,22,23,26,27,36,37,134-136,139,140), (2)-->(1,5,8,10,13,15,17,20,22,23,26,27), (134)-->(135,136,139,140), (139)~~>(140), (140)~~>(139), (36)-->(37), (37)-->(36), (3)==(30), (30)==(3) - │ │ │ │ │ │ │ │ │ │ ├── left-join (lookup pg_foreign_server [as=fs]) - │ │ │ │ │ │ │ │ │ │ │ ├── columns: c.oid:1!null c.relname:2!null c.relnamespace:3!null c.relowner:5!null c.reltablespace:8!null c.reltuples:10!null c.relhasindex:13!null c.relpersistence:15!null c.relkind:17!null c.relhasoids:20!null c.relhasrules:22!null c.relhastriggers:23!null c.relacl:26 c.reloptions:27 n.oid:30!null n.nspname:31!null ftrelid:134 ftserver:135 ftoptions:136 fs.oid:139 srvname:140 - │ │ │ │ │ │ │ │ │ │ │ ├── key columns: [135] = [139] + │ │ │ │ │ │ │ │ ├── fd: ()-->(3,30,31), (1)-->(2,5,8,10,13,15,17,20,22,23,26,27,134-136,139,140), (2)-->(1,5,8,10,13,15,17,20,22,23,26,27), (134)-->(135,136,139,140), (139)~~>(140), (140)~~>(139), (84)-->(85), (1,84)-->(36,37,91,105,106), (105)-->(106), (36)-->(37), (37)-->(36), (3)==(30), (30)==(3) + │ │ │ │ │ │ │ │ ├── left-join (lookup pg_index [as=ind]) + │ │ │ │ │ │ │ │ │ ├── columns: c.oid:1!null c.relname:2!null c.relnamespace:3!null c.relowner:5!null c.reltablespace:8!null c.reltuples:10!null c.relhasindex:13!null c.relpersistence:15!null c.relkind:17!null c.relhasoids:20!null c.relhasrules:22!null c.relhastriggers:23!null c.relacl:26 c.reloptions:27 n.oid:30!null n.nspname:31!null t.oid:36 spcname:37 indexrelid:84 indrelid:85 indisclustered:91 ftrelid:134 ftserver:135 ftoptions:136 fs.oid:139 srvname:140 + │ │ │ │ │ │ │ │ │ ├── key columns: [956] = [84] + │ │ │ │ │ │ │ │ │ ├── lookup columns are key + │ │ │ │ │ │ │ │ │ ├── second join in paired joiner + │ │ │ │ │ │ │ │ │ ├── key: (1,84) + │ │ │ │ │ │ │ │ │ ├── fd: ()-->(3,30,31), (1)-->(2,5,8,10,13,15,17,20,22,23,26,27,134-136,139,140), (2)-->(1,5,8,10,13,15,17,20,22,23,26,27), (134)-->(135,136,139,140), (139)~~>(140), (140)~~>(139), (84)-->(85), (1,84)-->(36,37,91), (36)-->(37), (37)-->(36), (3)==(30), (30)==(3) + │ │ │ │ │ │ │ │ │ ├── left-join (lookup pg_index@pg_index_indrelid_index [as=ind]) + │ │ │ │ │ │ │ │ │ │ ├── columns: c.oid:1!null c.relname:2!null c.relnamespace:3!null c.relowner:5!null c.reltablespace:8!null c.reltuples:10!null c.relhasindex:13!null c.relpersistence:15!null c.relkind:17!null c.relhasoids:20!null c.relhasrules:22!null c.relhastriggers:23!null c.relacl:26 c.reloptions:27 n.oid:30!null n.nspname:31!null t.oid:36 spcname:37 ftrelid:134 ftserver:135 ftoptions:136 fs.oid:139 srvname:140 indexrelid:956 indrelid:957 continuation:977 + │ │ │ │ │ │ │ │ │ │ ├── key columns: [1] = [957] + │ │ │ │ │ │ │ │ │ │ ├── first join in paired joiner; continuation column: continuation:977 + │ │ │ │ │ │ │ │ │ │ ├── key: (1,956) + │ │ │ │ │ │ │ │ │ │ ├── fd: ()-->(3,30,31), (1)-->(2,5,8,10,13,15,17,20,22,23,26,27,36,37,134-136,139,140), (2)-->(1,5,8,10,13,15,17,20,22,23,26,27), (134)-->(135,136,139,140), (139)~~>(140), (140)~~>(139), (36)-->(37), (37)-->(36), (3)==(30), (30)==(3), (956)-->(957,977) + │ │ │ │ │ │ │ │ │ │ ├── left-join (lookup pg_tablespace [as=t]) + │ │ │ │ │ │ │ │ │ │ │ ├── columns: c.oid:1!null c.relname:2!null c.relnamespace:3!null c.relowner:5!null c.reltablespace:8!null c.reltuples:10!null c.relhasindex:13!null c.relpersistence:15!null c.relkind:17!null c.relhasoids:20!null c.relhasrules:22!null c.relhastriggers:23!null c.relacl:26 c.reloptions:27 n.oid:30!null n.nspname:31!null t.oid:36 spcname:37 ftrelid:134 ftserver:135 ftoptions:136 fs.oid:139 srvname:140 + │ │ │ │ │ │ │ │ │ │ │ ├── key columns: [8] = [36] │ │ │ │ │ │ │ │ │ │ │ ├── lookup columns are key │ │ │ │ │ │ │ │ │ │ │ ├── key: (1) - │ │ │ │ │ │ │ │ │ │ │ ├── fd: ()-->(3,30,31), (1)-->(2,5,8,10,13,15,17,20,22,23,26,27,134-136,139,140), (2)-->(1,5,8,10,13,15,17,20,22,23,26,27), (134)-->(135,136,139,140), (139)~~>(140), (140)~~>(139), (3)==(30), (30)==(3) - │ │ │ │ │ │ │ │ │ │ │ ├── left-join (lookup pg_foreign_table [as=ft]) - │ │ │ │ │ │ │ │ │ │ │ │ ├── columns: c.oid:1!null c.relname:2!null c.relnamespace:3!null c.relowner:5!null c.reltablespace:8!null c.reltuples:10!null c.relhasindex:13!null c.relpersistence:15!null c.relkind:17!null c.relhasoids:20!null c.relhasrules:22!null c.relhastriggers:23!null c.relacl:26 c.reloptions:27 n.oid:30!null n.nspname:31!null ftrelid:134 ftserver:135 ftoptions:136 - │ │ │ │ │ │ │ │ │ │ │ │ ├── key columns: [1] = [134] + │ │ │ │ │ │ │ │ │ │ │ ├── fd: ()-->(3,30,31), (1)-->(2,5,8,10,13,15,17,20,22,23,26,27,36,37,134-136,139,140), (2)-->(1,5,8,10,13,15,17,20,22,23,26,27), (134)-->(135,136,139,140), (139)~~>(140), (140)~~>(139), (36)-->(37), (37)-->(36), (3)==(30), (30)==(3) + │ │ │ │ │ │ │ │ │ │ │ ├── left-join (lookup pg_foreign_server [as=fs]) + │ │ │ │ │ │ │ │ │ │ │ │ ├── columns: c.oid:1!null c.relname:2!null c.relnamespace:3!null c.relowner:5!null c.reltablespace:8!null c.reltuples:10!null c.relhasindex:13!null c.relpersistence:15!null c.relkind:17!null c.relhasoids:20!null c.relhasrules:22!null c.relhastriggers:23!null c.relacl:26 c.reloptions:27 n.oid:30!null n.nspname:31!null ftrelid:134 ftserver:135 ftoptions:136 fs.oid:139 srvname:140 + │ │ │ │ │ │ │ │ │ │ │ │ ├── key columns: [135] = [139] │ │ │ │ │ │ │ │ │ │ │ │ ├── lookup columns are key │ │ │ │ │ │ │ │ │ │ │ │ ├── key: (1) - │ │ │ │ │ │ │ │ │ │ │ │ ├── fd: ()-->(3,30,31), (1)-->(2,5,8,10,13,15,17,20,22,23,26,27,134-136), (2)-->(1,5,8,10,13,15,17,20,22,23,26,27), (134)-->(135,136), (3)==(30), (30)==(3) - │ │ │ │ │ │ │ │ │ │ │ │ ├── inner-join (hash) - │ │ │ │ │ │ │ │ │ │ │ │ │ ├── columns: c.oid:1!null c.relname:2!null c.relnamespace:3!null c.relowner:5!null c.reltablespace:8!null c.reltuples:10!null c.relhasindex:13!null c.relpersistence:15!null c.relkind:17!null c.relhasoids:20!null c.relhasrules:22!null c.relhastriggers:23!null c.relacl:26 c.reloptions:27 n.oid:30!null n.nspname:31!null - │ │ │ │ │ │ │ │ │ │ │ │ │ ├── multiplicity: left-rows(zero-or-one), right-rows(zero-or-more) + │ │ │ │ │ │ │ │ │ │ │ │ ├── fd: ()-->(3,30,31), (1)-->(2,5,8,10,13,15,17,20,22,23,26,27,134-136,139,140), (2)-->(1,5,8,10,13,15,17,20,22,23,26,27), (134)-->(135,136,139,140), (139)~~>(140), (140)~~>(139), (3)==(30), (30)==(3) + │ │ │ │ │ │ │ │ │ │ │ │ ├── left-join (lookup pg_foreign_table [as=ft]) + │ │ │ │ │ │ │ │ │ │ │ │ │ ├── columns: c.oid:1!null c.relname:2!null c.relnamespace:3!null c.relowner:5!null c.reltablespace:8!null c.reltuples:10!null c.relhasindex:13!null c.relpersistence:15!null c.relkind:17!null c.relhasoids:20!null c.relhasrules:22!null c.relhastriggers:23!null c.relacl:26 c.reloptions:27 n.oid:30!null n.nspname:31!null ftrelid:134 ftserver:135 ftoptions:136 + │ │ │ │ │ │ │ │ │ │ │ │ │ ├── key columns: [1] = [134] + │ │ │ │ │ │ │ │ │ │ │ │ │ ├── lookup columns are key │ │ │ │ │ │ │ │ │ │ │ │ │ ├── key: (1) - │ │ │ │ │ │ │ │ │ │ │ │ │ ├── fd: ()-->(3,30,31), (1)-->(2,5,8,10,13,15,17,20,22,23,26,27), (2)-->(1,5,8,10,13,15,17,20,22,23,26,27), (3)==(30), (30)==(3) - │ │ │ │ │ │ │ │ │ │ │ │ │ ├── select - │ │ │ │ │ │ │ │ │ │ │ │ │ │ ├── columns: c.oid:1!null c.relname:2!null c.relnamespace:3!null c.relowner:5!null c.reltablespace:8!null c.reltuples:10!null c.relhasindex:13!null c.relpersistence:15!null c.relkind:17!null c.relhasoids:20!null c.relhasrules:22!null c.relhastriggers:23!null c.relacl:26 c.reloptions:27 + │ │ │ │ │ │ │ │ │ │ │ │ │ ├── fd: ()-->(3,30,31), (1)-->(2,5,8,10,13,15,17,20,22,23,26,27,134-136), (2)-->(1,5,8,10,13,15,17,20,22,23,26,27), (134)-->(135,136), (3)==(30), (30)==(3) + │ │ │ │ │ │ │ │ │ │ │ │ │ ├── inner-join (hash) + │ │ │ │ │ │ │ │ │ │ │ │ │ │ ├── columns: c.oid:1!null c.relname:2!null c.relnamespace:3!null c.relowner:5!null c.reltablespace:8!null c.reltuples:10!null c.relhasindex:13!null c.relpersistence:15!null c.relkind:17!null c.relhasoids:20!null c.relhasrules:22!null c.relhastriggers:23!null c.relacl:26 c.reloptions:27 n.oid:30!null n.nspname:31!null + │ │ │ │ │ │ │ │ │ │ │ │ │ │ ├── multiplicity: left-rows(zero-or-one), right-rows(zero-or-more) │ │ │ │ │ │ │ │ │ │ │ │ │ │ ├── key: (1) - │ │ │ │ │ │ │ │ │ │ │ │ │ │ ├── fd: (1)-->(2,3,5,8,10,13,15,17,20,22,23,26,27), (2,3)-->(1,5,8,10,13,15,17,20,22,23,26,27) - │ │ │ │ │ │ │ │ │ │ │ │ │ │ ├── scan pg_class [as=c] + │ │ │ │ │ │ │ │ │ │ │ │ │ │ ├── fd: ()-->(3,30,31), (1)-->(2,5,8,10,13,15,17,20,22,23,26,27), (2)-->(1,5,8,10,13,15,17,20,22,23,26,27), (3)==(30), (30)==(3) + │ │ │ │ │ │ │ │ │ │ │ │ │ │ ├── select │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ ├── columns: c.oid:1!null c.relname:2!null c.relnamespace:3!null c.relowner:5!null c.reltablespace:8!null c.reltuples:10!null c.relhasindex:13!null c.relpersistence:15!null c.relkind:17!null c.relhasoids:20!null c.relhasrules:22!null c.relhastriggers:23!null c.relacl:26 c.reloptions:27 │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ ├── key: (1) - │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ └── fd: (1)-->(2,3,5,8,10,13,15,17,20,22,23,26,27), (2,3)-->(1,5,8,10,13,15,17,20,22,23,26,27) + │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ ├── fd: (1)-->(2,3,5,8,10,13,15,17,20,22,23,26,27), (2,3)-->(1,5,8,10,13,15,17,20,22,23,26,27) + │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ ├── scan pg_class [as=c] + │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ ├── columns: c.oid:1!null c.relname:2!null c.relnamespace:3!null c.relowner:5!null c.reltablespace:8!null c.reltuples:10!null c.relhasindex:13!null c.relpersistence:15!null c.relkind:17!null c.relhasoids:20!null c.relhasrules:22!null c.relhastriggers:23!null c.relacl:26 c.reloptions:27 + │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ ├── key: (1) + │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ └── fd: (1)-->(2,3,5,8,10,13,15,17,20,22,23,26,27), (2,3)-->(1,5,8,10,13,15,17,20,22,23,26,27) + │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ └── filters + │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ └── (c.relkind:17 = 'r') OR (c.relkind:17 = 'f') [outer=(17), constraints=(/17: [/'f' - /'f'] [/'r' - /'r']; tight)] + │ │ │ │ │ │ │ │ │ │ │ │ │ │ ├── scan pg_namespace@pg_namespace_nspname_index [as=n] + │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ ├── columns: n.oid:30!null n.nspname:31!null + │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ ├── constraint: /31: [/'public' - /'public'] + │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ ├── cardinality: [0 - 1] + │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ ├── key: () + │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ └── fd: ()-->(30,31) │ │ │ │ │ │ │ │ │ │ │ │ │ │ └── filters - │ │ │ │ │ │ │ │ │ │ │ │ │ │ └── (c.relkind:17 = 'r') OR (c.relkind:17 = 'f') [outer=(17), constraints=(/17: [/'f' - /'f'] [/'r' - /'r']; tight)] - │ │ │ │ │ │ │ │ │ │ │ │ │ ├── scan pg_namespace@pg_namespace_nspname_index [as=n] - │ │ │ │ │ │ │ │ │ │ │ │ │ │ ├── columns: n.oid:30!null n.nspname:31!null - │ │ │ │ │ │ │ │ │ │ │ │ │ │ ├── constraint: /31: [/'public' - /'public'] - │ │ │ │ │ │ │ │ │ │ │ │ │ │ ├── cardinality: [0 - 1] - │ │ │ │ │ │ │ │ │ │ │ │ │ │ ├── key: () - │ │ │ │ │ │ │ │ │ │ │ │ │ │ └── fd: ()-->(30,31) - │ │ │ │ │ │ │ │ │ │ │ │ │ └── filters - │ │ │ │ │ │ │ │ │ │ │ │ │ └── n.oid:30 = c.relnamespace:3 [outer=(3,30), constraints=(/3: (/NULL - ]; /30: (/NULL - ]), fd=(3)==(30), (30)==(3)] + │ │ │ │ │ │ │ │ │ │ │ │ │ │ └── n.oid:30 = c.relnamespace:3 [outer=(3,30), constraints=(/3: (/NULL - ]; /30: (/NULL - ]), fd=(3)==(30), (30)==(3)] + │ │ │ │ │ │ │ │ │ │ │ │ │ └── filters (true) │ │ │ │ │ │ │ │ │ │ │ │ └── filters (true) │ │ │ │ │ │ │ │ │ │ │ └── filters (true) │ │ │ │ │ │ │ │ │ │ └── filters (true) - │ │ │ │ │ │ │ │ │ └── filters (true) - │ │ │ │ │ │ │ │ └── filters - │ │ │ │ │ │ │ │ └── indisclustered:91 [outer=(91), constraints=(/91: [/true - /true]; tight), fd=()-->(91)] - │ │ │ │ │ │ │ └── filters (true) - │ │ │ │ │ │ └── filters - │ │ │ │ │ │ └── i.inhrelid:44 = c.oid:1 [outer=(1,44), constraints=(/1: (/NULL - ]; /44: (/NULL - ]), fd=(1)==(44), (44)==(1)] - │ │ │ │ │ └── filters (true) + │ │ │ │ │ │ │ │ │ └── filters + │ │ │ │ │ │ │ │ │ └── indisclustered:91 [outer=(91), constraints=(/91: [/true - /true]; tight), fd=()-->(91)] + │ │ │ │ │ │ │ │ └── filters (true) + │ │ │ │ │ │ │ └── filters + │ │ │ │ │ │ │ └── i.inhrelid:44 = c.oid:1 [outer=(1,44), constraints=(/1: (/NULL - ]; /44: (/NULL - ]), fd=(1)==(44), (44)==(1)] + │ │ │ │ │ │ └── filters (true) + │ │ │ │ │ └── projections + │ │ │ │ │ └── assignment-cast: STRING [as=column172:172, outer=(5), immutable, correlated-subquery] + │ │ │ │ │ └── coalesce + │ │ │ │ │ ├── subquery + │ │ │ │ │ │ └── project + │ │ │ │ │ │ ├── columns: rolname:158 + │ │ │ │ │ │ ├── outer: (5) + │ │ │ │ │ │ ├── cardinality: [0 - 1] + │ │ │ │ │ │ ├── key: () + │ │ │ │ │ │ ├── fd: ()-->(158) + │ │ │ │ │ │ └── limit + │ │ │ │ │ │ ├── columns: pg_catalog.pg_roles.oid:157!null rolname:158 + │ │ │ │ │ │ ├── outer: (5) + │ │ │ │ │ │ ├── cardinality: [0 - 1] + │ │ │ │ │ │ ├── key: () + │ │ │ │ │ │ ├── fd: ()-->(157,158) + │ │ │ │ │ │ ├── select + │ │ │ │ │ │ │ ├── columns: pg_catalog.pg_roles.oid:157!null rolname:158 + │ │ │ │ │ │ │ ├── outer: (5) + │ │ │ │ │ │ │ ├── fd: ()-->(157) + │ │ │ │ │ │ │ ├── limit hint: 1.00 + │ │ │ │ │ │ │ ├── scan pg_roles + │ │ │ │ │ │ │ │ ├── columns: pg_catalog.pg_roles.oid:157 rolname:158 + │ │ │ │ │ │ │ │ └── limit hint: 1.01 + │ │ │ │ │ │ │ └── filters + │ │ │ │ │ │ │ └── pg_catalog.pg_roles.oid:157 = c.relowner:5 [outer=(5,157), constraints=(/5: (/NULL - ]; /157: (/NULL - ]), fd=(5)==(157), (157)==(5)] + │ │ │ │ │ │ └── 1 + │ │ │ │ │ └── (('unknown (OID=' || c.relowner:5) || ')')::NAME │ │ │ │ ├── select │ │ │ │ │ ├── columns: objoid:176 objsubid:178!null pg_catalog.pg_description.description:179 │ │ │ │ │ ├── fd: ()-->(178) @@ -294,8 +331,6 @@ sort │ │ │ │ └── c.oid:1 │ │ │ ├── const-agg [as=c.relname:2, outer=(2)] │ │ │ │ └── c.relname:2 - │ │ │ ├── const-agg [as=c.relowner:5, outer=(5)] - │ │ │ │ └── c.relowner:5 │ │ │ ├── const-agg [as=c.reltuples:10, outer=(10)] │ │ │ │ └── c.reltuples:10 │ │ │ ├── const-agg [as=c.relhasindex:13, outer=(13)] @@ -328,6 +363,8 @@ sort │ │ │ │ └── ftoptions:136 │ │ │ ├── const-agg [as=srvname:140, outer=(140)] │ │ │ │ └── srvname:140 + │ │ │ ├── const-agg [as=column172:172, outer=(172)] + │ │ │ │ └── column172:172 │ │ │ └── first-agg [as=pg_catalog.pg_description.description:179, outer=(179)] │ │ │ └── pg_catalog.pg_description.description:179 │ │ └── filters @@ -339,8 +376,6 @@ sort │ │ └── c.oid:1 │ ├── const-agg [as=c.relname:2, outer=(2)] │ │ └── c.relname:2 - │ ├── const-agg [as=c.relowner:5, outer=(5)] - │ │ └── c.relowner:5 │ ├── const-agg [as=c.reltuples:10, outer=(10)] │ │ └── c.reltuples:10 │ ├── const-agg [as=c.relhasindex:13, outer=(13)] @@ -373,49 +408,11 @@ sort │ │ └── ftoptions:136 │ ├── const-agg [as=srvname:140, outer=(140)] │ │ └── srvname:140 + │ ├── const-agg [as=column172:172, outer=(172)] + │ │ └── column172:172 │ └── const-agg [as=pg_catalog.pg_description.description:179, outer=(179)] │ └── pg_catalog.pg_description.description:179 └── projections - ├── case [as=tableowner:173, outer=(5), immutable, correlated-subquery] - │ ├── true - │ ├── when - │ │ ├── c.relowner:5 IS NULL - │ │ └── CAST(NULL AS STRING) - │ └── subquery - │ └── values - │ ├── columns: column172:172 - │ ├── outer: (5) - │ ├── cardinality: [1 - 1] - │ ├── immutable - │ ├── key: () - │ ├── fd: ()-->(172) - │ └── tuple - │ └── assignment-cast: STRING - │ └── coalesce - │ ├── subquery - │ │ └── project - │ │ ├── columns: rolname:158 - │ │ ├── outer: (5) - │ │ ├── cardinality: [0 - 1] - │ │ ├── key: () - │ │ ├── fd: ()-->(158) - │ │ └── limit - │ │ ├── columns: pg_catalog.pg_roles.oid:157!null rolname:158 - │ │ ├── outer: (5) - │ │ ├── cardinality: [0 - 1] - │ │ ├── key: () - │ │ ├── fd: ()-->(157,158) - │ │ ├── select - │ │ │ ├── columns: pg_catalog.pg_roles.oid:157!null rolname:158 - │ │ │ ├── outer: (5) - │ │ │ ├── fd: ()-->(157) - │ │ │ ├── limit hint: 1.00 - │ │ │ ├── scan pg_roles - │ │ │ │ ├── columns: pg_catalog.pg_roles.oid:157 rolname:158 - │ │ │ │ └── limit hint: 1.01 - │ │ │ └── filters - │ │ │ └── pg_catalog.pg_roles.oid:157 = c.relowner:5 [outer=(5,157), constraints=(/5: (/NULL - ]; /157: (/NULL - ]), fd=(5)==(157), (157)==(5)] - │ │ └── 1 - │ └── (('unknown (OID=' || c.relowner:5) || ')')::NAME - ├── CASE WHEN c.oid:1 IS NULL THEN CAST(NULL AS STRING) ELSE pg_catalog.pg_description.description:179 END [as=description:180, outer=(1,179)] + ├── column172:172 [as=tableowner:173, outer=(172)] + ├── pg_catalog.pg_description.description:179 [as=description:180, outer=(179)] └── count_rows:154 > 0 [as=inhtable:181, outer=(154)] diff --git a/pkg/sql/opt/xform/testdata/external/pgjdbc b/pkg/sql/opt/xform/testdata/external/pgjdbc index 3ada70d2e8a2..e9e40a3843ef 100644 --- a/pkg/sql/opt/xform/testdata/external/pgjdbc +++ b/pkg/sql/opt/xform/testdata/external/pgjdbc @@ -37,19 +37,19 @@ project ├── columns: type_cat:71 type_schem:35!null type_name:3!null class_name:71 data_type:72 remarks:122 base_type:123 ├── fd: ()-->(71) ├── ensure-distinct-on - │ ├── columns: t.oid:2!null t.typname:3!null t.typtype:8 nspname:35!null case:70 description:79 rownum:124!null + │ ├── columns: t.typname:3!null t.typtype:8 nspname:35!null case:70 description:79 rownum:124!null │ ├── grouping columns: rownum:124!null │ ├── error: "more than one row returned by a subquery used as an expression" │ ├── key: (124) - │ ├── fd: (124)-->(2,3,8,35,70,79) + │ ├── fd: (124)-->(3,8,35,70,79) │ ├── left-join (hash) - │ │ ├── columns: t.oid:2!null t.typname:3!null t.typtype:8 t.typbasetype:26 nspname:35!null pg_catalog.pg_type.oid:39 case:70 description:79 rownum:124!null - │ │ ├── fd: (124)-->(2,3,8,26,35,79) + │ │ ├── columns: t.typname:3!null t.typtype:8 t.typbasetype:26 nspname:35!null pg_catalog.pg_type.oid:39 case:70 description:79 rownum:124!null + │ │ ├── fd: (124)-->(3,8,26,35,79) │ │ ├── distinct-on - │ │ │ ├── columns: t.oid:2!null t.typname:3!null t.typtype:8 t.typbasetype:26 nspname:35!null description:79 rownum:124!null + │ │ │ ├── columns: t.typname:3!null t.typtype:8 t.typbasetype:26 nspname:35!null description:79 rownum:124!null │ │ │ ├── grouping columns: rownum:124!null │ │ │ ├── key: (124) - │ │ │ ├── fd: (124)-->(2,3,8,26,35,79) + │ │ │ ├── fd: (124)-->(3,8,26,35,79) │ │ │ ├── left-join (hash) │ │ │ │ ├── columns: t.oid:2!null t.typname:3!null t.typnamespace:4!null t.typtype:8 t.typbasetype:26 n.oid:34!null nspname:35!null objoid:76 classoid:77 objsubid:78 description:79 c.oid:81 relname:82 relnamespace:83 n.oid:118 nspname:119 rownum:124!null │ │ │ │ ├── fd: (4)==(34), (34)==(4), (124)-->(2-4,8,26,34,35), (77)==(81), (81)==(77), (83)==(118), (118)==(83) @@ -98,8 +98,6 @@ project │ │ │ │ └── filters │ │ │ │ └── objoid:76 = t.oid:2 [outer=(2,76), constraints=(/2: (/NULL - ]; /76: (/NULL - ]), fd=(2)==(76), (76)==(2)] │ │ │ └── aggregations - │ │ │ ├── const-agg [as=t.oid:2, outer=(2)] - │ │ │ │ └── t.oid:2 │ │ │ ├── const-agg [as=t.typname:3, outer=(3)] │ │ │ │ └── t.typname:3 │ │ │ ├── const-agg [as=t.typtype:8, outer=(8)] @@ -119,8 +117,6 @@ project │ │ └── filters │ │ └── pg_catalog.pg_type.oid:39 = t.typbasetype:26 [outer=(26,39), constraints=(/26: (/NULL - ]; /39: (/NULL - ]), fd=(26)==(39), (39)==(26)] │ └── aggregations - │ ├── const-agg [as=t.oid:2, outer=(2)] - │ │ └── t.oid:2 │ ├── const-agg [as=t.typname:3, outer=(3)] │ │ └── t.typname:3 │ ├── const-agg [as=t.typtype:8, outer=(8)] @@ -134,7 +130,7 @@ project └── projections ├── NULL [as=type_cat:71] ├── CASE WHEN t.typtype:8 = 'c' THEN 'STRUCT' ELSE 'DISTINCT' END [as=data_type:72, outer=(8)] - ├── CASE WHEN t.oid:2 IS NULL THEN CAST(NULL AS STRING) ELSE description:79 END [as=remarks:122, outer=(2,79)] + ├── description:79 [as=remarks:122, outer=(79)] └── CASE WHEN t.typtype:8 = 'd' THEN case:70 ELSE CAST(NULL AS STRING) END [as=base_type:123, outer=(8,70)] diff --git a/pkg/sql/sem/builtins/builtins_test.go b/pkg/sql/sem/builtins/builtins_test.go index 59af222206b8..b8d2d1155dbb 100644 --- a/pkg/sql/sem/builtins/builtins_test.go +++ b/pkg/sql/sem/builtins/builtins_test.go @@ -680,3 +680,83 @@ func TestTruncateTimestamp(t *testing.T) { }) } } + +func TestPGBuiltinsCalledOnNull(t *testing.T) { + defer leaktest.AfterTest(t)() + ctx := context.Background() + + params := base.TestServerArgs{} + s, db, _ := serverutils.StartServer(t, params) + defer s.Stopper().Stop(ctx) + + tdb := sqlutils.MakeSQLRunner(db) + + testCases := []struct { + sql string + }{ + { // Case 1 + sql: "SELECT pg_get_functiondef(NULL);", + }, + { // Case 2 + sql: "SELECT pg_get_function_arguments(NULL);", + }, + { // Case 3 + sql: "SELECT pg_get_function_result(NULL);", + }, + { // Case 4 + sql: "SELECT pg_get_function_identity_arguments(NULL);", + }, + { // Case 5 + sql: "SELECT pg_get_indexdef(NULL);", + }, + { // Case 6 + sql: "SELECT pg_get_userbyid(NULL);", + }, + { // Case 7 + sql: "SELECT pg_sequence_parameters(NULL);", + }, + { // Case 8 + sql: "SELECT col_description(NULL, NULL);", + }, + { // Case 9 + sql: "SELECT col_description(NULL, 0);", + }, + { // Case 10 + sql: "SELECT col_description(0, NULL);", + }, + { // Case 11 + sql: "SELECT obj_description(NULL);", + }, + { // Case 12 + sql: "SELECT obj_description(NULL, NULL);", + }, + { // Case 13 + sql: "SELECT obj_description(NULL, 'foo');", + }, + { // Case 14 + sql: "SELECT obj_description(0, NULL);", + }, + { // Case 15 + sql: "SELECT shobj_description(NULL, NULL);", + }, + { // Case 16 + sql: "SELECT shobj_description(NULL, 'foo');", + }, + { // Case 17 + sql: "SELECT shobj_description(0, NULL);", + }, + { // Case 18 + sql: "SELECT pg_function_is_visible(NULL);", + }, + { // Case 19 + sql: "SELECT pg_table_is_visible(NULL);", + }, + { // Case 20 + sql: "SELECT pg_type_is_visible(NULL);", + }, + } + for i, tc := range testCases { + res := tdb.QueryStr(t, tc.sql) + require.Equalf(t, [][]string{{"NULL"}}, res, "failed test case %d", i+1) + } +} diff --git a/pkg/sql/sem/builtins/pg_builtins.go b/pkg/sql/sem/builtins/pg_builtins.go index 4a10ed242d43..b01c09522535 100644 --- a/pkg/sql/sem/builtins/pg_builtins.go +++ b/pkg/sql/sem/builtins/pg_builtins.go @@ -608,7 +608,8 @@ var pgBuiltins = map[string]builtinDefinition{ LIMIT 1`, oidext.CockroachPredefinedOIDMax), Info: "For user-defined functions, returns the definition of the specified function. " + "For builtin functions, returns the name of the function.", - Volatility: volatility.Stable, + Volatility: volatility.Stable, + CalledOnNullInput: true, }, ), @@ -621,7 +622,8 @@ var pgBuiltins = map[string]builtinDefinition{ Body: getFunctionArgStringQuery, Info: "Returns the argument list (with defaults) necessary to identify a function, " + "in the form it would need to appear in within CREATE FUNCTION.", - Volatility: volatility.Stable, + Volatility: volatility.Stable, + CalledOnNullInput: true, }, ), @@ -640,8 +642,9 @@ var pgBuiltins = map[string]builtinDefinition{ JOIN pg_catalog.pg_type t ON prorettype=t.oid WHERE p.oid=$1 LIMIT 1`, - Info: "Returns the types of the result of the specified function.", - Volatility: volatility.Stable, + Info: "Returns the types of the result of the specified function.", + Volatility: volatility.Stable, + CalledOnNullInput: true, }, ), @@ -658,7 +661,8 @@ var pgBuiltins = map[string]builtinDefinition{ Body: getFunctionArgStringQuery, Info: "Returns the argument list (without defaults) necessary to identify a function, " + "in the form it would need to appear in within ALTER FUNCTION, for instance.", - Volatility: volatility.Stable, + Volatility: volatility.Stable, + CalledOnNullInput: true, }, ), @@ -667,12 +671,13 @@ var pgBuiltins = map[string]builtinDefinition{ "pg_get_indexdef": makeBuiltin( tree.FunctionProperties{Category: builtinconstants.CategorySystemInfo, DistsqlBlocklist: true}, tree.Overload{ - IsUDF: true, - Types: tree.ParamTypes{{Name: "index_oid", Typ: types.Oid}}, - ReturnType: tree.FixedReturnType(types.String), - Body: `SELECT indexdef FROM pg_catalog.pg_indexes WHERE crdb_oid = $1`, - Info: "Gets the CREATE INDEX command for index", - Volatility: volatility.Stable, + IsUDF: true, + Types: tree.ParamTypes{{Name: "index_oid", Typ: types.Oid}}, + ReturnType: tree.FixedReturnType(types.String), + Body: `SELECT indexdef FROM pg_catalog.pg_indexes WHERE crdb_oid = $1`, + Info: "Gets the CREATE INDEX command for index", + Volatility: volatility.Stable, + CalledOnNullInput: true, }, tree.Overload{ IsUDF: true, @@ -846,11 +851,12 @@ var pgBuiltins = map[string]builtinDefinition{ Types: tree.ParamTypes{ {Name: "role_oid", Typ: types.Oid}, }, - ReturnType: tree.FixedReturnType(types.String), - IsUDF: true, - Body: `SELECT COALESCE((SELECT rolname FROM pg_catalog.pg_roles WHERE oid=$1 LIMIT 1), 'unknown (OID=' || $1 || ')')`, - Info: notUsableInfo, - Volatility: volatility.Stable, + ReturnType: tree.FixedReturnType(types.String), + IsUDF: true, + Body: `SELECT COALESCE((SELECT rolname FROM pg_catalog.pg_roles WHERE oid=$1 LIMIT 1), 'unknown (OID=' || $1 || ')')`, + Info: notUsableInfo, + Volatility: volatility.Stable, + CalledOnNullInput: true, }, ), @@ -870,8 +876,9 @@ var pgBuiltins = map[string]builtinDefinition{ Body: `SELECT COALESCE ((SELECT (seqstart, seqmin, seqmax, seqincrement, seqcycle, seqcache, seqtypid) FROM pg_catalog.pg_sequence WHERE seqrelid=$1 LIMIT 1), CASE WHEN crdb_internal.force_error('42P01', 'relation with OID ' || $1 || ' does not exist') > 0 THEN NULL ELSE NULL END)`, - Info: notUsableInfo, - Volatility: volatility.Stable, + Info: notUsableInfo, + Volatility: volatility.Stable, + CalledOnNullInput: true, }, ), @@ -948,7 +955,8 @@ var pgBuiltins = map[string]builtinDefinition{ catconstants.MinVirtualID), Info: "Returns the comment for a table column, which is specified by the OID of its table and its column number. " + "(obj_description cannot be used for table columns, since columns do not have OIDs of their own.)", - Volatility: volatility.Stable, + Volatility: volatility.Stable, + CalledOnNullInput: true, }, ), @@ -965,7 +973,8 @@ var pgBuiltins = map[string]builtinDefinition{ Info: "Returns the comment for a database object specified by its OID alone. " + "This is deprecated since there is no guarantee that OIDs are unique across different system catalogs; " + "therefore, the wrong comment might be returned.", - Volatility: volatility.Stable, + Volatility: volatility.Stable, + CalledOnNullInput: true, }, tree.Overload{ IsUDF: true, @@ -984,7 +993,8 @@ var pgBuiltins = map[string]builtinDefinition{ LIMIT 1`, Info: "Returns the comment for a database object specified by its OID and the name of the containing system catalog. " + "For example, obj_description(123456, 'pg_class') would retrieve the comment for the table with OID 123456.", - Volatility: volatility.Stable, + Volatility: volatility.Stable, + CalledOnNullInput: true, }, ), @@ -1017,7 +1027,8 @@ var pgBuiltins = map[string]builtinDefinition{ LIMIT 1`, Info: "Returns the comment for a shared database object specified by its OID and the name of the containing system catalog. " + "This is just like obj_description except that it is used for retrieving comments on shared objects (e.g. databases). ", - Volatility: volatility.Stable, + Volatility: volatility.Stable, + CalledOnNullInput: true, }, ), @@ -1072,8 +1083,9 @@ var pgBuiltins = map[string]builtinDefinition{ INNER LOOKUP JOIN pg_catalog.pg_namespace n ON p.pronamespace = n.oid WHERE p.oid=$1 LIMIT 1`, - Info: "Returns whether the function with the given OID belongs to one of the schemas on the search path.", - Volatility: volatility.Stable, + CalledOnNullInput: true, + Info: "Returns whether the function with the given OID belongs to one of the schemas on the search path.", + Volatility: volatility.Stable, }, ), // pg_table_is_visible returns true if the input oid corresponds to a table @@ -1089,8 +1101,9 @@ var pgBuiltins = map[string]builtinDefinition{ INNER LOOKUP JOIN pg_catalog.pg_namespace n ON c.relnamespace = n.oid WHERE c.oid=$1 LIMIT 1`, - Info: "Returns whether the table with the given OID belongs to one of the schemas on the search path.", - Volatility: volatility.Stable, + CalledOnNullInput: true, + Info: "Returns whether the table with the given OID belongs to one of the schemas on the search path.", + Volatility: volatility.Stable, }, ), @@ -1110,8 +1123,9 @@ var pgBuiltins = map[string]builtinDefinition{ INNER LOOKUP JOIN pg_catalog.pg_namespace n ON t.typnamespace = n.oid WHERE t.oid=$1 LIMIT 1`, - Info: "Returns whether the type with the given OID belongs to one of the schemas on the search path.", - Volatility: volatility.Stable, + CalledOnNullInput: true, + Info: "Returns whether the type with the given OID belongs to one of the schemas on the search path.", + Volatility: volatility.Stable, }, ),