github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/sql/opt/norm/testdata/rules/with (about)

     1  build format=show-all
     2  WITH foo AS (SELECT 1) (SELECT * FROM foo) UNION ALL (SELECT * FROM foo)
     3  ----
     4  with &1 (foo)
     5   ├── columns: "?column?":4(int!null)
     6   ├── cardinality: [2 - 2]
     7   ├── stats: [rows=2]
     8   ├── cost: 0.11
     9   ├── prune: (4)
    10   ├── project
    11   │    ├── columns: "?column?":1(int!null)
    12   │    ├── cardinality: [1 - 1]
    13   │    ├── stats: [rows=1]
    14   │    ├── cost: 0.05
    15   │    ├── key: ()
    16   │    ├── fd: ()-->(1)
    17   │    ├── prune: (1)
    18   │    ├── values
    19   │    │    ├── cardinality: [1 - 1]
    20   │    │    ├── stats: [rows=1]
    21   │    │    ├── cost: 0.02
    22   │    │    ├── key: ()
    23   │    │    └── tuple [type=tuple]
    24   │    └── projections
    25   │         └── const: 1 [as="?column?":1, type=int]
    26   └── union-all
    27        ├── columns: "?column?":4(int!null)
    28        ├── left columns: "?column?":2(int)
    29        ├── right columns: "?column?":3(int)
    30        ├── cardinality: [2 - 2]
    31        ├── stats: [rows=2]
    32        ├── cost: 0.05
    33        ├── prune: (4)
    34        ├── cte-uses
    35        │    └── &1: count=2 used-columns=(1)
    36        ├── with-scan &1 (foo)
    37        │    ├── columns: "?column?":2(int!null)
    38        │    ├── mapping:
    39        │    │    └──  "?column?":1(int) => "?column?":2(int)
    40        │    ├── cardinality: [1 - 1]
    41        │    ├── stats: [rows=1]
    42        │    ├── cost: 0.01
    43        │    ├── key: ()
    44        │    ├── fd: ()-->(2)
    45        │    ├── prune: (2)
    46        │    └── cte-uses
    47        │         └── &1: count=1 used-columns=(1)
    48        └── with-scan &1 (foo)
    49             ├── columns: "?column?":3(int!null)
    50             ├── mapping:
    51             │    └──  "?column?":1(int) => "?column?":3(int)
    52             ├── cardinality: [1 - 1]
    53             ├── stats: [rows=1]
    54             ├── cost: 0.01
    55             ├── key: ()
    56             ├── fd: ()-->(3)
    57             ├── prune: (3)
    58             └── cte-uses
    59                  └── &1: count=1 used-columns=(1)
    60  
    61  norm format=show-all expect=InlineWith
    62  WITH foo AS (SELECT 1) SELECT * FROM foo
    63  ----
    64  values
    65   ├── columns: "?column?":2(int!null)
    66   ├── cardinality: [1 - 1]
    67   ├── stats: [rows=1]
    68   ├── cost: 0.02
    69   ├── key: ()
    70   ├── fd: ()-->(2)
    71   ├── prune: (2)
    72   └── tuple [type=tuple{int}]
    73        └── const: 1 [type=int]
    74  
    75  norm format=show-all expect=InlineWith
    76  WITH foo AS (SELECT 1) SELECT * FROM foo CROSS JOIN (VALUES (2))
    77  ----
    78  inner-join (cross)
    79   ├── columns: "?column?":2(int!null) column1:3(int!null)
    80   ├── cardinality: [1 - 1]
    81   ├── stats: [rows=1]
    82   ├── cost: 0.09
    83   ├── key: ()
    84   ├── fd: ()-->(2,3)
    85   ├── prune: (2,3)
    86   ├── multiplicity: left-rows(exactly-one), right-rows(exactly-one)
    87   ├── values
    88   │    ├── columns: "?column?":2(int!null)
    89   │    ├── cardinality: [1 - 1]
    90   │    ├── stats: [rows=1]
    91   │    ├── cost: 0.02
    92   │    ├── key: ()
    93   │    ├── fd: ()-->(2)
    94   │    ├── prune: (2)
    95   │    └── tuple [type=tuple{int}]
    96   │         └── const: 1 [type=int]
    97   ├── values
    98   │    ├── columns: column1:3(int!null)
    99   │    ├── cardinality: [1 - 1]
   100   │    ├── stats: [rows=1]
   101   │    ├── cost: 0.02
   102   │    ├── key: ()
   103   │    ├── fd: ()-->(3)
   104   │    ├── prune: (3)
   105   │    └── tuple [type=tuple{int}]
   106   │         └── const: 2 [type=int]
   107   └── filters (true)
   108  
   109  norm expect=InlineWith
   110  WITH foo AS (SELECT 1), bar AS (SELECT 2) SELECT * FROM foo CROSS JOIN bar
   111  ----
   112  inner-join (cross)
   113   ├── columns: "?column?":3!null "?column?":4!null
   114   ├── cardinality: [1 - 1]
   115   ├── key: ()
   116   ├── fd: ()-->(3,4)
   117   ├── values
   118   │    ├── columns: "?column?":3!null
   119   │    ├── cardinality: [1 - 1]
   120   │    ├── key: ()
   121   │    ├── fd: ()-->(3)
   122   │    └── (1,)
   123   ├── values
   124   │    ├── columns: "?column?":4!null
   125   │    ├── cardinality: [1 - 1]
   126   │    ├── key: ()
   127   │    ├── fd: ()-->(4)
   128   │    └── (2,)
   129   └── filters (true)
   130  
   131  # Descend into scalar expressions.
   132  
   133  norm expect=InlineWith
   134  WITH foo AS (SELECT 1), bar AS (SELECT 2) SELECT (SELECT * FROM foo) + (SELECT * FROM bar)
   135  ----
   136  values
   137   ├── columns: "?column?":5
   138   ├── cardinality: [1 - 1]
   139   ├── key: ()
   140   ├── fd: ()-->(5)
   141   └── tuple
   142        └── plus
   143             ├── subquery
   144             │    └── values
   145             │         ├── columns: "?column?":3!null
   146             │         ├── cardinality: [1 - 1]
   147             │         ├── key: ()
   148             │         ├── fd: ()-->(3)
   149             │         └── (1,)
   150             └── subquery
   151                  └── values
   152                       ├── columns: "?column?":4!null
   153                       ├── cardinality: [1 - 1]
   154                       ├── key: ()
   155                       ├── fd: ()-->(4)
   156                       └── (2,)
   157  
   158  norm expect=InlineWith
   159  WITH foo AS (SELECT 1), bar AS (SELECT 2) SELECT (SELECT * FROM foo) + (SELECT * FROM bar) + (SELECT * FROM bar)
   160  ----
   161  with &2 (bar)
   162   ├── columns: "?column?":6
   163   ├── cardinality: [1 - 1]
   164   ├── key: ()
   165   ├── fd: ()-->(6)
   166   ├── values
   167   │    ├── columns: "?column?":2!null
   168   │    ├── cardinality: [1 - 1]
   169   │    ├── key: ()
   170   │    ├── fd: ()-->(2)
   171   │    └── (2,)
   172   └── values
   173        ├── columns: "?column?":6
   174        ├── cardinality: [1 - 1]
   175        ├── key: ()
   176        ├── fd: ()-->(6)
   177        └── tuple
   178             └── plus
   179                  ├── plus
   180                  │    ├── subquery
   181                  │    │    └── values
   182                  │    │         ├── columns: "?column?":3!null
   183                  │    │         ├── cardinality: [1 - 1]
   184                  │    │         ├── key: ()
   185                  │    │         ├── fd: ()-->(3)
   186                  │    │         └── (1,)
   187                  │    └── subquery
   188                  │         └── with-scan &2 (bar)
   189                  │              ├── columns: "?column?":4!null
   190                  │              ├── mapping:
   191                  │              │    └──  "?column?":2 => "?column?":4
   192                  │              ├── cardinality: [1 - 1]
   193                  │              ├── key: ()
   194                  │              └── fd: ()-->(4)
   195                  └── subquery
   196                       └── with-scan &2 (bar)
   197                            ├── columns: "?column?":5!null
   198                            ├── mapping:
   199                            │    └──  "?column?":2 => "?column?":5
   200                            ├── cardinality: [1 - 1]
   201                            ├── key: ()
   202                            └── fd: ()-->(5)
   203  
   204  # We should inline foo, but not bar.
   205  norm expect=InlineWith
   206  WITH foo AS (SELECT 1), bar AS (SELECT 2) SELECT * FROM foo CROSS JOIN bar CROSS JOIN bar AS bar2
   207  ----
   208  with &2 (bar)
   209   ├── columns: "?column?":3!null "?column?":4!null "?column?":5!null
   210   ├── cardinality: [1 - 1]
   211   ├── key: ()
   212   ├── fd: ()-->(3-5)
   213   ├── values
   214   │    ├── columns: "?column?":2!null
   215   │    ├── cardinality: [1 - 1]
   216   │    ├── key: ()
   217   │    ├── fd: ()-->(2)
   218   │    └── (2,)
   219   └── inner-join (cross)
   220        ├── columns: "?column?":3!null "?column?":4!null "?column?":5!null
   221        ├── cardinality: [1 - 1]
   222        ├── key: ()
   223        ├── fd: ()-->(3-5)
   224        ├── inner-join (cross)
   225        │    ├── columns: "?column?":3!null "?column?":4!null
   226        │    ├── cardinality: [1 - 1]
   227        │    ├── key: ()
   228        │    ├── fd: ()-->(3,4)
   229        │    ├── values
   230        │    │    ├── columns: "?column?":3!null
   231        │    │    ├── cardinality: [1 - 1]
   232        │    │    ├── key: ()
   233        │    │    ├── fd: ()-->(3)
   234        │    │    └── (1,)
   235        │    ├── with-scan &2 (bar)
   236        │    │    ├── columns: "?column?":4!null
   237        │    │    ├── mapping:
   238        │    │    │    └──  "?column?":2 => "?column?":4
   239        │    │    ├── cardinality: [1 - 1]
   240        │    │    ├── key: ()
   241        │    │    └── fd: ()-->(4)
   242        │    └── filters (true)
   243        ├── with-scan &2 (bar)
   244        │    ├── columns: "?column?":5!null
   245        │    ├── mapping:
   246        │    │    └──  "?column?":2 => "?column?":5
   247        │    ├── cardinality: [1 - 1]
   248        │    ├── key: ()
   249        │    └── fd: ()-->(5)
   250        └── filters (true)
   251  
   252  norm format=show-all
   253  WITH
   254      foo AS (SELECT 1), bar AS (SELECT 2)
   255  SELECT
   256      *
   257  FROM
   258      foo CROSS JOIN bar CROSS JOIN bar AS bar2 CROSS JOIN foo AS foo2
   259  ----
   260  with &1 (foo)
   261   ├── columns: "?column?":3(int!null) "?column?":4(int!null) "?column?":5(int!null) "?column?":6(int!null)
   262   ├── cardinality: [1 - 1]
   263   ├── stats: [rows=1]
   264   ├── cost: 0.25
   265   ├── key: ()
   266   ├── fd: ()-->(3-6)
   267   ├── prune: (3-6)
   268   ├── values
   269   │    ├── columns: "?column?":1(int!null)
   270   │    ├── cardinality: [1 - 1]
   271   │    ├── stats: [rows=1]
   272   │    ├── cost: 0.02
   273   │    ├── key: ()
   274   │    ├── fd: ()-->(1)
   275   │    ├── prune: (1)
   276   │    └── tuple [type=tuple{int}]
   277   │         └── const: 1 [type=int]
   278   └── with &2 (bar)
   279        ├── columns: "?column?":3(int!null) "?column?":4(int!null) "?column?":5(int!null) "?column?":6(int!null)
   280        ├── cardinality: [1 - 1]
   281        ├── stats: [rows=1]
   282        ├── cost: 0.22
   283        ├── key: ()
   284        ├── fd: ()-->(3-6)
   285        ├── prune: (3-6)
   286        ├── cte-uses
   287        │    └── &1: count=2 used-columns=(1)
   288        ├── values
   289        │    ├── columns: "?column?":2(int!null)
   290        │    ├── cardinality: [1 - 1]
   291        │    ├── stats: [rows=1]
   292        │    ├── cost: 0.02
   293        │    ├── key: ()
   294        │    ├── fd: ()-->(2)
   295        │    ├── prune: (2)
   296        │    └── tuple [type=tuple{int}]
   297        │         └── const: 2 [type=int]
   298        └── inner-join (cross)
   299             ├── columns: "?column?":3(int!null) "?column?":4(int!null) "?column?":5(int!null) "?column?":6(int!null)
   300             ├── cardinality: [1 - 1]
   301             ├── stats: [rows=1]
   302             ├── cost: 0.19
   303             ├── key: ()
   304             ├── fd: ()-->(3-6)
   305             ├── prune: (3-6)
   306             ├── multiplicity: left-rows(exactly-one), right-rows(exactly-one)
   307             ├── cte-uses
   308             │    ├── &1: count=2 used-columns=(1)
   309             │    └── &2: count=2 used-columns=(2)
   310             ├── inner-join (cross)
   311             │    ├── columns: "?column?":3(int!null) "?column?":4(int!null) "?column?":5(int!null)
   312             │    ├── cardinality: [1 - 1]
   313             │    ├── stats: [rows=1]
   314             │    ├── cost: 0.13
   315             │    ├── key: ()
   316             │    ├── fd: ()-->(3-5)
   317             │    ├── prune: (3-5)
   318             │    ├── join-size: 3
   319             │    ├── multiplicity: left-rows(exactly-one), right-rows(exactly-one)
   320             │    ├── cte-uses
   321             │    │    ├── &1: count=1 used-columns=(1)
   322             │    │    └── &2: count=2 used-columns=(2)
   323             │    ├── inner-join (cross)
   324             │    │    ├── columns: "?column?":3(int!null) "?column?":4(int!null)
   325             │    │    ├── cardinality: [1 - 1]
   326             │    │    ├── stats: [rows=1]
   327             │    │    ├── cost: 0.07
   328             │    │    ├── key: ()
   329             │    │    ├── fd: ()-->(3,4)
   330             │    │    ├── prune: (3,4)
   331             │    │    ├── join-size: 2
   332             │    │    ├── multiplicity: left-rows(exactly-one), right-rows(exactly-one)
   333             │    │    ├── cte-uses
   334             │    │    │    ├── &1: count=1 used-columns=(1)
   335             │    │    │    └── &2: count=1 used-columns=(2)
   336             │    │    ├── with-scan &1 (foo)
   337             │    │    │    ├── columns: "?column?":3(int!null)
   338             │    │    │    ├── mapping:
   339             │    │    │    │    └──  "?column?":1(int) => "?column?":3(int)
   340             │    │    │    ├── cardinality: [1 - 1]
   341             │    │    │    ├── stats: [rows=1]
   342             │    │    │    ├── cost: 0.01
   343             │    │    │    ├── key: ()
   344             │    │    │    ├── fd: ()-->(3)
   345             │    │    │    ├── prune: (3)
   346             │    │    │    └── cte-uses
   347             │    │    │         └── &1: count=1 used-columns=(1)
   348             │    │    ├── with-scan &2 (bar)
   349             │    │    │    ├── columns: "?column?":4(int!null)
   350             │    │    │    ├── mapping:
   351             │    │    │    │    └──  "?column?":2(int) => "?column?":4(int)
   352             │    │    │    ├── cardinality: [1 - 1]
   353             │    │    │    ├── stats: [rows=1]
   354             │    │    │    ├── cost: 0.01
   355             │    │    │    ├── key: ()
   356             │    │    │    ├── fd: ()-->(4)
   357             │    │    │    ├── prune: (4)
   358             │    │    │    └── cte-uses
   359             │    │    │         └── &2: count=1 used-columns=(2)
   360             │    │    └── filters (true)
   361             │    ├── with-scan &2 (bar)
   362             │    │    ├── columns: "?column?":5(int!null)
   363             │    │    ├── mapping:
   364             │    │    │    └──  "?column?":2(int) => "?column?":5(int)
   365             │    │    ├── cardinality: [1 - 1]
   366             │    │    ├── stats: [rows=1]
   367             │    │    ├── cost: 0.01
   368             │    │    ├── key: ()
   369             │    │    ├── fd: ()-->(5)
   370             │    │    ├── prune: (5)
   371             │    │    └── cte-uses
   372             │    │         └── &2: count=1 used-columns=(2)
   373             │    └── filters (true)
   374             ├── with-scan &1 (foo)
   375             │    ├── columns: "?column?":6(int!null)
   376             │    ├── mapping:
   377             │    │    └──  "?column?":1(int) => "?column?":6(int)
   378             │    ├── cardinality: [1 - 1]
   379             │    ├── stats: [rows=1]
   380             │    ├── cost: 0.01
   381             │    ├── key: ()
   382             │    ├── fd: ()-->(6)
   383             │    ├── prune: (6)
   384             │    └── cte-uses
   385             │         └── &1: count=1 used-columns=(1)
   386             └── filters (true)
   387  
   388  exec-ddl
   389  CREATE TABLE a (k INT PRIMARY KEY, i INT, f FLOAT, s STRING, j JSON)
   390  ----
   391  
   392  norm
   393  WITH foo AS (VALUES (1))
   394  SELECT * FROM a WHERE NOT EXISTS(SELECT * FROM (VALUES (k), ((SELECT * FROM foo))) WHERE column1=k)
   395  ----
   396  anti-join-apply
   397   ├── columns: k:2!null i:3 f:4 s:5 j:6
   398   ├── key: (2)
   399   ├── fd: (2)-->(3-6)
   400   ├── scan a
   401   │    ├── columns: k:2!null i:3 f:4 s:5 j:6
   402   │    ├── key: (2)
   403   │    └── fd: (2)-->(3-6)
   404   ├── values
   405   │    ├── columns: column1:8
   406   │    ├── outer: (2)
   407   │    ├── cardinality: [2 - 2]
   408   │    ├── (k:2,)
   409   │    └── tuple
   410   │         └── subquery
   411   │              └── values
   412   │                   ├── columns: column1:7!null
   413   │                   ├── cardinality: [1 - 1]
   414   │                   ├── key: ()
   415   │                   ├── fd: ()-->(7)
   416   │                   └── (1,)
   417   └── filters
   418        └── column1:8 = k:2 [outer=(2,8), constraints=(/2: (/NULL - ]; /8: (/NULL - ]), fd=(2)==(8), (8)==(2)]
   419  
   420  # Don't inline side-effecting expressions.
   421  norm
   422  WITH foo AS (INSERT INTO a VALUES (1) RETURNING *) SELECT * FROM foo
   423  ----
   424  with &1 (foo)
   425   ├── columns: k:11!null i:12 f:13 s:14 j:15
   426   ├── cardinality: [1 - 1]
   427   ├── volatile, side-effects, mutations
   428   ├── key: ()
   429   ├── fd: ()-->(11-15)
   430   ├── insert a
   431   │    ├── columns: a.k:1!null a.i:2 a.f:3 a.s:4 a.j:5
   432   │    ├── insert-mapping:
   433   │    │    ├── column1:6 => a.k:1
   434   │    │    ├── column7:7 => a.i:2
   435   │    │    ├── column8:8 => a.f:3
   436   │    │    ├── column9:9 => a.s:4
   437   │    │    └── column10:10 => a.j:5
   438   │    ├── cardinality: [1 - 1]
   439   │    ├── volatile, side-effects, mutations
   440   │    ├── key: ()
   441   │    ├── fd: ()-->(1-5)
   442   │    └── values
   443   │         ├── columns: column1:6!null column7:7 column8:8 column9:9 column10:10
   444   │         ├── cardinality: [1 - 1]
   445   │         ├── key: ()
   446   │         ├── fd: ()-->(6-10)
   447   │         └── (1, NULL, NULL, NULL, NULL)
   448   └── with-scan &1 (foo)
   449        ├── columns: k:11!null i:12 f:13 s:14 j:15
   450        ├── mapping:
   451        │    ├──  a.k:1 => k:11
   452        │    ├──  a.i:2 => i:12
   453        │    ├──  a.f:3 => f:13
   454        │    ├──  a.s:4 => s:14
   455        │    └──  a.j:5 => j:15
   456        ├── cardinality: [1 - 1]
   457        ├── key: ()
   458        └── fd: ()-->(11-15)
   459  
   460  norm expect-not=InlineWith
   461  WITH foo AS (SELECT 1/0) SELECT * FROM foo
   462  ----
   463  with &1 (foo)
   464   ├── columns: "?column?":2
   465   ├── cardinality: [1 - 1]
   466   ├── immutable, side-effects
   467   ├── key: ()
   468   ├── fd: ()-->(2)
   469   ├── values
   470   │    ├── columns: "?column?":1
   471   │    ├── cardinality: [1 - 1]
   472   │    ├── immutable, side-effects
   473   │    ├── key: ()
   474   │    ├── fd: ()-->(1)
   475   │    └── (1 / 0,)
   476   └── with-scan &1 (foo)
   477        ├── columns: "?column?":2
   478        ├── mapping:
   479        │    └──  "?column?":1 => "?column?":2
   480        ├── cardinality: [1 - 1]
   481        ├── key: ()
   482        └── fd: ()-->(2)
   483  
   484  norm expect=InlineWith
   485  WITH foo AS (SELECT 1), bar AS (SELECT * FROM foo) SELECT * FROM foo
   486  ----
   487  values
   488   ├── columns: "?column?":3!null
   489   ├── cardinality: [1 - 1]
   490   ├── key: ()
   491   ├── fd: ()-->(3)
   492   └── (1,)
   493  
   494  norm expect=InlineWith
   495  WITH foo AS (SELECT 1), bar AS (SELECT * FROM foo) SELECT * FROM foo
   496  ----
   497  values
   498   ├── columns: "?column?":3!null
   499   ├── cardinality: [1 - 1]
   500   ├── key: ()
   501   ├── fd: ()-->(3)
   502   └── (1,)
   503  
   504  # Inline nested Withs.
   505  norm expect=InlineWith
   506  WITH
   507      t (x) AS (WITH t (x) AS (SELECT 1) SELECT x * 10 FROM t)
   508  SELECT
   509      x + 2
   510  FROM
   511      t
   512  ----
   513  values
   514   ├── columns: "?column?":5!null
   515   ├── cardinality: [1 - 1]
   516   ├── key: ()
   517   ├── fd: ()-->(5)
   518   └── (12,)
   519  
   520  # Regression test for #43148: WithScans with no columns should still be
   521  # uniquely identifiable. Without this uniqueness, they can't be assigned
   522  # different required physical properties.
   523  norm
   524  WITH cte AS (SELECT * FROM a) (SELECT 1 FROM cte LIMIT 9) UNION (SELECT 1 FROM cte LIMIT 10)
   525  ----
   526  with &1 (cte)
   527   ├── columns: "?column?":18!null
   528   ├── cardinality: [0 - 19]
   529   ├── key: (18)
   530   ├── scan a
   531   │    ├── columns: a.k:1!null a.i:2 a.f:3 a.s:4 a.j:5
   532   │    ├── key: (1)
   533   │    └── fd: (1)-->(2-5)
   534   └── union
   535        ├── columns: "?column?":18!null
   536        ├── left columns: "?column?":11
   537        ├── right columns: "?column?":17
   538        ├── cardinality: [0 - 19]
   539        ├── key: (18)
   540        ├── project
   541        │    ├── columns: "?column?":11!null
   542        │    ├── cardinality: [0 - 9]
   543        │    ├── fd: ()-->(11)
   544        │    ├── limit
   545        │    │    ├── cardinality: [0 - 9]
   546        │    │    ├── with-scan &1 (cte)
   547        │    │    │    ├── mapping:
   548        │    │    │    └── limit hint: 9.00
   549        │    │    └── 9
   550        │    └── projections
   551        │         └── 1 [as="?column?":11]
   552        └── project
   553             ├── columns: "?column?":17!null
   554             ├── cardinality: [0 - 10]
   555             ├── fd: ()-->(17)
   556             ├── limit
   557             │    ├── cardinality: [0 - 10]
   558             │    ├── with-scan &1 (cte)
   559             │    │    ├── mapping:
   560             │    │    └── limit hint: 10.00
   561             │    └── 10
   562             └── projections
   563                  └── 1 [as="?column?":17]
   564  
   565  # Check cte-uses when used with mutations (for FK checks).
   566  exec-ddl
   567  CREATE TABLE parent (p INT PRIMARY KEY)
   568  ----
   569  
   570  exec-ddl
   571  CREATE TABLE child (c INT PRIMARY KEY, p INT REFERENCES parent(p))
   572  ----
   573  
   574  norm format=show-all
   575  WITH cte AS (INSERT INTO child VALUES (1, 1) RETURNING c) SELECT c FROM cte UNION SELECT c+1 FROM cte
   576  ----
   577  with &2 (cte)
   578   ├── columns: c:10(int!null)
   579   ├── cardinality: [1 - 2]
   580   ├── volatile, side-effects, mutations
   581   ├── stats: [rows=2, distinct(10)=2, null(10)=0]
   582   ├── cost: 1037.7025
   583   ├── key: (10)
   584   ├── insert t.public.child
   585   │    ├── columns: t.public.child.c:1(int!null)
   586   │    ├── insert-mapping:
   587   │    │    ├── column1:3 => t.public.child.c:1
   588   │    │    └── column2:4 => t.public.child.p:2
   589   │    ├── input binding: &1
   590   │    ├── cardinality: [1 - 1]
   591   │    ├── volatile, side-effects, mutations
   592   │    ├── stats: [rows=1]
   593   │    ├── cost: 1037.5925
   594   │    ├── key: ()
   595   │    ├── fd: ()-->(1)
   596   │    ├── values
   597   │    │    ├── columns: column1:3(int!null) column2:4(int!null)
   598   │    │    ├── cardinality: [1 - 1]
   599   │    │    ├── stats: [rows=1]
   600   │    │    ├── cost: 0.02
   601   │    │    ├── key: ()
   602   │    │    ├── fd: ()-->(3,4)
   603   │    │    ├── prune: (3,4)
   604   │    │    └── tuple [type=tuple{int, int}]
   605   │    │         ├── const: 1 [type=int]
   606   │    │         └── const: 1 [type=int]
   607   │    └── f-k-checks
   608   │         └── f-k-checks-item: child(p) -> parent(p)
   609   │              └── anti-join (hash)
   610   │                   ├── columns: column2:5(int!null)
   611   │                   ├── cardinality: [0 - 1]
   612   │                   ├── stats: [rows=1e-10]
   613   │                   ├── cost: 1037.5625
   614   │                   ├── key: ()
   615   │                   ├── fd: ()-->(5)
   616   │                   ├── cte-uses
   617   │                   │    └── &1: count=1 used-columns=(4)
   618   │                   ├── with-scan &1
   619   │                   │    ├── columns: column2:5(int!null)
   620   │                   │    ├── mapping:
   621   │                   │    │    └──  column2:4(int) => column2:5(int)
   622   │                   │    ├── cardinality: [1 - 1]
   623   │                   │    ├── stats: [rows=1, distinct(5)=1, null(5)=0]
   624   │                   │    ├── cost: 0.01
   625   │                   │    ├── key: ()
   626   │                   │    ├── fd: ()-->(5)
   627   │                   │    ├── prune: (5)
   628   │                   │    └── cte-uses
   629   │                   │         └── &1: count=1 used-columns=(4)
   630   │                   ├── scan t.public.parent
   631   │                   │    ├── columns: t.public.parent.p:6(int!null)
   632   │                   │    ├── stats: [rows=1000, distinct(6)=1000, null(6)=0]
   633   │                   │    ├── cost: 1020.02
   634   │                   │    ├── key: (6)
   635   │                   │    ├── prune: (6)
   636   │                   │    └── interesting orderings: (+6)
   637   │                   └── filters
   638   │                        └── eq [type=bool, outer=(5,6), constraints=(/5: (/NULL - ]; /6: (/NULL - ]), fd=(5)==(6), (6)==(5)]
   639   │                             ├── variable: column2:5 [type=int]
   640   │                             └── variable: t.public.parent.p:6 [type=int]
   641   └── union
   642        ├── columns: c:10(int!null)
   643        ├── left columns: c:7(int)
   644        ├── right columns: "?column?":9(int)
   645        ├── cardinality: [1 - 2]
   646        ├── stats: [rows=2, distinct(10)=2, null(10)=0]
   647        ├── cost: 0.1
   648        ├── key: (10)
   649        ├── with-scan &2 (cte)
   650        │    ├── columns: c:7(int!null)
   651        │    ├── mapping:
   652        │    │    └──  t.public.child.c:1(int) => c:7(int)
   653        │    ├── cardinality: [1 - 1]
   654        │    ├── stats: [rows=1, distinct(7)=1, null(7)=0]
   655        │    ├── cost: 0.01
   656        │    ├── key: ()
   657        │    ├── fd: ()-->(7)
   658        │    └── prune: (7)
   659        └── project
   660             ├── columns: "?column?":9(int!null)
   661             ├── cardinality: [1 - 1]
   662             ├── stats: [rows=1, distinct(9)=1, null(9)=0]
   663             ├── cost: 0.04
   664             ├── key: ()
   665             ├── fd: ()-->(9)
   666             ├── prune: (9)
   667             ├── with-scan &2 (cte)
   668             │    ├── columns: c:8(int!null)
   669             │    ├── mapping:
   670             │    │    └──  t.public.child.c:1(int) => c:8(int)
   671             │    ├── cardinality: [1 - 1]
   672             │    ├── stats: [rows=1, distinct(8)=1, null(8)=0]
   673             │    ├── cost: 0.01
   674             │    ├── key: ()
   675             │    ├── fd: ()-->(8)
   676             │    └── prune: (8)
   677             └── projections
   678                  └── plus [as="?column?":9, type=int, outer=(8)]
   679                       ├── variable: c:8 [type=int]
   680                       └── const: 1 [type=int]
   681  
   682  # Original CTE is inlined, adding "NOT MATERIALIZED" should not change the behavior.
   683  norm format=show-all expect=InlineWith
   684  WITH foo AS NOT MATERIALIZED (SELECT 1) SELECT * FROM foo
   685  ----
   686  values
   687   ├── columns: "?column?":2(int!null)
   688   ├── cardinality: [1 - 1]
   689   ├── stats: [rows=1]
   690   ├── cost: 0.02
   691   ├── key: ()
   692   ├── fd: ()-->(2)
   693   ├── prune: (2)
   694   └── tuple [type=tuple{int}]
   695        └── const: 1 [type=int]
   696  
   697  # Original CTE is inlined, adding "MATERIALIZED" should prevent inlining.
   698  norm format=show-all expect-not=InlineWith
   699  WITH foo AS MATERIALIZED (SELECT 1) SELECT * FROM foo
   700  ----
   701  with &1 (foo)
   702   ├── columns: "?column?":2(int!null)
   703   ├── materialized
   704   ├── cardinality: [1 - 1]
   705   ├── stats: [rows=1]
   706   ├── cost: 0.04
   707   ├── key: ()
   708   ├── fd: ()-->(2)
   709   ├── prune: (2)
   710   ├── values
   711   │    ├── columns: "?column?":1(int!null)
   712   │    ├── cardinality: [1 - 1]
   713   │    ├── stats: [rows=1]
   714   │    ├── cost: 0.02
   715   │    ├── key: ()
   716   │    ├── fd: ()-->(1)
   717   │    ├── prune: (1)
   718   │    └── tuple [type=tuple{int}]
   719   │         └── const: 1 [type=int]
   720   └── with-scan &1 (foo)
   721        ├── columns: "?column?":2(int!null)
   722        ├── mapping:
   723        │    └──  "?column?":1(int) => "?column?":2(int)
   724        ├── cardinality: [1 - 1]
   725        ├── stats: [rows=1]
   726        ├── cost: 0.01
   727        ├── key: ()
   728        ├── fd: ()-->(2)
   729        └── prune: (2)
   730  
   731  # Original CTE is not inlined, adding "MATERIALIZED" should not change the behavior.
   732  norm expect-not=InlineWith
   733  WITH foo AS MATERIALIZED (SELECT 1/0) SELECT * FROM foo
   734  ----
   735  with &1 (foo)
   736   ├── columns: "?column?":2
   737   ├── materialized
   738   ├── cardinality: [1 - 1]
   739   ├── immutable, side-effects
   740   ├── key: ()
   741   ├── fd: ()-->(2)
   742   ├── values
   743   │    ├── columns: "?column?":1
   744   │    ├── cardinality: [1 - 1]
   745   │    ├── immutable, side-effects
   746   │    ├── key: ()
   747   │    ├── fd: ()-->(1)
   748   │    └── (1 / 0,)
   749   └── with-scan &1 (foo)
   750        ├── columns: "?column?":2
   751        ├── mapping:
   752        │    └──  "?column?":1 => "?column?":2
   753        ├── cardinality: [1 - 1]
   754        ├── key: ()
   755        └── fd: ()-->(2)
   756  
   757  # Original CTE is not inlined, adding "NOT MATERIALIZED" should force the inline.
   758  norm expect=InlineWith
   759  WITH foo AS NOT MATERIALIZED (SELECT 1/0) SELECT * FROM foo
   760  ----
   761  values
   762   ├── columns: "?column?":2
   763   ├── cardinality: [1 - 1]
   764   ├── immutable, side-effects
   765   ├── key: ()
   766   ├── fd: ()-->(2)
   767   └── (1 / 0,)
   768  
   769  # Original CTE is not inlined, adding "NOT MATERIALIZED" should force the inline.
   770  norm expect=InlineWith
   771  WITH foo AS NOT MATERIALIZED (SELECT 1) SELECT * FROM foo UNION ALL SELECT * FROM foo;
   772  ----
   773  union-all
   774   ├── columns: "?column?":4!null
   775   ├── left columns: "?column?":2
   776   ├── right columns: "?column?":3
   777   ├── cardinality: [2 - 2]
   778   ├── values
   779   │    ├── columns: "?column?":2!null
   780   │    ├── cardinality: [1 - 1]
   781   │    ├── key: ()
   782   │    ├── fd: ()-->(2)
   783   │    └── (1,)
   784   └── values
   785        ├── columns: "?column?":3!null
   786        ├── cardinality: [1 - 1]
   787        ├── key: ()
   788        ├── fd: ()-->(3)
   789        └── (1,)
   790  
   791  # Recursive CTEs should respect "MATERIALIZED".
   792  norm expect-not=InlineWith
   793  WITH RECURSIVE t(n) AS MATERIALIZED (VALUES (1) UNION ALL SELECT n+1 FROM t WHERE n < 100 ) SELECT sum(n) FROM t;
   794  ----
   795  with &2 (t)
   796   ├── columns: sum:6
   797   ├── materialized
   798   ├── cardinality: [1 - 1]
   799   ├── key: ()
   800   ├── fd: ()-->(6)
   801   ├── recursive-c-t-e
   802   │    ├── columns: n:2
   803   │    ├── working table binding: &1
   804   │    ├── initial columns: column1:1
   805   │    ├── recursive columns: "?column?":4
   806   │    ├── cardinality: [1 - ]
   807   │    ├── values
   808   │    │    ├── columns: column1:1!null
   809   │    │    ├── cardinality: [1 - 1]
   810   │    │    ├── key: ()
   811   │    │    ├── fd: ()-->(1)
   812   │    │    └── (1,)
   813   │    └── project
   814   │         ├── columns: "?column?":4!null
   815   │         ├── select
   816   │         │    ├── columns: n:3!null
   817   │         │    ├── with-scan &1 (t)
   818   │         │    │    ├── columns: n:3
   819   │         │    │    ├── mapping:
   820   │         │    │    │    └──  n:2 => n:3
   821   │         │    │    └── cardinality: [1 - ]
   822   │         │    └── filters
   823   │         │         └── n:3 < 100 [outer=(3), constraints=(/3: (/NULL - /99]; tight)]
   824   │         └── projections
   825   │              └── n:3 + 1 [as="?column?":4, outer=(3)]
   826   └── scalar-group-by
   827        ├── columns: sum:6
   828        ├── cardinality: [1 - 1]
   829        ├── key: ()
   830        ├── fd: ()-->(6)
   831        ├── with-scan &2 (t)
   832        │    ├── columns: n:5
   833        │    ├── mapping:
   834        │    │    └──  n:2 => n:5
   835        │    └── cardinality: [1 - ]
   836        └── aggregations
   837             └── sum [as=sum:6, outer=(5)]
   838                  └── n:5
   839  
   840  # Recursive CTEs should respect "NOT MATERIALIZED".
   841  norm expect=InlineWith
   842  WITH RECURSIVE t(n) AS NOT MATERIALIZED (VALUES (1) UNION ALL SELECT n+1 FROM t WHERE n < 100 ) SELECT sum(n) FROM t;
   843  ----
   844  scalar-group-by
   845   ├── columns: sum:6
   846   ├── cardinality: [1 - 1]
   847   ├── key: ()
   848   ├── fd: ()-->(6)
   849   ├── project
   850   │    ├── columns: n:5
   851   │    ├── cardinality: [1 - ]
   852   │    ├── recursive-c-t-e
   853   │    │    ├── columns: n:2
   854   │    │    ├── working table binding: &1
   855   │    │    ├── initial columns: column1:1
   856   │    │    ├── recursive columns: "?column?":4
   857   │    │    ├── cardinality: [1 - ]
   858   │    │    ├── values
   859   │    │    │    ├── columns: column1:1!null
   860   │    │    │    ├── cardinality: [1 - 1]
   861   │    │    │    ├── key: ()
   862   │    │    │    ├── fd: ()-->(1)
   863   │    │    │    └── (1,)
   864   │    │    └── project
   865   │    │         ├── columns: "?column?":4!null
   866   │    │         ├── select
   867   │    │         │    ├── columns: n:3!null
   868   │    │         │    ├── with-scan &1 (t)
   869   │    │         │    │    ├── columns: n:3
   870   │    │         │    │    ├── mapping:
   871   │    │         │    │    │    └──  n:2 => n:3
   872   │    │         │    │    └── cardinality: [1 - ]
   873   │    │         │    └── filters
   874   │    │         │         └── n:3 < 100 [outer=(3), constraints=(/3: (/NULL - /99]; tight)]
   875   │    │         └── projections
   876   │    │              └── n:3 + 1 [as="?column?":4, outer=(3)]
   877   │    └── projections
   878   │         └── n:2 [as=n:5, outer=(2)]
   879   └── aggregations
   880        └── sum [as=sum:6, outer=(5)]
   881             └── n:5