jupyter-duckdb 1.4.105__py3-none-any.whl → 1.4.106__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -8,7 +8,7 @@ class And(LogicOperator):
8
8
 
9
9
  @staticmethod
10
10
  def symbols() -> Tuple[str, ...]:
11
- return '∧', 'and', 'and'
11
+ return '∧', 'and'
12
12
 
13
13
  @property
14
14
  def sql_symbol(self) -> str:
@@ -8,7 +8,7 @@ from ...util.RenamableColumnList import RenamableColumnList
8
8
  class Cross(RABinaryOperator):
9
9
  @staticmethod
10
10
  def symbols() -> Tuple[str, ...]:
11
- return chr(215), 'x'
11
+ return chr(215), 'x', 'times'
12
12
 
13
13
  def to_sql(self, tables: Dict[str, Table]) -> Tuple[str, RenamableColumnList]:
14
14
  # execute subqueries
@@ -0,0 +1,24 @@
1
+ from typing import Tuple, Dict
2
+
3
+ from duckdb_kernel.db import Table
4
+ from ..RABinaryOperator import RABinaryOperator
5
+ from ...util.RenamableColumnList import RenamableColumnList
6
+
7
+
8
+ class LeftSemiJoin(RABinaryOperator):
9
+ @staticmethod
10
+ def symbols() -> Tuple[str, ...]:
11
+ return chr(8905), 'lsjoin'
12
+
13
+ def to_sql(self, tables: Dict[str, Table]) -> Tuple[str, RenamableColumnList]:
14
+ # execute subqueries
15
+ lq, lcols = self.left.to_sql(tables)
16
+ rq, rcols = self.right.to_sql(tables)
17
+
18
+ # find matching columns
19
+ join_cols, all_cols = lcols.intersect(rcols)
20
+
21
+ on_clause = ' AND '.join(f'{l.current_name} = {r.current_name}' for l, r in join_cols)
22
+
23
+ # create sql
24
+ return f'SELECT {lcols.list} FROM ({lq}) {self._name()} JOIN ({rq}) {self._name()} ON {on_clause}', lcols
@@ -0,0 +1,24 @@
1
+ from typing import Tuple, Dict
2
+
3
+ from duckdb_kernel.db import Table
4
+ from ..RABinaryOperator import RABinaryOperator
5
+ from ...util.RenamableColumnList import RenamableColumnList
6
+
7
+
8
+ class RightSemiJoin(RABinaryOperator):
9
+ @staticmethod
10
+ def symbols() -> Tuple[str, ...]:
11
+ return chr(8906), 'rsjoin'
12
+
13
+ def to_sql(self, tables: Dict[str, Table]) -> Tuple[str, RenamableColumnList]:
14
+ # execute subqueries
15
+ lq, lcols = self.left.to_sql(tables)
16
+ rq, rcols = self.right.to_sql(tables)
17
+
18
+ # find matching columns
19
+ join_cols, all_cols = lcols.intersect(rcols, prefer_right=True)
20
+
21
+ on_clause = ' AND '.join(f'{l.current_name} = {r.current_name}' for l, r in join_cols)
22
+
23
+ # create sql
24
+ return f'SELECT {rcols.list} FROM ({lq}) {self._name()} JOIN ({rq}) {self._name()} ON {on_clause}', rcols
@@ -3,7 +3,9 @@ from .Difference import Difference
3
3
  from .Intersection import Intersection
4
4
  from .Join import Join
5
5
  from .LeftOuterJoin import LeftOuterJoin
6
+ from .LeftSemiJoin import LeftSemiJoin
6
7
  from .RightOuterJoin import RightOuterJoin
8
+ from .RightSemiJoin import RightSemiJoin
7
9
  from .FullOuterJoin import FullOuterJoin
8
10
  from .Union import Union
9
11
 
@@ -37,7 +39,7 @@ RA_BINARY_OPERATORS = [
37
39
  [Union],
38
40
  [Intersection],
39
41
  [Join],
40
- [LeftOuterJoin, RightOuterJoin, FullOuterJoin],
42
+ [LeftOuterJoin, RightOuterJoin, FullOuterJoin, LeftSemiJoin, RightSemiJoin],
41
43
  [Cross],
42
44
  [Division]
43
45
  ]
@@ -105,6 +105,7 @@ def test_comments():
105
105
  def test_binary_operator_cross():
106
106
  for query in (
107
107
  r'Shows x Seasons',
108
+ r'Shows times Seasons',
108
109
  ):
109
110
  root = RAParser.parse_query(query)
110
111
 
@@ -315,6 +316,52 @@ def test_binary_operator_fjoin():
315
316
  ]
316
317
 
317
318
 
319
+ def test_binary_operator_lsjoin():
320
+ for query in (
321
+ r'Users ⋉ BannedUsers',
322
+ r'Users lsjoin BannedUsers'
323
+ ):
324
+ root = RAParser.parse_query(query)
325
+
326
+ assert isinstance(root, BinaryOperators.LeftSemiJoin)
327
+ assert isinstance(root.left, RAOperand) and root.left.name == 'Users'
328
+ assert isinstance(root.right, RAOperand) and root.right.name == 'BannedUsers'
329
+
330
+ with Connection() as con:
331
+ cols, rows = con.execute_ra_return_cols(root)
332
+
333
+ assert [c.lower() for c in cols] == [
334
+ 'id',
335
+ 'username'
336
+ ]
337
+ assert rows == [
338
+ (2, 'Bob')
339
+ ]
340
+
341
+
342
+ def test_binary_operator_rsjoin():
343
+ for query in (
344
+ r'Users ⋊ BannedUsers',
345
+ r'Users rsjoin BannedUsers'
346
+ ):
347
+ root = RAParser.parse_query(query)
348
+
349
+ assert isinstance(root, BinaryOperators.RightSemiJoin)
350
+ assert isinstance(root.left, RAOperand) and root.left.name == 'Users'
351
+ assert isinstance(root.right, RAOperand) and root.right.name == 'BannedUsers'
352
+
353
+ with Connection() as con:
354
+ cols, rows = con.execute_ra_return_cols(root)
355
+
356
+ assert [c.lower() for c in cols] == [
357
+ 'id',
358
+ 'bannedusername'
359
+ ]
360
+ assert rows == [
361
+ (2, 'Bob')
362
+ ]
363
+
364
+
318
365
  def test_binary_operator_union():
