exec-ddl
CREATE TABLE a (x INT PRIMARY KEY, y INT)
----
TABLE a
 ├── x int not null
 ├── y int
 └── INDEX primary
      └── x int not null

exec-ddl
CREATE TABLE b (x STRING PRIMARY KEY, z DECIMAL NOT NULL)
----
TABLE b
 ├── x string not null
 ├── z decimal not null
 └── INDEX primary
      └── x string not null

build
SELECT y, b.x, y+1 AS c
FROM a, b
WHERE a.y>1 AND a.x::string=b.x
ORDER BY y
LIMIT 10
----
limit
 ├── columns: y:2(int!null) x:3(string!null) c:5(int)
 ├── internal-ordering: +2
 ├── cardinality: [0 - 10]
 ├── fd: (2)-->(5)
 ├── ordering: +2
 ├── sort
 │    ├── columns: y:2(int!null) b.x:3(string!null) c:5(int)
 │    ├── fd: (2)-->(5)
 │    ├── ordering: +2
 │    └── project
 │         ├── columns: c:5(int) y:2(int!null) b.x:3(string!null)
 │         ├── fd: (2)-->(5)
 │         ├── select
 │         │    ├── columns: a.x:1(int!null) y:2(int!null) b.x:3(string!null) z:4(decimal!null)
 │         │    ├── key: (1,3)
 │         │    ├── fd: (1)-->(2), (3)-->(4)
 │         │    ├── inner-join
 │         │    │    ├── columns: a.x:1(int!null) y:2(int) b.x:3(string!null) z:4(decimal!null)
 │         │    │    ├── key: (1,3)
 │         │    │    ├── fd: (1)-->(2), (3)-->(4)
 │         │    │    ├── scan a
 │         │    │    │    ├── columns: a.x:1(int!null) y:2(int)
 │         │    │    │    ├── key: (1)
 │         │    │    │    └── fd: (1)-->(2)
 │         │    │    ├── scan b
 │         │    │    │    ├── columns: b.x:3(string!null) z:4(decimal!null)
 │         │    │    │    ├── key: (3)
 │         │    │    │    └── fd: (3)-->(4)
 │         │    │    └── true [type=bool]
 │         │    └── filters [type=bool, outer=(1-3), constraints=(/2: [/2 - ])]
 │         │         └── and [type=bool, outer=(1-3), constraints=(/2: [/2 - ])]
 │         │              ├── gt [type=bool, outer=(2), constraints=(/2: [/2 - ]; tight)]
 │         │              │    ├── variable: y [type=int, outer=(2)]
 │         │              │    └── const: 1 [type=int]
 │         │              └── eq [type=bool, outer=(1,3)]
 │         │                   ├── cast: STRING [type=string, outer=(1)]
 │         │                   │    └── variable: a.x [type=int, outer=(1)]
 │         │                   └── variable: b.x [type=string, outer=(3)]
 │         └── projections [outer=(2,3)]
 │              └── plus [type=int, outer=(2)]
 │                   ├── variable: y [type=int, outer=(2)]
 │                   └── const: 1 [type=int]
 └── const: 10 [type=int]

