diff --git a/pkg/bench/rttanalysis/testdata/benchmark_expectations b/pkg/bench/rttanalysis/testdata/benchmark_expectations index 8ce14a971792..4fff2a504ff2 100644 --- a/pkg/bench/rttanalysis/testdata/benchmark_expectations +++ b/pkg/bench/rttanalysis/testdata/benchmark_expectations @@ -61,8 +61,8 @@ exp,benchmark 4,ORMQueries/django_column_introspection_1_table 4,ORMQueries/django_column_introspection_4_tables 4,ORMQueries/django_column_introspection_8_tables -5,ORMQueries/django_table_introspection_1_table -5,ORMQueries/django_table_introspection_8_tables +3,ORMQueries/django_table_introspection_1_table +3,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/logictest/testdata/logic_test/udf b/pkg/sql/logictest/testdata/logic_test/udf index eca6514c9b34..79938a317851 100644 --- a/pkg/sql/logictest/testdata/logic_test/udf +++ b/pkg/sql/logictest/testdata/logic_test/udf @@ -2517,6 +2517,58 @@ CREATE FUNCTION err(i imp) RETURNS INT LANGUAGE SQL AS $$ $$ +subtest strict + +statement ok +CREATE FUNCTION strict_fn(i INT, t TEXT, b BOOL) RETURNS INT STRICT LANGUAGE SQL AS $$ + SELECT 1 +$$ + +query I +SELECT strict_fn(1, 'foo', true) +---- +1 + +# Same as above, but with non-constant arguments. +query I +WITH tmp(a, b, c) AS MATERIALIZED (VALUES (1, 'foo', true)) +SELECT strict_fn(a, b, c) FROM tmp +---- +1 + +query III +SELECT strict_fn(NULL, 'foo', true), strict_fn(1, NULL, true), strict_fn(1, 'foo', NULL) +---- +NULL NULL NULL + +query III +SELECT strict_fn(NULL, NULL, true), strict_fn(1, NULL, NULL), strict_fn(NULL, 'foo', NULL) +---- +NULL NULL NULL + +query I +SELECT strict_fn(NULL, NULL, NULL) +---- +NULL + +statement ok +CREATE FUNCTION strict_fn_imp(t TEXT, i imp) RETURNS INT RETURNS NULL ON NULL INPUT LANGUAGE SQL AS $$ + SELECT 1 +$$ + +# A tuple with all NULL elements is not considered "NULL INPUT" for a UDF, even +# though IS NULL returns true for it. +query IB +SELECT strict_fn_imp('foo', (NULL,NULL,NULL)), (NULL,NULL,NULL)::imp IS NULL +---- +1 true + +query I +SELECT strict_fn_imp('foo', NULL) +---- +NULL + + subtest return_type_assignment_casts # Do not allow functions with return type mismatches that cannot be cast in an @@ -2788,7 +2840,20 @@ SELECT oid, proname, pronamespace, proowner, prolang, proleakproof, proisstrict, FROM pg_catalog.pg_proc WHERE proname IN ('f_93314', 'f_93314_alias', 'f_93314_comp', 'f_93314_comp_t') ORDER BY oid; ---- -100257 f_93314 105 1546506610 14 false false false v 0 100256 · {} NULL SELECT i, e FROM test.public.t_93314 ORDER BY i LIMIT 1; -100259 f_93314_alias 105 1546506610 14 false false false v 0 100258 · {} NULL SELECT i, e FROM test.public.t_93314_alias ORDER BY i LIMIT 1; -100263 f_93314_comp 105 1546506610 14 false false false v 0 100260 · {} NULL SELECT (1, 2); -100264 f_93314_comp_t 105 1546506610 14 false false false v 0 100262 · {} NULL SELECT a, c FROM test.public.t_93314_comp LIMIT 1; +100259 f_93314 105 1546506610 14 false false false v 0 100258 · {} NULL SELECT i, e FROM test.public.t_93314 ORDER BY i LIMIT 1; +100261 f_93314_alias 105 1546506610 14 false false false v 0 100260 · {} NULL SELECT i, e FROM test.public.t_93314_alias ORDER BY i LIMIT 1; +100265 f_93314_comp 105 1546506610 14 false false false v 0 100262 · {} NULL SELECT (1, 2); +100266 f_93314_comp_t 105 1546506610 14 false false false v 0 100264 · {} NULL SELECT a, c FROM test.public.t_93314_comp LIMIT 1; + +# Regression test for #95240. Strict UDFs that are inlined should result in NULL +# when presented with NULL arguments. +statement ok +CREATE FUNCTION f95240(i INT) RETURNS INT STRICT LANGUAGE SQL AS 'SELECT 33'; +CREATE TABLE t95240 (a INT); +INSERT INTO t95240 VALUES (1), (NULL) + +query I +SELECT f95240(a) FROM t95240 +---- +33 +NULL diff --git a/pkg/sql/opt/exec/execbuilder/scalar.go b/pkg/sql/opt/exec/execbuilder/scalar.go index 85ed373bc0a7..576697f428b7 100644 --- a/pkg/sql/opt/exec/execbuilder/scalar.go +++ b/pkg/sql/opt/exec/execbuilder/scalar.go @@ -659,7 +659,6 @@ func (b *Builder) buildSubquery( 1, /* numStmts */ subquery.Typ, false, /* enableStepping */ - true, /* calledOnNullInput */ ), nil } @@ -708,7 +707,6 @@ func (b *Builder) buildSubquery( 1, /* numStmts */ subquery.Typ, false, /* enableStepping */ - true, /* calledOnNullInput */ ), nil } @@ -786,7 +784,6 @@ func (b *Builder) buildUDF(ctx *buildScalarCtx, scalar opt.ScalarExpr) (tree.Typ len(udf.Body), udf.Typ, enableStepping, - udf.CalledOnNullInput, ), nil } diff --git a/pkg/sql/opt/norm/testdata/rules/udf b/pkg/sql/opt/norm/testdata/rules/udf index 5f9cb9c8716c..f73ced1db00b 100644 --- a/pkg/sql/opt/norm/testdata/rules/udf +++ b/pkg/sql/opt/norm/testdata/rules/udf @@ -22,3 +22,48 @@ values ├── fd: ()-->(1) └── tuple └── const: 1 + +exec-ddl +CREATE FUNCTION strict_fn(i INT, t TEXT, b BOOl) RETURNS INT STRICT LANGUAGE SQL AS 'SELECT i' +---- + +# Strict UDFs should be folded to NULL in the presence of a constant NULL +# argument. +norm format=show-scalars +SELECT strict_fn(1, 'foo', NULL) +---- +values + ├── columns: strict_fn:1 + ├── cardinality: [1 - 1] + ├── key: () + ├── fd: ()-->(1) + └── tuple + └── null + +# The CASE expression used to check for NULL arguments in strict UDFs should be +# folded in the presence of all non-NULL arguments. +norm format=show-scalars +SELECT strict_fn(1, 'foo', true) +---- +values + ├── columns: strict_fn:5 + ├── cardinality: [1 - 1] + ├── volatile + ├── key: () + ├── fd: ()-->(5) + └── tuple + └── udf: strict_fn + ├── params: i:1 t:2 b:3 + ├── args + │ ├── const: 1 + │ ├── const: 'foo' + │ └── true + └── body + └── values + ├── columns: i:4 + ├── outer: (1) + ├── cardinality: [1 - 1] + ├── key: () + ├── fd: ()-->(4) + └── tuple + └── variable: i:1 diff --git a/pkg/sql/opt/ops/scalar.opt b/pkg/sql/opt/ops/scalar.opt index f0e44a4c2f78..e8ad8b0d5e89 100644 --- a/pkg/sql/opt/ops/scalar.opt +++ b/pkg/sql/opt/ops/scalar.opt @@ -1261,11 +1261,6 @@ define UDFPrivate { # immutable, or leakproof function will see a snapshot of the data as of the # start of the statement calling the function. Volatility Volatility - - # CalledOnNullInput is true if the function should be called when any of its - # inputs are NULL. If false, the function will not be evaluated in the - # presence of NULL inputs, and will instead evaluate directly to NULL. - CalledOnNullInput bool } # KVOptions is a set of KVOptionItems that specify arbitrary keys and values diff --git a/pkg/sql/opt/optbuilder/scalar.go b/pkg/sql/opt/optbuilder/scalar.go index bd4d6c9d92c2..a11d59aea4a7 100644 --- a/pkg/sql/opt/optbuilder/scalar.go +++ b/pkg/sql/opt/optbuilder/scalar.go @@ -731,14 +731,49 @@ func (b *Builder) buildUDF( out = b.factory.ConstructUDF( args, &memo.UDFPrivate{ - Name: def.Name, - Params: params, - Body: rels, - Typ: f.ResolvedType(), - Volatility: o.Volatility, - CalledOnNullInput: o.CalledOnNullInput, + Name: def.Name, + Params: params, + Body: rels, + Typ: f.ResolvedType(), + Volatility: o.Volatility, }, ) + + // If the UDF is strict, it should not be invoked when any of the arguments + // are NULL. To achieve this, we wrap the UDF in a CASE expression like: + // + // CASE WHEN arg1 IS NULL OR arg2 IS NULL OR ... THEN NULL ELSE udf() END + // + if !o.CalledOnNullInput { + var anyArgIsNull opt.ScalarExpr + for i := range args { + // Note: We do NOT use a TupleIsNullExpr here if the argument is a + // tuple because a strict UDF will be called if an argument, T, is a + // tuple with all NULL elements, even though T IS NULL evaluates to + // true. For example: + // + // SELECT strict_fn(1, (NULL, NULL)) -- the UDF will be called + // SELECT (NULL, NULL) IS NULL -- returns true + // + argIsNull := b.factory.ConstructIs(args[i], memo.NullSingleton) + if anyArgIsNull == nil { + anyArgIsNull = argIsNull + continue + } + anyArgIsNull = b.factory.ConstructOr(argIsNull, anyArgIsNull) + } + out = b.factory.ConstructCase( + memo.TrueSingleton, + memo.ScalarListExpr{ + b.factory.ConstructWhen( + anyArgIsNull, + b.factory.ConstructNull(f.ResolvedType()), + ), + }, + out, + ) + } + return b.finishBuildScalar(f, out, inScope, outScope, outCol) } diff --git a/pkg/sql/opt/optbuilder/testdata/udf b/pkg/sql/opt/optbuilder/testdata/udf index a5102d72796c..4f4bc04dfb1a 100644 --- a/pkg/sql/opt/optbuilder/testdata/udf +++ b/pkg/sql/opt/optbuilder/testdata/udf @@ -1029,3 +1029,140 @@ project └── projections └── assignment-cast: CHAR [as=column3:3] └── variable: s:2 + + +# -------------------------------------------------- +# UDFs that are STRICT/RETURNS NULL ON NULL INPUT. +# -------------------------------------------------- + +exec-ddl +CREATE FUNCTION strict_fn(i INT, t TEXT, b BOOl) RETURNS INT STRICT LANGUAGE SQL AS 'SELECT i' +---- + +build format=show-scalars +SELECT strict_fn(1, 'foo', false) +---- +project + ├── columns: strict_fn:5 + ├── values + │ └── tuple + └── projections + └── case [as=strict_fn:5] + ├── true + ├── when + │ ├── or + │ │ ├── is + │ │ │ ├── false + │ │ │ └── null + │ │ └── or + │ │ ├── is + │ │ │ ├── const: 'foo' + │ │ │ └── null + │ │ └── is + │ │ ├── const: 1 + │ │ └── null + │ └── null + └── udf: strict_fn + ├── params: i:1 t:2 b:3 + ├── args + │ ├── const: 1 + │ ├── const: 'foo' + │ └── false + └── body + └── limit + ├── columns: i:4 + ├── project + │ ├── columns: i:4 + │ ├── values + │ │ └── tuple + │ └── projections + │ └── variable: i:1 [as=i:4] + └── const: 1 + +build format=show-scalars +SELECT strict_fn(a, b::TEXT, false) FROM abc WHERE strict_fn(a+1+2, b::TEXT, false) = 10 +---- +project + ├── columns: strict_fn:14 + ├── select + │ ├── columns: a:1!null abc.b:2 c:3 crdb_internal_mvcc_timestamp:4 tableoid:5 + │ ├── scan abc + │ │ └── columns: a:1!null abc.b:2 c:3 crdb_internal_mvcc_timestamp:4 tableoid:5 + │ └── filters + │ └── eq + │ ├── case + │ │ ├── true + │ │ ├── when + │ │ │ ├── or + │ │ │ │ ├── is + │ │ │ │ │ ├── false + │ │ │ │ │ └── null + │ │ │ │ └── or + │ │ │ │ ├── is + │ │ │ │ │ ├── cast: STRING + │ │ │ │ │ │ └── variable: abc.b:2 + │ │ │ │ │ └── null + │ │ │ │ └── is + │ │ │ │ ├── plus + │ │ │ │ │ ├── plus + │ │ │ │ │ │ ├── variable: a:1 + │ │ │ │ │ │ └── const: 1 + │ │ │ │ │ └── const: 2 + │ │ │ │ └── null + │ │ │ └── null + │ │ └── udf: strict_fn + │ │ ├── params: i:6 t:7 b:8 + │ │ ├── args + │ │ │ ├── plus + │ │ │ │ ├── plus + │ │ │ │ │ ├── variable: a:1 + │ │ │ │ │ └── const: 1 + │ │ │ │ └── const: 2 + │ │ │ ├── cast: STRING + │ │ │ │ └── variable: abc.b:2 + │ │ │ └── false + │ │ └── body + │ │ └── limit + │ │ ├── columns: i:9 + │ │ ├── project + │ │ │ ├── columns: i:9 + │ │ │ ├── values + │ │ │ │ └── tuple + │ │ │ └── projections + │ │ │ └── variable: i:6 [as=i:9] + │ │ └── const: 1 + │ └── const: 10 + └── projections + └── case [as=strict_fn:14] + ├── true + ├── when + │ ├── or + │ │ ├── is + │ │ │ ├── false + │ │ │ └── null + │ │ └── or + │ │ ├── is + │ │ │ ├── cast: STRING + │ │ │ │ └── variable: abc.b:2 + │ │ │ └── null + │ │ └── is + │ │ ├── variable: a:1 + │ │ └── null + │ └── null + └── udf: strict_fn + ├── params: i:10 t:11 b:12 + ├── args + │ ├── variable: a:1 + │ ├── cast: STRING + │ │ └── variable: abc.b:2 + │ └── false + └── body + └── limit + ├── columns: i:13 + ├── project + │ ├── columns: i:13 + │ ├── values + │ │ └── tuple + │ └── projections + │ └── variable: i:10 [as=i:13] + └── const: 1 diff --git a/pkg/sql/opt/xform/testdata/external/activerecord b/pkg/sql/opt/xform/testdata/external/activerecord index 4ca2a6428700..0d5658e02287 100644 --- a/pkg/sql/opt/xform/testdata/external/activerecord +++ b/pkg/sql/opt/xform/testdata/external/activerecord @@ -118,109 +118,98 @@ 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,85), (3,9)-->(75) + ├── fd: (6)-->(2,3,9,13,75-77,85), (2)-->(3,6,9,13,75-77), (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,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 + ├── 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 │ ├── key: (6) - │ ├── 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 + │ ├── 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 │ │ │ ├── key: (6) - │ │ │ ├── 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 + │ │ │ ├── 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,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 + │ │ │ │ ├── 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,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) + │ │ │ │ │ └── fd: ()-->(1), (6)-->(2,3,9,13,17,20), (2)-->(3,6,9,13,17,20) │ │ │ │ └── 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)] - │ │ │ └── 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 < 4294966994 [outer=(1), constraints=(/1: (/NULL - /4294966993]; 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 + │ │ │ │ └── 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)] └── 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)] - └── c.comment:84 [as=comment:85, outer=(84)] + └── 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 < 4294966994 [outer=(1), constraints=(/1: (/NULL - /4294966993]; tight)] + │ └── attnum:6 != 0 [outer=(6), constraints=(/6: (/NULL - /-1] [/1 - ]; tight)] + └── 1 diff --git a/pkg/sql/opt/xform/testdata/external/liquibase b/pkg/sql/opt/xform/testdata/external/liquibase index d9956826fd17..cc2c9a8be20b 100644 --- a/pkg/sql/opt/xform/testdata/external/liquibase +++ b/pkg/sql/opt/xform/testdata/external/liquibase @@ -165,186 +165,117 @@ 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.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:183!null - │ ├── grouping columns: rownum:183!null - │ ├── immutable - │ ├── key: (183) - │ ├── 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), (183)-->(1,2,10,13,15,17,20,22,23,26,27,31,37,50,79,106,136,140,154,172,179) + │ ├── 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 + │ ├── grouping columns: rownum:182!null + │ ├── 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) │ ├── right-join (hash) - │ │ ├── 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:183!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), (183)-->(1,2,10,13,15,17,20,22,23,26,27,37,50,79,106,136,140,172,179) + │ │ ├── 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) │ │ ├── scan pg_inherits │ │ │ └── columns: pg_inherits.inhparent:150!null │ │ ├── distinct-on - │ │ │ ├── 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:183!null - │ │ │ ├── grouping columns: rownum:183!null - │ │ │ ├── immutable - │ │ │ ├── key: (183) - │ │ │ ├── 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), (183)-->(1,2,10,13,15,17,20,22,23,26,27,31,37,50,79,106,136,140,172,179) + │ │ │ ├── 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 + │ │ │ ├── grouping columns: rownum:182!null + │ │ │ ├── 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) │ │ │ ├── left-join (hash) - │ │ │ │ ├── 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:183!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), (183)-->(1,2,10,13,15,17,20,22,23,26,27,37,50,79,106,136,140,172) + │ │ │ │ ├── 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) │ │ │ │ ├── ordinality - │ │ │ │ │ ├── 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:183!null - │ │ │ │ │ ├── immutable - │ │ │ │ │ ├── key: (183) - │ │ │ │ │ ├── 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), (183)-->(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) - │ │ │ │ │ ├── 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 rolname:158 rownum:182!null - │ │ │ │ │ │ ├── grouping columns: rownum:182!null - │ │ │ │ │ │ ├── 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,158) - │ │ │ │ │ │ ├── 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 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 pg_catalog.pg_roles.oid:157 rolname:158 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) - │ │ │ │ │ │ │ ├── scan pg_roles - │ │ │ │ │ │ │ │ └── columns: pg_catalog.pg_roles.oid:157 rolname:158 - │ │ │ │ │ │ │ ├── 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 - │ │ │ │ │ │ │ │ ├── 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: [957] = [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:957 indrelid:958 continuation:978 - │ │ │ │ │ │ │ │ │ │ │ │ ├── key columns: [1] = [958] - │ │ │ │ │ │ │ │ │ │ │ │ ├── first join in paired joiner; continuation column: continuation:978 - │ │ │ │ │ │ │ │ │ │ │ │ ├── key: (1,957) - │ │ │ │ │ │ │ │ │ │ │ │ ├── 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), (957)-->(958,978) - │ │ │ │ │ │ │ │ │ │ │ │ ├── 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] - │ │ │ │ │ │ │ │ │ │ │ │ │ │ ├── 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] - │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ ├── 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) - │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ ├── 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 - │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ ├── 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] - │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ ├── 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 - │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ └── 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 - │ │ │ │ │ │ │ │ │ │ │ └── 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) + │ │ │ │ │ ├── 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 + │ │ │ │ │ ├── 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 - │ │ │ │ │ │ │ └── pg_catalog.pg_roles.oid:157 = c.relowner:5 [outer=(5,157), constraints=(/5: (/NULL - ]; /157: (/NULL - ]), fd=(5)==(157), (157)==(5)] - │ │ │ │ │ │ └── aggregations - │ │ │ │ │ │ ├── const-agg [as=c.oid:1, outer=(1)] - │ │ │ │ │ │ │ └── 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)] - │ │ │ │ │ │ │ └── c.relhasindex:13 - │ │ │ │ │ │ ├── const-agg [as=c.relpersistence:15, outer=(15)] - │ │ │ │ │ │ │ └── c.relpersistence:15 - │ │ │ │ │ │ ├── const-agg [as=c.relkind:17, outer=(17)] - │ │ │ │ │ │ │ └── c.relkind:17 - │ │ │ │ │ │ ├── const-agg [as=c.relhasoids:20, outer=(20)] - │ │ │ │ │ │ │ └── c.relhasoids:20 - │ │ │ │ │ │ ├── const-agg [as=c.relhasrules:22, outer=(22)] - │ │ │ │ │ │ │ └── c.relhasrules:22 - │ │ │ │ │ │ ├── const-agg [as=c.relhastriggers:23, outer=(23)] - │ │ │ │ │ │ │ └── c.relhastriggers:23 - │ │ │ │ │ │ ├── const-agg [as=c.relacl:26, outer=(26)] - │ │ │ │ │ │ │ └── c.relacl:26 - │ │ │ │ │ │ ├── const-agg [as=c.reloptions:27, outer=(27)] - │ │ │ │ │ │ │ └── c.reloptions:27 - │ │ │ │ │ │ ├── const-agg [as=n.nspname:31, outer=(31)] - │ │ │ │ │ │ │ └── n.nspname:31 - │ │ │ │ │ │ ├── const-agg [as=spcname:37, outer=(37)] - │ │ │ │ │ │ │ └── spcname:37 - │ │ │ │ │ │ ├── const-agg [as=c2.relname:50, outer=(50)] - │ │ │ │ │ │ │ └── c2.relname:50 - │ │ │ │ │ │ ├── const-agg [as=n2.nspname:79, outer=(79)] - │ │ │ │ │ │ │ └── n2.nspname:79 - │ │ │ │ │ │ ├── const-agg [as=ci.relname:106, outer=(106)] - │ │ │ │ │ │ │ └── ci.relname:106 - │ │ │ │ │ │ ├── const-agg [as=ftoptions:136, outer=(136)] - │ │ │ │ │ │ │ └── ftoptions:136 - │ │ │ │ │ │ ├── const-agg [as=srvname:140, outer=(140)] - │ │ │ │ │ │ │ └── srvname:140 - │ │ │ │ │ │ └── first-agg [as=rolname:158, outer=(158)] - │ │ │ │ │ │ └── rolname:158 - │ │ │ │ │ └── projections - │ │ │ │ │ └── assignment-cast: STRING [as=column172:172, outer=(5,158), immutable] - │ │ │ │ │ └── COALESCE(rolname:158, (('unknown (OID=' || c.relowner:5) || ')')::NAME) + │ │ │ │ │ │ │ └── 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] + │ │ │ │ │ │ │ │ ├── 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] + │ │ │ │ │ │ │ │ │ │ │ ├── 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] + │ │ │ │ │ │ │ │ │ │ │ │ ├── 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) + │ │ │ │ │ │ │ │ │ │ │ │ │ ├── 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 + │ │ │ │ │ │ │ │ │ │ │ │ │ │ ├── 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] + │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ ├── 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 + │ │ │ │ │ │ │ │ │ │ │ │ │ └── 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 + │ │ │ │ │ │ │ │ └── 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) │ │ │ │ ├── select │ │ │ │ │ ├── columns: objoid:176 objsubid:178!null pg_catalog.pg_description.description:179 │ │ │ │ │ ├── fd: ()-->(178) @@ -359,6 +290,8 @@ 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)] @@ -391,8 +324,6 @@ 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 @@ -404,6 +335,8 @@ 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)] @@ -436,11 +369,44 @@ 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 - ├── column172:172 [as=tableowner:173, outer=(172)] - ├── pg_catalog.pg_description.description:179 [as=description:180, outer=(179)] + ├── case [as=tableowner:173, outer=(5), immutable, correlated-subquery] + │ ├── true + │ ├── when + │ │ ├── c.relowner:5 IS NULL + │ │ └── CAST(NULL AS STRING) + │ └── subquery + │ └── project + │ ├── columns: column172:172 + │ ├── outer: (5) + │ ├── cardinality: [1 - 1] + │ ├── immutable + │ ├── key: () + │ ├── fd: ()-->(172) + │ ├── limit + │ │ ├── columns: pg_catalog.pg_roles.oid:157 rolname:158 + │ │ ├── outer: (5) + │ │ ├── cardinality: [1 - 1] + │ │ ├── key: () + │ │ ├── fd: ()-->(157,158) + │ │ ├── right-join (cross) + │ │ │ ├── columns: pg_catalog.pg_roles.oid:157 rolname:158 + │ │ │ ├── outer: (5) + │ │ │ ├── cardinality: [1 - ] + │ │ │ ├── limit hint: 1.00 + │ │ │ ├── scan pg_roles + │ │ │ │ └── columns: pg_catalog.pg_roles.oid:157 rolname:158 + │ │ │ ├── values + │ │ │ │ ├── cardinality: [1 - 1] + │ │ │ │ ├── key: () + │ │ │ │ └── () + │ │ │ └── filters + │ │ │ └── pg_catalog.pg_roles.oid:157 = c.relowner:5 [outer=(5,157), constraints=(/5: (/NULL - ]; /157: (/NULL - ]), fd=(5)==(157), (157)==(5)] + │ │ └── 1 + │ └── projections + │ └── assignment-cast: STRING [as=column172:172, outer=(5,158), immutable] + │ └── COALESCE(rolname:158, (('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)] └── 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 a64f19748a5c..6b347f15c07f 100644 --- a/pkg/sql/opt/xform/testdata/external/navicat +++ b/pkg/sql/opt/xform/testdata/external/navicat @@ -169,186 +169,117 @@ 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.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:183!null - │ ├── grouping columns: rownum:183!null - │ ├── immutable - │ ├── key: (183) - │ ├── 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), (183)-->(1,2,10,13,15,17,20,22,23,26,27,31,37,50,79,106,136,140,154,172,179) + │ ├── 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 + │ ├── grouping columns: rownum:182!null + │ ├── 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) │ ├── right-join (hash) - │ │ ├── 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:183!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), (183)-->(1,2,10,13,15,17,20,22,23,26,27,37,50,79,106,136,140,172,179) + │ │ ├── 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) │ │ ├── scan pg_inherits │ │ │ └── columns: pg_inherits.inhparent:150!null │ │ ├── distinct-on - │ │ │ ├── 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:183!null - │ │ │ ├── grouping columns: rownum:183!null - │ │ │ ├── immutable - │ │ │ ├── key: (183) - │ │ │ ├── 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), (183)-->(1,2,10,13,15,17,20,22,23,26,27,31,37,50,79,106,136,140,172,179) + │ │ │ ├── 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 + │ │ │ ├── grouping columns: rownum:182!null + │ │ │ ├── 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) │ │ │ ├── left-join (hash) - │ │ │ │ ├── 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:183!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), (183)-->(1,2,10,13,15,17,20,22,23,26,27,37,50,79,106,136,140,172) + │ │ │ │ ├── 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) │ │ │ │ ├── ordinality - │ │ │ │ │ ├── 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:183!null - │ │ │ │ │ ├── immutable - │ │ │ │ │ ├── key: (183) - │ │ │ │ │ ├── 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), (183)-->(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) - │ │ │ │ │ ├── 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 rolname:158 rownum:182!null - │ │ │ │ │ │ ├── grouping columns: rownum:182!null - │ │ │ │ │ │ ├── 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,158) - │ │ │ │ │ │ ├── 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 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 pg_catalog.pg_roles.oid:157 rolname:158 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) - │ │ │ │ │ │ │ ├── scan pg_roles - │ │ │ │ │ │ │ │ └── columns: pg_catalog.pg_roles.oid:157 rolname:158 - │ │ │ │ │ │ │ ├── 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 - │ │ │ │ │ │ │ │ ├── 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: [957] = [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:957 indrelid:958 continuation:978 - │ │ │ │ │ │ │ │ │ │ │ │ ├── key columns: [1] = [958] - │ │ │ │ │ │ │ │ │ │ │ │ ├── first join in paired joiner; continuation column: continuation:978 - │ │ │ │ │ │ │ │ │ │ │ │ ├── key: (1,957) - │ │ │ │ │ │ │ │ │ │ │ │ ├── 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), (957)-->(958,978) - │ │ │ │ │ │ │ │ │ │ │ │ ├── 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] - │ │ │ │ │ │ │ │ │ │ │ │ │ │ ├── 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] - │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ ├── 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) - │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ ├── 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 - │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ ├── 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] - │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ ├── 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 - │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ └── 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 - │ │ │ │ │ │ │ │ │ │ │ └── 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) + │ │ │ │ │ ├── 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 + │ │ │ │ │ ├── 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 - │ │ │ │ │ │ │ └── pg_catalog.pg_roles.oid:157 = c.relowner:5 [outer=(5,157), constraints=(/5: (/NULL - ]; /157: (/NULL - ]), fd=(5)==(157), (157)==(5)] - │ │ │ │ │ │ └── aggregations - │ │ │ │ │ │ ├── const-agg [as=c.oid:1, outer=(1)] - │ │ │ │ │ │ │ └── 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)] - │ │ │ │ │ │ │ └── c.relhasindex:13 - │ │ │ │ │ │ ├── const-agg [as=c.relpersistence:15, outer=(15)] - │ │ │ │ │ │ │ └── c.relpersistence:15 - │ │ │ │ │ │ ├── const-agg [as=c.relkind:17, outer=(17)] - │ │ │ │ │ │ │ └── c.relkind:17 - │ │ │ │ │ │ ├── const-agg [as=c.relhasoids:20, outer=(20)] - │ │ │ │ │ │ │ └── c.relhasoids:20 - │ │ │ │ │ │ ├── const-agg [as=c.relhasrules:22, outer=(22)] - │ │ │ │ │ │ │ └── c.relhasrules:22 - │ │ │ │ │ │ ├── const-agg [as=c.relhastriggers:23, outer=(23)] - │ │ │ │ │ │ │ └── c.relhastriggers:23 - │ │ │ │ │ │ ├── const-agg [as=c.relacl:26, outer=(26)] - │ │ │ │ │ │ │ └── c.relacl:26 - │ │ │ │ │ │ ├── const-agg [as=c.reloptions:27, outer=(27)] - │ │ │ │ │ │ │ └── c.reloptions:27 - │ │ │ │ │ │ ├── const-agg [as=n.nspname:31, outer=(31)] - │ │ │ │ │ │ │ └── n.nspname:31 - │ │ │ │ │ │ ├── const-agg [as=spcname:37, outer=(37)] - │ │ │ │ │ │ │ └── spcname:37 - │ │ │ │ │ │ ├── const-agg [as=c2.relname:50, outer=(50)] - │ │ │ │ │ │ │ └── c2.relname:50 - │ │ │ │ │ │ ├── const-agg [as=n2.nspname:79, outer=(79)] - │ │ │ │ │ │ │ └── n2.nspname:79 - │ │ │ │ │ │ ├── const-agg [as=ci.relname:106, outer=(106)] - │ │ │ │ │ │ │ └── ci.relname:106 - │ │ │ │ │ │ ├── const-agg [as=ftoptions:136, outer=(136)] - │ │ │ │ │ │ │ └── ftoptions:136 - │ │ │ │ │ │ ├── const-agg [as=srvname:140, outer=(140)] - │ │ │ │ │ │ │ └── srvname:140 - │ │ │ │ │ │ └── first-agg [as=rolname:158, outer=(158)] - │ │ │ │ │ │ └── rolname:158 - │ │ │ │ │ └── projections - │ │ │ │ │ └── assignment-cast: STRING [as=column172:172, outer=(5,158), immutable] - │ │ │ │ │ └── COALESCE(rolname:158, (('unknown (OID=' || c.relowner:5) || ')')::NAME) + │ │ │ │ │ │ │ └── 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] + │ │ │ │ │ │ │ │ ├── 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] + │ │ │ │ │ │ │ │ │ │ │ ├── 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] + │ │ │ │ │ │ │ │ │ │ │ │ ├── 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) + │ │ │ │ │ │ │ │ │ │ │ │ │ ├── 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 + │ │ │ │ │ │ │ │ │ │ │ │ │ │ ├── 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] + │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ ├── 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 + │ │ │ │ │ │ │ │ │ │ │ │ │ └── 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 + │ │ │ │ │ │ │ │ └── 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) │ │ │ │ ├── select │ │ │ │ │ ├── columns: objoid:176 objsubid:178!null pg_catalog.pg_description.description:179 │ │ │ │ │ ├── fd: ()-->(178) @@ -363,6 +294,8 @@ 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)] @@ -395,8 +328,6 @@ 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 @@ -408,6 +339,8 @@ 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)] @@ -440,11 +373,44 @@ 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 - ├── column172:172 [as=tableowner:173, outer=(172)] - ├── pg_catalog.pg_description.description:179 [as=description:180, outer=(179)] + ├── case [as=tableowner:173, outer=(5), immutable, correlated-subquery] + │ ├── true + │ ├── when + │ │ ├── c.relowner:5 IS NULL + │ │ └── CAST(NULL AS STRING) + │ └── subquery + │ └── project + │ ├── columns: column172:172 + │ ├── outer: (5) + │ ├── cardinality: [1 - 1] + │ ├── immutable + │ ├── key: () + │ ├── fd: ()-->(172) + │ ├── limit + │ │ ├── columns: pg_catalog.pg_roles.oid:157 rolname:158 + │ │ ├── outer: (5) + │ │ ├── cardinality: [1 - 1] + │ │ ├── key: () + │ │ ├── fd: ()-->(157,158) + │ │ ├── right-join (cross) + │ │ │ ├── columns: pg_catalog.pg_roles.oid:157 rolname:158 + │ │ │ ├── outer: (5) + │ │ │ ├── cardinality: [1 - ] + │ │ │ ├── limit hint: 1.00 + │ │ │ ├── scan pg_roles + │ │ │ │ └── columns: pg_catalog.pg_roles.oid:157 rolname:158 + │ │ │ ├── values + │ │ │ │ ├── cardinality: [1 - 1] + │ │ │ │ ├── key: () + │ │ │ │ └── () + │ │ │ └── filters + │ │ │ └── pg_catalog.pg_roles.oid:157 = c.relowner:5 [outer=(5,157), constraints=(/5: (/NULL - ]; /157: (/NULL - ]), fd=(5)==(157), (157)==(5)] + │ │ └── 1 + │ └── projections + │ └── assignment-cast: STRING [as=column172:172, outer=(5,158), immutable] + │ └── COALESCE(rolname:158, (('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)] └── 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 e9e40a3843ef..3ada70d2e8a2 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.typname:3!null t.typtype:8 nspname:35!null case:70 description:79 rownum:124!null + │ ├── columns: t.oid:2!null 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)-->(3,8,35,70,79) + │ ├── fd: (124)-->(2,3,8,35,70,79) │ ├── left-join (hash) - │ │ ├── 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) + │ │ ├── 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) │ │ ├── distinct-on - │ │ │ ├── columns: t.typname:3!null t.typtype:8 t.typbasetype:26 nspname:35!null description:79 rownum:124!null + │ │ │ ├── columns: t.oid:2!null 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)-->(3,8,26,35,79) + │ │ │ ├── fd: (124)-->(2,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,6 +98,8 @@ 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)] @@ -117,6 +119,8 @@ 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)] @@ -130,7 +134,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)] - ├── description:79 [as=remarks:122, outer=(79)] + ├── CASE WHEN t.oid:2 IS NULL THEN CAST(NULL AS STRING) ELSE description:79 END [as=remarks:122, outer=(2,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/routine.go b/pkg/sql/routine.go index cc7c6af1eeaa..d69451662df3 100644 --- a/pkg/sql/routine.go +++ b/pkg/sql/routine.go @@ -27,16 +27,6 @@ import ( func (p *planner) EvalRoutineExpr( ctx context.Context, expr *tree.RoutineExpr, input tree.Datums, ) (result tree.Datum, err error) { - // If the routine should not be called on null input, then directly return - // NULL if any of the datums in the input are NULL. - if !expr.CalledOnNullInput { - for i := range input { - if input[i] == tree.DNull { - return tree.DNull, nil - } - } - } - retTypes := []*types.T{expr.ResolvedType()} // The result of the routine is the result of the last statement. The result diff --git a/pkg/sql/sem/tree/routine.go b/pkg/sql/sem/tree/routine.go index 5c6ae4b421da..adcf05fc37c7 100644 --- a/pkg/sql/sem/tree/routine.go +++ b/pkg/sql/sem/tree/routine.go @@ -61,11 +61,6 @@ type RoutineExpr struct { // routine will see a snapshot of the data as of the start of the statement // invoking the routine. EnableStepping bool - - // CalledOnNullInput is true if the function should be called when any of - // its inputs are NULL. If false, the function will not be evaluated in the - // presence of null inputs, and will instead evaluate directly to NULL. - CalledOnNullInput bool } // NewTypedRoutineExpr returns a new RoutineExpr that is well-typed. @@ -76,16 +71,14 @@ func NewTypedRoutineExpr( numStmts int, typ *types.T, enableStepping bool, - calledOnNullInput bool, ) *RoutineExpr { return &RoutineExpr{ - Args: args, - PlanFn: planFn, - NumStmts: numStmts, - Typ: typ, - EnableStepping: enableStepping, - CalledOnNullInput: calledOnNullInput, - Name: name, + Args: args, + PlanFn: planFn, + NumStmts: numStmts, + Typ: typ, + EnableStepping: enableStepping, + Name: name, } }