319
366
  for query in (
320
367
  r'Users ∪ BannedUsers',
@@ -589,7 +636,7 @@ def test_binary_left_to_right_evaluation_order():
589
636
  assert root.right.name == 'c'
590
637
 
591
638
  # outer join
592
- root = RAParser.parse_query(r'a ⟕ b ⟕ c')
639
+ root = RAParser.parse_query(r'a ⟕ b ⟕ c') # left outer, left outer
593
640
  assert isinstance(root, BinaryOperators.LeftOuterJoin)
594
641
  assert isinstance(root.left, BinaryOperators.LeftOuterJoin)
595
642
  assert isinstance(root.left.left, RAOperand)
@@ -599,7 +646,7 @@ def test_binary_left_to_right_evaluation_order():
599
646
  assert isinstance(root.right, RAOperand)
600
647
  assert root.right.name == 'c'
601
648
 
602
- root = RAParser.parse_query(r'a ⟖ b ⟖ c')
649
+ root = RAParser.parse_query(r'a ⟖ b ⟖ c') # right outer, right outer
603
650
  assert isinstance(root, BinaryOperators.RightOuterJoin)
604
651
  assert isinstance(root.left, BinaryOperators.RightOuterJoin)
605
652
  assert isinstance(root.left.left, RAOperand)
@@ -609,7 +656,7 @@ def test_binary_left_to_right_evaluation_order():
609
656
  assert isinstance(root.right, RAOperand)
610
657
  assert root.right.name == 'c'
611
658
 
612
- root = RAParser.parse_query(r'a ⟗ b ⟗ c')
659
+ root = RAParser.parse_query(r'a ⟗ b ⟗ c') # full outer, full outer
613
660
  assert isinstance(root, BinaryOperators.FullOuterJoin)
614
661
  assert isinstance(root.left, BinaryOperators.FullOuterJoin)
615
662
  assert isinstance(root.left.left, RAOperand)
@@ -619,8 +666,29 @@ def test_binary_left_to_right_evaluation_order():
619
666
  assert isinstance(root.right, RAOperand)
620
667
  assert root.right.name == 'c'
621
668
 
622
- # mixed outer joins
623
- root = RAParser.parse_query(r'a b c')
669
+ # semi join
670
+ root = RAParser.parse_query(r'a b c') # left semi, left semi
671
+ assert isinstance(root, BinaryOperators.LeftSemiJoin)
672
+ assert isinstance(root.left, BinaryOperators.LeftSemiJoin)
673
+ assert isinstance(root.left.left, RAOperand)
674
+ assert root.left.left.name == 'a'
675
+ assert isinstance(root.left.right, RAOperand)
676
+ assert root.left.right.name == 'b'
677
+ assert isinstance(root.right, RAOperand)
678
+ assert root.right.name == 'c'
679
+
680
+ root = RAParser.parse_query(r'a ⋊ b ⋊ c') # right semi, right semi
681
+ assert isinstance(root, BinaryOperators.RightSemiJoin)
682
+ assert isinstance(root.left, BinaryOperators.RightSemiJoin)
683
+ assert isinstance(root.left.left, RAOperand)
684
+ assert root.left.left.name == 'a'
685
+ assert isinstance(root.left.right, RAOperand)
686
+ assert root.left.right.name == 'b'
687
+ assert isinstance(root.right, RAOperand)
688
+ assert root.right.name == 'c'
689
+
690
+ # mixed outer and semi joins
691
+ root = RAParser.parse_query(r'a ⟕ b ⟖ c') # left outer, right outer
624
692
  assert isinstance(root, BinaryOperators.RightOuterJoin)
625
693
  assert isinstance(root.left, BinaryOperators.LeftOuterJoin)
626
694
  assert isinstance(root.left.left, RAOperand)
@@ -630,7 +698,7 @@ def test_binary_left_to_right_evaluation_order():
630
698
  assert isinstance(root.right, RAOperand)
631
699
  assert root.right.name == 'c'
632
700
 
633
- root = RAParser.parse_query(r'a ⟕ b ⟗ c')
701
+ root = RAParser.parse_query(r'a ⟕ b ⟗ c') # left outer, full outer
634
702
  assert isinstance(root, BinaryOperators.FullOuterJoin)
635
703
  assert isinstance(root.left, BinaryOperators.LeftOuterJoin)
636
704
  assert isinstance(root.left.left, RAOperand)
@@ -640,7 +708,27 @@ def test_binary_left_to_right_evaluation_order():
640
708
  assert isinstance(root.right, RAOperand)
641
709
  assert root.right.name == 'c'
642
710
 
643
- root = RAParser.parse_query(r'a b c')
711
+ root = RAParser.parse_query(r'a b c') # left outer, left semi
712
+ assert isinstance(root, BinaryOperators.LeftSemiJoin)
713
+ assert isinstance(root.left, BinaryOperators.LeftOuterJoin)
714
+ assert isinstance(root.left.left, RAOperand)
715
+ assert root.left.left.name == 'a'
716
+ assert isinstance(root.left.right, RAOperand)
717
+ assert root.left.right.name == 'b'
718
+ assert isinstance(root.right, RAOperand)
719
+ assert root.right.name == 'c'
720
+
721
+ root = RAParser.parse_query(r'a ⟕ b ⋊ c') # left outer, right semi
722
+ assert isinstance(root, BinaryOperators.RightSemiJoin)
723
+ assert isinstance(root.left, BinaryOperators.LeftOuterJoin)
724
+ assert isinstance(root.left.left, RAOperand)
725
+ assert root.left.left.name == 'a'
726
+ assert isinstance(root.left.right, RAOperand)
727
+ assert root.left.right.name == 'b'
728
+ assert isinstance(root.right, RAOperand)
729
+ assert root.right.name == 'c'
730
+
731
+ root = RAParser.parse_query(r'a ⟖ b ⟕ c') # right outer, left outer
644
732
  assert isinstance(root, BinaryOperators.LeftOuterJoin)
645
733
  assert isinstance(root.left, BinaryOperators.RightOuterJoin)
646
734
  assert isinstance(root.left.left, RAOperand)
@@ -650,7 +738,7 @@ def test_binary_left_to_right_evaluation_order():
650
738
  assert isinstance(root.right, RAOperand)
651
739
  assert root.right.name == 'c'
652
740
 
653
- root = RAParser.parse_query(r'a ⟖ b ⟗ c')
741
+ root = RAParser.parse_query(r'a ⟖ b ⟗ c') # right outer, full outer
654
742
  assert isinstance(root, BinaryOperators.FullOuterJoin)
655
743
  assert isinstance(root.left, BinaryOperators.RightOuterJoin)
656
744
  assert isinstance(root.left.left, RAOperand)
@@ -660,7 +748,27 @@ def test_binary_left_to_right_evaluation_order():
660
748
  assert isinstance(root.right, RAOperand)
661
749
  assert root.right.name == 'c'
662
750
 
663
- root = RAParser.parse_query(r'a b c')
751
+ root = RAParser.parse_query(r'a b c') # right outer, left semi
752
+ assert isinstance(root, BinaryOperators.LeftSemiJoin)
753
+ assert isinstance(root.left, BinaryOperators.RightOuterJoin)
754
+ assert isinstance(root.left.left, RAOperand)
755
+ assert root.left.left.name == 'a'
756
+ assert isinstance(root.left.right, RAOperand)
757
+ assert root.left.right.name == 'b'
758
+ assert isinstance(root.right, RAOperand)
759
+ assert root.right.name == 'c'
760
+
761
+ root = RAParser.parse_query(r'a ⟖ b ⋊ c') # right outer, right semi
762
+ assert isinstance(root, BinaryOperators.RightSemiJoin)
763
+ assert isinstance(root.left, BinaryOperators.RightOuterJoin)
764
+ assert isinstance(root.left.left, RAOperand)
765
+ assert root.left.left.name == 'a'
766
+ assert isinstance(root.left.right, RAOperand)
767
+ assert root.left.right.name == 'b'
768
+ assert isinstance(root.right, RAOperand)
769
+ assert root.right.name == 'c'
770
+
771
+ root = RAParser.parse_query(r'a ⟗ b ⟕ c') # full outer, left outer
664
772
  assert isinstance(root, BinaryOperators.LeftOuterJoin)
665
773
  assert isinstance(root.left, BinaryOperators.FullOuterJoin)
666
774
  assert isinstance(root.left.left, RAOperand)
@@ -670,7 +778,7 @@ def test_binary_left_to_right_evaluation_order():
670
778
  assert isinstance(root.right, RAOperand)
671
779
  assert root.right.name == 'c'
672
780
 
673
- root = RAParser.parse_query(r'a ⟗ b ⟖ c')
781
+ root = RAParser.parse_query(r'a ⟗ b ⟖ c') # full outer, right outer
674
782
  assert isinstance(root, BinaryOperators.RightOuterJoin)
675
783
  assert isinstance(root.left, BinaryOperators.FullOuterJoin)
676
784
  assert isinstance(root.left.left, RAOperand)
@@ -680,6 +788,106 @@ def test_binary_left_to_right_evaluation_order():
680
788
  assert isinstance(root.right, RAOperand)
681
789
  assert root.right.name == 'c'
682
790
 
791
+ root = RAParser.parse_query(r'a ⟗ b ⋉ c') # full outer, left semi
792
+ assert isinstance(root, BinaryOperators.LeftSemiJoin)
793
+ assert isinstance(root.left, BinaryOperators.FullOuterJoin)
794
+ assert isinstance(root.left.left, RAOperand)
795
+ assert root.left.left.name == 'a'
796
+ assert isinstance(root.left.right, RAOperand)
797
+ assert root.left.right.name == 'b'
798
+ assert isinstance(root.right, RAOperand)
799
+ assert root.right.name == 'c'
800
+
801
+ root = RAParser.parse_query(r'a ⟗ b ⋊ c') # full outer, right semi
802
+ assert isinstance(root, BinaryOperators.RightSemiJoin)
803
+ assert isinstance(root.left, BinaryOperators.FullOuterJoin)
804
+ assert isinstance(root.left.left, RAOperand)
805
+ assert root.left.left.name == 'a'
806
+ assert isinstance(root.left.right, RAOperand)
807
+ assert root.left.right.name == 'b'
808
+ assert isinstance(root.right, RAOperand)
809
+ assert root.right.name == 'c'
810
+
811
+ root = RAParser.parse_query(r'a ⋉ b ⟕ c') # left semi, left outer
812
+ assert isinstance(root, BinaryOperators.LeftOuterJoin)
813
+ assert isinstance(root.left, BinaryOperators.LeftSemiJoin)
814
+ assert isinstance(root.left.left, RAOperand)
815
+ assert root.left.left.name == 'a'
816
+ assert isinstance(root.left.right, RAOperand)
817
+ assert root.left.right.name == 'b'
818
+ assert isinstance(root.right, RAOperand)
819
+ assert root.right.name == 'c'
820
+
821
+ root = RAParser.parse_query(r'a ⋉ b ⟖ c') # left semi, right outer
822
+ assert isinstance(root, BinaryOperators.RightOuterJoin)
823
+ assert isinstance(root.left, BinaryOperators.LeftSemiJoin)
824
+ assert isinstance(root.left.left, RAOperand)
825
+ assert root.left.left.name == 'a'
826
+ assert isinstance(root.left.right, RAOperand)
827
+ assert root.left.right.name == 'b'
828
+ assert isinstance(root.right, RAOperand)
829
+ assert root.right.name == 'c'
830
+
831
+ root = RAParser.parse_query(r'a ⋉ b ⟗ c') # left semi, full outer
832
+ assert isinstance(root, BinaryOperators.FullOuterJoin)
833
+ assert isinstance(root.left, BinaryOperators.LeftSemiJoin)
834
+ assert isinstance(root.left.left, RAOperand)
835
+ assert root.left.left.name == 'a'
836
+ assert isinstance(root.left.right, RAOperand)
837
+ assert root.left.right.name == 'b'
838
+ assert isinstance(root.right, RAOperand)
839
+ assert root.right.name == 'c'
840
+
841
+ root = RAParser.parse_query(r'a ⋉ b ⋊ c') # left semi, right semi
842
+ assert isinstance(root, BinaryOperators.RightSemiJoin)
843
+ assert isinstance(root.left, BinaryOperators.LeftSemiJoin)
844
+ assert isinstance(root.left.left, RAOperand)
845
+ assert root.left.left.name == 'a'
846
+ assert isinstance(root.left.right, RAOperand)
847
+ assert root.left.right.name == 'b'
848
+ assert isinstance(root.right, RAOperand)
849
+ assert root.right.name == 'c'
850
+
851
+ root = RAParser.parse_query(r'a ⋊ b ⟕ c') # right semi, left outer
852
+ assert isinstance(root, BinaryOperators.LeftOuterJoin)
853
+ assert isinstance(root.left, BinaryOperators.RightSemiJoin)
854
+ assert isinstance(root.left.left, RAOperand)
855
+ assert root.left.left.name == 'a'
856
+ assert isinstance(root.left.right, RAOperand)
857
+ assert root.left.right.name == 'b'
858
+ assert isinstance(root.right, RAOperand)
859
+ assert root.right.name == 'c'
860
+
861
+ root = RAParser.parse_query(r'a ⋊ b ⟖ c') # right semi, right outer
862
+ assert isinstance(root, BinaryOperators.RightOuterJoin)
863
+ assert isinstance(root.left, BinaryOperators.RightSemiJoin)
864
+ assert isinstance(root.left.left, RAOperand)
865
+ assert root.left.left.name == 'a'
866
+ assert isinstance(root.left.right, RAOperand)
867
+ assert root.left.right.name == 'b'
868
+ assert isinstance(root.right, RAOperand)
869
+ assert root.right.name == 'c'
870
+
871
+ root = RAParser.parse_query(r'a ⋊ b ⟗ c') # right semi, full outer
872
+ assert isinstance(root, BinaryOperators.FullOuterJoin)
873
+ assert isinstance(root.left, BinaryOperators.RightSemiJoin)
874
+ assert isinstance(root.left.left, RAOperand)
875
+ assert root.left.left.name == 'a'
876
+ assert isinstance(root.left.right, RAOperand)
877
+ assert root.left.right.name == 'b'
878
+ assert isinstance(root.right, RAOperand)
879
+ assert root.right.name == 'c'
880
+
881
+ root = RAParser.parse_query(r'a ⋊ b ⋉ c') # right semi, left semi
882
+ assert isinstance(root, BinaryOperators.LeftSemiJoin)
883
+ assert isinstance(root.left, BinaryOperators.RightSemiJoin)
884
+ assert isinstance(root.left.left, RAOperand)
885
+ assert root.left.left.name == 'a'
886
+ assert isinstance(root.left.right, RAOperand)
887
+ assert root.left.right.name == 'b'
888
+ assert isinstance(root.right, RAOperand)
889
+ assert root.right.name == 'c'
890
+
683
891
  # cross join
684
892
  root = RAParser.parse_query(r'a x b x c')
685
893
  assert isinstance(root, BinaryOperators.Cross)
@@ -770,6 +978,22 @@ def test_binary_evaluation_order():
770
978
  assert isinstance(root, BinaryOperators.Difference)
771
979
  assert isinstance(root.right, RAOperand) and isinstance(root.left, BinaryOperators.FullOuterJoin)
772
980
 
981
+ root = RAParser.parse_query(r'a \ b ⋉ c')
982
+ assert isinstance(root, BinaryOperators.Difference)
983
+ assert isinstance(root.left, RAOperand) and isinstance(root.right, BinaryOperators.LeftSemiJoin)
984
+
985
+ root = RAParser.parse_query(r'a ⋉ b \ c')
986
+ assert isinstance(root, BinaryOperators.Difference)
987
+ assert isinstance(root.right, RAOperand) and isinstance(root.left, BinaryOperators.LeftSemiJoin)
988
+
989
+ root = RAParser.parse_query(r'a \ b ⋊ c')
990
+ assert isinstance(root, BinaryOperators.Difference)
991
+ assert isinstance(root.left, RAOperand) and isinstance(root.right, BinaryOperators.RightSemiJoin)
992
+
993
+ root = RAParser.parse_query(r'a ⋊ b \ c')
994
+ assert isinstance(root, BinaryOperators.Difference)
995
+ assert isinstance(root.right, RAOperand) and isinstance(root.left, BinaryOperators.RightSemiJoin)
996
+
773
997
  # difference <-> cross
774
998
  root = RAParser.parse_query(r'a \ b x c')
775
999
  assert isinstance(root, BinaryOperators.Difference)
@@ -830,6 +1054,22 @@ def test_binary_evaluation_order():
830
1054
  assert isinstance(root, BinaryOperators.Union)
831
1055
  assert isinstance(root.right, RAOperand) and isinstance(root.left, BinaryOperators.FullOuterJoin)
832
1056
 
1057
+ root = RAParser.parse_query(r'a ∪ b ⋉ c')
1058
+ assert isinstance(root, BinaryOperators.Union)
1059
+ assert isinstance(root.left, RAOperand) and isinstance(root.right, BinaryOperators.LeftSemiJoin)
1060
+
1061
+ root = RAParser.parse_query(r'a ⋉ b ∪ c')
1062
+ assert isinstance(root, BinaryOperators.Union)
1063
+ assert isinstance(root.right, RAOperand) and isinstance(root.left, BinaryOperators.LeftSemiJoin)
1064
+
1065
+ root = RAParser.parse_query(r'a ∪ b ⋊ c')
1066
+ assert isinstance(root, BinaryOperators.Union)
1067
+ assert isinstance(root.left, RAOperand) and isinstance(root.right, BinaryOperators.RightSemiJoin)
1068
+
1069
+ root = RAParser.parse_query(r'a ⋊ b ∪ c')
1070
+ assert isinstance(root, BinaryOperators.Union)
1071
+ assert isinstance(root.right, RAOperand) and isinstance(root.left, BinaryOperators.RightSemiJoin)
1072
+
833
1073
  # union <-> cross
834
1074
  root = RAParser.parse_query(r'a ∪ b x c')
835
1075
  assert isinstance(root, BinaryOperators.Union)
@@ -881,6 +1121,22 @@ def test_binary_evaluation_order():
881
1121
  assert isinstance(root, BinaryOperators.Intersection)
882
1122
  assert isinstance(root.right, RAOperand) and isinstance(root.left, BinaryOperators.FullOuterJoin)
883
1123
 
1124
+ root = RAParser.parse_query(r'a ∩ b ⋉ c')
1125
+ assert isinstance(root, BinaryOperators.Intersection)
1126
+ assert isinstance(root.left, RAOperand) and isinstance(root.right, BinaryOperators.LeftSemiJoin)
1127
+
1128
+ root = RAParser.parse_query(r'a ⋉ b ∩ c')
1129
+ assert isinstance(root, BinaryOperators.Intersection)
1130
+ assert isinstance(root.right, RAOperand) and isinstance(root.left, BinaryOperators.LeftSemiJoin)
1131
+
1132
+ root = RAParser.parse_query(r'a ∩ b ⋊ c')
1133
+ assert isinstance(root, BinaryOperators.Intersection)
1134
+ assert isinstance(root.left, RAOperand) and isinstance(root.right, BinaryOperators.RightSemiJoin)
1135
+
1136
+ root = RAParser.parse_query(r'a ⋊ b ∩ c')
1137
+ assert isinstance(root, BinaryOperators.Intersection)
1138
+ assert isinstance(root.right, RAOperand) and isinstance(root.left, BinaryOperators.RightSemiJoin)
1139
+
884
1140
  # intersection <-> cross
885
1141
  root = RAParser.parse_query(r'a ∩ b x c')
886
1142
  assert isinstance(root, BinaryOperators.Intersection)
@@ -932,6 +1188,22 @@ def test_binary_evaluation_order():
932
1188
  assert isinstance(root, BinaryOperators.FullOuterJoin)
933
1189
  assert isinstance(root.right, RAOperand) and isinstance(root.left, BinaryOperators.Cross)
934
1190
 
1191
+ root = RAParser.parse_query(r'a ⋉ b x c')
1192
+ assert isinstance(root, BinaryOperators.LeftSemiJoin)
1193
+ assert isinstance(root.left, RAOperand) and isinstance(root.right, BinaryOperators.Cross)
1194
+
1195
+ root = RAParser.parse_query(r'a x b ⋉ c')
1196
+ assert isinstance(root, BinaryOperators.LeftSemiJoin)
1197
+ assert isinstance(root.right, RAOperand) and isinstance(root.left, BinaryOperators.Cross)
1198
+
1199
+ root = RAParser.parse_query(r'a ⋊ b x c')
1200
+ assert isinstance(root, BinaryOperators.RightSemiJoin)
1201
+ assert isinstance(root.left, RAOperand) and isinstance(root.right, BinaryOperators.Cross)
1202
+
1203
+ root = RAParser.parse_query(r'a x b ⋊ c')
1204
+ assert isinstance(root, BinaryOperators.RightSemiJoin)
1205
+ assert isinstance(root.right, RAOperand) and isinstance(root.left, BinaryOperators.Cross)
1206
+
935
1207
  # join <-> division
936
1208
  root = RAParser.parse_query(r'a ⋈ b ÷ c')
937
1209
  assert isinstance(root, BinaryOperators.Join)
@@ -965,6 +1237,22 @@ def test_binary_evaluation_order():
965
1237
  assert isinstance(root, BinaryOperators.FullOuterJoin)
966
1238
  assert isinstance(root.right, RAOperand) and isinstance(root.left, BinaryOperators.Division)
967
1239
 
1240
+ root = RAParser.parse_query(r'a ⋉ b ÷ c')
1241
+ assert isinstance(root, BinaryOperators.LeftSemiJoin)
1242
+ assert isinstance(root.left, RAOperand) and isinstance(root.right, BinaryOperators.Division)
1243
+
1244
+ root = RAParser.parse_query(r'a ÷ b ⋉ c')
1245
+ assert isinstance(root, BinaryOperators.LeftSemiJoin)
1246
+ assert isinstance(root.right, RAOperand) and isinstance(root.left, BinaryOperators.Division)
1247
+
1248
+ root = RAParser.parse_query(r'a ⋊ b ÷ c')
1249
+ assert isinstance(root, BinaryOperators.RightSemiJoin)
1250
+ assert isinstance(root.left, RAOperand) and isinstance(root.right, BinaryOperators.Division)
1251
+
1252
+ root = RAParser.parse_query(r'a ÷ b ⋊ c')
1253
+ assert isinstance(root, BinaryOperators.RightSemiJoin)
1254
+ assert isinstance(root.right, RAOperand) and isinstance(root.left, BinaryOperators.Division)
1255
+
968
1256
  # natural join <-> outer join
969
1257
  root = RAParser.parse_query(r'a ⋈ b ⟕ c')
970
1258
  assert isinstance(root, BinaryOperators.Join)
@@ -990,6 +1278,22 @@ def test_binary_evaluation_order():
990
1278
  assert isinstance(root, BinaryOperators.Join)
991
1279
  assert isinstance(root.right, RAOperand) and isinstance(root.left, BinaryOperators.FullOuterJoin)
992
1280
 
1281
+ root = RAParser.parse_query(r'a ⋈ b ⋉ c')
1282
+ assert isinstance(root, BinaryOperators.Join)
1283
+ assert isinstance(root.left, RAOperand) and isinstance(root.right, BinaryOperators.LeftSemiJoin)
1284
+
1285
+ root = RAParser.parse_query(r'a ⋉ b ⋈ c')
1286
+ assert isinstance(root, BinaryOperators.Join)
1287
+ assert isinstance(root.right, RAOperand) and isinstance(root.left, BinaryOperators.LeftSemiJoin)
1288
+
1289
+ root = RAParser.parse_query(r'a ⋈ b ⋊ c')
1290
+ assert isinstance(root, BinaryOperators.Join)
1291
+ assert isinstance(root.left, RAOperand) and isinstance(root.right, BinaryOperators.RightSemiJoin)
1292
+
1293
+ root = RAParser.parse_query(r'a ⋊ b ⋈ c')
1294
+ assert isinstance(root, BinaryOperators.Join)
1295
+ assert isinstance(root.right, RAOperand) and isinstance(root.left, BinaryOperators.RightSemiJoin)
1296
+
993
1297
  # cross <-> division
994
1298
  root = RAParser.parse_query(r'a x b ÷ c')
995
1299
  assert isinstance(root, BinaryOperators.Cross)
@@ -1115,6 +1419,22 @@ def test_mixed_evaluation_order():
1115
1419
  assert isinstance(root, BinaryOperators.FullOuterJoin)
1116
1420
  assert isinstance(root.right, RAOperand) and isinstance(root.left, UnaryOperators.Projection)
1117
1421
 
1422
+ root = RAParser.parse_query(r'a ⋉ π [ Id ] b')
1423
+ assert isinstance(root, BinaryOperators.LeftSemiJoin)
1424
+ assert isinstance(root.left, RAOperand) and isinstance(root.right, UnaryOperators.Projection)
1425
+
1426
+ root = RAParser.parse_query(r'π [ Id ] a ⋉ b')
1427
+ assert isinstance(root, BinaryOperators.LeftSemiJoin)
1428
+ assert isinstance(root.right, RAOperand) and isinstance(root.left, UnaryOperators.Projection)
1429
+
1430
+ root = RAParser.parse_query(r'a ⋊ π [ Id ] b')
1431
+ assert isinstance(root, BinaryOperators.RightSemiJoin)
1432
+ assert isinstance(root.left, RAOperand) and isinstance(root.right, UnaryOperators.Projection)
1433
+
1434
+ root = RAParser.parse_query(r'π [ Id ] a ⋊ b')
1435
+ assert isinstance(root, BinaryOperators.RightSemiJoin)
1436
+ assert isinstance(root.right, RAOperand) and isinstance(root.left, UnaryOperators.Projection)
1437
+
1118
1438
  # join <-> rename
1119
1439
  root = RAParser.parse_query(r'a ⋈ β [ Id2 ← Id ] b')
1120
1440
  assert isinstance(root, BinaryOperators.Join)
@@ -1148,6 +1468,22 @@ def test_mixed_evaluation_order():
1148
1468
  assert isinstance(root, BinaryOperators.FullOuterJoin)
1149
1469
  assert isinstance(root.right, RAOperand) and isinstance(root.left, UnaryOperators.Rename)
1150
1470
 
1471
+ root = RAParser.parse_query(r'a ⋉ β [ Id2 ← Id ] b')
1472
+ assert isinstance(root, BinaryOperators.LeftSemiJoin)
1473
+ assert isinstance(root.left, RAOperand) and isinstance(root.right, UnaryOperators.Rename)
1474
+
1475
+ root = RAParser.parse_query(r'β [ Id2 ← Id ] a ⋉ b')
1476
+ assert isinstance(root, BinaryOperators.LeftSemiJoin)
1477
+ assert isinstance(root.right, RAOperand) and isinstance(root.left, UnaryOperators.Rename)
1478
+
1479
+ root = RAParser.parse_query(r'a ⋊ β [ Id2 ← Id ] b')
1480
+ assert isinstance(root, BinaryOperators.RightSemiJoin)
1481
+ assert isinstance(root.left, RAOperand) and isinstance(root.right, UnaryOperators.Rename)
1482
+
1483
+ root = RAParser.parse_query(r'β [ Id2 ← Id ] a ⋊ b')
1484
+ assert isinstance(root, BinaryOperators.RightSemiJoin)
1485
+ assert isinstance(root.right, RAOperand) and isinstance(root.left, UnaryOperators.Rename)
1486
+
1151
1487
  # join <-> selection
1152
1488
  root = RAParser.parse_query(r'a ⋈ σ [ Id > 1 ] b')
1153
1489
  assert isinstance(root, BinaryOperators.Join)
@@ -1181,6 +1517,22 @@ def test_mixed_evaluation_order():
1181
1517
  assert isinstance(root, BinaryOperators.FullOuterJoin)
1182
1518
  assert isinstance(root.right, RAOperand) and isinstance(root.left, UnaryOperators.Selection)
1183
1519
 
1520
+ root = RAParser.parse_query(r'a ⋉ σ [ Id > 1 ] b')
1521
+ assert isinstance(root, BinaryOperators.LeftSemiJoin)
1522
+ assert isinstance(root.left, RAOperand) and isinstance(root.right, UnaryOperators.Selection)
1523
+
1524
+ root = RAParser.parse_query(r'σ [ Id > 1 ] a ⋉ b')
1525
+ assert isinstance(root, BinaryOperators.LeftSemiJoin)
1526
+ assert isinstance(root.right, RAOperand) and isinstance(root.left, UnaryOperators.Selection)
1527
+
1528
+ root = RAParser.parse_query(r'a ⋊ σ [ Id > 1 ] b')
1529
+ assert isinstance(root, BinaryOperators.RightSemiJoin)
1530
+ assert isinstance(root.left, RAOperand) and isinstance(root.right, UnaryOperators.Selection)
1531
+
1532
+ root = RAParser.parse_query(r'σ [ Id > 1 ] a ⋊ b')
1533
+ assert isinstance(root, BinaryOperators.RightSemiJoin)
1534
+ assert isinstance(root.right, RAOperand) and isinstance(root.left, UnaryOperators.Selection)
1535
+
1184
1536
  # cross <-> projection
1185
1537
  root = RAParser.parse_query(r'a x π [ Id ] b')
1186
1538
  assert isinstance(root, BinaryOperators.Cross)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: jupyter-duckdb
3
- Version: 1.4.105
3
+ Version: 1.4.106
4
4
  Summary: a basic wrapper kernel for DuckDB
5
5
  Home-page: https://github.com/erictroebs/jupyter-duckdb
6
6
  Author: Eric Tröbs
@@ -40,10 +40,10 @@ duckdb_kernel/parser/elements/RAOperator.py,sha256=rtqMFBIBBqT-Bwg7Qm4WQwbDrE28N
40
40
  duckdb_kernel/parser/elements/RAUnaryOperator.py,sha256=XC1nphkSm88JaEu5V_HKnb_8JNoeBfE3EvNL4o0qh2c,654
41
41
  duckdb_kernel/parser/elements/__init__.py,sha256=t5H6SVOm3z8r6UWRYOI7HmMIuB4Yh6TLNu4_N3jg2t0,566
42
42
  duckdb_kernel/parser/elements/binary/Add.py,sha256=XGkZMfab01huk9EaI6JUfzkd2STbV1C_-TyC2guKE8I,190
43
- duckdb_kernel/parser/elements/binary/And.py,sha256=0jgetTG8yo5TJSeK70Kj-PI9ERyek1eyMQXX5HBxa4Y,274
43
+ duckdb_kernel/parser/elements/binary/And.py,sha256=p6TQE49DtHlMlTkH9GqyrQVcYWsVgdIMTTCxNuNORuQ,267
44
44
  duckdb_kernel/parser/elements/binary/ArrowLeft.py,sha256=u4fZSoyT9lfvWXBwuhUl4DdjVZAOqyVIKmMVbpElLD4,203
45
45
  duckdb_kernel/parser/elements/binary/ConditionalSet.py,sha256=yzUPWO4KL8BEIQ-SiV00bdLulwHoxgoJRxebyhsRSPU,17884
46
- duckdb_kernel/parser/elements/binary/Cross.py,sha256=jVY3cvD6qDWZkJ7q74lFUPO2VdDt4aAjdk2YAfg-ZC4,687
46
+ duckdb_kernel/parser/elements/binary/Cross.py,sha256=2tsPBPGN2Bmbx50-cCdZcSj7AqQwJugA7B4gECrMdlI,696
47
47
  duckdb_kernel/parser/elements/binary/Difference.py,sha256=4nyHhjo09UmYjtGNC3xGQxV5ROzCGOpPkyerUN-AlF4,746
48
48
  duckdb_kernel/parser/elements/binary/Divide.py,sha256=ubekU4C1wkCTidUSMLEj5neheRx0QjhWSrsPGuXTa1g,265
49
49
  duckdb_kernel/parser/elements/binary/Division.py,sha256=FOYxmeNGljRETwygtVn102POCUmt71t9DXdAnLFCXZM,1535
@@ -54,15 +54,17 @@ duckdb_kernel/parser/elements/binary/GreaterThanEqual.py,sha256=gO1I3J5CZwrpqZb5
54
54
  duckdb_kernel/parser/elements/binary/Intersection.py,sha256=K6NrwcLTJ1BUccifVQ2R2YHR5B71LhjuLhOalxZcM0g,757
55
55
  duckdb_kernel/parser/elements/binary/Join.py,sha256=9Z3JinEav3ulLbZZZM9DLbprloHC0oGuSm40Kf1A0mM,836
56
56
  duckdb_kernel/parser/elements/binary/LeftOuterJoin.py,sha256=qCyHLMboNjzSDK_FREtYVwZx4UYkfRcy3FMo2pEf93o,846
57
+ duckdb_kernel/parser/elements/binary/LeftSemiJoin.py,sha256=u5Xv-vS0wfZsG4X5go--r3JnoDVoeeaI07zKaS2pJiM,828
57
58
  duckdb_kernel/parser/elements/binary/LessThan.py,sha256=gNlyAvew0VyvU8x3ol88zbdh_t9GU51Kd2P_PmHUrAc,201
58
59
  duckdb_kernel/parser/elements/binary/LessThanEqual.py,sha256=BKKXBZ4TZQ4EBxBDSNzIpFl4Oz1IGI0tI0Oj7KZUoDo,283
59
60
  duckdb_kernel/parser/elements/binary/Minus.py,sha256=1XUTXCA0GcAcCnv9nq4B9ewT0XHJ91LlZGEW1y60POA,192
60
61
  duckdb_kernel/parser/elements/binary/Multiply.py,sha256=OctlfN71izFYxIpMo09Qwq-3BmQmSh6-PNKBljMsBrg,195
61
62
  duckdb_kernel/parser/elements/binary/Or.py,sha256=e1H_BuY7TQD7XHKGqJYLOebYQvrh1euWOUsXF0FT5dY,264
62
63
  duckdb_kernel/parser/elements/binary/RightOuterJoin.py,sha256=bDxTEQ_dJZ-MUuGbU1YL69kPFR0Hdkc1fow3wxOxfAY,867
64
+ duckdb_kernel/parser/elements/binary/RightSemiJoin.py,sha256=QYDR27H4sA57vCKIip5o_UKfHAOLpYW6cq36fdUUO4M,848
63
65
  duckdb_kernel/parser/elements/binary/Unequal.py,sha256=1hnC1RcPMxwKKv65OL5prunGgh9cRVDmzJutmtl7gtY,269
64
66
  duckdb_kernel/parser/elements/binary/Union.py,sha256=VYTj4M2PVEhWiDwjnyP8qpVVbGvIBSVshlEt-SZYCBY,739
65
- duckdb_kernel/parser/elements/binary/__init__.py,sha256=BieXw51EBgIwUEK-hn4jBb1b4VKJT6sRzaxwOrSXw2A,1342
67
+ duckdb_kernel/parser/elements/binary/__init__.py,sha256=-4ZY6vpsiyT8eDkLwyFGHJFWXIMCNYNz9ejFFcjEG5U,1451
66
68
  duckdb_kernel/parser/elements/unary/Not.py,sha256=kG0a-dp3TNjPodUMPiQ6ihtsBrbvn1iWeIPCvtyAwdo,632
67
69
  duckdb_kernel/parser/elements/unary/Projection.py,sha256=CJ-MIf1-__1ewTjNZVy5hOz3Z18CWnCDNJBxUdpWXVQ,1112
68
70
  duckdb_kernel/parser/elements/unary/Rename.py,sha256=Zr2n9EJ3nA476lND0Djz2b6493nnsbSpJ9kkEgk5B_Y,1273
@@ -77,7 +79,7 @@ duckdb_kernel/parser/util/RenamableColumnList.py,sha256=5oEDbtvl4YfHbkxu_Ny2pc0E
77
79
  duckdb_kernel/parser/util/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
78
80
  duckdb_kernel/tests/__init__.py,sha256=-BoPfo1FNQKnvAYt22Ioc21dbuO67QVFaV_SmS1zQw8,2731
79
81
  duckdb_kernel/tests/test_dc.py,sha256=HPJ6JGB7yXVKIOnDHB8KwX1A16ljU0I5Y8VFcJs-KVI,15192
80
- duckdb_kernel/tests/test_ra.py,sha256=YEL-Jwc9tIvCT-UGOaqfXJZZH0FAok3cj9sXK59xzkQ,53172
82
+ duckdb_kernel/tests/test_ra.py,sha256=z7ItArWzCIoPp07pgnk8NCxZ0WsjSYIeHChmi-jWE5c,69610
81
83
  duckdb_kernel/tests/test_result_comparison.py,sha256=TQVLPKKNyV2k3i4jCfasetPfVfCzgYZr92wxQmlzPnA,3859
82
84
  duckdb_kernel/tests/test_sql.py,sha256=p7UEokoJs2xc-url7xQ4PmWKxtExrDDYnMeoyR1JD0A,1208
83
85
  duckdb_kernel/util/ResultSetComparator.py,sha256=RZDIfjJyx8-eR-HIqQlEYgZd_V1ympbszpVRF4TlA7o,2262
@@ -94,7 +96,7 @@ duckdb_kernel/visualization/lib/__init__.py,sha256=LYi0YPtn5fXOejbLIqbt_3KzP-Xrw
94
96
  duckdb_kernel/visualization/lib/plotly-3.0.1.min.js,sha256=oy6Be7Eh6eiQFs5M7oXuPxxm9qbJXEtTpfSI93dW16Q,4653932
95
97
  duckdb_kernel/visualization/lib/ra.css,sha256=foz1v69EQ117BDduB9QyHH978PbRs2TG1kBS4VGqZbI,57
96
98
  duckdb_kernel/visualization/lib/ra.js,sha256=VzMRn55ztcd5Kfu2B6gdRPARpi8n-fvs8oNFnfp55Ec,1845
97
- jupyter_duckdb-1.4.105.dist-info/METADATA,sha256=uuenj_81-ZaSUb0TQ2Sy8-rcrtZsa7GHfZQ7nElAzZ0,9272
98
- jupyter_duckdb-1.4.105.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
99
- jupyter_duckdb-1.4.105.dist-info/top_level.txt,sha256=KvRRPMnmkQNuhyBsXoPmwyt26LRDp0O-0HN6u0Dm5jA,14
100
- jupyter_duckdb-1.4.105.dist-info/RECORD,,
99
+ jupyter_duckdb-1.4.106.dist-info/METADATA,sha256=IRd1kZI21gT9o4a8GopNzkctOcDixojRttR3ZMk7V4I,9272
100
+ jupyter_duckdb-1.4.106.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
101
+ jupyter_duckdb-1.4.106.dist-info/top_level.txt,sha256=KvRRPMnmkQNuhyBsXoPmwyt26LRDp0O-0HN6u0Dm5jA,14
102
+ jupyter_duckdb-1.4.106.dist-info/RECORD,,