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.
- duckdb_kernel/kernel.py +4 -0
- duckdb_kernel/parser/DCParser.py +7 -0
- duckdb_kernel/parser/RAParser.py +9 -8
- duckdb_kernel/parser/elements/LogicElement.py +0 -2
- duckdb_kernel/parser/elements/RARelationReference.py +86 -0
- duckdb_kernel/parser/elements/RAUnaryOperator.py +6 -0
- duckdb_kernel/parser/elements/__init__.py +1 -0
- duckdb_kernel/parser/elements/binary/Cross.py +1 -1
- duckdb_kernel/parser/elements/binary/FullOuterJoin.py +4 -1
- duckdb_kernel/parser/elements/binary/Join.py +4 -1
- duckdb_kernel/parser/elements/binary/LeftOuterJoin.py +4 -1
- duckdb_kernel/parser/elements/binary/LeftSemiJoin.py +4 -1
- duckdb_kernel/parser/elements/binary/RightOuterJoin.py +4 -1
- duckdb_kernel/parser/elements/binary/RightSemiJoin.py +4 -1
- duckdb_kernel/parser/elements/unary/AttributeRename.py +39 -0
- duckdb_kernel/parser/elements/unary/Projection.py +1 -1
- duckdb_kernel/parser/elements/unary/Rename.py +68 -14
- duckdb_kernel/parser/elements/unary/__init__.py +2 -0
- duckdb_kernel/tests/test_dc.py +29 -0
- duckdb_kernel/tests/test_ra.py +374 -38
- duckdb_kernel/util/ResultSetComparator.py +18 -3
- {jupyter_duckdb-1.4.106.dist-info → jupyter_duckdb-1.4.108.dist-info}/METADATA +1 -1
- {jupyter_duckdb-1.4.106.dist-info → jupyter_duckdb-1.4.108.dist-info}/RECORD +25 -23
- {jupyter_duckdb-1.4.106.dist-info → jupyter_duckdb-1.4.108.dist-info}/WHEEL +0 -0
- {jupyter_duckdb-1.4.106.dist-info → jupyter_duckdb-1.4.108.dist-info}/top_level.txt +0 -0
duckdb_kernel/tests/test_ra.py
CHANGED
|
@@ -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
|
|
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.
|
|
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.
|
|
550
|
+
assert isinstance(root, UnaryOperators.AttributeRename)
|
|
496
551
|
assert isinstance(root.arg, LogicElement)
|
|
497
|
-
assert isinstance(root.target, UnaryOperators.
|
|
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.
|
|
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.
|
|
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
|
-
|
|
1118
|
+
# π
|
|
1119
|
+
root = RAParser.parse_query(r'π [ Id ] σ [ Id > 1 ] (Users)')
|
|
905
1120
|
assert isinstance(root, UnaryOperators.Projection)
|
|
906
|
-
assert isinstance(root.target, UnaryOperators.
|
|
1121
|
+
assert isinstance(root.target, UnaryOperators.Selection)
|
|
907
1122
|
|
|
908
|
-
root = RAParser.parse_query(r'
|
|
909
|
-
assert isinstance(root, UnaryOperators.
|
|
910
|
-
assert isinstance(root.target, UnaryOperators.
|
|
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'π [
|
|
1127
|
+
root = RAParser.parse_query(r'π [ Id2 ] ρ [ R(Id2, Username2) ] (Users)')
|
|
913
1128
|
assert isinstance(root, UnaryOperators.Projection)
|
|
914
|
-
assert isinstance(root.target, UnaryOperators.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
1617
|
-
assert isinstance(root.right.target, UnaryOperators.
|
|
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]:
|