jupyter-duckdb 1.4.106__py3-none-any.whl → 1.4.108__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.
@@ -3,7 +3,7 @@ import pytest
3
3
  import duckdb_kernel.parser.elements.binary as BinaryOperators
4
4
  import duckdb_kernel.parser.elements.unary as UnaryOperators
5
5
  from duckdb_kernel.parser import RAParser, RAParserError
6
- from duckdb_kernel.parser.elements import RAOperand, LogicElement
6
+ from duckdb_kernel.parser.elements import RAOperand, LogicElement, RARelationReference
7
7
  from . import Connection
8
8
 
9
9
 
@@ -101,6 +101,13 @@ def test_comments():
101
101
  assert isinstance(root.left, RAOperand) and root.left.name == 'Shows'
102
102
  assert isinstance(root.right, RAOperand) and root.right.name == 'Seasons'
103
103
 
104
+ for query in (
105
+ '-- comment',
106
+ '/* comment */'
107
+ ):
108
+ root = RAParser.parse_query(query)
109
+ assert root is None
110
+
104
111
 
105
112
  def test_binary_operator_cross():
106
113
  for query in (
@@ -236,6 +243,14 @@ def test_binary_operator_join():
236
243
  (2, 'Show 2', 2, 'Show 2 / Season 2')
237
244
  ]
238
245
 
246
+ for query in (
247
+ r'Shows ⋈ Users',
248
+ ):
249
+ with pytest.raises(RAParserError):
250
+ with Connection() as con:
251
+ root = RAParser.parse_query(query)
252
+ con.execute_ra_return_cols(root)
253
+
239
254
 
240
255
  def test_binary_operator_ljoin():
241
256
  for query in (
@@ -262,6 +277,14 @@ def test_binary_operator_ljoin():
262
277
  (3, 'Charlie', None),
263
278
  ]
264
279
 
280
+ for query in (
281
+ r'Shows ⟕ Users',
282
+ ):
283
+ with pytest.raises(RAParserError):
284
+ with Connection() as con:
285
+ root = RAParser.parse_query(query)
286
+ con.execute_ra_return_cols(root)
287
+
265
288
 
266
289
  def test_binary_operator_rjoin():
267
290
  for query in (
@@ -287,6 +310,14 @@ def test_binary_operator_rjoin():
287
310
  (4, None, 'David')
288
311
  ]
289
312
 
313
+ for query in (
314
+ r'Shows ⟖ Users',
315
+ ):
316
+ with pytest.raises(RAParserError):
317
+ with Connection() as con:
318
+ root = RAParser.parse_query(query)
319
+ con.execute_ra_return_cols(root)
320
+
290
321
 
291
322
  def test_binary_operator_fjoin():
292
323
  for query in (
@@ -315,6 +346,14 @@ def test_binary_operator_fjoin():
315
346
  (4, None, 'David')
316
347
  ]
317
348
 
349
+ for query in (
350
+ r'Shows ⟗ Users',
351
+ ):
352
+ with pytest.raises(RAParserError):
353
+ with Connection() as con:
354
+ root = RAParser.parse_query(query)
355
+ con.execute_ra_return_cols(root)
356
+
318
357
 
319
358
  def test_binary_operator_lsjoin():
320
359
  for query in (
@@ -338,6 +377,14 @@ def test_binary_operator_lsjoin():
338
377
  (2, 'Bob')
339
378
  ]
340
379
 
380
+ for query in (
381
+ r'Shows ⋉ Users',
382
+ ):
383
+ with pytest.raises(RAParserError):
384
+ with Connection() as con:
385
+ root = RAParser.parse_query(query)
386
+ con.execute_ra_return_cols(root)
387
+
341
388
 
342
389
  def test_binary_operator_rsjoin():
343
390
  for query in (
@@ -361,6 +408,14 @@ def test_binary_operator_rsjoin():
361
408
  (2, 'Bob')
362
409
  ]
363
410
 
411
+ for query in (
412
+ r'Shows ⋊ Users',
413
+ ):
414
+ with pytest.raises(RAParserError):
415
+ with Connection() as con:
416
+ root = RAParser.parse_query(query)
417
+ con.execute_ra_return_cols(root)
418
+
364
419
 
365
420
  def test_binary_operator_union():
366
421
  for query in (
@@ -445,7 +500,7 @@ def test_unary_operator_projection():
445
500
  ]
446
501
 
447
502
 
448
- def test_unary_operator_rename():
503
+ def test_unary_operator_attributerename():
449
504
  with Connection() as con:
450
505
  for query in (
451
506
  r'β Id2 ← Id Users',
@@ -463,7 +518,7 @@ def test_unary_operator_rename():
463
518
  ):
464
519
  root = RAParser.parse_query(query)
465
520
 
