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