opt
SELECT y, b.x, y+1 AS c
FROM a, b
WHERE a.y>1 AND a.x::string=b.x
ORDER BY y
LIMIT 10
----
project
 ├── columns: y:2(int!null) x:3(string!null) c:6(int)
 ├── cardinality: [0 - 10]
 ├── 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]
 │    ├── fd: (3)==(5), (5)==(3)
 │    ├── ordering: +2
 │    ├── sort
 │    │    ├── columns: y:2(int!null) b.x:3(string!null) column5:5(string!null)
 │    │    ├── fd: (3)==(5), (5)==(3)
 │    │    ├── ordering: +2
 │    │    └── inner-join
 │    │         ├── columns: y:2(int!null) b.x:3(string!null) column5:5(string!null)
 │    │         ├── fd: (3)==(5), (5)==(3)
 │    │         ├── scan b
 │    │         │    ├── columns: b.x:3(string!null)
 │    │         │    └── key: (3)
 │    │         ├── project
 │    │         │    ├── columns: column5:5(string) y:2(int!null)
 │    │         │    ├── select
 │    │         │    │    ├── columns: a.x:1(int!null) y:2(int!null)
 │    │         │    │    ├── key: (1)
 │    │         │    │    ├── fd: (1)-->(2)
 │    │         │    │    ├── scan a
 │    │         │    │    │    ├── columns: a.x:1(int!null) y:2(int)
 │    │         │    │    │    ├── key: (1)
 │    │         │    │    │    └── fd: (1)-->(2)
 │    │         │    │    └── filters [type=bool, outer=(2), constraints=(/2: [/2 - ]; tight)]
 │    │         │    │         └── gt [type=bool, outer=(2), constraints=(/2: [/2 - ]; tight)]
 │    │         │    │              ├── variable: y [type=int, outer=(2)]
 │    │         │    │              └── const: 1 [type=int]
 │    │         │    └── projections [outer=(1,2)]
 │    │         │         └── cast: STRING [type=string, outer=(1)]
 │    │         │              └── variable: a.x [type=int, outer=(1)]
 │    │         └── filters [type=bool, outer=(3,5), constraints=(/3: (/NULL - ]; /5: (/NULL - ]), fd=(3)==(5), (5)==(3)]
 │    │              └── eq [type=bool, outer=(3,5), constraints=(/3: (/NULL - ]; /5: (/NULL - ])]
 │    │                   ├── variable: column5 [type=string, outer=(5)]
 │    │                   └── variable: b.x [type=string, outer=(3)]
 │    └── const: 10 [type=int]
 └── projections [outer=(2,3)]
      └── plus [type=int, outer=(2)]
           ├── variable: y [type=int, outer=(2)]
           └── const: 1 [type=int]

memo
SELECT y, b.x, y+1 AS c
FROM a, b
WHERE a.y>1 AND a.x::string=b.x
ORDER BY y
LIMIT 10
----
memo (optimized, ~24KB)
 ├── G1: (project G2 G3)
 │    ├── "[presentation: y:2,x:3,c:6] [ordering: +2]"
 │    │    ├── best: (project G2="[ordering: +2]" G3)
 │    │    └── cost: 2171.17
 │    └── ""
 │         ├── best: (project G2 G3)
 │         └── cost: 2171.17
 ├── G2: (limit G4 G5 ordering=+2)
 │    ├── ""
 │    │    ├── best: (limit G4="[ordering: +2]" G5 ordering=+2)
 │    │    └── cost: 2170.97
 │    └── "[ordering: +2]"
 │         ├── best: (limit G4="[ordering: +2]" G5 ordering=+2)
 │         └── cost: 2170.97
 ├── G3: (projections G6 y x)
 ├── G4: (inner-join G9 G8 G7) (inner-join G8 G9 G7) (lookup-join G9 G14 b,keyCols=[5],outCols=(2,3,5)) (merge-join G8 G9 G10)
 │    ├── ""
 │    │    ├── best: (inner-join G8 G9 G7)
 │    │    └── cost: 2108.33
 │    └── "[ordering: +2]"
 │         ├── best: (sort G4)
 │         └── cost: 2170.87
 ├── G5: (const 10)
 ├── G6: (plus G22 G23)
 ├── G7: (filters G11)
 ├── G8: (scan b,cols=(3))
 │    ├── ""
 │    │    ├── best: (scan b,cols=(3))
 │    │    └── cost: 1030.00
 │    └── "[ordering: +3]"
 │         ├── best: (scan b,cols=(3))
 │         └── cost: 1030.00
 ├── G9: (project G12 G13)
 │    ├── ""
 │    │    ├── best: (project G12 G13)
 │    │    └── cost: 1056.67
 │    ├── "[ordering: +2]"
 │    │    ├── best: (sort G9)
 │    │    └── cost: 1119.21
 │    └── "[ordering: +5]"
 │         ├── best: (sort G9)
 │         └── cost: 1119.21
 ├── G10: (merge-on G14 inner-join,+3,+5)
 ├── G11: (eq G15 G16)
 ├── G12: (select G17 G18)
 │    ├── ""
 │    │    ├── best: (select G17 G18)
 │    │    └── cost: 1050.00
 │    └── "[ordering: +2]"
 │         ├── best: (sort G12)
 │         └── cost: 1112.54
 ├── G13: (projections G19 y)
 ├── G14: (true)
 ├── G15: (variable column5)
 ├── G16: (variable b.x)
 ├── G17: (scan a)
 │    ├── ""
 │    │    ├── best: (scan a)
 │    │    └── cost: 1040.00
 │    └── "[ordering: +2]"
 │         ├── best: (sort G17)
 │         └── cost: 1259.32
 ├── G18: (filters G20)
 ├── G19: (cast G21 STRING)
 ├── G20: (gt G22 G23)
 ├── G21: (variable a.x)
 ├── G22: (variable y)
 └── G23: (const 1)