466
- assert isinstance(root, UnaryOperators.Rename)
521
+ assert isinstance(root, UnaryOperators.AttributeRename)
467
522
  assert isinstance(root.arg, LogicElement)
468
523
  assert isinstance(root.target, RAOperand) and root.target.name == 'Users'
469
524
 
@@ -492,9 +547,9 @@ def test_unary_operator_rename():
492
547
  ):
493
548
  root = RAParser.parse_query(query)
494
549
 
495
- assert isinstance(root, UnaryOperators.Rename)
550
+ assert isinstance(root, UnaryOperators.AttributeRename)
496
551
  assert isinstance(root.arg, LogicElement)
497
- assert isinstance(root.target, UnaryOperators.Rename)
552
+ assert isinstance(root.target, UnaryOperators.AttributeRename)
498
553
  assert isinstance(root.target.arg, LogicElement)
499
554
  assert isinstance(root.target.target, RAOperand) and root.target.target.name == 'Users'
500
555
 
@@ -511,6 +566,157 @@ def test_unary_operator_rename():
511
566
  ]
512
567
 
513
568
 
569
+ def test_unary_operator_rename():
570
+ with Connection() as con:
571
+ # relation
572
+ for query in (
573
+ # ρ
574
+ r'ρ R Users',
575
+ r'ρ R ( Users )',
576
+ r'ρ [ R ] Users',
577
+ r'ρ [ R ] ( Users )',
578
+ # ϱ
579
+ r'ϱ R Users',
580
+ r'ϱ R ( Users )',
581
+ r'ϱ [ R ] Users',
582
+ r'ϱ [ R ] ( Users )',
583
+ # rho
584
+ r'rho R Users',
585
+ r'rho R ( Users )',
586
+ r'rho [ R ] Users',
587
+ r'rho [ R ] ( Users )',
588
+ ):
589
+ root = RAParser.parse_query(query)
590
+
591
+ assert isinstance(root, UnaryOperators.Rename)
592
+ assert isinstance(root.arg, RARelationReference)
593
+ assert isinstance(root.target, RAOperand) and root.target.name == 'Users'
594
+
595
+ cols, rows = con.execute_ra_return_cols(root)
596
+
597
+ assert root.arg.relation == 'R'
598
+ assert root.arg.attributes is None
599
+
600
+ assert [c.lower() for c in cols] == [
601
+ 'id',
602
+ 'username'
603
+ ]
604
+ assert rows == [
605
+ (1, 'Alice'),
606
+ (2, 'Bob'),
607
+ (3, 'Charlie')
608
+ ]
609
+
610
+ # attributes
611
+ for query in (
612
+ # ρ
613
+ r'ρ (A,) Users',
614
+ r'ρ (A,) ( Users )',
615
+ r'ρ [ (A,) ] Users',
616
+ r'ρ [ (A,) ] ( Users )',
617
+ # ϱ
618
+ r'ϱ (A,) Users',
619
+ r'ϱ (A,) ( Users )',
620
+ r'ϱ [ (A,) ] Users',
621
+ r'ϱ [ (A,) ] ( Users )',
622
+ # rho
623
+ r'rho (A,) Users',
624
+ r'rho (A,) ( Users )',
625
+ r'rho [ (A,) ] Users',
626
+ r'rho [ (A,) ] ( Users )',
627
+ ):
628
+ root = RAParser.parse_query(query)
629
+
630
+ assert isinstance(root, UnaryOperators.Rename)
631
+ assert isinstance(root.arg, RARelationReference)
632
+ assert isinstance(root.target, RAOperand) and root.target.name == 'Users'
633
+
634
+ cols, rows = con.execute_ra_return_cols(root)
635
+
636
+ assert root.arg.relation is None
637
+ assert root.arg.attributes == ['A']
638
+
639
+ assert [c.lower() for c in cols] == [
640
+ 'a',
641
+ 'username'
642
+ ]
643
+ assert rows == [
644
+ (1, 'Alice'),
645
+ (2, 'Bob'),
646
+ (3, 'Charlie')
647
+ ]
648
+
649
+ for query in (
650
+ # ρ
651
+ r'ρ (A,B) Users',
652
+ r'ρ (A, B) Users',
653
+ r'ρ (A,B) ( Users )',
654
+ r'ρ (A, B) ( Users )',
655
+ r'ρ [ (A,B) ] Users',
656
+ r'ρ [ (A, B) ] Users',
657
+ r'ρ [ (A,B) ] ( Users )',
658
+ r'ρ [ (A, B) ] ( Users )',
659
+ # ϱ
660
+ r'ϱ (A,B) Users',
661
+ r'ϱ (A, B) Users',
662
+ r'ϱ (A,B) ( Users )',
663
+ r'ϱ (A, B) ( Users )',
664
+ r'ϱ [ (A,B) ] Users',
665
+ r'ϱ [ (A, B) ] Users',
666
+ r'ϱ [ (A,B) ] ( Users )',
667
+ r'ϱ [ (A, B) ] ( Users )',
668
+ # rho
669
+ r'rho (A,B) Users',
670
+ r'rho (A, B) Users',
671
+ r'rho (A,B) ( Users )',
672
+ r'rho (A, B) ( Users )',
673
+ r'rho [ (A,B) ] Users',
674
+ r'rho [ (A, B) ] Users',
675
+ r'rho [ (A,B) ] ( Users )',
676
+ r'rho [ (A, B) ] ( Users )',
677
+ ):
678
+ root = RAParser.parse_query(query)
679
+
680
+ assert isinstance(root, UnaryOperators.Rename)
681
+ assert isinstance(root.arg, RARelationReference)
682
+ assert isinstance(root.target, RAOperand) and root.target.name == 'Users'
683
+
684
+ cols, rows = con.execute_ra_return_cols(root)
685
+
686
+ assert root.arg.relation is None
687
+ assert root.arg.attributes == ['A', 'B']
688
+
689
+ assert [c.lower() for c in cols] == [
690
+ 'a',
691
+ 'b'
692
+ ]
693
+ assert rows == [
694
+ (1, 'Alice'),
695
+ (2, 'Bob'),
696
+ (3, 'Charlie')
697
+ ]
698
+
699
+ for query in (
700
+ # ρ
701
+ r'ρ (A,A) (Users)',
702
+ r'ρ (A,a) (Users)',
703
+ r'ρ (A, A) (Users)',
704
+ r'ρ (A, a) (Users)',
705
+ # ϱ
706
+ r'ϱ (A,A) (Users)',
707
+ r'ϱ (A,a) (Users)',
708
+ r'ϱ (A, A) (Users)',
709
+ r'ϱ (A, a) (Users)',
710
+ # rho
711
+ r'rho (A,A) (Users)',
712
+ r'rho (A,a) (Users)',
713
+ r'rho (A, A) (Users)',
714
+ r'rho (A, a) (Users)',
715
+ ):
716
+ with pytest.raises(RAParserError):
717
+ root = RAParser.parse_query(query)
718
+
719
+
514
720
  def test_unary_operator_selection():
