Commit 65173193 authored by Radu Berinde's avatar Radu Berinde

opt: incorporate casts volatility

This change incorporates the new cast volatility information into the
VolatilitySet property.

Release note: None
parent 8dc2cfdd
......@@ -1404,6 +1404,14 @@ func BuildSharedProps(e opt.Expr, shared *props.Shared) {
}
shared.VolatilitySet.Add(t.Overload.Volatility)
case *CastExpr:
from, to := t.Input.DataType(), t.Typ
volatility, ok := tree.LookupCastVolatility(from, to)
if !ok {
panic(errors.AssertionFailedf("no volatility for cast %s::%s", from, to))
}
shared.VolatilitySet.Add(volatility)
default:
if opt.IsMutationOp(e) {
shared.CanHaveSideEffects = true
......
......@@ -270,10 +270,12 @@ group-by
├── columns: column1:1(int)
├── grouping columns: column1:1(int)
├── cardinality: [1 - 4]
├── immutable
├── key: (1)
└── values
├── columns: column1:1(int)
├── cardinality: [4 - 4]
├── immutable
├── prune: (1)
├── tuple [type=tuple{int}]
│ └── const: 1 [type=int]
......
......@@ -68,7 +68,7 @@ insert abcde
│ └── projections
│ ├── const: 10 [as=column10:10, type=int]
│ ├── function: unique_rowid [as=column11:11, type=int, volatile, side-effects]
│ └── cast: INT8 [as=column12:12, type=int]
│ └── cast: INT8 [as=column12:12, type=int, immutable]
│ └── null [type=unknown]
└── projections
└── plus [as=column13:13, type=int, outer=(8,10)]
......@@ -136,7 +136,7 @@ project
│ └── projections
│ ├── const: 10 [as=column10:10, type=int]
│ ├── function: unique_rowid [as=column11:11, type=int, volatile, side-effects]
│ └── cast: INT8 [as=column12:12, type=int]
│ └── cast: INT8 [as=column12:12, type=int, immutable]
│ └── null [type=unknown]
└── projections
└── plus [as=column13:13, type=int, outer=(8,10)]
......@@ -187,7 +187,7 @@ project
│ └── projections
│ ├── const: 10 [as=column10:10, type=int]
│ ├── function: unique_rowid [as=column11:11, type=int, volatile, side-effects]
│ └── cast: INT8 [as=column12:12, type=int]
│ └── cast: INT8 [as=column12:12, type=int, immutable]
│ └── null [type=unknown]
└── projections
└── plus [as=column13:13, type=int, outer=(8,10)]
......@@ -239,7 +239,7 @@ insert abcde
│ └── projections
│ ├── const: 10 [as=column9:9, type=int]
│ ├── function: unique_rowid [as=column10:10, type=int, volatile, side-effects]
│ └── cast: INT8 [as=column11:11, type=int]
│ └── cast: INT8 [as=column11:11, type=int, immutable]
│ └── null [type=unknown]
└── projections
└── plus [as=column12:12, type=int, outer=(8,9)]
......@@ -280,6 +280,7 @@ project
│ ├── prune: (8,10-13)
│ ├── project
│ │ ├── columns: int8:10(int) y:8(int!null)
│ │ ├── immutable
│ │ ├── fd: ()-->(8)
│ │ ├── prune: (8,10)
│ │ ├── select
......@@ -299,14 +300,14 @@ project
│ │ │ ├── variable: y:8 [type=int]
│ │ │ └── const: 1 [type=int]
│ │ └── projections
│ │ └── cast: INT8 [as=int8:10, type=int, outer=(9)]
│ │ └── cast: INT8 [as=int8:10, type=int, outer=(9), immutable]
│ │ └── plus [type=float]
│ │ ├── variable: z:9 [type=float]
│ │ └── const: 1.0 [type=float]
│ └── projections
│ ├── const: 10 [as=column11:11, type=int]
│ ├── function: unique_rowid [as=column12:12, type=int, volatile, side-effects]
│ └── cast: INT8 [as=column13:13, type=int]
│ └── cast: INT8 [as=column13:13, type=int, immutable]
│ └── null [type=unknown]
└── projections
└── plus [as=column14:14, type=int, outer=(10,11)]
......
......@@ -607,6 +607,7 @@ SELECT * FROM xysd WHERE EXISTS(SELECT * FROM (SELECT x) INNER JOIN (SELECT y) O
----
select
├── columns: x:1(int!null) y:2(int) s:3(string) d:4(decimal!null)
├── immutable
├── key: (1)
├── fd: (1)-->(2-4), (3,4)~~>(1,2)
├── prune: (4)
......@@ -618,11 +619,12 @@ select
│ ├── prune: (1-4)
│ └── interesting orderings: (+1) (-3,+4,+1)
└── filters
└── exists [type=bool, outer=(1-3), correlated-subquery]
└── exists [type=bool, outer=(1-3), immutable, correlated-subquery]
└── inner-join (cross)
├── columns: x:5(int) y:6(int)
├── outer: (1-3)
├── cardinality: [0 - 1]
├── immutable
├── key: ()
├── fd: ()-->(5,6)
├── prune: (6)
......@@ -654,7 +656,7 @@ select
│ └── projections
│ └── variable: xysd.y:2 [as=y:6, type=int, outer=(2)]
└── filters
└── eq [type=bool, outer=(3,5)]
└── eq [type=bool, outer=(3,5), immutable]
├── cast: STRING [type=string]
│ └── variable: x:5 [type=int]
└── variable: s:3 [type=string]
......@@ -959,6 +961,7 @@ SELECT * FROM (VALUES (NULL), (NULL)) a FULL JOIN (VALUES (NULL), (NULL)) b ON a
full-join (cross)
├── columns: column1:1(unknown) column1:2(unknown)
├── cardinality: [2 - 4]
├── immutable
├── prune: (1,2)
├── reject-nulls: (1,2)
├── multiplicity: left-rows(one-or-more), right-rows(one-or-more)
......@@ -979,7 +982,7 @@ full-join (cross)
│ └── tuple [type=tuple{unknown}]
│ └── null [type=unknown]
└── filters
└── cast: BOOL [type=bool]
└── cast: BOOL [type=bool, immutable]
└── null [type=unknown]
# Calculate full-join cardinality of one input with unknown cardinality.
......
......@@ -153,6 +153,7 @@ SELECT 1 AS a, 'foo' AS b, NULL AS c, 1::decimal + NULL AS d, NULL::STRING AS e
----
project
├── columns: a:5(int!null) b:6(string!null) c:7(unknown) d:7(unknown) e:8(string)
├── immutable
├── fd: ()-->(5-8)
├── prune: (5-8)
├── scan xysd
......@@ -165,7 +166,7 @@ project
├── const: 1 [as=a:5, type=int]
├── const: 'foo' [as=b:6, type=string]
├── null [as=c:7, type=unknown]
└── cast: STRING [as=e:8, type=string]
└── cast: STRING [as=e:8, type=string, immutable]
└── null [type=unknown]
# Project constant over input with no needed columns and ensure that there is
......@@ -312,6 +313,7 @@ SELECT y, y::TEXT FROM xysd
----
project
├── columns: y:2(int) y:5(string)
├── immutable
├── fd: (2)-->(5)
├── prune: (2,5)
├── scan xysd
......@@ -321,7 +323,7 @@ project
│ ├── prune: (1-4)
│ └── interesting orderings: (+1) (-3,+4,+1)
└── projections
└── cast: STRING [as=y:5, type=string, outer=(2)]
└── cast: STRING [as=y:5, type=string, outer=(2), immutable]
└── variable: xysd.y:2 [type=int]
# We don't have the FD: d --> d::TEXT because d is a composite type.
......@@ -331,6 +333,7 @@ SELECT d, d::TEXT FROM xysd
----
project
├── columns: d:4(decimal!null) d:5(string!null)
├── immutable
├── prune: (4,5)
├── scan xysd
│ ├── columns: x:1(int!null) y:2(int) s:3(string) xysd.d:4(decimal!null)
......@@ -339,7 +342,7 @@ project
│ ├── prune: (1-4)
│ └── interesting orderings: (+1) (-3,+4,+1)
└── projections
└── cast: STRING [as=d:5, type=string, outer=(4)]
└── cast: STRING [as=d:5, type=string, outer=(4), immutable]
└── variable: xysd.d:4 [type=decimal]
# We have the equality relation between the synthesized column and the column
......
......@@ -6,6 +6,10 @@ exec-ddl
CREATE TABLE uv (u INT, v INT NOT NULL)
----
exec-ddl
CREATE TABLE sf (s STRING, f FLOAT)
----
build
SELECT * FROM xy WHERE x < 5
----
......@@ -257,6 +261,7 @@ SELECT x / 1, x::float / 2.0, x::decimal / 3.0 FROM xy
----
project
├── columns: "?column?":3(decimal!null) "?column?":4(float!null) "?column?":5(decimal!null)
├── immutable
├── prune: (3-5)
├── scan xy
│ ├── columns: x:1(int!null) y:2(int)
......@@ -268,11 +273,73 @@ project
├── div [as="?column?":3, type=decimal, outer=(1)]
│ ├── variable: x:1 [type=int]
│ └── const: 1 [type=int]
├── div [as="?column?":4, type=float, outer=(1)]
├── div [as="?column?":4, type=float, outer=(1), immutable]
│ ├── cast: FLOAT8 [type=float]
│ │ └── variable: x:1 [type=int]
│ └── const: 2.0 [type=float]
└── div [as="?column?":5, type=decimal, outer=(1)]
└── div [as="?column?":5, type=decimal, outer=(1), immutable]
├── cast: DECIMAL [type=decimal]
│ └── variable: x:1 [type=int]
└── const: 3.0 [type=decimal]
# Verify that we take into account the volatility of casts.
build
SELECT s::TIMESTAMP FROM sf
----
project
├── columns: s:4(timestamp)
├── stable
├── prune: (4)
├── scan sf
│ ├── columns: sf.s:1(string) f:2(float) rowid:3(int!null)
│ ├── key: (3)
│ ├── fd: (3)-->(1,2)
│ ├── prune: (1-3)
│ └── interesting orderings: (+3)
└── projections
└── cast: TIMESTAMP [as=s:4, type=timestamp, outer=(1), stable]
└── variable: sf.s:1 [type=string]
build
SELECT f::STRING FROM sf
----
project
├── columns: f:4(string)
├── stable
├── prune: (4)
├── scan sf
│ ├── columns: s:1(string) sf.f:2(float) rowid:3(int!null)
│ ├── key: (3)
│ ├── fd: (3)-->(1,2)
│ ├── prune: (1-3)
│ └── interesting orderings: (+3)
└── projections
└── cast: STRING [as=f:4, type=string, outer=(2), stable]
└── variable: sf.f:2 [type=float]
build
SELECT ARRAY(SELECT f FROM sf)::STRING[]
----
project
├── columns: array:4(string[])
├── cardinality: [1 - 1]
├── stable
├── key: ()
├── fd: ()-->(4)
├── prune: (4)
├── values
│ ├── cardinality: [1 - 1]
│ ├── key: ()
│ └── tuple [type=tuple]
└── projections
└── cast: STRING[] [as=array:4, type=string[], stable, subquery]
└── array-flatten [type=float[]]
└── project
├── columns: f:2(float)
├── prune: (2)
└── scan sf
├── columns: s:1(string) f:2(float) rowid:3(int!null)
├── key: (3)
├── fd: (3)-->(1,2)
├── prune: (1-3)
└── interesting orderings: (+3)
......@@ -8,6 +8,7 @@ SELECT * FROM (VALUES (1, 2), (3, 4), (NULL, 5))
values
├── columns: column1:1(int) column2:2(int!null)
├── cardinality: [3 - 3]
├── immutable
├── prune: (1,2)
├── tuple [type=tuple{int, int}]
│ ├── const: 1 [type=int]
......@@ -43,6 +44,7 @@ SELECT * FROM (VALUES (NULL, 2), (3, NULL), (5, 6))
values
├── columns: column1:1(int) column2:2(int)
├── cardinality: [3 - 3]
├── immutable
├── prune: (1,2)
├── tuple [type=tuple{int, int}]
│ ├── cast: INT8 [type=int]
......
......@@ -148,14 +148,17 @@ SELECT lag('foo'::string) OVER (), lag(1) OVER () FROM kv
----
project
├── columns: lag:8(string) lag:9(int)
├── immutable
├── prune: (8,9)
└── window partition=()
├── columns: k:1(int!null) v:2(int) w:3(int) f:4(float) d:5(decimal) s:6(string) b:7(bool) lag:8(string) lag:9(int) lag_1_arg1:10(string!null) lag_1_arg2:11(int!null) lag_1_arg3:12(string) lag_2_arg3:13(int)
├── immutable
├── key: (1)
├── fd: ()-->(10-13), (1)-->(2-7)
├── prune: (1-9)
├── project
│ ├── columns: lag_1_arg1:10(string!null) lag_1_arg2:11(int!null) lag_1_arg3:12(string) lag_2_arg3:13(int) k:1(int!null) v:2(int) w:3(int) f:4(float) d:5(decimal) s:6(string) b:7(bool)
│ ├── immutable
│ ├── key: (1)
│ ├── fd: ()-->(10-13), (1)-->(2-7)
│ ├── prune: (1-7,10-13)
......@@ -167,12 +170,12 @@ project
│ │ ├── prune: (1-7)
│ │ └── interesting orderings: (+1)
│ └── projections
│ ├── cast: STRING [as=lag_1_arg1:10, type=string]
│ ├── cast: STRING [as=lag_1_arg1:10, type=string, immutable]
│ │ └── const: 'foo' [type=string]
│ ├── const: 1 [as=lag_1_arg2:11, type=int]
│ ├── cast: STRING [as=lag_1_arg3:12, type=string]
│ ├── cast: STRING [as=lag_1_arg3:12, type=string, immutable]
│ │ └── null [type=unknown]
│ └── cast: INT8 [as=lag_2_arg3:13, type=int]
│ └── cast: INT8 [as=lag_2_arg3:13, type=int, immutable]
│ └── null [type=unknown]
└── windows
├── lag [as=lag:8, type=string, outer=(10-12)]
......
......@@ -117,14 +117,14 @@ WITH foo AS (SELECT $1::INT) SELECT 1 FROM foo
with &1 (foo)
├── columns: "?column?":3(int!null)
├── cardinality: [1 - 1]
├── has-placeholder
├── immutable, has-placeholder
├── key: ()
├── fd: ()-->(3)
├── prune: (3)
├── project
│ ├── columns: int8:1(int)
│ ├── cardinality: [1 - 1]
│ ├── has-placeholder
│ ├── immutable, has-placeholder
│ ├── key: ()
│ ├── fd: ()-->(1)
│ ├── prune: (1)
......@@ -133,7 +133,7 @@ with &1 (foo)
│ │ ├── key: ()
│ │ └── tuple [type=tuple]
│ └── projections
│ └── cast: INT8 [as=int8:1, type=int]
│ └── cast: INT8 [as=int8:1, type=int, immutable]
│ └── placeholder: $1 [type=string]
└── project
├── columns: "?column?":3(int!null)
......
......@@ -17,18 +17,22 @@ limit
├── columns: y:2(int!null) x:3(string!null) c:5(int!null)
├── internal-ordering: +2
├── cardinality: [0 - 10]
├── immutable
├── fd: (2)-->(5)
├── ordering: +2
├── sort
│ ├── columns: y:2(int!null) b.x:3(string!null) c:5(int!null)
│ ├── immutable
│ ├── fd: (2)-->(5)
│ ├── ordering: +2
│ ├── limit hint: 10.00
│ └── project
│ ├── columns: c:5(int!null) y:2(int!null) b.x:3(string!null)
│ ├── immutable
│ ├── fd: (2)-->(5)
│ ├── select
│ │ ├── columns: a.x:1(int!null) y:2(int!null) b.x:3(string!null) z:4(decimal!null)
│ │ ├── immutable
│ │ ├── key: (1,3)
│ │ ├── fd: (1)-->(2), (3)-->(4)
│ │ ├── inner-join (cross)
......@@ -45,7 +49,7 @@ limit
│ │ │ │ └── fd: (3)-->(4)
│ │ │ └── filters (true)
│ │ └── filters
│ │ └── and [type=bool, outer=(1-3), constraints=(/2: [/2 - ])]
│ │ └── and [type=bool, outer=(1-3), immutable, constraints=(/2: [/2 - ])]
│ │ ├── gt [type=bool]
│ │ │ ├── variable: y:2 [type=int]
│ │ │ └── const: 1 [type=int]
......@@ -69,27 +73,32 @@ LIMIT 10
project
├── columns: y:2(int!null) x:3(string!null) c:6(int!null)
├── cardinality: [0 - 10]
├── immutable
├── fd: (2)-->(6)
├── ordering: +2
├── limit
│ ├── columns: y:2(int!null) b.x:3(string!null) column5:5(string!null)
│ ├── internal-ordering: +2
│ ├── cardinality: [0 - 10]
│ ├── immutable
│ ├── fd: (3)==(5), (5)==(3)
│ ├── ordering: +2
│ ├── inner-join (lookup b)
│ │ ├── columns: y:2(int!null) b.x:3(string!null) column5:5(string!null)
│ │ ├── key columns: [5] = [3]
│ │ ├── lookup columns are key
│ │ ├── immutable
│ │ ├── fd: (3)==(5), (5)==(3)
│ │ ├── ordering: +2
│ │ ├── limit hint: 10.00
│ │ ├── sort
│ │ │ ├── columns: y:2(int!null) column5:5(string!null)
│ │ │ ├── immutable
│ │ │ ├── ordering: +2
│ │ │ ├── limit hint: 100.00
│ │ │ └── project
│ │ │ ├── columns: column5:5(string!null) y:2(int!null)
│ │ │ ├── immutable
│ │ │ ├── select
│ │ │ │ ├── columns: a.x:1(int!null) y:2(int!null)
│ │ │ │ ├── key: (1)
......@@ -103,7 +112,7 @@ project
│ │ │ │ ├── variable: y:2 [type=int]
│ │ │ │ └── const: 1 [type=int]
│ │ │ └── projections
│ │ │ └── cast: STRING [as=column5:5, type=string, outer=(1)]
│ │ │ └── cast: STRING [as=column5:5, type=string, outer=(1), immutable]
│ │ │ └── variable: a.x:1 [type=int]
│ │ └── filters (true)
│ └── const: 10 [type=int]
......
......@@ -1015,6 +1015,7 @@ SELECT a, b::string FROM t47742 WHERE b = true
----
project
├── columns: a:1(int) b:4(string!null)
├── immutable
├── stats: [rows=2640.64496]
├── fd: ()-->(4)
├── index-join t47742
......@@ -1032,7 +1033,7 @@ project
│ ├── key: (3)
│ └── fd: ()-->(2)
└── projections
└── t47742.b:2::STRING [as=b:4, type=string, outer=(2)]
└── t47742.b:2::STRING [as=b:4, type=string, outer=(2), immutable]
# Multi-column stats tests.
exec-ddl
......
......@@ -691,11 +691,13 @@ WHERE
----
index-join lineitem
├── columns: l_orderkey:1(int!null) l_partkey:2(int!null) l_suppkey:3(int!null) l_linenumber:4(int!null) l_quantity:5(float!null) l_extendedprice:6(float!null) l_discount:7(float!null) l_tax:8(float!null) l_returnflag:9(char!null) l_linestatus:10(char!null) l_shipdate:11(date!null) l_commitdate:12(date!null) l_receiptdate:13(date!null) l_shipinstruct:14(char!null) l_shipmode:15(char!null) l_comment:16(varchar!null)
├── stable
├── stats: [rows=111.111111, distinct(11)=33.3333333, null(11)=0]
├── key: (1,4)
├── fd: (1,4)-->(2,3,5-16)
└── select
├── columns: l_orderkey:1(int!null) l_linenumber:4(int!null) l_shipdate:11(date!null)
├── stable
├── stats: [rows=111.111111]
├── key: (1,4)
├── fd: (1,4)-->(11)
......@@ -706,7 +708,7 @@ index-join lineitem
│ ├── key: (1,4)
│ └── fd: (1,4)-->(11)
└── filters
└── l_shipdate:11::TIMESTAMPTZ < '1995-10-01' [type=bool, outer=(11)]
└── l_shipdate:11::TIMESTAMPTZ < '1995-10-01' [type=bool, outer=(11), stable]
# These queries should generate zigzag joins in xform rules. The column statistics
# should be comparable between the norm'd and fully optimized expressions.
......@@ -1419,10 +1421,12 @@ SELECT x FROM t WHERE x
----
with &1 (t)
├── columns: x:6(bool!null)
├── immutable
├── stats: [rows=1.98e+20, distinct(6)=1, null(6)=0]
├── fd: ()-->(6)
├── project
│ ├── columns: x:5(bool)
│ ├── immutable
│ ├── stats: [rows=4e+20]
│ ├── left-join (cross)
│ │ ├── columns: t1.x:1(bool) t2.x:3(bool)
......@@ -1435,7 +1439,7 @@ with &1 (t)
│ │ │ └── stats: [rows=2e+10]
│ │ └── filters (true)
│ └── projections
│ └── (t1.x:1::INT8 << 5533)::BOOL OR t2.x:3 [as=x:5, type=bool, outer=(1,3)]
│ └── (t1.x:1::INT8 << 5533)::BOOL OR t2.x:3 [as=x:5, type=bool, outer=(1,3), immutable]
└── select
├── columns: x:6(bool!null)
├── stats: [rows=1.98e+20, distinct(6)=1, null(6)=0]
......
......@@ -111,16 +111,19 @@ with &1
│ ├── stats: [rows=9.94974874]
│ └── project
│ ├── columns: upsert_x:13(string) upsert_y:14(int!null) upsert_z:15(float) a:4(int!null) b:5(string) column8:8(float) xyz.x:9(string) xyz.y:10(int) xyz.z:11(float) y_new:12(int!null)
│ ├── immutable
│ ├── stats: [rows=9.94974874]
│ ├── lax-key: (5,9)
│ ├── fd: ()-->(8,12), (5)~~>(4), (9)-->(10,11), (5,9)-->(13), (4,9)-->(14), (5,9)~~>(4,14,15)
│ ├── project
│ │ ├── columns: y_new:12(int!null) a:4(int!null) b:5(string) column8:8(float) xyz.x:9(string) xyz.y:10(int) xyz.z:11(float)
│ │ ├── immutable
│ │ ├── stats: [rows=9.94974874]
│ │ ├── lax-key: (5,9)
│ │ ├── fd: ()-->(8,12), (5)~~>(4), (9)-->(10,11)
│ │ ├── left-join (hash)
│ │ │ ├── columns: a:4(int!null) b:5(string) column8:8(float) xyz.x:9(string) xyz.y:10(int) xyz.z:11(float)
│ │ │ ├── immutable
│ │ │ ├── stats: [rows=9.94974874, distinct(9)=9.94974874, null(9)=0]
│ │ │ ├── lax-key: (5,9)
│ │ │ ├── fd: ()-->(8), (5)~~>(4), (9)-->(10,11)
......@@ -128,11 +131,13 @@ with &1
│ │ │ │ ├── columns: a:4(int!null) b:5(string) column8:8(float)
│ │ │ │ ├── grouping columns: b:5(string)
│ │ │ │ ├── error: "UPSERT or INSERT...ON CONFLICT command cannot affect row a second time"
│ │ │ │ ├── immutable
│ │ │ │ ├── stats: [rows=9.94974874, distinct(4)=6.31184239, null(4)=0, distinct(5)=9.94974874, null(5)=0]
│ │ │ │ ├── lax-key: (5)
│ │ │ │ ├── fd: ()-->(8), (5)~~>(4,8)
│ │ │ │ ├── project
│ │ │ │ │ ├── columns: column8:8(float) a:4(int!null) b:5(string)
│ │ │ │ │ ├── immutable
│ │ │ │ │ ├── stats: [rows=9.94974874, distinct(5)=6.31184239, null(5)=0]
│ │ │ │ │ ├── fd: ()-->(8)
│ │ │ │ │ ├── project
......@@ -154,7 +159,7 @@ with &1
│ │ │ │ │ │ └── filters
│ │ │ │ │ │ └── c:6 = 1.0 [type=bool, outer=(6), constraints=(/6: [/1.0 - /1.0]; tight), fd=()-->(6)]
│ │ │ │ │ └── projections
│ │ │ │ │ └── NULL::FLOAT8 [as=column8:8, type=float]
│ │ │ │ │ └── NULL::FLOAT8 [as=column8:8, type=float, immutable]
│ │ │ │ └── aggregations
│ │ │ │ ├── first-agg [as=a:4, type=int, outer=(4)]
│ │ │ │ │ └── a:4 [type=int]
......@@ -204,6 +209,7 @@ upsert xyz
└── project
├── columns: column8:8(float) a:4(int!null) b:5(string)
├── cardinality: [0 - 0]
├── immutable
├── stats: [rows=0]
├── fd: ()-->(8)
├── project
......@@ -227,7 +233,7 @@ upsert xyz
│ └── filters
│ └── false [type=bool]
└── projections
└── NULL::FLOAT8 [as=column8:8, type=float]
└── NULL::FLOAT8 [as=column8:8, type=float, immutable]
# Nullable conflict column. Ensure that ensure-upsert-distinct-on passes through
# the input's null count.
......@@ -280,6 +286,7 @@ upsert uv
│ │ │ │ ├── stats: [rows=1000, distinct(6)=100, null(6)=0]
│ │ │ │ ├── project
│ │ │ │ │ ├── columns: z:6(int)
│ │ │ │ │ ├── immutable
│ │ │ │ │ ├── stats: [rows=1000, distinct(6)=100, null(6)=0]
│ │ │ │ │ ├── scan xyz
│ │ │ │ │ │ ├── columns: x:3(string!null) y:4(int!null) xyz.z:5(float)
......@@ -287,7 +294,7 @@ upsert uv
│ │ │ │ │ │ ├── key: (3)
│ │ │ │ │ │ └── fd: (3)-->(4,5)
│ │ │ │ │ └── projections
│ │ │ │ │ └── xyz.z:5::INT8 [as=z:6, type=int, outer=(5)]
│ │ │ │ │ └── xyz.z:5::INT8 [as=z:6, type=int, outer=(5), immutable]
│ │ │ │ └── projections
│ │ │ │ └── unique_rowid() [as=column7:7, type=int, volatile, side-effects]
│ │ │ └── aggregations
......
......@@ -46,6 +46,7 @@ ORDER BY
sort
├── save-table-name: q11_sort_1
├── columns: ps_partkey:1(int!null) value:18(float!null)
├── immutable
├── stats: [rows=9927.82897, distinct(1)=9927.82897, null(1)=0, distinct(18)=9927.82897, null(18)=0]
├── key: (1)
├── fd: (1)-->(18)
......@@ -53,6 +54,7 @@ sort
└── select
├── save-table-name: q11_select_2
├── columns: ps_partkey:1(int!null) sum:18(float!null)
├── immutable
├── stats: [rows=9927.82897, distinct(1)=9927.82897, null(1)=0, distinct(18)=9927.82897, null(18)=0]
├── key: (1)
├── fd: (1)-->(18)
......@@ -60,12 +62,14 @@ sort
│ ├── save-table-name: q11_group_by_3
│ ├── columns: ps_partkey:1(int!null) sum:18(float!null)
│ ├── grouping columns: ps_partkey:1(int!null)
│ ├── immutable
│ ├── stats: [rows=29783.4869, distinct(1)=29783.4869, null(1)=0, distinct(18)=29783.4869, null(18)=0]
│ ├── key: (1)
│ ├── fd: (1)-->(18)
│ ├── project
│ │ ├── save-table-name: q11_project_4
│ │ ├── columns: column17:17(float!null) ps_partkey:1(int!null)
│ │ ├── immutable
│ │ ├── stats: [rows=32258.0645, distinct(1)=29783.4869, null(1)=0, distinct(17)=31617.9161, null(17)=0]
│ │ ├── inner-join (lookup partsupp)
│ │ │ ├── save-table-name: q11_lookup_join_5
......@@ -109,18 +113,19 @@ sort
│ │ │ │ └── filters (true)
│ │ │ └── filters (true)
│ │ └── projections
│ │ └── ps_supplycost:4 * ps_availqty:3::FLOAT8 [as=column17:17, type=float, outer=(3,4)]
│ │ └── ps_supplycost:4 * ps_availqty:3::FLOAT8 [as=column17:17, type=float, outer=(3,4), immutable]
│ └── aggregations
│ └── sum [as=sum:18, type=float, outer=(17)]
│ └── column17:17 [type=float]
└── filters
└── gt [type=bool, outer=(18), subquery, constraints=(/18: (/NULL - ])]
└── gt [type=bool, outer=(18), immutable, subquery, constraints=(/18: (/NULL - ])]
├── sum:18 [type=float]
└── subquery [type=float]
└── project
├── save-table-name: q11_project_10
├── columns: "?column?":37(float)
├── cardinality: [1 - 1]
├── immutable
├── stats: [rows=1, distinct(37)=1, null(37)=0]
├── key: ()
├── fd: ()-->(37)
......@@ -128,12 +133,14 @@ sort
│ ├── save-table-name: q11_scalar_group_by_11
│ ├── columns: sum:36(float)
│ ├── cardinality: [1 - 1]
│ ├── immutable
│ ├── stats: [rows=1, distinct(36)=1, null(36)=0]
│ ├── key: ()
│ ├── fd: ()-->(36)
│ ├── project
│ │ ├── save-table-name: q11_project_12
│ │ ├── columns: column35:35(float!null)
│ │ ├── immutable
│ │ ├── stats: [rows=32258.0645, distinct(35)=31617.9161, null(35)=0]
│ │ ├── inner-join (lookup partsupp)
│ │ │ ├── save-table-name: q11_lookup_join_13
......@@ -176,7 +183,7 @@ sort
│ │ │ │ └── filters (true)
│ │ │ └── filters (true)
│ │ └── projections
│ │ └── ps_supplycost:22 * ps_availqty:21::FLOAT8 [as=column35:35, type=float, outer=(21,22)]
│ │ └── ps_supplycost:22 * ps_availqty:21::FLOAT8 [as=column35:35, type=float, outer=(21,22), immutable]
│ └── aggregations
│ └── sum [as=sum:36, type=float, outer=(35)]
│ └── column35:35 [type=float]
......
......@@ -106,16 +106,18 @@ FROM a
scalar-group-by
├── columns: count:7!null sum:9 sum_int:10 avg:11 stddev:12 variance:13 xor_agg:15 array_agg:16 json_agg:17
├── cardinality: [1 - 1]
├── immutable
├── key: ()
├── fd: ()-->(7,9-13,15-17)
├── project
│ ├── columns: column8:8 column14:14 i:2 f:3 j:5
│ ├── immutable
│ ├── fd: (2)-->(8)
│ ├── scan a
│ │ └── columns: i:2 f:3 s:4 j:5
│ └── projections
│ ├── i:2 > 5 [as=column8:8, outer=(2)]
│ └── s:4::BYTES [as=column14:14, outer=(4)]
│ └── s:4::BYTES [as=column14:14, outer=(4), immutable]
└── aggregations
├── agg-distinct [as=count:7, outer=(2)]
│ └── count
......
......@@ -92,6 +92,7 @@ WHERE
select
├── columns: k:1!null i:2!null f:3 s:4 j:5 d:6
├── cardinality: [0 - 1]
├── immutable
├── key: ()
├── fd: ()-->(1-6)
├── scan a
......@@ -102,7 +103,7 @@ select
├── (i:2 >= 2) AND (i:2 > 6) [outer=(2), constraints=(/2: [/7 - ]; tight)]
├── k:1 = 1 [outer=(1), constraints=(/1: [/1 - /1]; tight), fd=()-->(1)]
├── (f:3 + f:3) < 3.0 [outer=(3)]
└── i:2::INTERVAL >= '01:00:00' [outer=(2)]
└── i:2::INTERVAL >= '01:00:00' [outer=(2), immutable]
# Try case that should not match pattern because Minus overload is not defined.
norm expect-not=NormalizeCmpPlusConst
......@@ -110,6 +111,7 @@ SELECT * FROM a WHERE s::date + '02:00:00'::time = '2000-01-01T02:00:00'::timest
----
select
├── columns: k:1!null i:2 f:3 s:4 j:5 d:6
├── stable
├── key: (1)
├── fd: (1)-->(2-6)
├── scan a
......@@ -117,7 +119,7 @@ select
│ ├── key: (1)
│ └── fd: (1)-->(2-6)
└── filters
└── (s:4::DATE + '02:00:00') = '2000-01-01 02:00:00+00:00' [outer=(4)]
└── (s:4::DATE + '02:00:00') = '2000-01-01 02:00:00+00:00' [outer=(4), stable]
# --------------------------------------------------
# NormalizeCmpMinusConst
......@@ -136,6 +138,7 @@ WHERE
select
├── columns: k:1!null i:2!null f:3 s:4 j:5 d:6!null
├── cardinality: [0 - 1]
├── immutable
├── key: ()
├── fd: ()-->(1-6)
├── scan a
......@@ -146,7 +149,7 @@ select
├── (i:2 >= 4) AND (i:2 < 14) [outer=(2), constraints=(/2: [/4 - /13]; tight)]
├── k:1 = 3 [outer=(1), constraints=(/1: [/3 - /3]; tight), fd=()-->(1)]
├── (f:3 + f:3) < 7.0 [outer=(3)]
├── (f:3 + i:2::FLOAT8) >= 110.0 [outer=(2,3)]
├── (f:3 + i:2::FLOAT8) >= 110.0 [outer=(2,3), immutable]