# Test interning of expressions.
memo
SELECT 1 AS a, 1+z AS b, left(x, 10)::TIMESTAMP AS c, left(x, 10)::TIMESTAMPTZ AS d
FROM b
WHERE z=1 AND concat(x, 'foo', x)=concat(x, 'foo', x)
----
memo (optimized, ~12KB)
 ├── G1: (project G2 G3)
 │    └── "[presentation: a:3,b:4,c:5,d:6]"
 │         ├── best: (project G2 G3)
 │         └── cost: 1050.17
 ├── G2: (select G4 G5)
 │    └── ""
 │         ├── best: (select G4 G5)
 │         └── cost: 1050.00
 ├── G3: (projections G6 G7 G8 G9)
 ├── G4: (scan b)
 │    └── ""
 │         ├── best: (scan b)
 │         └── cost: 1040.00
 ├── G5: (filters G10 G11)
 ├── G6: (const 1)
 ├── G7: (plus G13 G14)
 ├── G8: (cast G12 TIMESTAMP)
 ├── G9: (cast G12 TIMESTAMPTZ)
 ├── G10: (eq G13 G14)
 ├── G11: (eq G15 G15)
 ├── G12: (function G18 G16 left)
 ├── G13: (variable z)
 ├── G14: (const 1)
 ├── G15: (function G18 G17 G18 concat)
 ├── G16: (const 10)
 ├── G17: (const 'foo')
 └── G18: (variable x)

# Test topological sorting
memo
SELECT x FROM a WHERE x = 1 AND x+y = 1
----
memo (optimized, ~9KB)
 ├── G1: (project G2 G3)
 │    └── "[presentation: x:1]"
 │         ├── best: (project G2 G3)
 │         └── cost: 1.05
 ├── G2: (select G4 G5) (select G6 G7)
 │    └── ""
 │         ├── best: (select G6 G7)
 │         └── cost: 1.05
 ├── G3: (projections x)
 ├── G4: (scan a)
 │    └── ""
 │         ├── best: (scan a)
 │         └── cost: 1040.00
 ├── G5: (filters G8 G9)
 ├── G6: (scan a,constrained)
 │    └── ""
 │         ├── best: (scan a,constrained)
 │         └── cost: 1.04
 ├── G7: (filters G9)
 ├── G8: (eq G12 G11)
 ├── G9: (eq G10 G11)
 ├── G10: (plus G12 G13)
 ├── G11: (const 1)
 ├── G12: (variable x)
 └── G13: (variable y)

memo raw-memo
SELECT x FROM a WHERE x = 1 AND x+y = 1
----
root: G12, [presentation: x:1]
memo (optimized, ~9KB)
 ├── G1: (scan a)
 │    └── ""
 │         ├── best: (scan a)
 │         └── cost: 1040.00
 ├── G2: (variable x)
 ├── G3: (const 1)
 ├── G4: (eq G2 G3)
 ├── G5: (variable y)
 ├── G6: (plus G2 G5)
 ├── G7: (eq G6 G3)
 ├── G8: (and G4 G7)
 ├── G9: (filters G4 G7)
 ├── G10: (select G1 G9) (select G15 G14)
 │    └── ""
 │         ├── best: (select G15 G14)
 │         └── cost: 1.05
 ├── G11: (projections x)
 ├── G12: (project G10 G11)
 │    └── "[presentation: x:1]"
 │         ├── best: (project G10 G11)
 │         └── cost: 1.05
 ├── G13: (true)
 ├── G14: (filters G7)
 └── G15: (scan a,constrained)
      └── ""
           ├── best: (scan a,constrained)
           └── cost: 1.04

