jupyter-duckdb 1.2.7__py3-none-any.whl → 1.2.100__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/parser/elements/binary/Difference.py +1 -1
- duckdb_kernel/parser/elements/binary/Divide.py +1 -1
- duckdb_kernel/parser/elements/binary/Division.py +0 -4
- duckdb_kernel/parser/elements/binary/FullOuterJoin.py +10 -3
- duckdb_kernel/tests/__init__.py +76 -0
- duckdb_kernel/tests/test_dc.py +454 -0
- duckdb_kernel/tests/test_ra.py +1250 -0
- duckdb_kernel/tests/test_result_comparison.py +173 -0
- duckdb_kernel/tests/test_sql.py +48 -0
- {jupyter_duckdb-1.2.7.dist-info → jupyter_duckdb-1.2.100.dist-info}/METADATA +2 -2
- {jupyter_duckdb-1.2.7.dist-info → jupyter_duckdb-1.2.100.dist-info}/RECORD +13 -8
- {jupyter_duckdb-1.2.7.dist-info → jupyter_duckdb-1.2.100.dist-info}/WHEEL +0 -0
- {jupyter_duckdb-1.2.7.dist-info → jupyter_duckdb-1.2.100.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,1250 @@
|
|
|
1
|
+
import pytest
|
|
2
|
+
|
|
3
|
+
import duckdb_kernel.parser.elements.binary as BinaryOperators
|
|
4
|
+
import duckdb_kernel.parser.elements.unary as UnaryOperators
|
|
5
|
+
from duckdb_kernel.parser import RAParser, RAParserError
|
|
6
|
+
from duckdb_kernel.parser.elements import RAOperand, LogicElement
|
|
7
|
+
from . import Connection
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def test_case_insensitivity():
|
|
11
|
+
for query in (
|
|
12
|
+
'Users',
|
|
13
|
+
'users',
|
|
14
|
+
'USERS',
|
|
15
|
+
'userS'
|
|
16
|
+
):
|
|
17
|
+
root = RAParser.parse_query(query)
|
|
18
|
+
|
|
19
|
+
# root is an RAOperand
|
|
20
|
+
assert isinstance(root, RAOperand)
|
|
21
|
+
|
|
22
|
+
# Root's name is the relation name in whatever case
|
|
23
|
+
# it has been written.
|
|
24
|
+
assert root.name == query
|
|
25
|
+
|
|
26
|
+
# execute to test case insensitivity
|
|
27
|
+
with Connection() as con:
|
|
28
|
+
cols, rows = con.execute_ra_return_cols(root)
|
|
29
|
+
|
|
30
|
+
assert [c.lower() for c in cols] == [
|
|
31
|
+
'id',
|
|
32
|
+
'username'
|
|
33
|
+
]
|
|
34
|
+
assert rows == [
|
|
35
|
+
(1, 'Alice'),
|
|
36
|
+
(2, 'Bob'),
|
|
37
|
+
(3, 'Charlie')
|
|
38
|
+
]
|
|
39
|
+
|
|
40
|
+
for query in (
|
|
41
|
+
'π [ Username ] ( Users )',
|
|
42
|
+
'π [ username ] ( Users )',
|
|
43
|
+
'π [ userName ] ( Users )'
|
|
44
|
+
):
|
|
45
|
+
root = RAParser.parse_query(query)
|
|
46
|
+
|
|
47
|
+
# execute to test case insensitivity
|
|
48
|
+
with (Connection() as con):
|
|
49
|
+
cols, rows = con.execute_ra_return_cols(root)
|
|
50
|
+
|
|
51
|
+
assert [c.lower() for c in cols] == [
|
|
52
|
+
'username'
|
|
53
|
+
]
|
|
54
|
+
assert rows == [
|
|
55
|
+
('Alice',),
|
|
56
|
+
('Bob',),
|
|
57
|
+
('Charlie',)
|
|
58
|
+
]
|
|
59
|
+
|
|
60
|
+
for query in (
|
|
61
|
+
'π [ Id, Username ] ( Users )',
|
|
62
|
+
'π [ id, username ] ( Users )',
|
|
63
|
+
'π [ iD, userName ] ( Users )'
|
|
64
|
+
):
|
|
65
|
+
root = RAParser.parse_query(query)
|
|
66
|
+
|
|
67
|
+
# execute to test case insensitivity
|
|
68
|
+
with Connection() as con:
|
|
69
|
+
cols, rows = con.execute_ra_return_cols(root)
|
|
70
|
+
|
|
71
|
+
assert [c.lower() for c in cols] == [
|
|
72
|
+
'id',
|
|
73
|
+
'username'
|
|
74
|
+
]
|
|
75
|
+
assert rows == [
|
|
76
|
+
(1, 'Alice'),
|
|
77
|
+
(2, 'Bob'),
|
|
78
|
+
(3, 'Charlie')
|
|
79
|
+
]
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
def test_binary_operator_cross():
|
|
83
|
+
for query in (
|
|
84
|
+
r'Shows x Seasons',
|
|
85
|
+
):
|
|
86
|
+
root = RAParser.parse_query(query)
|
|
87
|
+
|
|
88
|
+
assert isinstance(root, BinaryOperators.Cross)
|
|
89
|
+
assert isinstance(root.left, RAOperand) and root.left.name == 'Shows'
|
|
90
|
+
assert isinstance(root.right, RAOperand) and root.right.name == 'Seasons'
|
|
91
|
+
|
|
92
|
+
with Connection() as con:
|
|
93
|
+
cols, rows = con.execute_ra_return_cols(root)
|
|
94
|
+
|
|
95
|
+
assert [c.lower() for c in cols] == [
|
|
96
|
+
'shows.showid',
|
|
97
|
+
'shows.showname',
|
|
98
|
+
'seasons.seasonnumber',
|
|
99
|
+
'seasons.showid',
|
|
100
|
+
'seasons.seasonname'
|
|
101
|
+
]
|
|
102
|
+
assert rows == [
|
|
103
|
+
(1, 'Show 1', 1, 1, 'Show 1 / Season 1'),
|
|
104
|
+
(1, 'Show 1', 1, 2, 'Show 2 / Season 1'),
|
|
105
|
+
(1, 'Show 1', 2, 1, 'Show 1 / Season 2'),
|
|
106
|
+
(1, 'Show 1', 2, 2, 'Show 2 / Season 2'),
|
|
107
|
+
(2, 'Show 2', 1, 1, 'Show 1 / Season 1'),
|
|
108
|
+
(2, 'Show 2', 1, 2, 'Show 2 / Season 1'),
|
|
109
|
+
(2, 'Show 2', 2, 1, 'Show 1 / Season 2'),
|
|
110
|
+
(2, 'Show 2', 2, 2, 'Show 2 / Season 2')
|
|
111
|
+
]
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
def test_binary_operator_difference():
|
|
115
|
+
for query in (
|
|
116
|
+
r'Users - BannedUsers',
|
|
117
|
+
r'Users \ BannedUsers',
|
|
118
|
+
):
|
|
119
|
+
root = RAParser.parse_query(query)
|
|
120
|
+
|
|
121
|
+
assert isinstance(root, BinaryOperators.Difference)
|
|
122
|
+
assert isinstance(root.left, RAOperand) and root.left.name == 'Users'
|
|
123
|
+
assert isinstance(root.right, RAOperand) and root.right.name == 'BannedUsers'
|
|
124
|
+
|
|
125
|
+
with Connection() as con:
|
|
126
|
+
cols, rows = con.execute_ra_return_cols(root)
|
|
127
|
+
|
|
128
|
+
assert [c.lower() for c in cols] == [
|
|
129
|
+
'id',
|
|
130
|
+
'username'
|
|
131
|
+
]
|
|
132
|
+
assert rows == [
|
|
133
|
+
(1, 'Alice'),
|
|
134
|
+
(3, 'Charlie')
|
|
135
|
+
]
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
def test_binary_operator_division():
|
|
139
|
+
for query in (
|
|
140
|
+
r'π [ShowId, SeasonNumber, EpisodeNumber] (Episodes) ÷ π [ EpisodeNumber ] (σ [ ShowId = 1 AND SeasonNumber = 1 ] (Episodes))',
|
|
141
|
+
r'π [ShowId, SeasonNumber, EpisodeNumber] (Episodes) : π [ EpisodeNumber ] (σ [ ShowId = 1 AND SeasonNumber = 1 ] (Episodes))',
|
|
142
|
+
):
|
|
143
|
+
root = RAParser.parse_query(query)
|
|
144
|
+
|
|
145
|
+
assert isinstance(root, BinaryOperators.Division)
|
|
146
|
+
assert isinstance(root.left, UnaryOperators.Projection)
|
|
147
|
+
assert isinstance(root.left.target, RAOperand) and root.left.target.name == 'Episodes'
|
|
148
|
+
assert isinstance(root.right, UnaryOperators.Projection)
|
|
149
|
+
assert isinstance(root.right.target, UnaryOperators.Selection)
|
|
150
|
+
assert isinstance(root.right.target.target, RAOperand) and root.right.target.target.name == 'Episodes'
|
|
151
|
+
|
|
152
|
+
with Connection() as con:
|
|
153
|
+
cols, rows = con.execute_ra_return_cols(root)
|
|
154
|
+
|
|
155
|
+
assert [c.lower() for c in cols] == [
|
|
156
|
+
'showid',
|
|
157
|
+
'seasonnumber'
|
|
158
|
+
]
|
|
159
|
+
assert rows == [
|
|
160
|
+
(1, 1),
|
|
161
|
+
(1, 2)
|
|
162
|
+
]
|
|
163
|
+
|
|
164
|
+
|
|
165
|
+
def test_binary_operator_intersection():
|
|
166
|
+
for query in (
|
|
167
|
+
r'Users ∩ BannedUsers',
|
|
168
|
+
r'Users cap BannedUsers'
|
|
169
|
+
):
|
|
170
|
+
root = RAParser.parse_query(query)
|
|
171
|
+
|
|
172
|
+
assert isinstance(root, BinaryOperators.Intersection)
|
|
173
|
+
assert isinstance(root.left, RAOperand) and root.left.name == 'Users'
|
|
174
|
+
assert isinstance(root.right, RAOperand) and root.right.name == 'BannedUsers'
|
|
175
|
+
|
|
176
|
+
with Connection() as con:
|
|
177
|
+
cols, rows = con.execute_ra_return_cols(root)
|
|
178
|
+
|
|
179
|
+
assert [c.lower() for c in cols] == [
|
|
180
|
+
'id',
|
|
181
|
+
'username'
|
|
182
|
+
]
|
|
183
|
+
assert rows == [
|
|
184
|
+
(2, 'Bob')
|
|
185
|
+
]
|
|
186
|
+
|
|
187
|
+
|
|
188
|
+
def test_binary_operator_join():
|
|
189
|
+
for query in (
|
|
190
|
+
r'Shows ⋈ Seasons',
|
|
191
|
+
r'Shows join Seasons'
|
|
192
|
+
):
|
|
193
|
+
root = RAParser.parse_query(query)
|
|
194
|
+
|
|
195
|
+
assert isinstance(root, BinaryOperators.Join)
|
|
196
|
+
assert isinstance(root.left, RAOperand) and root.left.name == 'Shows'
|
|
197
|
+
assert isinstance(root.right, RAOperand) and root.right.name == 'Seasons'
|
|
198
|
+
|
|
199
|
+
with Connection() as con:
|
|
200
|
+
cols, rows = con.execute_ra_return_cols(root)
|
|
201
|
+
|
|
202
|
+
assert [c.lower() for c in cols] == [
|
|
203
|
+
'shows.showid',
|
|
204
|
+
'shows.showname',
|
|
205
|
+
'seasons.seasonnumber',
|
|
206
|
+
'seasons.seasonname'
|
|
207
|
+
]
|
|
208
|
+
assert rows == [
|
|
209
|
+
(1, 'Show 1', 1, 'Show 1 / Season 1'),
|
|
210
|
+
(1, 'Show 1', 2, 'Show 1 / Season 2'),
|
|
211
|
+
(2, 'Show 2', 1, 'Show 2 / Season 1'),
|
|
212
|
+
(2, 'Show 2', 2, 'Show 2 / Season 2')
|
|
213
|
+
]
|
|
214
|
+
|
|
215
|
+
|
|
216
|
+
def test_binary_operator_ljoin():
|
|
217
|
+
for query in (
|
|
218
|
+
r'Users ⟕ BannedUsers',
|
|
219
|
+
r'Users ljoin BannedUsers'
|
|
220
|
+
):
|
|
221
|
+
root = RAParser.parse_query(query)
|
|
222
|
+
|
|
223
|
+
assert isinstance(root, BinaryOperators.LeftOuterJoin)
|
|
224
|
+
assert isinstance(root.left, RAOperand) and root.left.name == 'Users'
|
|
225
|
+
assert isinstance(root.right, RAOperand) and root.right.name == 'BannedUsers'
|
|
226
|
+
|
|
227
|
+
with Connection() as con:
|
|
228
|
+
cols, rows = con.execute_ra_return_cols(root)
|
|
229
|
+
|
|
230
|
+
assert [c.lower() for c in cols] == [
|
|
231
|
+
'users.id',
|
|
232
|
+
'users.username',
|
|
233
|
+
'bannedusers.bannedusername'
|
|
234
|
+
]
|
|
235
|
+
assert rows == [
|
|
236
|
+
(1, 'Alice', None),
|
|
237
|
+
(2, 'Bob', 'Bob'),
|
|
238
|
+
(3, 'Charlie', None),
|
|
239
|
+
]
|
|
240
|
+
|
|
241
|
+
|
|
242
|
+
def test_binary_operator_rjoin():
|
|
243
|
+
for query in (
|
|
244
|
+
r'Users ⟖ BannedUsers',
|
|
245
|
+
r'Users rjoin BannedUsers'
|
|
246
|
+
):
|
|
247
|
+
root = RAParser.parse_query(query)
|
|
248
|
+
|
|
249
|
+
assert isinstance(root, BinaryOperators.RightOuterJoin)
|
|
250
|
+
assert isinstance(root.left, RAOperand) and root.left.name == 'Users'
|
|
251
|
+
assert isinstance(root.right, RAOperand) and root.right.name == 'BannedUsers'
|
|
252
|
+
|
|
253
|
+
with Connection() as con:
|
|
254
|
+
cols, rows = con.execute_ra_return_cols(root)
|
|
255
|
+
|
|
256
|
+
assert [c.lower() for c in cols] == [
|
|
257
|
+
'bannedusers.id',
|
|
258
|
+
'users.username',
|
|
259
|
+
'bannedusers.bannedusername'
|
|
260
|
+
]
|
|
261
|
+
assert rows == [
|
|
262
|
+
(2, 'Bob', 'Bob'),
|
|
263
|
+
(4, None, 'David')
|
|
264
|
+
]
|
|
265
|
+
|
|
266
|
+
|
|
267
|
+
def test_binary_operator_fjoin():
|
|
268
|
+
for query in (
|
|
269
|
+
r'Users ⟗ BannedUsers',
|
|
270
|
+
r'Users fjoin BannedUsers',
|
|
271
|
+
r'Users ojoin BannedUsers'
|
|
272
|
+
):
|
|
273
|
+
root = RAParser.parse_query(query)
|
|
274
|
+
|
|
275
|
+
assert isinstance(root, BinaryOperators.FullOuterJoin)
|
|
276
|
+
assert isinstance(root.left, RAOperand) and root.left.name == 'Users'
|
|
277
|
+
assert isinstance(root.right, RAOperand) and root.right.name == 'BannedUsers'
|
|
278
|
+
|
|
279
|
+
with Connection() as con:
|
|
280
|
+
cols, rows = con.execute_ra_return_cols(root)
|
|
281
|
+
|
|
282
|
+
assert [c.lower() for c in cols] == [
|
|
283
|
+
'users.id',
|
|
284
|
+
'users.username',
|
|
285
|
+
'bannedusers.bannedusername'
|
|
286
|
+
]
|
|
287
|
+
assert rows == [
|
|
288
|
+
(1, 'Alice', None),
|
|
289
|
+
(2, 'Bob', 'Bob'),
|
|
290
|
+
(3, 'Charlie', None),
|
|
291
|
+
(4, None, 'David')
|
|
292
|
+
]
|
|
293
|
+
|
|
294
|
+
|
|
295
|
+
def test_binary_operator_union():
|
|
296
|
+
for query in (
|
|
297
|
+
r'Users ∪ BannedUsers',
|
|
298
|
+
r'Users cup BannedUsers'
|
|
299
|
+
):
|
|
300
|
+
root = RAParser.parse_query(query)
|
|
301
|
+
|
|
302
|
+
assert isinstance(root, BinaryOperators.Union)
|
|
303
|
+
assert isinstance(root.left, RAOperand) and root.left.name == 'Users'
|
|
304
|
+
assert isinstance(root.right, RAOperand) and root.right.name == 'BannedUsers'
|
|
305
|
+
|
|
306
|
+
with Connection() as con:
|
|
307
|
+
cols, rows = con.execute_ra_return_cols(root)
|
|
308
|
+
|
|
309
|
+
assert [c.lower() for c in cols] == [
|
|
310
|
+
'id',
|
|
311
|
+
'username'
|
|
312
|
+
]
|
|
313
|
+
assert rows == [
|
|
314
|
+
(1, 'Alice'),
|
|
315
|
+
(2, 'Bob'),
|
|
316
|
+
(3, 'Charlie'),
|
|
317
|
+
(4, 'David')
|
|
318
|
+
]
|
|
319
|
+
|
|
320
|
+
|
|
321
|
+
def test_unary_operator_projection():
|
|
322
|
+
with Connection() as con:
|
|
323
|
+
for query in (
|
|
324
|
+
r'π Id Users',
|
|
325
|
+
r'π [ Id ] Users',
|
|
326
|
+
r'π [ Id ] ( Users )',
|
|
327
|
+
r'π[Id](Users)',
|
|
328
|
+
r'Pi Id Users',
|
|
329
|
+
r'Pi [ Id ] Users',
|
|
330
|
+
r'Pi [ Id ] ( Users )',
|
|
331
|
+
r'Pi[Id](Users)'
|
|
332
|
+
):
|
|
333
|
+
root = RAParser.parse_query(query)
|
|
334
|
+
|
|
335
|
+
assert isinstance(root, UnaryOperators.Projection)
|
|
336
|
+
assert isinstance(root.arg, LogicElement)
|
|
337
|
+
assert isinstance(root.target, RAOperand) and root.target.name == 'Users'
|
|
338
|
+
|
|
339
|
+
cols, rows = con.execute_ra_return_cols(root)
|
|
340
|
+
|
|
341
|
+
assert [c.lower() for c in cols] == [
|
|
342
|
+
'id'
|
|
343
|
+
]
|
|
344
|
+
assert rows == [
|
|
345
|
+
(1,),
|
|
346
|
+
(2,),
|
|
347
|
+
(3,)
|
|
348
|
+
]
|
|
349
|
+
|
|
350
|
+
for query in (
|
|
351
|
+
r'π Id π Id, Username Users',
|
|
352
|
+
r'π [ Id ] (π [ Id, Username ] (Users))',
|
|
353
|
+
r'π[Id]π[Id,Username]Users',
|
|
354
|
+
r'Pi Id Pi Id, Username Users',
|
|
355
|
+
r'Pi [ Id ] (Pi [ Id, Username ] (Users))',
|
|
356
|
+
r'Pi[Id]Pi[Id,Username]Users'
|
|
357
|
+
):
|
|
358
|
+
root = RAParser.parse_query(query)
|
|
359
|
+
|
|
360
|
+
assert isinstance(root, UnaryOperators.Projection)
|
|
361
|
+
assert isinstance(root.arg, LogicElement)
|
|
362
|
+
assert isinstance(root.target, UnaryOperators.Projection)
|
|
363
|
+
assert isinstance(root.target.arg, LogicElement)
|
|
364
|
+
assert isinstance(root.target.target, RAOperand) and root.target.target.name == 'Users'
|
|
365
|
+
|
|
366
|
+
cols, rows = con.execute_ra_return_cols(root)
|
|
367
|
+
|
|
368
|
+
assert [c.lower() for c in cols] == [
|
|
369
|
+
'id'
|
|
370
|
+
]
|
|
371
|
+
assert rows == [
|
|
372
|
+
(1,),
|
|
373
|
+
(2,),
|
|
374
|
+
(3,)
|
|
375
|
+
]
|
|
376
|
+
|
|
377
|
+
|
|
378
|
+
def test_unary_operator_rename():
|
|
379
|
+
with Connection() as con:
|
|
380
|
+
for query in (
|
|
381
|
+
r'β Id2 ← Id Users',
|
|
382
|
+
r'β [ Id2 ← Id ] Users',
|
|
383
|
+
r'β [ Id2 ← Id ] ( Users )',
|
|
384
|
+
r'β[Id2←Id](Users)',
|
|
385
|
+
r'Beta Id2 ← Id Users',
|
|
386
|
+
r'Beta [ Id2 ← Id ] Users',
|
|
387
|
+
r'Beta [ Id2 ← Id ] ( Users )',
|
|
388
|
+
r'Beta[Id2←Id](Users)',
|
|
389
|
+
r'Beta Id2 <- Id Users',
|
|
390
|
+
r'Beta [ Id2 <- Id ] Users',
|
|
391
|
+
r'Beta [ Id2 <- Id ] ( Users )',
|
|
392
|
+
r'Beta[Id2<-Id](Users)'
|
|
393
|
+
):
|
|
394
|
+
root = RAParser.parse_query(query)
|
|
395
|
+
|
|
396
|
+
assert isinstance(root, UnaryOperators.Rename)
|
|
397
|
+
assert isinstance(root.arg, LogicElement)
|
|
398
|
+
assert isinstance(root.target, RAOperand) and root.target.name == 'Users'
|
|
399
|
+
|
|
400
|
+
cols, rows = con.execute_ra_return_cols(root)
|
|
401
|
+
|
|
402
|
+
assert [c.lower() for c in cols] == [
|
|
403
|
+
'id2',
|
|
404
|
+
'username'
|
|
405
|
+
]
|
|
406
|
+
assert rows == [
|
|
407
|
+
(1, 'Alice'),
|
|
408
|
+
(2, 'Bob'),
|
|
409
|
+
(3, 'Charlie')
|
|
410
|
+
]
|
|
411
|
+
|
|
412
|
+
for query in (
|
|
413
|
+
r'β Id ← Id2 β Id2 ← Id Users',
|
|
414
|
+
r'β [Id ← Id2] (β [Id2 ← Id] (Users))',
|
|
415
|
+
r'βId←Id2βId2←Id Users',
|
|
416
|
+
r'beta Id ← Id2 beta Id2 ← Id Users',
|
|
417
|
+
r'beta [Id ← Id2] (beta [Id2 ← Id] (Users))',
|
|
418
|
+
r'beta Id←Id2 beta Id2←Id Users',
|
|
419
|
+
r'beta Id <- Id2 beta Id2 <- Id Users',
|
|
420
|
+
r'beta [Id <- Id2] (beta [Id2 <- Id] (Users))',
|
|
421
|
+
r'beta Id<-Id2 beta Id2<-Id Users'
|
|
422
|
+
):
|
|
423
|
+
root = RAParser.parse_query(query)
|
|
424
|
+
|
|
425
|
+
assert isinstance(root, UnaryOperators.Rename)
|
|
426
|
+
assert isinstance(root.arg, LogicElement)
|
|
427
|
+
assert isinstance(root.target, UnaryOperators.Rename)
|
|
428
|
+
assert isinstance(root.target.arg, LogicElement)
|
|
429
|
+
assert isinstance(root.target.target, RAOperand) and root.target.target.name == 'Users'
|
|
430
|
+
|
|
431
|
+
cols, rows = con.execute_ra_return_cols(root)
|
|
432
|
+
|
|
433
|
+
assert [c.lower() for c in cols] == [
|
|
434
|
+
'id',
|
|
435
|
+
'username'
|
|
436
|
+
]
|
|
437
|
+
assert rows == [
|
|
438
|
+
(1, 'Alice'),
|
|
439
|
+
(2, 'Bob'),
|
|
440
|
+
(3, 'Charlie')
|
|
441
|
+
]
|
|
442
|
+
|
|
443
|
+
|
|
444
|
+
def test_unary_operator_selection():
|
|
445
|
+
with Connection() as con:
|
|
446
|
+
for query in (
|
|
447
|
+
r'σ Id > 1 Users',
|
|
448
|
+
r'σ [ Id > 1 ] Users',
|
|
449
|
+
r'σ [ Id > 1 ] ( Users )',
|
|
450
|
+
r'σ[Id>1](Users)',
|
|
451
|
+
r'Sigma Id > 1 Users',
|
|
452
|
+
r'Sigma [ Id > 1 ] Users',
|
|
453
|
+
r'Sigma [ Id > 1 ] ( Users )',
|
|
454
|
+
r'Sigma[Id>1](Users)'
|
|
455
|
+
):
|
|
456
|
+
root = RAParser.parse_query(query)
|
|
457
|
+
|
|
458
|
+
assert isinstance(root, UnaryOperators.Selection)
|
|
459
|
+
assert isinstance(root.target, RAOperand) and root.target.name == 'Users'
|
|
460
|
+
assert isinstance(root.arg, LogicElement)
|
|
461
|
+
|
|
462
|
+
cols, rows = con.execute_ra_return_cols(root)
|
|
463
|
+
|
|
464
|
+
assert [c.lower() for c in cols] == [
|
|
465
|
+
'id',
|
|
466
|
+
'username'
|
|
467
|
+
]
|
|
468
|
+
assert rows == [
|
|
469
|
+
(2, 'Bob'),
|
|
470
|
+
(3, 'Charlie')
|
|
471
|
+
]
|
|
472
|
+
|
|
473
|
+
for query in (
|
|
474
|
+
r'σ Id > 1 σ Id > 0 Users',
|
|
475
|
+
r'σ [ Id > 1 ] (σ [Id > 1] (Users))',
|
|
476
|
+
r'σ[Id>1]σ[Id>1]Users',
|
|
477
|
+
r'Sigma Id > 1 Sigma Id > 0 Users',
|
|
478
|
+
r'Sigma [ Id > 1 ] (Sigma [Id > 1] (Users))',
|
|
479
|
+
r'Sigma[Id>1]Sigma[Id>1]Users'
|
|
480
|
+
):
|
|
481
|
+
root = RAParser.parse_query(query)
|
|
482
|
+
|
|
483
|
+
assert isinstance(root, UnaryOperators.Selection)
|
|
484
|
+
assert isinstance(root.arg, LogicElement)
|
|
485
|
+
assert isinstance(root.target, UnaryOperators.Selection)
|
|
486
|
+
assert isinstance(root.target.arg, LogicElement)
|
|
487
|
+
assert isinstance(root.target.target, RAOperand) and root.target.target.name == 'Users'
|
|
488
|
+
|
|
489
|
+
cols, rows = con.execute_ra_return_cols(root)
|
|
490
|
+
|
|
491
|
+
assert [c.lower() for c in cols] == [
|
|
492
|
+
'id',
|
|
493
|
+
'username'
|
|
494
|
+
]
|
|
495
|
+
assert rows == [
|
|
496
|
+
(2, 'Bob'),
|
|
497
|
+
(3, 'Charlie')
|
|
498
|
+
]
|
|
499
|
+
|
|
500
|
+
|
|
501
|
+
def test_unary_inner_to_outer_evaluation_order():
|
|
502
|
+
root = RAParser.parse_query(r'π [ Id ] π [ Id, Username ] (Users)')
|
|
503
|
+
assert isinstance(root, UnaryOperators.Projection) and root.columns == ('Id',)
|
|
504
|
+
assert isinstance(root.target, UnaryOperators.Projection) and root.target.columns == ('Id', 'Username')
|
|
505
|
+
|
|
506
|
+
root = RAParser.parse_query(r'σ [ Id > 2 ] σ [ Id > 1 ] (Users)')
|
|
507
|
+
assert isinstance(root, UnaryOperators.Selection)
|
|
508
|
+
assert isinstance(root.condition, BinaryOperators.GreaterThan)
|
|
509
|
+
assert root.condition.left == ('Id',) and root.condition.right == ('2',)
|
|
510
|
+
assert isinstance(root.target, UnaryOperators.Selection)
|
|
511
|
+
assert isinstance(root.target.condition, BinaryOperators.GreaterThan)
|
|
512
|
+
assert root.target.condition.left == ('Id',) and root.target.condition.right == ('1',)
|
|
513
|
+
|
|
514
|
+
root = RAParser.parse_query(r'β [ Id3 ← Id2 ] β [ Id2 ← Id ] (Users)')
|
|
515
|
+
assert isinstance(root, UnaryOperators.Rename)
|
|
516
|
+
assert isinstance(root.arrow, BinaryOperators.ArrowLeft)
|
|
517
|
+
assert root.arrow.left == ('Id3',) and root.arrow.right == ('Id2',)
|
|
518
|
+
assert isinstance(root.target, UnaryOperators.Rename)
|
|
519
|
+
assert isinstance(root.target.arrow, BinaryOperators.ArrowLeft)
|
|
520
|
+
assert root.target.arrow.left == ('Id2',) and root.target.arrow.right == ('Id',)
|
|
521
|
+
|
|
522
|
+
|
|
523
|
+
def test_binary_left_to_right_evaluation_order():
|
|
524
|
+
# difference
|
|
525
|
+
root = RAParser.parse_query(r'a \ b \ c')
|
|
526
|
+
assert isinstance(root, BinaryOperators.Difference)
|
|
527
|
+
assert isinstance(root.left, BinaryOperators.Difference)
|
|
528
|
+
assert isinstance(root.left.left, RAOperand)
|
|
529
|
+
assert root.left.left.name == 'a'
|
|
530
|
+
assert isinstance(root.left.right, RAOperand)
|
|
531
|
+
assert root.left.right.name == 'b'
|
|
532
|
+
assert isinstance(root.right, RAOperand)
|
|
533
|
+
assert root.right.name == 'c'
|
|
534
|
+
|
|
535
|
+
# union
|
|
536
|
+
root = RAParser.parse_query(r'a ∪ b ∪ c')
|
|
537
|
+
assert isinstance(root, BinaryOperators.Union)
|
|
538
|
+
assert isinstance(root.left, BinaryOperators.Union)
|
|
539
|
+
assert isinstance(root.left.left, RAOperand)
|
|
540
|
+
assert root.left.left.name == 'a'
|
|
541
|
+
assert isinstance(root.left.right, RAOperand)
|
|
542
|
+
assert root.left.right.name == 'b'
|
|
543
|
+
assert isinstance(root.right, RAOperand)
|
|
544
|
+
assert root.right.name == 'c'
|
|
545
|
+
|
|
546
|
+
# intersection
|
|
547
|
+
root = RAParser.parse_query(r'a ∩ b ∩ c')
|
|
548
|
+
assert isinstance(root, BinaryOperators.Intersection)
|
|
549
|
+
assert isinstance(root.left, BinaryOperators.Intersection)
|
|
550
|
+
assert isinstance(root.left.left, RAOperand)
|
|
551
|
+
assert root.left.left.name == 'a'
|
|
552
|
+
assert isinstance(root.left.right, RAOperand)
|
|
553
|
+
assert root.left.right.name == 'b'
|
|
554
|
+
assert isinstance(root.right, RAOperand)
|
|
555
|
+
assert root.right.name == 'c'
|
|
556
|
+
|
|
557
|
+
# natural join
|
|
558
|
+
root = RAParser.parse_query(r'a ⋈ b ⋈ c')
|
|
559
|
+
assert isinstance(root, BinaryOperators.Join)
|
|
560
|
+
assert isinstance(root.left, BinaryOperators.Join)
|
|
561
|
+
assert isinstance(root.left.left, RAOperand)
|
|
562
|
+
assert root.left.left.name == 'a'
|
|
563
|
+
assert isinstance(root.left.right, RAOperand)
|
|
564
|
+
assert root.left.right.name == 'b'
|
|
565
|
+
assert isinstance(root.right, RAOperand)
|
|
566
|
+
assert root.right.name == 'c'
|
|
567
|
+
|
|
568
|
+
# outer join
|
|
569
|
+
root = RAParser.parse_query(r'a ⟕ b ⟕ c')
|
|
570
|
+
assert isinstance(root, BinaryOperators.LeftOuterJoin)
|
|
571
|
+
assert isinstance(root.left, BinaryOperators.LeftOuterJoin)
|
|
572
|
+
assert isinstance(root.left.left, RAOperand)
|
|
573
|
+
assert root.left.left.name == 'a'
|
|
574
|
+
assert isinstance(root.left.right, RAOperand)
|
|
575
|
+
assert root.left.right.name == 'b'
|
|
576
|
+
assert isinstance(root.right, RAOperand)
|
|
577
|
+
assert root.right.name == 'c'
|
|
578
|
+
|
|
579
|
+
root = RAParser.parse_query(r'a ⟖ b ⟖ c')
|
|
580
|
+
assert isinstance(root, BinaryOperators.RightOuterJoin)
|
|
581
|
+
assert isinstance(root.left, BinaryOperators.RightOuterJoin)
|
|
582
|
+
assert isinstance(root.left.left, RAOperand)
|
|
583
|
+
assert root.left.left.name == 'a'
|
|
584
|
+
assert isinstance(root.left.right, RAOperand)
|
|
585
|
+
assert root.left.right.name == 'b'
|
|
586
|
+
assert isinstance(root.right, RAOperand)
|
|
587
|
+
assert root.right.name == 'c'
|
|
588
|
+
|
|
589
|
+
root = RAParser.parse_query(r'a ⟗ b ⟗ c')
|
|
590
|
+
assert isinstance(root, BinaryOperators.FullOuterJoin)
|
|
591
|
+
assert isinstance(root.left, BinaryOperators.FullOuterJoin)
|
|
592
|
+
assert isinstance(root.left.left, RAOperand)
|
|
593
|
+
assert root.left.left.name == 'a'
|
|
594
|
+
assert isinstance(root.left.right, RAOperand)
|
|
595
|
+
assert root.left.right.name == 'b'
|
|
596
|
+
assert isinstance(root.right, RAOperand)
|
|
597
|
+
assert root.right.name == 'c'
|
|
598
|
+
|
|
599
|
+
# mixed outer joins
|
|
600
|
+
root = RAParser.parse_query(r'a ⟕ b ⟖ c')
|
|
601
|
+
assert isinstance(root, BinaryOperators.RightOuterJoin)
|
|
602
|
+
assert isinstance(root.left, BinaryOperators.LeftOuterJoin)
|
|
603
|
+
assert isinstance(root.left.left, RAOperand)
|
|
604
|
+
assert root.left.left.name == 'a'
|
|
605
|
+
assert isinstance(root.left.right, RAOperand)
|
|
606
|
+
assert root.left.right.name == 'b'
|
|
607
|
+
assert isinstance(root.right, RAOperand)
|
|
608
|
+
assert root.right.name == 'c'
|
|
609
|
+
|
|
610
|
+
root = RAParser.parse_query(r'a ⟕ b ⟗ c')
|
|
611
|
+
assert isinstance(root, BinaryOperators.FullOuterJoin)
|
|
612
|
+
assert isinstance(root.left, BinaryOperators.LeftOuterJoin)
|
|
613
|
+
assert isinstance(root.left.left, RAOperand)
|
|
614
|
+
assert root.left.left.name == 'a'
|
|
615
|
+
assert isinstance(root.left.right, RAOperand)
|
|
616
|
+
assert root.left.right.name == 'b'
|
|
617
|
+
assert isinstance(root.right, RAOperand)
|
|
618
|
+
assert root.right.name == 'c'
|
|
619
|
+
|
|
620
|
+
root = RAParser.parse_query(r'a ⟖ b ⟕ c')
|
|
621
|
+
assert isinstance(root, BinaryOperators.LeftOuterJoin)
|
|
622
|
+
assert isinstance(root.left, BinaryOperators.RightOuterJoin)
|
|
623
|
+
assert isinstance(root.left.left, RAOperand)
|
|
624
|
+
assert root.left.left.name == 'a'
|
|
625
|
+
assert isinstance(root.left.right, RAOperand)
|
|
626
|
+
assert root.left.right.name == 'b'
|
|
627
|
+
assert isinstance(root.right, RAOperand)
|
|
628
|
+
assert root.right.name == 'c'
|
|
629
|
+
|
|
630
|
+
root = RAParser.parse_query(r'a ⟖ b ⟗ c')
|
|
631
|
+
assert isinstance(root, BinaryOperators.FullOuterJoin)
|
|
632
|
+
assert isinstance(root.left, BinaryOperators.RightOuterJoin)
|
|
633
|
+
assert isinstance(root.left.left, RAOperand)
|
|
634
|
+
assert root.left.left.name == 'a'
|
|
635
|
+
assert isinstance(root.left.right, RAOperand)
|
|
636
|
+
assert root.left.right.name == 'b'
|
|
637
|
+
assert isinstance(root.right, RAOperand)
|
|
638
|
+
assert root.right.name == 'c'
|
|
639
|
+
|
|
640
|
+
root = RAParser.parse_query(r'a ⟗ b ⟕ c')
|
|
641
|
+
assert isinstance(root, BinaryOperators.LeftOuterJoin)
|
|
642
|
+
assert isinstance(root.left, BinaryOperators.FullOuterJoin)
|
|
643
|
+
assert isinstance(root.left.left, RAOperand)
|
|
644
|
+
assert root.left.left.name == 'a'
|
|
645
|
+
assert isinstance(root.left.right, RAOperand)
|
|
646
|
+
assert root.left.right.name == 'b'
|
|
647
|
+
assert isinstance(root.right, RAOperand)
|
|
648
|
+
assert root.right.name == 'c'
|
|
649
|
+
|
|
650
|
+
root = RAParser.parse_query(r'a ⟗ b ⟖ c')
|
|
651
|
+
assert isinstance(root, BinaryOperators.RightOuterJoin)
|
|
652
|
+
assert isinstance(root.left, BinaryOperators.FullOuterJoin)
|
|
653
|
+
assert isinstance(root.left.left, RAOperand)
|
|
654
|
+
assert root.left.left.name == 'a'
|
|
655
|
+
assert isinstance(root.left.right, RAOperand)
|
|
656
|
+
assert root.left.right.name == 'b'
|
|
657
|
+
assert isinstance(root.right, RAOperand)
|
|
658
|
+
assert root.right.name == 'c'
|
|
659
|
+
|
|
660
|
+
# cross join
|
|
661
|
+
root = RAParser.parse_query(r'a x b x c')
|
|
662
|
+
assert isinstance(root, BinaryOperators.Cross)
|
|
663
|
+
assert isinstance(root.left, BinaryOperators.Cross)
|
|
664
|
+
assert isinstance(root.left.left, RAOperand)
|
|
665
|
+
assert root.left.left.name == 'a'
|
|
666
|
+
assert isinstance(root.left.right, RAOperand)
|
|
667
|
+
assert root.left.right.name == 'b'
|
|
668
|
+
assert isinstance(root.right, RAOperand)
|
|
669
|
+
assert root.right.name == 'c'
|
|
670
|
+
|
|
671
|
+
|
|
672
|
+
def test_unary_evaluation_order():
|
|
673
|
+
root = RAParser.parse_query(r'π [ Id2 ] β [ Id2 ← Id ] (Users)')
|
|
674
|
+
assert isinstance(root, UnaryOperators.Projection)
|
|
675
|
+
assert isinstance(root.target, UnaryOperators.Rename)
|
|
676
|
+
|
|
677
|
+
root = RAParser.parse_query(r'β [ Id2 ← Id ] π [ Id ] (Users)')
|
|
678
|
+
assert isinstance(root, UnaryOperators.Rename)
|
|
679
|
+
assert isinstance(root.target, UnaryOperators.Projection)
|
|
680
|
+
|
|
681
|
+
root = RAParser.parse_query(r'π [ Id ] σ [ Id > 1 ] (Users)')
|
|
682
|
+
assert isinstance(root, UnaryOperators.Projection)
|
|
683
|
+
assert isinstance(root.target, UnaryOperators.Selection)
|
|
684
|
+
|
|
685
|
+
root = RAParser.parse_query(r'σ [ Id > 1 ] π [ Id ] (Users)')
|
|
686
|
+
assert isinstance(root, UnaryOperators.Selection)
|
|
687
|
+
assert isinstance(root.target, UnaryOperators.Projection)
|
|
688
|
+
|
|
689
|
+
root = RAParser.parse_query(r'σ [ Id2 > 1 ] β [ Id2 ← Id ] (Users)')
|
|
690
|
+
assert isinstance(root, UnaryOperators.Selection)
|
|
691
|
+
assert isinstance(root.target, UnaryOperators.Rename)
|
|
692
|
+
|
|
693
|
+
root = RAParser.parse_query(r'β [ Id2 ← Id ] σ [ Id > 1 ] (Users)')
|
|
694
|
+
assert isinstance(root, UnaryOperators.Rename)
|
|
695
|
+
assert isinstance(root.target, UnaryOperators.Selection)
|
|
696
|
+
|
|
697
|
+
|
|
698
|
+
def test_binary_evaluation_order():
|
|
699
|
+
# difference <-> union
|
|
700
|
+
root = RAParser.parse_query(r'a \ b ∪ c')
|
|
701
|
+
assert isinstance(root, BinaryOperators.Difference)
|
|
702
|
+
assert isinstance(root.left, RAOperand) and isinstance(root.right, BinaryOperators.Union)
|
|
703
|
+
|
|
704
|
+
root = RAParser.parse_query(r'a ∪ b \ c')
|
|
705
|
+
assert isinstance(root, BinaryOperators.Difference)
|
|
706
|
+
assert isinstance(root.right, RAOperand) and isinstance(root.left, BinaryOperators.Union)
|
|
707
|
+
|
|
708
|
+
# difference <-> intersection
|
|
709
|
+
root = RAParser.parse_query(r'a \ b ∩ c')
|
|
710
|
+
assert isinstance(root, BinaryOperators.Difference)
|
|
711
|
+
assert isinstance(root.left, RAOperand) and isinstance(root.right, BinaryOperators.Intersection)
|
|
712
|
+
|
|
713
|
+
root = RAParser.parse_query(r'a ∩ b \ c')
|
|
714
|
+
assert isinstance(root, BinaryOperators.Difference)
|
|
715
|
+
assert isinstance(root.right, RAOperand) and isinstance(root.left, BinaryOperators.Intersection)
|
|
716
|
+
|
|
717
|
+
# difference <-> join
|
|
718
|
+
root = RAParser.parse_query(r'a \ b ⋈ c')
|
|
719
|
+
assert isinstance(root, BinaryOperators.Difference)
|
|
720
|
+
assert isinstance(root.left, RAOperand) and isinstance(root.right, BinaryOperators.Join)
|
|
721
|
+
|
|
722
|
+
root = RAParser.parse_query(r'a ⋈ b \ c')
|
|
723
|
+
assert isinstance(root, BinaryOperators.Difference)
|
|
724
|
+
assert isinstance(root.right, RAOperand) and isinstance(root.left, BinaryOperators.Join)
|
|
725
|
+
|
|
726
|
+
root = RAParser.parse_query(r'a \ b ⟕ c')
|
|
727
|
+
assert isinstance(root, BinaryOperators.Difference)
|
|
728
|
+
assert isinstance(root.left, RAOperand) and isinstance(root.right, BinaryOperators.LeftOuterJoin)
|
|
729
|
+
|
|
730
|
+
root = RAParser.parse_query(r'a ⟕ b \ c')
|
|
731
|
+
assert isinstance(root, BinaryOperators.Difference)
|
|
732
|
+
assert isinstance(root.right, RAOperand) and isinstance(root.left, BinaryOperators.LeftOuterJoin)
|
|
733
|
+
|
|
734
|
+
root = RAParser.parse_query(r'a \ b ⟖ c')
|
|
735
|
+
assert isinstance(root, BinaryOperators.Difference)
|
|
736
|
+
assert isinstance(root.left, RAOperand) and isinstance(root.right, BinaryOperators.RightOuterJoin)
|
|
737
|
+
|
|
738
|
+
root = RAParser.parse_query(r'a ⟖ b \ c')
|
|
739
|
+
assert isinstance(root, BinaryOperators.Difference)
|
|
740
|
+
assert isinstance(root.right, RAOperand) and isinstance(root.left, BinaryOperators.RightOuterJoin)
|
|
741
|
+
|
|
742
|
+
root = RAParser.parse_query(r'a \ b ⟗ c')
|
|
743
|
+
assert isinstance(root, BinaryOperators.Difference)
|
|
744
|
+
assert isinstance(root.left, RAOperand) and isinstance(root.right, BinaryOperators.FullOuterJoin)
|
|
745
|
+
|
|
746
|
+
root = RAParser.parse_query(r'a ⟗ b \ c')
|
|
747
|
+
assert isinstance(root, BinaryOperators.Difference)
|
|
748
|
+
assert isinstance(root.right, RAOperand) and isinstance(root.left, BinaryOperators.FullOuterJoin)
|
|
749
|
+
|
|
750
|
+
# difference <-> cross
|
|
751
|
+
root = RAParser.parse_query(r'a \ b x c')
|
|
752
|
+
assert isinstance(root, BinaryOperators.Difference)
|
|
753
|
+
assert isinstance(root.left, RAOperand) and isinstance(root.right, BinaryOperators.Cross)
|
|
754
|
+
|
|
755
|
+
root = RAParser.parse_query(r'a x b \ c')
|
|
756
|
+
assert isinstance(root, BinaryOperators.Difference)
|
|
757
|
+
assert isinstance(root.right, RAOperand) and isinstance(root.left, BinaryOperators.Cross)
|
|
758
|
+
|
|
759
|
+
# difference <-> division
|
|
760
|
+
root = RAParser.parse_query(r'a \ b ÷ c')
|
|
761
|
+
assert isinstance(root, BinaryOperators.Difference)
|
|
762
|
+
assert isinstance(root.left, RAOperand) and isinstance(root.right, BinaryOperators.Division)
|
|
763
|
+
|
|
764
|
+
root = RAParser.parse_query(r'a ÷ b \ c')
|
|
765
|
+
assert isinstance(root, BinaryOperators.Difference)
|
|
766
|
+
assert isinstance(root.right, RAOperand) and isinstance(root.left, BinaryOperators.Division)
|
|
767
|
+
|
|
768
|
+
# union <-> intersection
|
|
769
|
+
root = RAParser.parse_query(r'a ∪ b ∩ c')
|
|
770
|
+
assert isinstance(root, BinaryOperators.Union)
|
|
771
|
+
assert isinstance(root.left, RAOperand) and isinstance(root.right, BinaryOperators.Intersection)
|
|
772
|
+
|
|
773
|
+
root = RAParser.parse_query(r'a ∩ b ∪ c')
|
|
774
|
+
assert isinstance(root, BinaryOperators.Union)
|
|
775
|
+
assert isinstance(root.right, RAOperand) and isinstance(root.left, BinaryOperators.Intersection)
|
|
776
|
+
|
|
777
|
+
# union <-> join
|
|
778
|
+
root = RAParser.parse_query(r'a ∪ b ⋈ c')
|
|
779
|
+
assert isinstance(root, BinaryOperators.Union)
|
|
780
|
+
assert isinstance(root.left, RAOperand) and isinstance(root.right, BinaryOperators.Join)
|
|
781
|
+
|
|
782
|
+
root = RAParser.parse_query(r'a ⋈ b ∪ c')
|
|
783
|
+
assert isinstance(root, BinaryOperators.Union)
|
|
784
|
+
assert isinstance(root.right, RAOperand) and isinstance(root.left, BinaryOperators.Join)
|
|
785
|
+
|
|
786
|
+
root = RAParser.parse_query(r'a ∪ b ⟕ c')
|
|
787
|
+
assert isinstance(root, BinaryOperators.Union)
|
|
788
|
+
assert isinstance(root.left, RAOperand) and isinstance(root.right, BinaryOperators.LeftOuterJoin)
|
|
789
|
+
|
|
790
|
+
root = RAParser.parse_query(r'a ⟕ b ∪ c')
|
|
791
|
+
assert isinstance(root, BinaryOperators.Union)
|
|
792
|
+
assert isinstance(root.right, RAOperand) and isinstance(root.left, BinaryOperators.LeftOuterJoin)
|
|
793
|
+
|
|
794
|
+
root = RAParser.parse_query(r'a ∪ b ⟖ c')
|
|
795
|
+
assert isinstance(root, BinaryOperators.Union)
|
|
796
|
+
assert isinstance(root.left, RAOperand) and isinstance(root.right, BinaryOperators.RightOuterJoin)
|
|
797
|
+
|
|
798
|
+
root = RAParser.parse_query(r'a ⟖ b ∪ c')
|
|
799
|
+
assert isinstance(root, BinaryOperators.Union)
|
|
800
|
+
assert isinstance(root.right, RAOperand) and isinstance(root.left, BinaryOperators.RightOuterJoin)
|
|
801
|
+
|
|
802
|
+
root = RAParser.parse_query(r'a ∪ b ⟗ c')
|
|
803
|
+
assert isinstance(root, BinaryOperators.Union)
|
|
804
|
+
assert isinstance(root.left, RAOperand) and isinstance(root.right, BinaryOperators.FullOuterJoin)
|
|
805
|
+
|
|
806
|
+
root = RAParser.parse_query(r'a ⟗ b ∪ c')
|
|
807
|
+
assert isinstance(root, BinaryOperators.Union)
|
|
808
|
+
assert isinstance(root.right, RAOperand) and isinstance(root.left, BinaryOperators.FullOuterJoin)
|
|
809
|
+
|
|
810
|
+
# union <-> cross
|
|
811
|
+
root = RAParser.parse_query(r'a ∪ b x c')
|
|
812
|
+
assert isinstance(root, BinaryOperators.Union)
|
|
813
|
+
assert isinstance(root.left, RAOperand) and isinstance(root.right, BinaryOperators.Cross)
|
|
814
|
+
|
|
815
|
+
root = RAParser.parse_query(r'a x b ∪ c')
|
|
816
|
+
assert isinstance(root, BinaryOperators.Union)
|
|
817
|
+
assert isinstance(root.right, RAOperand) and isinstance(root.left, BinaryOperators.Cross)
|
|
818
|
+
|
|
819
|
+
# union <-> division
|
|
820
|
+
root = RAParser.parse_query(r'a ∪ b ÷ c')
|
|
821
|
+
assert isinstance(root, BinaryOperators.Union)
|
|
822
|
+
assert isinstance(root.left, RAOperand) and isinstance(root.right, BinaryOperators.Division)
|
|
823
|
+
|
|
824
|
+
root = RAParser.parse_query(r'a ÷ b ∪ c')
|
|
825
|
+
assert isinstance(root, BinaryOperators.Union)
|
|
826
|
+
assert isinstance(root.right, RAOperand) and isinstance(root.left, BinaryOperators.Division)
|
|
827
|
+
|
|
828
|
+
# intersection <-> join
|
|
829
|
+
root = RAParser.parse_query(r'a ∩ b ⋈ c')
|
|
830
|
+
assert isinstance(root, BinaryOperators.Intersection)
|
|
831
|
+
assert isinstance(root.left, RAOperand) and isinstance(root.right, BinaryOperators.Join)
|
|
832
|
+
|
|
833
|
+
root = RAParser.parse_query(r'a ⋈ b ∩ c')
|
|
834
|
+
assert isinstance(root, BinaryOperators.Intersection)
|
|
835
|
+
assert isinstance(root.right, RAOperand) and isinstance(root.left, BinaryOperators.Join)
|
|
836
|
+
|
|
837
|
+
root = RAParser.parse_query(r'a ∩ b ⟕ c')
|
|
838
|
+
assert isinstance(root, BinaryOperators.Intersection)
|
|
839
|
+
assert isinstance(root.left, RAOperand) and isinstance(root.right, BinaryOperators.LeftOuterJoin)
|
|
840
|
+
|
|
841
|
+
root = RAParser.parse_query(r'a ⟕ b ∩ c')
|
|
842
|
+
assert isinstance(root, BinaryOperators.Intersection)
|
|
843
|
+
assert isinstance(root.right, RAOperand) and isinstance(root.left, BinaryOperators.LeftOuterJoin)
|
|
844
|
+
|
|
845
|
+
root = RAParser.parse_query(r'a ∩ b ⟖ c')
|
|
846
|
+
assert isinstance(root, BinaryOperators.Intersection)
|
|
847
|
+
assert isinstance(root.left, RAOperand) and isinstance(root.right, BinaryOperators.RightOuterJoin)
|
|
848
|
+
|
|
849
|
+
root = RAParser.parse_query(r'a ⟖ b ∩ c')
|
|
850
|
+
assert isinstance(root, BinaryOperators.Intersection)
|
|
851
|
+
assert isinstance(root.right, RAOperand) and isinstance(root.left, BinaryOperators.RightOuterJoin)
|
|
852
|
+
|
|
853
|
+
root = RAParser.parse_query(r'a ∩ b ⟗ c')
|
|
854
|
+
assert isinstance(root, BinaryOperators.Intersection)
|
|
855
|
+
assert isinstance(root.left, RAOperand) and isinstance(root.right, BinaryOperators.FullOuterJoin)
|
|
856
|
+
|
|
857
|
+
root = RAParser.parse_query(r'a ⟗ b ∩ c')
|
|
858
|
+
assert isinstance(root, BinaryOperators.Intersection)
|
|
859
|
+
assert isinstance(root.right, RAOperand) and isinstance(root.left, BinaryOperators.FullOuterJoin)
|
|
860
|
+
|
|
861
|
+
# intersection <-> cross
|
|
862
|
+
root = RAParser.parse_query(r'a ∩ b x c')
|
|
863
|
+
assert isinstance(root, BinaryOperators.Intersection)
|
|
864
|
+
assert isinstance(root.left, RAOperand) and isinstance(root.right, BinaryOperators.Cross)
|
|
865
|
+
|
|
866
|
+
root = RAParser.parse_query(r'a x b ∩ c')
|
|
867
|
+
assert isinstance(root, BinaryOperators.Intersection)
|
|
868
|
+
assert isinstance(root.right, RAOperand) and isinstance(root.left, BinaryOperators.Cross)
|
|
869
|
+
|
|
870
|
+
# intersection <-> division
|
|
871
|
+
root = RAParser.parse_query(r'a ∩ b ÷ c')
|
|
872
|
+
assert isinstance(root, BinaryOperators.Intersection)
|
|
873
|
+
assert isinstance(root.left, RAOperand) and isinstance(root.right, BinaryOperators.Division)
|
|
874
|
+
|
|
875
|
+
root = RAParser.parse_query(r'a ÷ b ∩ c')
|
|
876
|
+
assert isinstance(root, BinaryOperators.Intersection)
|
|
877
|
+
assert isinstance(root.right, RAOperand) and isinstance(root.left, BinaryOperators.Division)
|
|
878
|
+
|
|
879
|
+
# join <-> cross
|
|
880
|
+
root = RAParser.parse_query(r'a ⋈ b x c')
|
|
881
|
+
assert isinstance(root, BinaryOperators.Join)
|
|
882
|
+
assert isinstance(root.left, RAOperand) and isinstance(root.right, BinaryOperators.Cross)
|
|
883
|
+
|
|
884
|
+
root = RAParser.parse_query(r'a x b ⋈ c')
|
|
885
|
+
assert isinstance(root, BinaryOperators.Join)
|
|
886
|
+
assert isinstance(root.right, RAOperand) and isinstance(root.left, BinaryOperators.Cross)
|
|
887
|
+
|
|
888
|
+
root = RAParser.parse_query(r'a ⟕ b x c')
|
|
889
|
+
assert isinstance(root, BinaryOperators.LeftOuterJoin)
|
|
890
|
+
assert isinstance(root.left, RAOperand) and isinstance(root.right, BinaryOperators.Cross)
|
|
891
|
+
|
|
892
|
+
root = RAParser.parse_query(r'a x b ⟕ c')
|
|
893
|
+
assert isinstance(root, BinaryOperators.LeftOuterJoin)
|
|
894
|
+
assert isinstance(root.right, RAOperand) and isinstance(root.left, BinaryOperators.Cross)
|
|
895
|
+
|
|
896
|
+
root = RAParser.parse_query(r'a ⟖ b x c')
|
|
897
|
+
assert isinstance(root, BinaryOperators.RightOuterJoin)
|
|
898
|
+
assert isinstance(root.left, RAOperand) and isinstance(root.right, BinaryOperators.Cross)
|
|
899
|
+
|
|
900
|
+
root = RAParser.parse_query(r'a x b ⟖ c')
|
|
901
|
+
assert isinstance(root, BinaryOperators.RightOuterJoin)
|
|
902
|
+
assert isinstance(root.right, RAOperand) and isinstance(root.left, BinaryOperators.Cross)
|
|
903
|
+
|
|
904
|
+
root = RAParser.parse_query(r'a ⟗ b x c')
|
|
905
|
+
assert isinstance(root, BinaryOperators.FullOuterJoin)
|
|
906
|
+
assert isinstance(root.left, RAOperand) and isinstance(root.right, BinaryOperators.Cross)
|
|
907
|
+
|
|
908
|
+
root = RAParser.parse_query(r'a x b ⟗ c')
|
|
909
|
+
assert isinstance(root, BinaryOperators.FullOuterJoin)
|
|
910
|
+
assert isinstance(root.right, RAOperand) and isinstance(root.left, BinaryOperators.Cross)
|
|
911
|
+
|
|
912
|
+
# join <-> division
|
|
913
|
+
root = RAParser.parse_query(r'a ⋈ b ÷ c')
|
|
914
|
+
assert isinstance(root, BinaryOperators.Join)
|
|
915
|
+
assert isinstance(root.left, RAOperand) and isinstance(root.right, BinaryOperators.Division)
|
|
916
|
+
|
|
917
|
+
root = RAParser.parse_query(r'a ÷ b ⋈ c')
|
|
918
|
+
assert isinstance(root, BinaryOperators.Join)
|
|
919
|
+
assert isinstance(root.right, RAOperand) and isinstance(root.left, BinaryOperators.Division)
|
|
920
|
+
|
|
921
|
+
root = RAParser.parse_query(r'a ⟕ b ÷ c')
|
|
922
|
+
assert isinstance(root, BinaryOperators.LeftOuterJoin)
|
|
923
|
+
assert isinstance(root.left, RAOperand) and isinstance(root.right, BinaryOperators.Division)
|
|
924
|
+
|
|
925
|
+
root = RAParser.parse_query(r'a ÷ b ⟕ c')
|
|
926
|
+
assert isinstance(root, BinaryOperators.LeftOuterJoin)
|
|
927
|
+
assert isinstance(root.right, RAOperand) and isinstance(root.left, BinaryOperators.Division)
|
|
928
|
+
|
|
929
|
+
root = RAParser.parse_query(r'a ⟖ b ÷ c')
|
|
930
|
+
assert isinstance(root, BinaryOperators.RightOuterJoin)
|
|
931
|
+
assert isinstance(root.left, RAOperand) and isinstance(root.right, BinaryOperators.Division)
|
|
932
|
+
|
|
933
|
+
root = RAParser.parse_query(r'a ÷ b ⟖ c')
|
|
934
|
+
assert isinstance(root, BinaryOperators.RightOuterJoin)
|
|
935
|
+
assert isinstance(root.right, RAOperand) and isinstance(root.left, BinaryOperators.Division)
|
|
936
|
+
|
|
937
|
+
root = RAParser.parse_query(r'a ⟗ b ÷ c')
|
|
938
|
+
assert isinstance(root, BinaryOperators.FullOuterJoin)
|
|
939
|
+
assert isinstance(root.left, RAOperand) and isinstance(root.right, BinaryOperators.Division)
|
|
940
|
+
|
|
941
|
+
root = RAParser.parse_query(r'a ÷ b ⟗ c')
|
|
942
|
+
assert isinstance(root, BinaryOperators.FullOuterJoin)
|
|
943
|
+
assert isinstance(root.right, RAOperand) and isinstance(root.left, BinaryOperators.Division)
|
|
944
|
+
|
|
945
|
+
# natural join <-> outer join
|
|
946
|
+
root = RAParser.parse_query(r'a ⋈ b ⟕ c')
|
|
947
|
+
assert isinstance(root, BinaryOperators.Join)
|
|
948
|
+
assert isinstance(root.left, RAOperand) and isinstance(root.right, BinaryOperators.LeftOuterJoin)
|
|
949
|
+
|
|
950
|
+
root = RAParser.parse_query(r'a ⟕ b ⋈ c')
|
|
951
|
+
assert isinstance(root, BinaryOperators.Join)
|
|
952
|
+
assert isinstance(root.right, RAOperand) and isinstance(root.left, BinaryOperators.LeftOuterJoin)
|
|
953
|
+
|
|
954
|
+
root = RAParser.parse_query(r'a ⋈ b ⟖ c')
|
|
955
|
+
assert isinstance(root, BinaryOperators.Join)
|
|
956
|
+
assert isinstance(root.left, RAOperand) and isinstance(root.right, BinaryOperators.RightOuterJoin)
|
|
957
|
+
|
|
958
|
+
root = RAParser.parse_query(r'a ⟖ b ⋈ c')
|
|
959
|
+
assert isinstance(root, BinaryOperators.Join)
|
|
960
|
+
assert isinstance(root.right, RAOperand) and isinstance(root.left, BinaryOperators.RightOuterJoin)
|
|
961
|
+
|
|
962
|
+
root = RAParser.parse_query(r'a ⋈ b ⟗ c')
|
|
963
|
+
assert isinstance(root, BinaryOperators.Join)
|
|
964
|
+
assert isinstance(root.left, RAOperand) and isinstance(root.right, BinaryOperators.FullOuterJoin)
|
|
965
|
+
|
|
966
|
+
root = RAParser.parse_query(r'a ⟗ b ⋈ c')
|
|
967
|
+
assert isinstance(root, BinaryOperators.Join)
|
|
968
|
+
assert isinstance(root.right, RAOperand) and isinstance(root.left, BinaryOperators.FullOuterJoin)
|
|
969
|
+
|
|
970
|
+
# cross <-> division
|
|
971
|
+
root = RAParser.parse_query(r'a x b ÷ c')
|
|
972
|
+
assert isinstance(root, BinaryOperators.Cross)
|
|
973
|
+
assert isinstance(root.left, RAOperand) and isinstance(root.right, BinaryOperators.Division)
|
|
974
|
+
|
|
975
|
+
root = RAParser.parse_query(r'a ÷ b x c')
|
|
976
|
+
assert isinstance(root, BinaryOperators.Cross)
|
|
977
|
+
assert isinstance(root.right, RAOperand) and isinstance(root.left, BinaryOperators.Division)
|
|
978
|
+
|
|
979
|
+
|
|
980
|
+
def test_mixed_evaluation_order():
|
|
981
|
+
# difference <-> projection
|
|
982
|
+
root = RAParser.parse_query(r'a \ π [ Id ] b')
|
|
983
|
+
assert isinstance(root, BinaryOperators.Difference)
|
|
984
|
+
assert isinstance(root.left, RAOperand) and isinstance(root.right, UnaryOperators.Projection)
|
|
985
|
+
|
|
986
|
+
root = RAParser.parse_query(r'π [ Id ] a \ b')
|
|
987
|
+
assert isinstance(root, BinaryOperators.Difference)
|
|
988
|
+
assert isinstance(root.right, RAOperand) and isinstance(root.left, UnaryOperators.Projection)
|
|
989
|
+
|
|
990
|
+
# difference <-> rename
|
|
991
|
+
root = RAParser.parse_query(r'a \ β [ Id2 ← Id ] b')
|
|
992
|
+
assert isinstance(root, BinaryOperators.Difference)
|
|
993
|
+
assert isinstance(root.left, RAOperand) and isinstance(root.right, UnaryOperators.Rename)
|
|
994
|
+
|
|
995
|
+
root = RAParser.parse_query(r'β [ Id2 ← Id ] a \ b')
|
|
996
|
+
assert isinstance(root, BinaryOperators.Difference)
|
|
997
|
+
assert isinstance(root.right, RAOperand) and isinstance(root.left, UnaryOperators.Rename)
|
|
998
|
+
|
|
999
|
+
# difference <-> selection
|
|
1000
|
+
root = RAParser.parse_query(r'a \ σ [ Id > 1 ] b')
|
|
1001
|
+
assert isinstance(root, BinaryOperators.Difference)
|
|
1002
|
+
assert isinstance(root.left, RAOperand) and isinstance(root.right, UnaryOperators.Selection)
|
|
1003
|
+
|
|
1004
|
+
root = RAParser.parse_query(r'σ [ Id > 1 ] a \ b')
|
|
1005
|
+
assert isinstance(root, BinaryOperators.Difference)
|
|
1006
|
+
assert isinstance(root.right, RAOperand) and isinstance(root.left, UnaryOperators.Selection)
|
|
1007
|
+
|
|
1008
|
+
# union <-> projection
|
|
1009
|
+
root = RAParser.parse_query(r'a ∪ π [ Id ] b')
|
|
1010
|
+
assert isinstance(root, BinaryOperators.Union)
|
|
1011
|
+
assert isinstance(root.left, RAOperand) and isinstance(root.right, UnaryOperators.Projection)
|
|
1012
|
+
|
|
1013
|
+
root = RAParser.parse_query(r'π [ Id ] a ∪ b')
|
|
1014
|
+
assert isinstance(root, BinaryOperators.Union)
|
|
1015
|
+
assert isinstance(root.right, RAOperand) and isinstance(root.left, UnaryOperators.Projection)
|
|
1016
|
+
|
|
1017
|
+
# union <-> rename
|
|
1018
|
+
root = RAParser.parse_query(r'a ∪ β [ Id2 ← Id ] b')
|
|
1019
|
+
assert isinstance(root, BinaryOperators.Union)
|
|
1020
|
+
assert isinstance(root.left, RAOperand) and isinstance(root.right, UnaryOperators.Rename)
|
|
1021
|
+
|
|
1022
|
+
root = RAParser.parse_query(r'β [ Id2 ← Id ] a ∪ b')
|
|
1023
|
+
assert isinstance(root, BinaryOperators.Union)
|
|
1024
|
+
assert isinstance(root.right, RAOperand) and isinstance(root.left, UnaryOperators.Rename)
|
|
1025
|
+
|
|
1026
|
+
# union <-> selection
|
|
1027
|
+
root = RAParser.parse_query(r'a ∪ σ [ Id > 1 ] b')
|
|
1028
|
+
assert isinstance(root, BinaryOperators.Union)
|
|
1029
|
+
assert isinstance(root.left, RAOperand) and isinstance(root.right, UnaryOperators.Selection)
|
|
1030
|
+
|
|
1031
|
+
root = RAParser.parse_query(r'σ [ Id > 1 ] a ∪ b')
|
|
1032
|
+
assert isinstance(root, BinaryOperators.Union)
|
|
1033
|
+
assert isinstance(root.right, RAOperand) and isinstance(root.left, UnaryOperators.Selection)
|
|
1034
|
+
|
|
1035
|
+
# intersection <-> projection
|
|
1036
|
+
root = RAParser.parse_query(r'a ∩ π [ Id ] b')
|
|
1037
|
+
assert isinstance(root, BinaryOperators.Intersection)
|
|
1038
|
+
assert isinstance(root.left, RAOperand) and isinstance(root.right, UnaryOperators.Projection)
|
|
1039
|
+
|
|
1040
|
+
root = RAParser.parse_query(r'π [ Id ] a ∩ b')
|
|
1041
|
+
assert isinstance(root, BinaryOperators.Intersection)
|
|
1042
|
+
assert isinstance(root.right, RAOperand) and isinstance(root.left, UnaryOperators.Projection)
|
|
1043
|
+
|
|
1044
|
+
# intersection <-> rename
|
|
1045
|
+
root = RAParser.parse_query(r'a ∩ β [ Id2 ← Id ] b')
|
|
1046
|
+
assert isinstance(root, BinaryOperators.Intersection)
|
|
1047
|
+
assert isinstance(root.left, RAOperand) and isinstance(root.right, UnaryOperators.Rename)
|
|
1048
|
+
|
|
1049
|
+
root = RAParser.parse_query(r'β [ Id2 ← Id ] a ∩ b')
|
|
1050
|
+
assert isinstance(root, BinaryOperators.Intersection)
|
|
1051
|
+
assert isinstance(root.right, RAOperand) and isinstance(root.left, UnaryOperators.Rename)
|
|
1052
|
+
|
|
1053
|
+
# intersection <-> selection
|
|
1054
|
+
root = RAParser.parse_query(r'a ∩ σ [ Id > 1 ] b')
|
|
1055
|
+
assert isinstance(root, BinaryOperators.Intersection)
|
|
1056
|
+
assert isinstance(root.left, RAOperand) and isinstance(root.right, UnaryOperators.Selection)
|
|
1057
|
+
|
|
1058
|
+
root = RAParser.parse_query(r'σ [ Id > 1 ] a ∩ b')
|
|
1059
|
+
assert isinstance(root, BinaryOperators.Intersection)
|
|
1060
|
+
assert isinstance(root.right, RAOperand) and isinstance(root.left, UnaryOperators.Selection)
|
|
1061
|
+
|
|
1062
|
+
# join <-> projection
|
|
1063
|
+
root = RAParser.parse_query(r'a ⋈ π [ Id ] b')
|
|
1064
|
+
assert isinstance(root, BinaryOperators.Join)
|
|
1065
|
+
assert isinstance(root.left, RAOperand) and isinstance(root.right, UnaryOperators.Projection)
|
|
1066
|
+
|
|
1067
|
+
root = RAParser.parse_query(r'π [ Id ] a ⋈ b')
|
|
1068
|
+
assert isinstance(root, BinaryOperators.Join)
|
|
1069
|
+
assert isinstance(root.right, RAOperand) and isinstance(root.left, UnaryOperators.Projection)
|
|
1070
|
+
|
|
1071
|
+
root = RAParser.parse_query(r'a ⟕ π [ Id ] b')
|
|
1072
|
+
assert isinstance(root, BinaryOperators.LeftOuterJoin)
|
|
1073
|
+
assert isinstance(root.left, RAOperand) and isinstance(root.right, UnaryOperators.Projection)
|
|
1074
|
+
|
|
1075
|
+
root = RAParser.parse_query(r'π [ Id ] a ⟕ b')
|
|
1076
|
+
assert isinstance(root, BinaryOperators.LeftOuterJoin)
|
|
1077
|
+
assert isinstance(root.right, RAOperand) and isinstance(root.left, UnaryOperators.Projection)
|
|
1078
|
+
|
|
1079
|
+
root = RAParser.parse_query(r'a ⟖ π [ Id ] b')
|
|
1080
|
+
assert isinstance(root, BinaryOperators.RightOuterJoin)
|
|
1081
|
+
assert isinstance(root.left, RAOperand) and isinstance(root.right, UnaryOperators.Projection)
|
|
1082
|
+
|
|
1083
|
+
root = RAParser.parse_query(r'π [ Id ] a ⟖ b')
|
|
1084
|
+
assert isinstance(root, BinaryOperators.RightOuterJoin)
|
|
1085
|
+
assert isinstance(root.right, RAOperand) and isinstance(root.left, UnaryOperators.Projection)
|
|
1086
|
+
|
|
1087
|
+
root = RAParser.parse_query(r'a ⟗ π [ Id ] b')
|
|
1088
|
+
assert isinstance(root, BinaryOperators.FullOuterJoin)
|
|
1089
|
+
assert isinstance(root.left, RAOperand) and isinstance(root.right, UnaryOperators.Projection)
|
|
1090
|
+
|
|
1091
|
+
root = RAParser.parse_query(r'π [ Id ] a ⟗ b')
|
|
1092
|
+
assert isinstance(root, BinaryOperators.FullOuterJoin)
|
|
1093
|
+
assert isinstance(root.right, RAOperand) and isinstance(root.left, UnaryOperators.Projection)
|
|
1094
|
+
|
|
1095
|
+
# join <-> rename
|
|
1096
|
+
root = RAParser.parse_query(r'a ⋈ β [ Id2 ← Id ] b')
|
|
1097
|
+
assert isinstance(root, BinaryOperators.Join)
|
|
1098
|
+
assert isinstance(root.left, RAOperand) and isinstance(root.right, UnaryOperators.Rename)
|
|
1099
|
+
|
|
1100
|
+
root = RAParser.parse_query(r'β [ Id2 ← Id ] a ⋈ b')
|
|
1101
|
+
assert isinstance(root, BinaryOperators.Join)
|
|
1102
|
+
assert isinstance(root.right, RAOperand) and isinstance(root.left, UnaryOperators.Rename)
|
|
1103
|
+
|
|
1104
|
+
root = RAParser.parse_query(r'a ⟕ β [ Id2 ← Id ] b')
|
|
1105
|
+
assert isinstance(root, BinaryOperators.LeftOuterJoin)
|
|
1106
|
+
assert isinstance(root.left, RAOperand) and isinstance(root.right, UnaryOperators.Rename)
|
|
1107
|
+
|
|
1108
|
+
root = RAParser.parse_query(r'β [ Id2 ← Id ] a ⟕ b')
|
|
1109
|
+
assert isinstance(root, BinaryOperators.LeftOuterJoin)
|
|
1110
|
+
assert isinstance(root.right, RAOperand) and isinstance(root.left, UnaryOperators.Rename)
|
|
1111
|
+
|
|
1112
|
+
root = RAParser.parse_query(r'a ⟖ β [ Id2 ← Id ] b')
|
|
1113
|
+
assert isinstance(root, BinaryOperators.RightOuterJoin)
|
|
1114
|
+
assert isinstance(root.left, RAOperand) and isinstance(root.right, UnaryOperators.Rename)
|
|
1115
|
+
|
|
1116
|
+
root = RAParser.parse_query(r'β [ Id2 ← Id ] a ⟖ b')
|
|
1117
|
+
assert isinstance(root, BinaryOperators.RightOuterJoin)
|
|
1118
|
+
assert isinstance(root.right, RAOperand) and isinstance(root.left, UnaryOperators.Rename)
|
|
1119
|
+
|
|
1120
|
+
root = RAParser.parse_query(r'a ⟗ β [ Id2 ← Id ] b')
|
|
1121
|
+
assert isinstance(root, BinaryOperators.FullOuterJoin)
|
|
1122
|
+
assert isinstance(root.left, RAOperand) and isinstance(root.right, UnaryOperators.Rename)
|
|
1123
|
+
|
|
1124
|
+
root = RAParser.parse_query(r'β [ Id2 ← Id ] a ⟗ b')
|
|
1125
|
+
assert isinstance(root, BinaryOperators.FullOuterJoin)
|
|
1126
|
+
assert isinstance(root.right, RAOperand) and isinstance(root.left, UnaryOperators.Rename)
|
|
1127
|
+
|
|
1128
|
+
# join <-> selection
|
|
1129
|
+
root = RAParser.parse_query(r'a ⋈ σ [ Id > 1 ] b')
|
|
1130
|
+
assert isinstance(root, BinaryOperators.Join)
|
|
1131
|
+
assert isinstance(root.left, RAOperand) and isinstance(root.right, UnaryOperators.Selection)
|
|
1132
|
+
|
|
1133
|
+
root = RAParser.parse_query(r'σ [ Id > 1 ] a ⋈ b')
|
|
1134
|
+
assert isinstance(root, BinaryOperators.Join)
|
|
1135
|
+
assert isinstance(root.right, RAOperand) and isinstance(root.left, UnaryOperators.Selection)
|
|
1136
|
+
|
|
1137
|
+
root = RAParser.parse_query(r'a ⟕ σ [ Id > 1 ] b')
|
|
1138
|
+
assert isinstance(root, BinaryOperators.LeftOuterJoin)
|
|
1139
|
+
assert isinstance(root.left, RAOperand) and isinstance(root.right, UnaryOperators.Selection)
|
|
1140
|
+
|
|
1141
|
+
root = RAParser.parse_query(r'σ [ Id > 1 ] a ⟕ b')
|
|
1142
|
+
assert isinstance(root, BinaryOperators.LeftOuterJoin)
|
|
1143
|
+
assert isinstance(root.right, RAOperand) and isinstance(root.left, UnaryOperators.Selection)
|
|
1144
|
+
|
|
1145
|
+
root = RAParser.parse_query(r'a ⟖ σ [ Id > 1 ] b')
|
|
1146
|
+
assert isinstance(root, BinaryOperators.RightOuterJoin)
|
|
1147
|
+
assert isinstance(root.left, RAOperand) and isinstance(root.right, UnaryOperators.Selection)
|
|
1148
|
+
|
|
1149
|
+
root = RAParser.parse_query(r'σ [ Id > 1 ] a ⟖ b')
|
|
1150
|
+
assert isinstance(root, BinaryOperators.RightOuterJoin)
|
|
1151
|
+
assert isinstance(root.right, RAOperand) and isinstance(root.left, UnaryOperators.Selection)
|
|
1152
|
+
|
|
1153
|
+
root = RAParser.parse_query(r'a ⟗ σ [ Id > 1 ] b')
|
|
1154
|
+
assert isinstance(root, BinaryOperators.FullOuterJoin)
|
|
1155
|
+
assert isinstance(root.left, RAOperand) and isinstance(root.right, UnaryOperators.Selection)
|
|
1156
|
+
|
|
1157
|
+
root = RAParser.parse_query(r'σ [ Id > 1 ] a ⟗ b')
|
|
1158
|
+
assert isinstance(root, BinaryOperators.FullOuterJoin)
|
|
1159
|
+
assert isinstance(root.right, RAOperand) and isinstance(root.left, UnaryOperators.Selection)
|
|
1160
|
+
|
|
1161
|
+
# cross <-> projection
|
|
1162
|
+
root = RAParser.parse_query(r'a x π [ Id ] b')
|
|
1163
|
+
assert isinstance(root, BinaryOperators.Cross)
|
|
1164
|
+
assert isinstance(root.left, RAOperand) and isinstance(root.right, UnaryOperators.Projection)
|
|
1165
|
+
|
|
1166
|
+
root = RAParser.parse_query(r'π [ Id ] a x b')
|
|
1167
|
+
assert isinstance(root, BinaryOperators.Cross)
|
|
1168
|
+
assert isinstance(root.right, RAOperand) and isinstance(root.left, UnaryOperators.Projection)
|
|
1169
|
+
|
|
1170
|
+
# cross <-> rename
|
|
1171
|
+
root = RAParser.parse_query(r'a x β [ Id2 ← Id ] b')
|
|
1172
|
+
assert isinstance(root, BinaryOperators.Cross)
|
|
1173
|
+
assert isinstance(root.left, RAOperand) and isinstance(root.right, UnaryOperators.Rename)
|
|
1174
|
+
|
|
1175
|
+
root = RAParser.parse_query(r'β [ Id2 ← Id ] a x b')
|
|
1176
|
+
assert isinstance(root, BinaryOperators.Cross)
|
|
1177
|
+
assert isinstance(root.right, RAOperand) and isinstance(root.left, UnaryOperators.Rename)
|
|
1178
|
+
|
|
1179
|
+
# cross <-> selection
|
|
1180
|
+
root = RAParser.parse_query(r'a x σ [ Id > 1 ] b')
|
|
1181
|
+
assert isinstance(root, BinaryOperators.Cross)
|
|
1182
|
+
assert isinstance(root.left, RAOperand) and isinstance(root.right, UnaryOperators.Selection)
|
|
1183
|
+
|
|
1184
|
+
root = RAParser.parse_query(r'σ [ Id > 1 ] a x b')
|
|
1185
|
+
assert isinstance(root, BinaryOperators.Cross)
|
|
1186
|
+
assert isinstance(root.right, RAOperand) and isinstance(root.left, UnaryOperators.Selection)
|
|
1187
|
+
|
|
1188
|
+
# division <-> projection
|
|
1189
|
+
root = RAParser.parse_query(r'a ÷ π [ Id ] b')
|
|
1190
|
+
assert isinstance(root, BinaryOperators.Division)
|
|
1191
|
+
assert isinstance(root.left, RAOperand) and isinstance(root.right, UnaryOperators.Projection)
|
|
1192
|
+
|
|
1193
|
+
root = RAParser.parse_query(r'π [ Id ] a ÷ b')
|
|
1194
|
+
assert isinstance(root, BinaryOperators.Division)
|
|
1195
|
+
assert isinstance(root.right, RAOperand) and isinstance(root.left, UnaryOperators.Projection)
|
|
1196
|
+
|
|
1197
|
+
# division <-> rename
|
|
1198
|
+
root = RAParser.parse_query(r'a ÷ β [ Id2 ← Id ] b')
|
|
1199
|
+
assert isinstance(root, BinaryOperators.Division)
|
|
1200
|
+
assert isinstance(root.left, RAOperand) and isinstance(root.right, UnaryOperators.Rename)
|
|
1201
|
+
|
|
1202
|
+
root = RAParser.parse_query(r'β [ Id2 ← Id ] a ÷ b')
|
|
1203
|
+
assert isinstance(root, BinaryOperators.Division)
|
|
1204
|
+
assert isinstance(root.right, RAOperand) and isinstance(root.left, UnaryOperators.Rename)
|
|
1205
|
+
|
|
1206
|
+
# division <-> selection
|
|
1207
|
+
root = RAParser.parse_query(r'a ÷ σ [ Id > 1 ] b')
|
|
1208
|
+
assert isinstance(root, BinaryOperators.Division)
|
|
1209
|
+
assert isinstance(root.left, RAOperand) and isinstance(root.right, UnaryOperators.Selection)
|
|
1210
|
+
|
|
1211
|
+
root = RAParser.parse_query(r'σ [ Id > 1 ] a ÷ b')
|
|
1212
|
+
assert isinstance(root, BinaryOperators.Division)
|
|
1213
|
+
assert isinstance(root.right, RAOperand) and isinstance(root.left, UnaryOperators.Selection)
|
|
1214
|
+
|
|
1215
|
+
|
|
1216
|
+
def test_special_queries():
|
|
1217
|
+
with Connection() as con:
|
|
1218
|
+
# Consecutive operators triggered a recursion error in a previous
|
|
1219
|
+
# version, leading to an infinite loop / stack overflow.
|
|
1220
|
+
with pytest.raises(RAParserError, match='right operand missing after x'):
|
|
1221
|
+
RAParser.parse_query(r'''
|
|
1222
|
+
Users x x BannedUsers
|
|
1223
|
+
''')
|
|
1224
|
+
|
|
1225
|
+
# Enclosing parentheses are removed. In the following case
|
|
1226
|
+
# the parentheses may only be removed from each subquery
|
|
1227
|
+
# independently *after* the cross join is applied. Otherwise,
|
|
1228
|
+
# the result is a parsing error.
|
|
1229
|
+
root = RAParser.parse_query(r'''
|
|
1230
|
+
(
|
|
1231
|
+
Sigma [ Id > 1 ] Pi [ Username, Id ] (Users)
|
|
1232
|
+
) x (
|
|
1233
|
+
Beta [ Username2 <- BannedUsername ] Beta [ Id2 <- Id ] (BannedUsers)
|
|
1234
|
+
)
|
|
1235
|
+
''')
|
|
1236
|
+
|
|
1237
|
+
assert isinstance(root, BinaryOperators.Cross)
|
|
1238
|
+
assert isinstance(root.left, UnaryOperators.Selection)
|
|
1239
|
+
assert isinstance(root.left.target, UnaryOperators.Projection)
|
|
1240
|
+
assert isinstance(root.left.target.target, RAOperand) and root.left.target.target.name == 'Users'
|
|
1241
|
+
assert isinstance(root.right, UnaryOperators.Rename)
|
|
1242
|
+
assert isinstance(root.right.target, UnaryOperators.Rename)
|
|
1243
|
+
assert isinstance(root.right.target.target, RAOperand) and root.right.target.target.name == 'BannedUsers'
|
|
1244
|
+
|
|
1245
|
+
assert con.execute_ra(root) == [
|
|
1246
|
+
('Bob', 2, 2, 'Bob'),
|
|
1247
|
+
('Bob', 2, 4, 'David'),
|
|
1248
|
+
('Charlie', 3, 2, 'Bob'),
|
|
1249
|
+
('Charlie', 3, 4, 'David')
|
|
1250
|
+
]
|