515
721
  with Connection() as con:
516
722
  for query in (
@@ -582,13 +788,21 @@ def test_unary_inner_to_outer_evaluation_order():
582
788
  assert root.target.condition.left == ('Id',) and root.target.condition.right == ('1',)
583
789
 
584
790
  root = RAParser.parse_query(r'β [ Id3 ← Id2 ] β [ Id2 ← Id ] (Users)')
585
- assert isinstance(root, UnaryOperators.Rename)
791
+ assert isinstance(root, UnaryOperators.AttributeRename)
586
792
  assert isinstance(root.arrow, BinaryOperators.ArrowLeft)
587
793
  assert root.arrow.left == ('Id3',) and root.arrow.right == ('Id2',)
588
- assert isinstance(root.target, UnaryOperators.Rename)
794
+ assert isinstance(root.target, UnaryOperators.AttributeRename)
589
795
  assert isinstance(root.target.arrow, BinaryOperators.ArrowLeft)
590
796
  assert root.target.arrow.left == ('Id2',) and root.target.arrow.right == ('Id',)
591
797
 
798
+ root = RAParser.parse_query(r'ρ [ S(X, Y) ] ρ [ R(A, B) ] (Users)')
799
+ assert isinstance(root, UnaryOperators.Rename)
800
+ assert isinstance(root.arg, RARelationReference)
801
+ assert root.arg.relation == 'S' and root.arg.attributes == ['X', 'Y']
802
+ assert isinstance(root.target, UnaryOperators.Rename)
803
+ assert isinstance(root.target.arg, RARelationReference)
804
+ assert root.target.arg.relation == 'R' and root.target.arg.attributes == ['A', 'B']
805
+
592
806
 
593
807
  def test_binary_left_to_right_evaluation_order():
594
808
  # difference
@@ -901,30 +1115,58 @@ def test_binary_left_to_right_evaluation_order():
901
1115
 
902
1116
 
903
1117
  def test_unary_evaluation_order():
904
- root = RAParser.parse_query(r'π [ Id2 ] β [ Id2 ← Id ] (Users)')
1118
+ # π
1119
+ root = RAParser.parse_query(r'π [ Id ] σ [ Id > 1 ] (Users)')
905
1120
  assert isinstance(root, UnaryOperators.Projection)
906
- assert isinstance(root.target, UnaryOperators.Rename)
1121
+ assert isinstance(root.target, UnaryOperators.Selection)
907
1122
 
908
- root = RAParser.parse_query(r'β [ Id2 ← Id ] π [ Id ] (Users)')
909
- assert isinstance(root, UnaryOperators.Rename)
910
- assert isinstance(root.target, UnaryOperators.Projection)
1123
+ root = RAParser.parse_query(r'π [ Id2 ] β [ Id2 ← Id ] (Users)')
1124
+ assert isinstance(root, UnaryOperators.Projection)
1125
+ assert isinstance(root.target, UnaryOperators.AttributeRename)
911
1126
 
912
- root = RAParser.parse_query(r'π [ Id ] σ [ Id > 1 ] (Users)')
1127
+ root = RAParser.parse_query(r'π [ Id2 ] ρ [ R(Id2, Username2) ] (Users)')
913
1128
  assert isinstance(root, UnaryOperators.Projection)
914
- assert isinstance(root.target, UnaryOperators.Selection)
1129
+ assert isinstance(root.target, UnaryOperators.Rename)
915
1130
 
1131
+ # σ
916
1132
  root = RAParser.parse_query(r'σ [ Id > 1 ] π [ Id ] (Users)')
917
1133
  assert isinstance(root, UnaryOperators.Selection)
918
1134
  assert isinstance(root.target, UnaryOperators.Projection)
919
1135
 
920
1136
  root = RAParser.parse_query(r'σ [ Id2 > 1 ] β [ Id2 ← Id ] (Users)')
921
1137
  assert isinstance(root, UnaryOperators.Selection)
1138
+ assert isinstance(root.target, UnaryOperators.AttributeRename)
1139
+
1140
+ root = RAParser.parse_query(r'σ [ Id2 > 1 ] ρ [ R(Id2, Username2) ] (Users)')
1141
+ assert isinstance(root, UnaryOperators.Selection)
922
1142
  assert isinstance(root.target, UnaryOperators.Rename)
923
1143
 
1144
+ # β
1145
+ root = RAParser.parse_query(r'β [ Id2 ← Id ] π [ Id ] (Users)')
1146
+ assert isinstance(root, UnaryOperators.AttributeRename)
1147
+ assert isinstance(root.target, UnaryOperators.Projection)
1148
+
924
1149
  root = RAParser.parse_query(r'β [ Id2 ← Id ] σ [ Id > 1 ] (Users)')
1150
+ assert isinstance(root, UnaryOperators.AttributeRename)
1151
+ assert isinstance(root.target, UnaryOperators.Selection)
1152
+
1153
+ root = RAParser.parse_query(r'β [ Id3 ← Id2 ] ρ [ R(Id2, Username2) ] (Users)')
1154
+ assert isinstance(root, UnaryOperators.AttributeRename)
1155
+ assert isinstance(root.target, UnaryOperators.Rename)
1156
+
1157
+ # ρ
1158
+ root = RAParser.parse_query(r'ρ [ R(Id2,) ] π [ Id ] (Users)')
1159
+ assert isinstance(root, UnaryOperators.Rename)
1160
+ assert isinstance(root.target, UnaryOperators.Projection)
1161
+
1162
+ root = RAParser.parse_query(r'ρ [ R(Id2, Username2) ] σ [ Id > 1 ] (Users)')
925
1163
  assert isinstance(root, UnaryOperators.Rename)
926
1164
  assert isinstance(root.target, UnaryOperators.Selection)
927
1165
 
1166
+ root = RAParser.parse_query(r'ρ [ R(Id3, Username2) ] β [ Id2 ← Id ] (Users)')
1167
+ assert isinstance(root, UnaryOperators.Rename)
1168
+ assert isinstance(root.target, UnaryOperators.AttributeRename)
1169
+
928
1170
 
929
1171
  def test_binary_evaluation_order():
930
1172
  # difference <-> union
@@ -1314,13 +1556,22 @@ def test_mixed_evaluation_order():
1314
1556
  assert isinstance(root, BinaryOperators.Difference)
1315
1557
  assert isinstance(root.right, RAOperand) and isinstance(root.left, UnaryOperators.Projection)
1316
1558
 
1317
- # difference <-> rename
1559
+ # difference <-> attribute rename
1318
1560
  root = RAParser.parse_query(r'a \ β [ Id2 ← Id ] b')
1319
1561
  assert isinstance(root, BinaryOperators.Difference)
1320
- assert isinstance(root.left, RAOperand) and isinstance(root.right, UnaryOperators.Rename)
1562
+ assert isinstance(root.left, RAOperand) and isinstance(root.right, UnaryOperators.AttributeRename)
1321
1563
 
1322
1564
  root = RAParser.parse_query(r'β [ Id2 ← Id ] a \ b')
1323
1565
  assert isinstance(root, BinaryOperators.Difference)
1566
+ assert isinstance(root.right, RAOperand) and isinstance(root.left, UnaryOperators.AttributeRename)
1567
+
1568
+ # difference <-> rename
1569
+ root = RAParser.parse_query(r'a \ ρ [ R(Id2) ] b')
1570
+ assert isinstance(root, BinaryOperators.Difference)
1571
+ assert isinstance(root.left, RAOperand) and isinstance(root.right, UnaryOperators.Rename)
1572
+
1573
+ root = RAParser.parse_query(r'ρ [ R(Id2) ] a \ b')
1574
+ assert isinstance(root, BinaryOperators.Difference)
1324
1575
  assert isinstance(root.right, RAOperand) and isinstance(root.left, UnaryOperators.Rename)
1325
1576
 
1326
1577
  # difference <-> selection
@@ -1341,13 +1592,22 @@ def test_mixed_evaluation_order():
1341
1592
  assert isinstance(root, BinaryOperators.Union)
1342
1593
  assert isinstance(root.right, RAOperand) and isinstance(root.left, UnaryOperators.Projection)
1343
1594
 
1344
- # union <-> rename
1595
+ # union <-> attribute rename
1345
1596
  root = RAParser.parse_query(r'a ∪ β [ Id2 ← Id ] b')
1346
1597
  assert isinstance(root, BinaryOperators.Union)
1347
- assert isinstance(root.left, RAOperand) and isinstance(root.right, UnaryOperators.Rename)
1598
+ assert isinstance(root.left, RAOperand) and isinstance(root.right, UnaryOperators.AttributeRename)
1348
1599
 
1349
1600
  root = RAParser.parse_query(r'β [ Id2 ← Id ] a ∪ b')
1350
1601
  assert isinstance(root, BinaryOperators.Union)
1602
+ assert isinstance(root.right, RAOperand) and isinstance(root.left, UnaryOperators.AttributeRename)
1603
+
1604
+ # union <-> rename
1605
+ root = RAParser.parse_query(r'a ∪ ρ [ R(Id2) ] b')
1606
+ assert isinstance(root, BinaryOperators.Union)
1607
+ assert isinstance(root.left, RAOperand) and isinstance(root.right, UnaryOperators.Rename)
1608
+
1609
+ root = RAParser.parse_query(r'ρ [ R(Id2) ] a ∪ b')
1610
+ assert isinstance(root, BinaryOperators.Union)
1351
1611
  assert isinstance(root.right, RAOperand) and isinstance(root.left, UnaryOperators.Rename)
1352
1612
 
1353
1613
  # union <-> selection
@@ -1368,13 +1628,22 @@ def test_mixed_evaluation_order():
1368
1628
  assert isinstance(root, BinaryOperators.Intersection)
1369
1629
  assert isinstance(root.right, RAOperand) and isinstance(root.left, UnaryOperators.Projection)
1370
1630
 
1371
- # intersection <-> rename
1631
+ # intersection <-> attribute rename
1372
1632
  root = RAParser.parse_query(r'a ∩ β [ Id2 ← Id ] b')
1373
1633
  assert isinstance(root, BinaryOperators.Intersection)
1374
- assert isinstance(root.left, RAOperand) and isinstance(root.right, UnaryOperators.Rename)
1634
+ assert isinstance(root.left, RAOperand) and isinstance(root.right, UnaryOperators.AttributeRename)
1375
1635
 
1376
1636
  root = RAParser.parse_query(r'β [ Id2 ← Id ] a ∩ b')
1377
1637
  assert isinstance(root, BinaryOperators.Intersection)
1638
+ assert isinstance(root.right, RAOperand) and isinstance(root.left, UnaryOperators.AttributeRename)
1639
+
1640
+ # intersection <-> rename
1641
+ root = RAParser.parse_query(r'a ∩ ρ [ R(Id2) ] b')
1642
+ assert isinstance(root, BinaryOperators.Intersection)
1643
+ assert isinstance(root.left, RAOperand) and isinstance(root.right, UnaryOperators.Rename)
1644
+
1645
+ root = RAParser.parse_query(r'ρ [ R(Id2) ] a ∩ b')
1646
+ assert isinstance(root, BinaryOperators.Intersection)
1378
1647
  assert isinstance(root.right, RAOperand) and isinstance(root.left, UnaryOperators.Rename)
1379
1648
 
1380
1649
  # intersection <-> selection
@@ -1435,53 +1704,102 @@ def test_mixed_evaluation_order():
1435
1704
  assert isinstance(root, BinaryOperators.RightSemiJoin)
1436
1705
  assert isinstance(root.right, RAOperand) and isinstance(root.left, UnaryOperators.Projection)
1437
1706
 
1438
- # join <-> rename
1707
+ # join <-> attribute rename
1439
1708
  root = RAParser.parse_query(r'a ⋈ β [ Id2 ← Id ] b')
1440
1709
  assert isinstance(root, BinaryOperators.Join)
1441
- assert isinstance(root.left, RAOperand) and isinstance(root.right, UnaryOperators.Rename)
1710
+ assert isinstance(root.left, RAOperand) and isinstance(root.right, UnaryOperators.AttributeRename)
1442
1711
 
1443
1712
  root = RAParser.parse_query(r'β [ Id2 ← Id ] a ⋈ b')
1444
1713
  assert isinstance(root, BinaryOperators.Join)
1445
- assert isinstance(root.right, RAOperand) and isinstance(root.left, UnaryOperators.Rename)
1714
+ assert isinstance(root.right, RAOperand) and isinstance(root.left, UnaryOperators.AttributeRename)
1446
1715
 
1447
1716
  root = RAParser.parse_query(r'a ⟕ β [ Id2 ← Id ] b')
1448
1717
  assert isinstance(root, BinaryOperators.LeftOuterJoin)
1449
- assert isinstance(root.left, RAOperand) and isinstance(root.right, UnaryOperators.Rename)
1718
+ assert isinstance(root.left, RAOperand) and isinstance(root.right, UnaryOperators.AttributeRename)
1450
1719
 
1451
1720
  root = RAParser.parse_query(r'β [ Id2 ← Id ] a ⟕ b')
1452
1721
  assert isinstance(root, BinaryOperators.LeftOuterJoin)
1453
- assert isinstance(root.right, RAOperand) and isinstance(root.left, UnaryOperators.Rename)
1722
+ assert isinstance(root.right, RAOperand) and isinstance(root.left, UnaryOperators.AttributeRename)
1454
1723
 
1455
1724
  root = RAParser.parse_query(r'a ⟖ β [ Id2 ← Id ] b')
1456
1725
  assert isinstance(root, BinaryOperators.RightOuterJoin)
1457
- assert isinstance(root.left, RAOperand) and isinstance(root.right, UnaryOperators.Rename)
1726
+ assert isinstance(root.left, RAOperand) and isinstance(root.right, UnaryOperators.AttributeRename)
1458
1727
 
1459
1728
  root = RAParser.parse_query(r'β [ Id2 ← Id ] a ⟖ b')
1460
1729
  assert isinstance(root, BinaryOperators.RightOuterJoin)
1461
- assert isinstance(root.right, RAOperand) and isinstance(root.left, UnaryOperators.Rename)
1730
+ assert isinstance(root.right, RAOperand) and isinstance(root.left, UnaryOperators.AttributeRename)
1462
1731
 
1463
1732
  root = RAParser.parse_query(r'a ⟗ β [ Id2 ← Id ] b')
1464
1733
  assert isinstance(root, BinaryOperators.FullOuterJoin)
1465
- assert isinstance(root.left, RAOperand) and isinstance(root.right, UnaryOperators.Rename)
1734
+ assert isinstance(root.left, RAOperand) and isinstance(root.right, UnaryOperators.AttributeRename)
1466
1735
 
1467
1736
  root = RAParser.parse_query(r'β [ Id2 ← Id ] a ⟗ b')
1468
1737
  assert isinstance(root, BinaryOperators.FullOuterJoin)
1469
- assert isinstance(root.right, RAOperand) and isinstance(root.left, UnaryOperators.Rename)
1738
+ assert isinstance(root.right, RAOperand) and isinstance(root.left, UnaryOperators.AttributeRename)
1470
1739
 
1471
1740
  root = RAParser.parse_query(r'a ⋉ β [ Id2 ← Id ] b')
1472
1741
  assert isinstance(root, BinaryOperators.LeftSemiJoin)
1473
- assert isinstance(root.left, RAOperand) and isinstance(root.right, UnaryOperators.Rename)
1742
+ assert isinstance(root.left, RAOperand) and isinstance(root.right, UnaryOperators.AttributeRename)
1474
1743
 
1475
1744
  root = RAParser.parse_query(r'β [ Id2 ← Id ] a ⋉ b')
1476
1745
  assert isinstance(root, BinaryOperators.LeftSemiJoin)
1477
- assert isinstance(root.right, RAOperand) and isinstance(root.left, UnaryOperators.Rename)
1746
+ assert isinstance(root.right, RAOperand) and isinstance(root.left, UnaryOperators.AttributeRename)
1478
1747
 
1479
1748
  root = RAParser.parse_query(r'a ⋊ β [ Id2 ← Id ] b')
1480
1749
  assert isinstance(root, BinaryOperators.RightSemiJoin)
1481
- assert isinstance(root.left, RAOperand) and isinstance(root.right, UnaryOperators.Rename)
1750
+ assert isinstance(root.left, RAOperand) and isinstance(root.right, UnaryOperators.AttributeRename)
1482
1751
 
1483
1752
  root = RAParser.parse_query(r'β [ Id2 ← Id ] a ⋊ b')
1484
1753
  assert isinstance(root, BinaryOperators.RightSemiJoin)
1754
+ assert isinstance(root.right, RAOperand) and isinstance(root.left, UnaryOperators.AttributeRename)
1755
+
1756
+ # join <-> rename
1757
+ root = RAParser.parse_query(r'a ⋈ ρ [ R(Id2) ] b')
1758
+ assert isinstance(root, BinaryOperators.Join)
1759
+ assert isinstance(root.left, RAOperand) and isinstance(root.right, UnaryOperators.Rename)
1760
+
1761
+ root = RAParser.parse_query(r'ρ [ R(Id2) ] a ⋈ b')
1762
+ assert isinstance(root, BinaryOperators.Join)
1763
+ assert isinstance(root.right, RAOperand) and isinstance(root.left, UnaryOperators.Rename)
1764
+
1765
+ root = RAParser.parse_query(r'a ⟕ ρ [ R(Id2) ] b')
1766
+ assert isinstance(root, BinaryOperators.LeftOuterJoin)
1767
+ assert isinstance(root.left, RAOperand) and isinstance(root.right, UnaryOperators.Rename)
1768
+
1769
+ root = RAParser.parse_query(r'ρ [ R(Id2) ] a ⟕ b')
1770
+ assert isinstance(root, BinaryOperators.LeftOuterJoin)
1771
+ assert isinstance(root.right, RAOperand) and isinstance(root.left, UnaryOperators.Rename)
1772
+
1773
+ root = RAParser.parse_query(r'a ⟖ ρ [ R(Id2) ] b')
1774
+ assert isinstance(root, BinaryOperators.RightOuterJoin)
1775
+ assert isinstance(root.left, RAOperand) and isinstance(root.right, UnaryOperators.Rename)
1776
+
1777
+ root = RAParser.parse_query(r'ρ [ R(Id2) ] a ⟖ b')
1778
+ assert isinstance(root, BinaryOperators.RightOuterJoin)
1779
+ assert isinstance(root.right, RAOperand) and isinstance(root.left, UnaryOperators.Rename)
1780
+
1781
+ root = RAParser.parse_query(r'a ⟗ ρ [ R(Id2) ] b')
1782
+ assert isinstance(root, BinaryOperators.FullOuterJoin)
1783
+ assert isinstance(root.left, RAOperand) and isinstance(root.right, UnaryOperators.Rename)
1784
+
1785
+ root = RAParser.parse_query(r'ρ [ R(Id2) ] a ⟗ b')
1786
+ assert isinstance(root, BinaryOperators.FullOuterJoin)
1787
+ assert isinstance(root.right, RAOperand) and isinstance(root.left, UnaryOperators.Rename)
1788
+
1789
+ root = RAParser.parse_query(r'a ⋉ ρ [ R(Id2) ] b')
1790
+ assert isinstance(root, BinaryOperators.LeftSemiJoin)
1791
+ assert isinstance(root.left, RAOperand) and isinstance(root.right, UnaryOperators.Rename)
1792
+
1793
+ root = RAParser.parse_query(r'ρ [ R(Id2) ] a ⋉ b')
1794
+ assert isinstance(root, BinaryOperators.LeftSemiJoin)
1795
+ assert isinstance(root.right, RAOperand) and isinstance(root.left, UnaryOperators.Rename)
1796
+
1797
+ root = RAParser.parse_query(r'a ⋊ ρ [ R(Id2) ] b')
1798
+ assert isinstance(root, BinaryOperators.RightSemiJoin)
1799
+ assert isinstance(root.left, RAOperand) and isinstance(root.right, UnaryOperators.Rename)
1800
+
1801
+ root = RAParser.parse_query(r'ρ [ R(Id2) ] a ⋊ b')
1802
+ assert isinstance(root, BinaryOperators.RightSemiJoin)
1485
1803
  assert isinstance(root.right, RAOperand) and isinstance(root.left, UnaryOperators.Rename)
1486
1804
 
1487
1805
  # join <-> selection
@@ -1542,13 +1860,22 @@ def test_mixed_evaluation_order():
1542
1860
  assert isinstance(root, BinaryOperators.Cross)
1543
1861
  assert isinstance(root.right, RAOperand) and isinstance(root.left, UnaryOperators.Projection)
1544
1862
 
1545
- # cross <-> rename
1863
+ # cross <-> attribute rename
1546
1864
  root = RAParser.parse_query(r'a x β [ Id2 ← Id ] b')
1547
1865
  assert isinstance(root, BinaryOperators.Cross)
1548
- assert isinstance(root.left, RAOperand) and isinstance(root.right, UnaryOperators.Rename)
1866
+ assert isinstance(root.left, RAOperand) and isinstance(root.right, UnaryOperators.AttributeRename)
1549
1867
 
1550
1868
  root = RAParser.parse_query(r'β [ Id2 ← Id ] a x b')
1551
1869
  assert isinstance(root, BinaryOperators.Cross)
1870
+ assert isinstance(root.right, RAOperand) and isinstance(root.left, UnaryOperators.AttributeRename)
1871
+
1872
+ # cross <-> rename
1873
+ root = RAParser.parse_query(r'a x ρ [ R(Id2) ] b')
1874
+ assert isinstance(root, BinaryOperators.Cross)
1875
+ assert isinstance(root.left, RAOperand) and isinstance(root.right, UnaryOperators.Rename)
1876
+
1877
+ root = RAParser.parse_query(r'ρ [ R(Id2) ] a x b')
1878
+ assert isinstance(root, BinaryOperators.Cross)
1552
1879
  assert isinstance(root.right, RAOperand) and isinstance(root.left, UnaryOperators.Rename)
1553
1880
 
1554
1881
  # cross <-> selection
@@ -1569,13 +1896,22 @@ def test_mixed_evaluation_order():
1569
1896
  assert isinstance(root, BinaryOperators.Division)
1570
1897
  assert isinstance(root.right, RAOperand) and isinstance(root.left, UnaryOperators.Projection)
1571
1898
 
1572
- # division <-> rename
1899
+ # division <-> attribute rename
1573
1900
  root = RAParser.parse_query(r'a ÷ β [ Id2 ← Id ] b')
1574
1901
  assert isinstance(root, BinaryOperators.Division)
1575
- assert isinstance(root.left, RAOperand) and isinstance(root.right, UnaryOperators.Rename)
1902
+ assert isinstance(root.left, RAOperand) and isinstance(root.right, UnaryOperators.AttributeRename)
1576
1903
 
1577
1904
  root = RAParser.parse_query(r'β [ Id2 ← Id ] a ÷ b')
1578
1905
  assert isinstance(root, BinaryOperators.Division)
1906
+ assert isinstance(root.right, RAOperand) and isinstance(root.left, UnaryOperators.AttributeRename)
1907
+
1908
+ # division <-> rename
1909
+ root = RAParser.parse_query(r'a ÷ ρ [ R(Id2) ] b')
1910
+ assert isinstance(root, BinaryOperators.Division)
1911
+ assert isinstance(root.left, RAOperand) and isinstance(root.right, UnaryOperators.Rename)
1912
+
1913
+ root = RAParser.parse_query(r'ρ [ R(Id2) ] a ÷ b')
1914
+ assert isinstance(root, BinaryOperators.Division)
1579
1915
  assert isinstance(root.right, RAOperand) and isinstance(root.left, UnaryOperators.Rename)
1580
1916
 
1581
1917
  # division <-> selection
@@ -1613,8 +1949,8 @@ def test_special_queries():
1613
1949
  assert isinstance(root.left, UnaryOperators.Selection)
1614
1950
  assert isinstance(root.left.target, UnaryOperators.Projection)
1615
1951
  assert isinstance(root.left.target.target, RAOperand) and root.left.target.target.name == 'Users'
1616
- assert isinstance(root.right, UnaryOperators.Rename)
1617
- assert isinstance(root.right.target, UnaryOperators.Rename)
1952
+ assert isinstance(root.right, UnaryOperators.AttributeRename)
1953
+ assert isinstance(root.right.target, UnaryOperators.AttributeRename)
1618
1954
  assert isinstance(root.right.target.target, RAOperand) and root.right.target.target.name == 'BannedUsers'
1619
1955
 
1620
1956
  assert con.execute_ra(root) == [
@@ -1,11 +1,26 @@
1
+ import datetime
1
2
  from datetime import date
2
- from typing import Tuple, List, Optional
3
+ from typing import Tuple, List, Optional, Any
3
4
 
4
5
 
5
6
  class ResultSetComparator:
6
7
  def __init__(self, left: List[Tuple | List], right: List[Tuple | List]):
7
- self._left: List[Tuple] = [tuple(t) for t in left]
8
- self._right: List[Tuple] = [tuple(t) for t in right]
8
+ self._left: List[Tuple] = [tuple(self.format_value(t)) for t in left]
9
+ self._right: List[Tuple] = [tuple(self.format_value(t)) for t in right]
10
+
11
+ @staticmethod
12
+ def format_value(value: Any) -> Any:
13
+ if isinstance(value, tuple) or isinstance(value, list):
14
+ return tuple(ResultSetComparator.format_value(t) for t in value)
15
+
16
+ if isinstance(value, datetime.datetime):
17
+ return value.strftime("%Y-%m-%d %H:%M:%S")
18
+ if isinstance(value, datetime.date):
19
+ return value.strftime("%Y-%m-%d")
20
+ if isinstance(value, datetime.time):
21
+ return value.strftime("%H:%M:%S")
22
+
23
+ return value
9
24
 
10
25
  @property
11
26
  def left_only(self) -> List[Tuple]:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: jupyter-duckdb
3
- Version: 1.4.106
3
+ Version: 1.4.108
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