memo 
SELECT x, y FROM a UNION SELECT x+1, y+1 FROM a
----
memo (optimized, ~6KB)
 ├── G1: (union G2 G3)
 │    └── "[presentation: x:7,y:8]"
 │         ├── best: (union G2 G3)
 │         └── cost: 2150.00
 ├── G2: (scan a)
 │    └── ""
 │         ├── best: (scan a)
 │         └── cost: 1040.00
 ├── G3: (project G4 G5)
 │    └── ""
 │         ├── best: (project G4 G5)
 │         └── cost: 1070.00
 ├── G4: (scan a)
 │    └── ""
 │         ├── best: (scan a)
 │         └── cost: 1040.00
 ├── G5: (projections G6 G7)
 ├── G6: (plus G8 G10)
 ├── G7: (plus G9 G10)
 ├── G8: (variable a.x)
 ├── G9: (variable a.y)
 └── G10: (const 1)

memo
SELECT array_agg(x) FROM (SELECT * FROM a)
----
memo (optimized, ~4KB)
 ├── G1: (scalar-group-by G2 G3 cols=())
 │    └── "[presentation: array_agg:3]"
 │         ├── best: (scalar-group-by G2 G3 cols=())
 │         └── cost: 1040.01
 ├── G2: (scan a,cols=(1))
 │    └── ""
 │         ├── best: (scan a,cols=(1))
 │         └── cost: 1030.00
 ├── G3: (aggregations G4)
 ├── G4: (array-agg G5)
 └── G5: (variable x)

memo
SELECT array_agg(x) FROM (SELECT * FROM a) GROUP BY y
----
memo (optimized, ~4KB)
 ├── G1: (project G2 G3)
 │    └── "[presentation: array_agg:3]"
 │         ├── best: (project G2 G3)
 │         └── cost: 1072.00
 ├── G2: (group-by G4 G5 cols=(2))
 │    └── ""
 │         ├── best: (group-by G4 G5 cols=(2))
 │         └── cost: 1071.00
 ├── G3: (projections array_agg)
 ├── G4: (scan a)
 │    └── ""
 │         ├── best: (scan a)
 │         └── cost: 1040.00
 ├── G5: (aggregations G6)
 ├── G6: (array-agg G7)
 └── G7: (variable x)

memo
SELECT array_agg(x) FROM (SELECT * FROM a ORDER BY y)
----
memo (optimized, ~3KB)
 ├── G1: (scalar-group-by G2 G3 cols=(),ordering=+2)
 │    └── "[presentation: array_agg:3]"
 │         ├── best: (scalar-group-by G2="[ordering: +2]" G3 cols=(),ordering=+2)
 │         └── cost: 1269.33
 ├── G2: (scan a)
 │    ├── ""
 │    │    ├── best: (scan a)
 │    │    └── cost: 1040.00
 │    └── "[ordering: +2]"
 │         ├── best: (sort G2)
 │         └── cost: 1259.32
 ├── G3: (aggregations G4)
 ├── G4: (array-agg G5)
 └── G5: (variable x)

memo
SELECT DISTINCT field FROM [EXPLAIN SELECT 123 AS k]
----
memo (optimized, ~6KB)
 ├── G1: (distinct-on G2 G3 cols=(3))
 │    └── "[presentation: field:3]"
 │         ├── best: (distinct-on G2 G3 cols=(3))
 │         └── cost: 0.03
 ├── G2: (explain G4 [presentation: k:1])
 │    └── ""
 │         ├── best: (explain G4="[presentation: k:1]" [presentation: k:1])
 │         └── cost: 0.03
 ├── G3: (aggregations)
 ├── G4: (project G5 G6)
 │    └── "[presentation: k:1]"
 │         ├── best: (project G5 G6)
 │         └── cost: 0.03
 ├── G5: (values G7)
 │    └── ""
 │         ├── best: (values G7)
 │         └── cost: 0.01
 ├── G6: (projections G8)
 ├── G7: (tuple)
 └── G8: (const 123)

memo
SELECT DISTINCT tag FROM [SHOW TRACE FOR SESSION]
----
memo (optimized, ~3KB)
 ├── G1: (distinct-on G2 G3 cols=(4))
 │    └── "[presentation: tag:4]"
 │         ├── best: (distinct-on G2 G3 cols=(4))
 │         └── cost: 0.00
 ├── G2: (show-trace-for-session &{TRACE false [1 2 3 4 5 6 7]})
 │    └── ""
 │         ├── best: (show-trace-for-session &{TRACE false [1 2 3 4 5 6 7]})
 │         └── cost: 0.00
 └── G3: (aggregations)
