@@ -322,6 +322,7 @@ impl Unparser<'_> {
322
322
}
323
323
}
324
324
325
+ #[ cfg_attr( feature = "recursive_protection" , recursive:: recursive) ]
325
326
fn select_to_sql_recursively (
326
327
& self ,
327
328
plan : & LogicalPlan ,
@@ -566,14 +567,20 @@ impl Unparser<'_> {
566
567
}
567
568
LogicalPlan :: Join ( join) => {
568
569
let mut table_scan_filters = vec ! [ ] ;
570
+ let ( left_plan, right_plan) = match join. join_type {
571
+ JoinType :: RightSemi | JoinType :: RightAnti => {
572
+ ( & join. right , & join. left )
573
+ }
574
+ _ => ( & join. left , & join. right ) ,
575
+ } ;
569
576
570
577
let left_plan =
571
- match try_transform_to_simple_table_scan_with_filters ( & join . left ) ? {
578
+ match try_transform_to_simple_table_scan_with_filters ( left_plan ) ? {
572
579
Some ( ( plan, filters) ) => {
573
580
table_scan_filters. extend ( filters) ;
574
581
Arc :: new ( plan)
575
582
}
576
- None => Arc :: clone ( & join . left ) ,
583
+ None => Arc :: clone ( left_plan ) ,
577
584
} ;
578
585
579
586
self . select_to_sql_recursively (
@@ -584,12 +591,12 @@ impl Unparser<'_> {
584
591
) ?;
585
592
586
593
let right_plan =
587
- match try_transform_to_simple_table_scan_with_filters ( & join . right ) ? {
594
+ match try_transform_to_simple_table_scan_with_filters ( right_plan ) ? {
588
595
Some ( ( plan, filters) ) => {
589
596
table_scan_filters. extend ( filters) ;
590
597
Arc :: new ( plan)
591
598
}
592
- None => Arc :: clone ( & join . right ) ,
599
+ None => Arc :: clone ( right_plan ) ,
593
600
} ;
594
601
595
602
let mut right_relation = RelationBuilder :: default ( ) ;
@@ -641,19 +648,70 @@ impl Unparser<'_> {
641
648
& mut right_relation,
642
649
) ?;
643
650
644
- let Ok ( Some ( relation) ) = right_relation. build ( ) else {
645
- return internal_err ! ( "Failed to build right relation" ) ;
646
- } ;
647
-
648
- let ast_join = ast:: Join {
649
- relation,
650
- global : false ,
651
- join_operator : self
652
- . join_operator_to_sql ( join. join_type , join_constraint) ?,
651
+ match join. join_type {
652
+ JoinType :: LeftSemi
653
+ | JoinType :: LeftAnti
654
+ | JoinType :: LeftMark
655
+ | JoinType :: RightSemi
656
+ | JoinType :: RightAnti => {
657
+ let mut query_builder = QueryBuilder :: default ( ) ;
658
+ let mut from = TableWithJoinsBuilder :: default ( ) ;
659
+ let mut exists_select: SelectBuilder = SelectBuilder :: default ( ) ;
660
+ from. relation ( right_relation) ;
661
+ exists_select. push_from ( from) ;
662
+ if let Some ( filter) = & join. filter {
663
+ exists_select. selection ( Some ( self . expr_to_sql ( filter) ?) ) ;
664
+ }
665
+ for ( left, right) in & join. on {
666
+ exists_select. selection ( Some (
667
+ self . expr_to_sql ( & left. clone ( ) . eq ( right. clone ( ) ) ) ?,
668
+ ) ) ;
669
+ }
670
+ exists_select. projection ( vec ! [ ast:: SelectItem :: UnnamedExpr (
671
+ ast:: Expr :: Value ( ast:: Value :: Number ( "1" . to_string( ) , false ) ) ,
672
+ ) ] ) ;
673
+ query_builder. body ( Box :: new ( SetExpr :: Select ( Box :: new (
674
+ exists_select. build ( ) ?,
675
+ ) ) ) ) ;
676
+
677
+ let negated = match join. join_type {
678
+ JoinType :: LeftSemi
679
+ | JoinType :: RightSemi
680
+ | JoinType :: LeftMark => false ,
681
+ JoinType :: LeftAnti | JoinType :: RightAnti => true ,
682
+ _ => unreachable ! ( ) ,
683
+ } ;
684
+ let exists_expr = ast:: Expr :: Exists {
685
+ subquery : Box :: new ( query_builder. build ( ) ?) ,
686
+ negated,
687
+ } ;
688
+ if join. join_type == JoinType :: LeftMark {
689
+ let ( table_ref, _) = right_plan. schema ( ) . qualified_field ( 0 ) ;
690
+ let column = self
691
+ . col_to_sql ( & Column :: new ( table_ref. cloned ( ) , "mark" ) ) ?;
692
+ select. replace_mark ( & column, & exists_expr) ;
693
+ } else {
694
+ select. selection ( Some ( exists_expr) ) ;
695
+ }
696
+ }
697
+ JoinType :: Inner
698
+ | JoinType :: Left
699
+ | JoinType :: Right
700
+ | JoinType :: Full => {
701
+ let Ok ( Some ( relation) ) = right_relation. build ( ) else {
702
+ return internal_err ! ( "Failed to build right relation" ) ;
703
+ } ;
704
+ let ast_join = ast:: Join {
705
+ relation,
706
+ global : false ,
707
+ join_operator : self
708
+ . join_operator_to_sql ( join. join_type , join_constraint) ?,
709
+ } ;
710
+ let mut from = select. pop_from ( ) . unwrap ( ) ;
711
+ from. push_join ( ast_join) ;
712
+ select. push_from ( from) ;
713
+ }
653
714
} ;
654
- let mut from = select. pop_from ( ) . unwrap ( ) ;
655
- from. push_join ( ast_join) ;
656
- select. push_from ( from) ;
657
715
658
716
Ok ( ( ) )
659
717
}
0 commit comments