@@ -8458,3 +8458,294 @@ project
8458
8458
│ └── key: (8)
8459
8459
└── filters
8460
8460
└── x:8 = k:1 [outer=(1,8), constraints=(/1: (/NULL - ]; /8: (/NULL - ]), fd=(1)==(8), (8)==(1)]
8461
+
8462
+ # --------------------------------------------------
8463
+ # HoistUnboundJoinFilterFromExistsSubquery
8464
+ # --------------------------------------------------
8465
+
8466
+ norm expect=HoistUnboundJoinFilterFromExistsSubquery
8467
+ SELECT * FROM a WHERE EXISTS (
8468
+ SELECT * FROM xy INNER JOIN uv ON x = u AND a.i = 100
8469
+ );
8470
+ ----
8471
+ select
8472
+ ├── columns: k:1!null i:2!null f:3 s:4 j:5
8473
+ ├── key: (1)
8474
+ ├── fd: ()-->(2), (1)-->(3-5)
8475
+ ├── scan a
8476
+ │ ├── columns: k:1!null i:2 f:3 s:4 j:5
8477
+ │ ├── key: (1)
8478
+ │ └── fd: (1)-->(2-5)
8479
+ └── filters
8480
+ ├── coalesce [subquery]
8481
+ │ ├── subquery
8482
+ │ │ └── project
8483
+ │ │ ├── columns: column17:17!null
8484
+ │ │ ├── cardinality: [0 - 1]
8485
+ │ │ ├── key: ()
8486
+ │ │ ├── fd: ()-->(17)
8487
+ │ │ ├── limit
8488
+ │ │ │ ├── columns: x:8!null u:12!null
8489
+ │ │ │ ├── cardinality: [0 - 1]
8490
+ │ │ │ ├── key: ()
8491
+ │ │ │ ├── fd: ()-->(8,12), (8)==(12), (12)==(8)
8492
+ │ │ │ ├── inner-join (hash)
8493
+ │ │ │ │ ├── columns: x:8!null u:12!null
8494
+ │ │ │ │ ├── multiplicity: left-rows(zero-or-one), right-rows(zero-or-one)
8495
+ │ │ │ │ ├── key: (12)
8496
+ │ │ │ │ ├── fd: (8)==(12), (12)==(8)
8497
+ │ │ │ │ ├── limit hint: 1.00
8498
+ │ │ │ │ ├── scan xy
8499
+ │ │ │ │ │ ├── columns: x:8!null
8500
+ │ │ │ │ │ └── key: (8)
8501
+ │ │ │ │ ├── scan uv
8502
+ │ │ │ │ │ ├── columns: u:12!null
8503
+ │ │ │ │ │ └── key: (12)
8504
+ │ │ │ │ └── filters
8505
+ │ │ │ │ └── x:8 = u:12 [outer=(8,12), constraints=(/8: (/NULL - ]; /12: (/NULL - ]), fd=(8)==(12), (12)==(8)]
8506
+ │ │ │ └── 1
8507
+ │ │ └── projections
8508
+ │ │ └── true [as=column17:17]
8509
+ │ └── false
8510
+ └── i:2 = 100 [outer=(2), constraints=(/2: [/100 - /100]; tight), fd=()-->(2)]
8511
+
8512
+ norm expect=HoistUnboundJoinFilterFromExistsSubquery
8513
+ SELECT * FROM a WHERE EXISTS (
8514
+ SELECT * FROM xy INNER JOIN LATERAL (
8515
+ WITH foo(u, v) AS MATERIALIZED (SELECT * FROM uv WHERE y > 5) SELECT * FROM foo
8516
+ ) ON x = u AND a.i = 100
8517
+ );
8518
+ ----
8519
+ select
8520
+ ├── columns: k:1!null i:2!null f:3 s:4 j:5
8521
+ ├── key: (1)
8522
+ ├── fd: ()-->(2), (1)-->(3-5)
8523
+ ├── scan a
8524
+ │ ├── columns: k:1!null i:2 f:3 s:4 j:5
8525
+ │ ├── key: (1)
8526
+ │ └── fd: (1)-->(2-5)
8527
+ └── filters
8528
+ ├── coalesce [subquery]
8529
+ │ ├── subquery
8530
+ │ │ └── project
8531
+ │ │ ├── columns: column19:19!null
8532
+ │ │ ├── cardinality: [0 - 1]
8533
+ │ │ ├── key: ()
8534
+ │ │ ├── fd: ()-->(19)
8535
+ │ │ ├── limit
8536
+ │ │ │ ├── columns: x:8!null y:9 u:16!null
8537
+ │ │ │ ├── cardinality: [0 - 1]
8538
+ │ │ │ ├── key: ()
8539
+ │ │ │ ├── fd: ()-->(8,9,16), (8)==(16), (16)==(8)
8540
+ │ │ │ ├── inner-join-apply
8541
+ │ │ │ │ ├── columns: x:8!null y:9 u:16!null
8542
+ │ │ │ │ ├── key: (16)
8543
+ │ │ │ │ ├── fd: (8)-->(9), (8)==(16), (16)==(8)
8544
+ │ │ │ │ ├── limit hint: 1.00
8545
+ │ │ │ │ ├── scan xy
8546
+ │ │ │ │ │ ├── columns: x:8!null y:9
8547
+ │ │ │ │ │ ├── key: (8)
8548
+ │ │ │ │ │ └── fd: (8)-->(9)
8549
+ │ │ │ │ ├── with &1 (foo)
8550
+ │ │ │ │ │ ├── columns: u:16!null
8551
+ │ │ │ │ │ ├── materialized
8552
+ │ │ │ │ │ ├── outer: (9)
8553
+ │ │ │ │ │ ├── key: (16)
8554
+ │ │ │ │ │ ├── select
8555
+ │ │ │ │ │ │ ├── columns: uv.u:12!null uv.v:13
8556
+ │ │ │ │ │ │ ├── outer: (9)
8557
+ │ │ │ │ │ │ ├── key: (12)
8558
+ │ │ │ │ │ │ ├── fd: (12)-->(13)
8559
+ │ │ │ │ │ │ ├── scan uv
8560
+ │ │ │ │ │ │ │ ├── columns: uv.u:12!null uv.v:13
8561
+ │ │ │ │ │ │ │ ├── key: (12)
8562
+ │ │ │ │ │ │ │ └── fd: (12)-->(13)
8563
+ │ │ │ │ │ │ └── filters
8564
+ │ │ │ │ │ │ └── y:9 > 5 [outer=(9), constraints=(/9: [/6 - ]; tight)]
8565
+ │ │ │ │ │ └── with-scan &1 (foo)
8566
+ │ │ │ │ │ ├── columns: u:16!null
8567
+ │ │ │ │ │ ├── mapping:
8568
+ │ │ │ │ │ │ └── uv.u:12 => u:16
8569
+ │ │ │ │ │ └── key: (16)
8570
+ │ │ │ │ └── filters
8571
+ │ │ │ │ └── x:8 = u:16 [outer=(8,16), constraints=(/8: (/NULL - ]; /16: (/NULL - ]), fd=(8)==(16), (16)==(8)]
8572
+ │ │ │ └── 1
8573
+ │ │ └── projections
8574
+ │ │ └── true [as=column19:19]
8575
+ │ └── false
8576
+ └── i:2 = 100 [outer=(2), constraints=(/2: [/100 - /100]; tight), fd=()-->(2)]
8577
+
8578
+ norm expect=HoistUnboundJoinFilterFromExistsSubquery
8579
+ SELECT * FROM a WHERE EXISTS (
8580
+ SELECT * FROM xy WHERE EXISTS (
8581
+ SELECT * FROM uv WHERE x = u AND a.i = 100
8582
+ )
8583
+ );
8584
+ ----
8585
+ select
8586
+ ├── columns: k:1!null i:2!null f:3 s:4 j:5
8587
+ ├── key: (1)
8588
+ ├── fd: ()-->(2), (1)-->(3-5)
8589
+ ├── scan a
8590
+ │ ├── columns: k:1!null i:2 f:3 s:4 j:5
8591
+ │ ├── key: (1)
8592
+ │ └── fd: (1)-->(2-5)
8593
+ └── filters
8594
+ ├── coalesce [subquery]
8595
+ │ ├── subquery
8596
+ │ │ └── project
8597
+ │ │ ├── columns: column18:18!null
8598
+ │ │ ├── cardinality: [0 - 1]
8599
+ │ │ ├── key: ()
8600
+ │ │ ├── fd: ()-->(18)
8601
+ │ │ ├── limit
8602
+ │ │ │ ├── columns: x:8!null
8603
+ │ │ │ ├── cardinality: [0 - 1]
8604
+ │ │ │ ├── key: ()
8605
+ │ │ │ ├── fd: ()-->(8)
8606
+ │ │ │ ├── semi-join (hash)
8607
+ │ │ │ │ ├── columns: x:8!null
8608
+ │ │ │ │ ├── key: (8)
8609
+ │ │ │ │ ├── limit hint: 1.00
8610
+ │ │ │ │ ├── scan xy
8611
+ │ │ │ │ │ ├── columns: x:8!null
8612
+ │ │ │ │ │ └── key: (8)
8613
+ │ │ │ │ ├── scan uv
8614
+ │ │ │ │ │ ├── columns: u:12!null
8615
+ │ │ │ │ │ └── key: (12)
8616
+ │ │ │ │ └── filters
8617
+ │ │ │ │ └── x:8 = u:12 [outer=(8,12), constraints=(/8: (/NULL - ]; /12: (/NULL - ]), fd=(8)==(12), (12)==(8)]
8618
+ │ │ │ └── 1
8619
+ │ │ └── projections
8620
+ │ │ └── true [as=column18:18]
8621
+ │ └── false
8622
+ └── i:2 = 100 [outer=(2), constraints=(/2: [/100 - /100]; tight), fd=()-->(2)]
8623
+
8624
+ norm expect=HoistUnboundJoinFilterFromExistsSubquery
8625
+ SELECT * FROM a WHERE EXISTS (
8626
+ SELECT * FROM xy WHERE EXISTS (
8627
+ SELECT * FROM (
8628
+ WITH foo(u, v) AS MATERIALIZED (SELECT * FROM uv WHERE y > 5) SELECT * FROM foo
8629
+ ) WHERE x = u AND a.i = 100
8630
+ )
8631
+ );
8632
+ ----
8633
+ select
8634
+ ├── columns: k:1!null i:2!null f:3 s:4 j:5
8635
+ ├── key: (1)
8636
+ ├── fd: ()-->(2), (1)-->(3-5)
8637
+ ├── scan a
8638
+ │ ├── columns: k:1!null i:2 f:3 s:4 j:5
8639
+ │ ├── key: (1)
8640
+ │ └── fd: (1)-->(2-5)
8641
+ └── filters
8642
+ ├── coalesce [subquery]
8643
+ │ ├── subquery
8644
+ │ │ └── project
8645
+ │ │ ├── columns: column20:20!null
8646
+ │ │ ├── cardinality: [0 - 1]
8647
+ │ │ ├── key: ()
8648
+ │ │ ├── fd: ()-->(20)
8649
+ │ │ ├── limit
8650
+ │ │ │ ├── columns: x:8!null y:9
8651
+ │ │ │ ├── cardinality: [0 - 1]
8652
+ │ │ │ ├── key: ()
8653
+ │ │ │ ├── fd: ()-->(8,9)
8654
+ │ │ │ ├── semi-join-apply
8655
+ │ │ │ │ ├── columns: x:8!null y:9
8656
+ │ │ │ │ ├── key: (8)
8657
+ │ │ │ │ ├── fd: (8)-->(9)
8658
+ │ │ │ │ ├── limit hint: 1.00
8659
+ │ │ │ │ ├── scan xy
8660
+ │ │ │ │ │ ├── columns: x:8!null y:9
8661
+ │ │ │ │ │ ├── key: (8)
8662
+ │ │ │ │ │ └── fd: (8)-->(9)
8663
+ │ │ │ │ ├── with &1 (foo)
8664
+ │ │ │ │ │ ├── columns: u:16!null
8665
+ │ │ │ │ │ ├── materialized
8666
+ │ │ │ │ │ ├── outer: (9)
8667
+ │ │ │ │ │ ├── key: (16)
8668
+ │ │ │ │ │ ├── select
8669
+ │ │ │ │ │ │ ├── columns: uv.u:12!null uv.v:13
8670
+ │ │ │ │ │ │ ├── outer: (9)
8671
+ │ │ │ │ │ │ ├── key: (12)
8672
+ │ │ │ │ │ │ ├── fd: (12)-->(13)
8673
+ │ │ │ │ │ │ ├── scan uv
8674
+ │ │ │ │ │ │ │ ├── columns: uv.u:12!null uv.v:13
8675
+ │ │ │ │ │ │ │ ├── key: (12)
8676
+ │ │ │ │ │ │ │ └── fd: (12)-->(13)
8677
+ │ │ │ │ │ │ └── filters
8678
+ │ │ │ │ │ │ └── y:9 > 5 [outer=(9), constraints=(/9: [/6 - ]; tight)]
8679
+ │ │ │ │ │ └── with-scan &1 (foo)
8680
+ │ │ │ │ │ ├── columns: u:16!null
8681
+ │ │ │ │ │ ├── mapping:
8682
+ │ │ │ │ │ │ └── uv.u:12 => u:16
8683
+ │ │ │ │ │ └── key: (16)
8684
+ │ │ │ │ └── filters
8685
+ │ │ │ │ └── x:8 = u:16 [outer=(8,16), constraints=(/8: (/NULL - ]; /16: (/NULL - ]), fd=(8)==(16), (16)==(8)]
8686
+ │ │ │ └── 1
8687
+ │ │ └── projections
8688
+ │ │ └── true [as=column20:20]
8689
+ │ └── false
8690
+ └── i:2 = 100 [outer=(2), constraints=(/2: [/100 - /100]; tight), fd=()-->(2)]
8691
+
8692
+ # No-op because of the left-join.
8693
+ norm expect-not=HoistUnboundJoinFilterFromExistsSubquery
8694
+ SELECT * FROM a WHERE EXISTS (
8695
+ SELECT * FROM xy LEFT JOIN uv ON x = u AND a.i = 100
8696
+ );
8697
+ ----
8698
+ semi-join-apply
8699
+ ├── columns: k:1!null i:2 f:3 s:4 j:5
8700
+ ├── key: (1)
8701
+ ├── fd: (1)-->(2-5)
8702
+ ├── scan a
8703
+ │ ├── columns: k:1!null i:2 f:3 s:4 j:5
8704
+ │ ├── key: (1)
8705
+ │ └── fd: (1)-->(2-5)
8706
+ ├── left-join (hash)
8707
+ │ ├── columns: x:8!null u:12
8708
+ │ ├── outer: (2)
8709
+ │ ├── multiplicity: left-rows(exactly-one), right-rows(zero-or-one)
8710
+ │ ├── key: (8)
8711
+ │ ├── fd: (8)-->(12)
8712
+ │ ├── scan xy
8713
+ │ │ ├── columns: x:8!null
8714
+ │ │ └── key: (8)
8715
+ │ ├── scan uv
8716
+ │ │ ├── columns: u:12!null
8717
+ │ │ └── key: (12)
8718
+ │ └── filters
8719
+ │ ├── x:8 = u:12 [outer=(8,12), constraints=(/8: (/NULL - ]; /12: (/NULL - ]), fd=(8)==(12), (12)==(8)]
8720
+ │ └── i:2 = 100 [outer=(2), constraints=(/2: [/100 - /100]; tight), fd=()-->(2)]
8721
+ └── filters (true)
8722
+
8723
+ # No-op because of the full-join.
8724
+ norm expect-not=HoistUnboundJoinFilterFromExistsSubquery
8725
+ SELECT * FROM a WHERE EXISTS (
8726
+ SELECT * FROM xy FULL JOIN uv ON x = u AND a.i = 100
8727
+ );
8728
+ ----
8729
+ semi-join-apply
8730
+ ├── columns: k:1!null i:2 f:3 s:4 j:5
8731
+ ├── key: (1)
8732
+ ├── fd: (1)-->(2-5)
8733
+ ├── scan a
8734
+ │ ├── columns: k:1!null i:2 f:3 s:4 j:5
8735
+ │ ├── key: (1)
8736
+ │ └── fd: (1)-->(2-5)
8737
+ ├── full-join (hash)
8738
+ │ ├── columns: x:8 u:12
8739
+ │ ├── outer: (2)
8740
+ │ ├── multiplicity: left-rows(exactly-one), right-rows(exactly-one)
8741
+ │ ├── key: (8,12)
8742
+ │ ├── scan xy
8743
+ │ │ ├── columns: x:8!null
8744
+ │ │ └── key: (8)
8745
+ │ ├── scan uv
8746
+ │ │ ├── columns: u:12!null
8747
+ │ │ └── key: (12)
8748
+ │ └── filters
8749
+ │ ├── x:8 = u:12 [outer=(8,12), constraints=(/8: (/NULL - ]; /12: (/NULL - ]), fd=(8)==(12), (12)==(8)]
8750
+ │ └── i:2 = 100 [outer=(2), constraints=(/2: [/100 - /100]; tight), fd=()-->(2)]
8751
+ └── filters (true)
0 commit comments