jupyter-duckdb 0.9.2.1.dev202311171355__tar.gz → 0.9.2.2__tar.gz
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.
- {jupyter-duckdb-0.9.2.1.dev202311171355 → jupyter-duckdb-0.9.2.2}/PKG-INFO +1 -1
- {jupyter-duckdb-0.9.2.1.dev202311171355 → jupyter-duckdb-0.9.2.2}/setup.py +3 -4
- {jupyter-duckdb-0.9.2.1.dev202311171355 → jupyter-duckdb-0.9.2.2}/src/duckdb_kernel/kernel.py +37 -3
- {jupyter-duckdb-0.9.2.1.dev202311171355 → jupyter-duckdb-0.9.2.2}/src/duckdb_kernel/parser/elements/RAOperand.py +5 -2
- {jupyter-duckdb-0.9.2.1.dev202311171355 → jupyter-duckdb-0.9.2.2}/src/duckdb_kernel/parser/elements/binary/ConditionalSet.py +29 -8
- {jupyter-duckdb-0.9.2.1.dev202311171355 → jupyter-duckdb-0.9.2.2}/src/jupyter_duckdb.egg-info/PKG-INFO +1 -1
- {jupyter-duckdb-0.9.2.1.dev202311171355 → jupyter-duckdb-0.9.2.2}/test/test_dc.py +35 -0
- {jupyter-duckdb-0.9.2.1.dev202311171355 → jupyter-duckdb-0.9.2.2}/test/test_ra.py +25 -0
- {jupyter-duckdb-0.9.2.1.dev202311171355 → jupyter-duckdb-0.9.2.2}/README.md +0 -0
- {jupyter-duckdb-0.9.2.1.dev202311171355 → jupyter-duckdb-0.9.2.2}/setup.cfg +0 -0
- {jupyter-duckdb-0.9.2.1.dev202311171355 → jupyter-duckdb-0.9.2.2}/src/duckdb_kernel/__init__.py +0 -0
- {jupyter-duckdb-0.9.2.1.dev202311171355 → jupyter-duckdb-0.9.2.2}/src/duckdb_kernel/__main__.py +0 -0
- {jupyter-duckdb-0.9.2.1.dev202311171355 → jupyter-duckdb-0.9.2.2}/src/duckdb_kernel/db/Column.py +0 -0
- {jupyter-duckdb-0.9.2.1.dev202311171355 → jupyter-duckdb-0.9.2.2}/src/duckdb_kernel/db/Connection.py +0 -0
- {jupyter-duckdb-0.9.2.1.dev202311171355 → jupyter-duckdb-0.9.2.2}/src/duckdb_kernel/db/Constraint.py +0 -0
- {jupyter-duckdb-0.9.2.1.dev202311171355 → jupyter-duckdb-0.9.2.2}/src/duckdb_kernel/db/DatabaseError.py +0 -0
- {jupyter-duckdb-0.9.2.1.dev202311171355 → jupyter-duckdb-0.9.2.2}/src/duckdb_kernel/db/ForeignKey.py +0 -0
- {jupyter-duckdb-0.9.2.1.dev202311171355 → jupyter-duckdb-0.9.2.2}/src/duckdb_kernel/db/Table.py +0 -0
- {jupyter-duckdb-0.9.2.1.dev202311171355 → jupyter-duckdb-0.9.2.2}/src/duckdb_kernel/db/__init__.py +0 -0
- {jupyter-duckdb-0.9.2.1.dev202311171355 → jupyter-duckdb-0.9.2.2}/src/duckdb_kernel/db/duckdb/Connection.py +0 -0
- {jupyter-duckdb-0.9.2.1.dev202311171355 → jupyter-duckdb-0.9.2.2}/src/duckdb_kernel/db/duckdb/__init__.py +0 -0
- {jupyter-duckdb-0.9.2.1.dev202311171355 → jupyter-duckdb-0.9.2.2}/src/duckdb_kernel/db/sqlite/Connection.py +0 -0
- {jupyter-duckdb-0.9.2.1.dev202311171355 → jupyter-duckdb-0.9.2.2}/src/duckdb_kernel/db/sqlite/__init__.py +0 -0
- {jupyter-duckdb-0.9.2.1.dev202311171355 → jupyter-duckdb-0.9.2.2}/src/duckdb_kernel/kernel.json +0 -0
- {jupyter-duckdb-0.9.2.1.dev202311171355 → jupyter-duckdb-0.9.2.2}/src/duckdb_kernel/magics/MagicCommand.py +0 -0
- {jupyter-duckdb-0.9.2.1.dev202311171355 → jupyter-duckdb-0.9.2.2}/src/duckdb_kernel/magics/MagicCommandCallback.py +0 -0
- {jupyter-duckdb-0.9.2.1.dev202311171355 → jupyter-duckdb-0.9.2.2}/src/duckdb_kernel/magics/MagicCommandException.py +0 -0
- {jupyter-duckdb-0.9.2.1.dev202311171355 → jupyter-duckdb-0.9.2.2}/src/duckdb_kernel/magics/MagicCommandHandler.py +0 -0
- {jupyter-duckdb-0.9.2.1.dev202311171355 → jupyter-duckdb-0.9.2.2}/src/duckdb_kernel/magics/__init__.py +0 -0
- {jupyter-duckdb-0.9.2.1.dev202311171355 → jupyter-duckdb-0.9.2.2}/src/duckdb_kernel/parser/DCParser.py +0 -0
- {jupyter-duckdb-0.9.2.1.dev202311171355 → jupyter-duckdb-0.9.2.2}/src/duckdb_kernel/parser/LogicParser.py +0 -0
- {jupyter-duckdb-0.9.2.1.dev202311171355 → jupyter-duckdb-0.9.2.2}/src/duckdb_kernel/parser/RAParser.py +0 -0
- {jupyter-duckdb-0.9.2.1.dev202311171355 → jupyter-duckdb-0.9.2.2}/src/duckdb_kernel/parser/__init__.py +0 -0
- {jupyter-duckdb-0.9.2.1.dev202311171355 → jupyter-duckdb-0.9.2.2}/src/duckdb_kernel/parser/elements/DCOperand.py +0 -0
- {jupyter-duckdb-0.9.2.1.dev202311171355 → jupyter-duckdb-0.9.2.2}/src/duckdb_kernel/parser/elements/LogicElement.py +0 -0
- {jupyter-duckdb-0.9.2.1.dev202311171355 → jupyter-duckdb-0.9.2.2}/src/duckdb_kernel/parser/elements/LogicOperand.py +0 -0
- {jupyter-duckdb-0.9.2.1.dev202311171355 → jupyter-duckdb-0.9.2.2}/src/duckdb_kernel/parser/elements/LogicOperator.py +0 -0
- {jupyter-duckdb-0.9.2.1.dev202311171355 → jupyter-duckdb-0.9.2.2}/src/duckdb_kernel/parser/elements/RABinaryOperator.py +0 -0
- {jupyter-duckdb-0.9.2.1.dev202311171355 → jupyter-duckdb-0.9.2.2}/src/duckdb_kernel/parser/elements/RAElement.py +0 -0
- {jupyter-duckdb-0.9.2.1.dev202311171355 → jupyter-duckdb-0.9.2.2}/src/duckdb_kernel/parser/elements/RAOperator.py +0 -0
- {jupyter-duckdb-0.9.2.1.dev202311171355 → jupyter-duckdb-0.9.2.2}/src/duckdb_kernel/parser/elements/RAUnaryOperator.py +0 -0
- {jupyter-duckdb-0.9.2.1.dev202311171355 → jupyter-duckdb-0.9.2.2}/src/duckdb_kernel/parser/elements/__init__.py +0 -0
- {jupyter-duckdb-0.9.2.1.dev202311171355 → jupyter-duckdb-0.9.2.2}/src/duckdb_kernel/parser/elements/binary/Add.py +0 -0
- {jupyter-duckdb-0.9.2.1.dev202311171355 → jupyter-duckdb-0.9.2.2}/src/duckdb_kernel/parser/elements/binary/And.py +0 -0
- {jupyter-duckdb-0.9.2.1.dev202311171355 → jupyter-duckdb-0.9.2.2}/src/duckdb_kernel/parser/elements/binary/ArrowLeft.py +0 -0
- {jupyter-duckdb-0.9.2.1.dev202311171355 → jupyter-duckdb-0.9.2.2}/src/duckdb_kernel/parser/elements/binary/Cross.py +0 -0
- {jupyter-duckdb-0.9.2.1.dev202311171355 → jupyter-duckdb-0.9.2.2}/src/duckdb_kernel/parser/elements/binary/Difference.py +0 -0
- {jupyter-duckdb-0.9.2.1.dev202311171355 → jupyter-duckdb-0.9.2.2}/src/duckdb_kernel/parser/elements/binary/Divide.py +0 -0
- {jupyter-duckdb-0.9.2.1.dev202311171355 → jupyter-duckdb-0.9.2.2}/src/duckdb_kernel/parser/elements/binary/Equal.py +0 -0
- {jupyter-duckdb-0.9.2.1.dev202311171355 → jupyter-duckdb-0.9.2.2}/src/duckdb_kernel/parser/elements/binary/GreaterThan.py +0 -0
- {jupyter-duckdb-0.9.2.1.dev202311171355 → jupyter-duckdb-0.9.2.2}/src/duckdb_kernel/parser/elements/binary/GreaterThanEqual.py +0 -0
- {jupyter-duckdb-0.9.2.1.dev202311171355 → jupyter-duckdb-0.9.2.2}/src/duckdb_kernel/parser/elements/binary/Intersection.py +0 -0
- {jupyter-duckdb-0.9.2.1.dev202311171355 → jupyter-duckdb-0.9.2.2}/src/duckdb_kernel/parser/elements/binary/Join.py +0 -0
- {jupyter-duckdb-0.9.2.1.dev202311171355 → jupyter-duckdb-0.9.2.2}/src/duckdb_kernel/parser/elements/binary/LessThan.py +0 -0
- {jupyter-duckdb-0.9.2.1.dev202311171355 → jupyter-duckdb-0.9.2.2}/src/duckdb_kernel/parser/elements/binary/LessThanEqual.py +0 -0
- {jupyter-duckdb-0.9.2.1.dev202311171355 → jupyter-duckdb-0.9.2.2}/src/duckdb_kernel/parser/elements/binary/Minus.py +0 -0
- {jupyter-duckdb-0.9.2.1.dev202311171355 → jupyter-duckdb-0.9.2.2}/src/duckdb_kernel/parser/elements/binary/Multiply.py +0 -0
- {jupyter-duckdb-0.9.2.1.dev202311171355 → jupyter-duckdb-0.9.2.2}/src/duckdb_kernel/parser/elements/binary/Or.py +0 -0
- {jupyter-duckdb-0.9.2.1.dev202311171355 → jupyter-duckdb-0.9.2.2}/src/duckdb_kernel/parser/elements/binary/Unequal.py +0 -0
- {jupyter-duckdb-0.9.2.1.dev202311171355 → jupyter-duckdb-0.9.2.2}/src/duckdb_kernel/parser/elements/binary/Union.py +0 -0
- {jupyter-duckdb-0.9.2.1.dev202311171355 → jupyter-duckdb-0.9.2.2}/src/duckdb_kernel/parser/elements/binary/__init__.py +0 -0
- {jupyter-duckdb-0.9.2.1.dev202311171355 → jupyter-duckdb-0.9.2.2}/src/duckdb_kernel/parser/elements/unary/Not.py +0 -0
- {jupyter-duckdb-0.9.2.1.dev202311171355 → jupyter-duckdb-0.9.2.2}/src/duckdb_kernel/parser/elements/unary/Projection.py +0 -0
- {jupyter-duckdb-0.9.2.1.dev202311171355 → jupyter-duckdb-0.9.2.2}/src/duckdb_kernel/parser/elements/unary/Rename.py +0 -0
- {jupyter-duckdb-0.9.2.1.dev202311171355 → jupyter-duckdb-0.9.2.2}/src/duckdb_kernel/parser/elements/unary/Selection.py +0 -0
- {jupyter-duckdb-0.9.2.1.dev202311171355 → jupyter-duckdb-0.9.2.2}/src/duckdb_kernel/parser/elements/unary/__init__.py +0 -0
- {jupyter-duckdb-0.9.2.1.dev202311171355 → jupyter-duckdb-0.9.2.2}/src/duckdb_kernel/parser/tokenizer/Token.py +0 -0
- {jupyter-duckdb-0.9.2.1.dev202311171355 → jupyter-duckdb-0.9.2.2}/src/duckdb_kernel/parser/tokenizer/Tokenizer.py +0 -0
- {jupyter-duckdb-0.9.2.1.dev202311171355 → jupyter-duckdb-0.9.2.2}/src/duckdb_kernel/parser/tokenizer/__init__.py +0 -0
- {jupyter-duckdb-0.9.2.1.dev202311171355 → jupyter-duckdb-0.9.2.2}/src/duckdb_kernel/parser/util/RenamableColumn.py +0 -0
- {jupyter-duckdb-0.9.2.1.dev202311171355 → jupyter-duckdb-0.9.2.2}/src/duckdb_kernel/parser/util/RenamableColumnList.py +0 -0
- {jupyter-duckdb-0.9.2.1.dev202311171355 → jupyter-duckdb-0.9.2.2}/src/duckdb_kernel/parser/util/__init__.py +0 -0
- {jupyter-duckdb-0.9.2.1.dev202311171355 → jupyter-duckdb-0.9.2.2}/src/duckdb_kernel/util/ResultSetComparator.py +0 -0
- {jupyter-duckdb-0.9.2.1.dev202311171355 → jupyter-duckdb-0.9.2.2}/src/duckdb_kernel/util/__init__.py +0 -0
- {jupyter-duckdb-0.9.2.1.dev202311171355 → jupyter-duckdb-0.9.2.2}/src/duckdb_kernel/util/formatting.py +0 -0
- {jupyter-duckdb-0.9.2.1.dev202311171355 → jupyter-duckdb-0.9.2.2}/src/duckdb_kernel/visualization/Drawer.py +0 -0
- {jupyter-duckdb-0.9.2.1.dev202311171355 → jupyter-duckdb-0.9.2.2}/src/duckdb_kernel/visualization/RATreeDrawer.py +0 -0
- {jupyter-duckdb-0.9.2.1.dev202311171355 → jupyter-duckdb-0.9.2.2}/src/duckdb_kernel/visualization/SchemaDrawer.py +0 -0
- {jupyter-duckdb-0.9.2.1.dev202311171355 → jupyter-duckdb-0.9.2.2}/src/duckdb_kernel/visualization/__init__.py +0 -0
- {jupyter-duckdb-0.9.2.1.dev202311171355 → jupyter-duckdb-0.9.2.2}/src/jupyter_duckdb.egg-info/SOURCES.txt +0 -0
- {jupyter-duckdb-0.9.2.1.dev202311171355 → jupyter-duckdb-0.9.2.2}/src/jupyter_duckdb.egg-info/dependency_links.txt +0 -0
- {jupyter-duckdb-0.9.2.1.dev202311171355 → jupyter-duckdb-0.9.2.2}/src/jupyter_duckdb.egg-info/requires.txt +0 -0
- {jupyter-duckdb-0.9.2.1.dev202311171355 → jupyter-duckdb-0.9.2.2}/src/jupyter_duckdb.egg-info/top_level.txt +0 -0
- {jupyter-duckdb-0.9.2.1.dev202311171355 → jupyter-duckdb-0.9.2.2}/test/test_result_comparison.py +0 -0
|
@@ -1,13 +1,12 @@
|
|
|
1
1
|
import os
|
|
2
|
+
import re
|
|
2
3
|
from datetime import datetime
|
|
3
4
|
|
|
4
5
|
from setuptools import setup, find_packages
|
|
5
6
|
|
|
6
7
|
# version
|
|
7
|
-
version = '0
|
|
8
|
-
|
|
9
|
-
if os.getenv('DEV') == '1':
|
|
10
|
-
version += '.dev' + datetime.now().strftime('%Y%m%d%H%M')
|
|
8
|
+
version = os.getenv('PACKAGE_VERSION', '1.0')
|
|
9
|
+
version = re.sub(r'[^dev0-9._]', '', version)
|
|
11
10
|
|
|
12
11
|
# install requires
|
|
13
12
|
install_requires = [
|
{jupyter-duckdb-0.9.2.1.dev202311171355 → jupyter-duckdb-0.9.2.2}/src/duckdb_kernel/kernel.py
RENAMED
|
@@ -41,7 +41,7 @@ class DuckDBKernel(Kernel):
|
|
|
41
41
|
MagicCommand('all', 'all_rows').on(self._all_magic),
|
|
42
42
|
MagicCommand('max_rows').arg('count').on(self._max_rows_magic),
|
|
43
43
|
MagicCommand('query_max_rows').arg('count').on(self._query_max_rows_magic),
|
|
44
|
-
MagicCommand('schema').flag('td').on(self._schema_magic),
|
|
44
|
+
MagicCommand('schema').flag('td').opt('only').on(self._schema_magic),
|
|
45
45
|
MagicCommand('ra').flag('analyze').code(True).on(self._ra_magic),
|
|
46
46
|
MagicCommand('dc').code(True).on(self._dc_magic)
|
|
47
47
|
)
|
|
@@ -336,7 +336,7 @@ class DuckDBKernel(Kernel):
|
|
|
336
336
|
'max_rows': int(count) if count.lower() != 'none' else None
|
|
337
337
|
}
|
|
338
338
|
|
|
339
|
-
def _schema_magic(self, silent: bool, td: bool):
|
|
339
|
+
def _schema_magic(self, silent: bool, td: bool, only: Optional[str]):
|
|
340
340
|
if self._db is None:
|
|
341
341
|
raise AssertionError('load a database first')
|
|
342
342
|
|
|
@@ -346,8 +346,42 @@ class DuckDBKernel(Kernel):
|
|
|
346
346
|
# analyze tables
|
|
347
347
|
tables = self._db.analyze()
|
|
348
348
|
|
|
349
|
+
# apply filter
|
|
350
|
+
if only is None:
|
|
351
|
+
table_values = list(tables.values())
|
|
352
|
+
|
|
353
|
+
else:
|
|
354
|
+
whitelist = set()
|
|
355
|
+
|
|
356
|
+
# split and strip names
|
|
357
|
+
names = [n.strip() for n in re.split(r'[, \t]', only)]
|
|
358
|
+
|
|
359
|
+
# add initial tables to result set
|
|
360
|
+
for name in names:
|
|
361
|
+
if name not in tables:
|
|
362
|
+
raise AssertionError(f'table {name} not found')
|
|
363
|
+
whitelist.add(tables[name])
|
|
364
|
+
|
|
365
|
+
# iterate until the result set does not change
|
|
366
|
+
last_size = 0
|
|
367
|
+
while last_size < len(whitelist):
|
|
368
|
+
last_size = len(whitelist)
|
|
369
|
+
|
|
370
|
+
# everything a foreign key reaches from this group
|
|
371
|
+
for rel in list(whitelist):
|
|
372
|
+
for fe in rel.foreign_keys:
|
|
373
|
+
whitelist.add(fe.constraint.table)
|
|
374
|
+
|
|
375
|
+
# everything that is reachable using a foreign key
|
|
376
|
+
for rel in tables.values():
|
|
377
|
+
for fe in rel.foreign_keys:
|
|
378
|
+
if fe.constraint.table in whitelist:
|
|
379
|
+
whitelist.add(rel)
|
|
380
|
+
|
|
381
|
+
table_values = list(whitelist)
|
|
382
|
+
|
|
349
383
|
# create and show visualization
|
|
350
|
-
vd = SchemaDrawer(
|
|
384
|
+
vd = SchemaDrawer(table_values)
|
|
351
385
|
svg = vd.to_svg(not td)
|
|
352
386
|
|
|
353
387
|
self.print_data(svg)
|
|
@@ -22,10 +22,13 @@ class RAOperand(RAElement):
|
|
|
22
22
|
yield
|
|
23
23
|
|
|
24
24
|
def to_sql(self, tables: Dict[str, Table]) -> Tuple[str, RenamableColumnList]:
|
|
25
|
-
|
|
25
|
+
table_keys = {key.lower(): key for key in tables}
|
|
26
|
+
relation_lower = self.relation.lower()
|
|
27
|
+
|
|
28
|
+
if relation_lower not in table_keys:
|
|
26
29
|
raise AssertionError(f'unknown relation {self.relation}')
|
|
27
30
|
|
|
28
|
-
cols = RenamableColumnList.from_iter(tables[
|
|
31
|
+
cols = RenamableColumnList.from_iter(tables[table_keys[relation_lower]].columns)
|
|
29
32
|
column_names = ', '.join(c.rename() for c in cols)
|
|
30
33
|
|
|
31
34
|
return f'SELECT DISTINCT {column_names} FROM {self.relation}', cols
|
|
@@ -149,9 +149,9 @@ class ConditionalSet:
|
|
|
149
149
|
# names for the attributes. We store the related operands and the join conditions.
|
|
150
150
|
# Furthermore, `select_columns` contains a mapping from column names to a part of
|
|
151
151
|
# a "select as" statement and joined_columns is a list of all columns that were
|
|
152
|
-
# used for joins, so the resulting sql
|
|
152
|
+
# used for joins, so the resulting sql statements do not become ambiguous if they
|
|
153
153
|
# are used for filtering.
|
|
154
|
-
positive_joins: List[Tuple[str, str, List[str]]] = []
|
|
154
|
+
positive_joins: List[Tuple[str, str, Optional[List[str]]]] = []
|
|
155
155
|
select_columns: Dict[str, str] = {}
|
|
156
156
|
joined_columns: RenamableColumnList = RenamableColumnList()
|
|
157
157
|
|
|
@@ -206,9 +206,22 @@ class ConditionalSet:
|
|
|
206
206
|
already_joined.add(join_tuple)
|
|
207
207
|
discovered_joins += 1
|
|
208
208
|
|
|
209
|
-
# If no
|
|
209
|
+
# If no common attributes were discovered using this table,
|
|
210
|
+
# a cross join is used instead.
|
|
210
211
|
if discovered_joins == 0:
|
|
211
|
-
|
|
212
|
+
# Find any other table for the cross join, so the joins
|
|
213
|
+
# can later be constructed.
|
|
214
|
+
for right_name, _, _ in relevant_positive:
|
|
215
|
+
if left_name != right_name:
|
|
216
|
+
break
|
|
217
|
+
else:
|
|
218
|
+
raise AssertionError(f'could not build join for relation {left_name}')
|
|
219
|
+
|
|
220
|
+
join_tuple = min(left_name, right_name), max(left_name, right_name)
|
|
221
|
+
|
|
222
|
+
# Store the join with a join condition that is None.
|
|
223
|
+
positive_joins.append((left_name, right_name, None))
|
|
224
|
+
already_joined.add(join_tuple)
|
|
212
225
|
|
|
213
226
|
# Last but not least we need to include the "negative" joins. They only
|
|
214
227
|
# remove tuples and never add any attributes, so we only track the
|
|
@@ -249,12 +262,17 @@ class ConditionalSet:
|
|
|
249
262
|
for _, target_name, join_condition in positive_joins:
|
|
250
263
|
if target_name not in all_positive_conditions:
|
|
251
264
|
all_positive_conditions[target_name] = []
|
|
252
|
-
|
|
265
|
+
if join_condition is not None:
|
|
266
|
+
all_positive_conditions[target_name].extend(join_condition)
|
|
253
267
|
|
|
254
|
-
sorted_positive_joins: List[Tuple[str, str, str]] = []
|
|
268
|
+
sorted_positive_joins: List[Tuple[str, str, Optional[str]]] = []
|
|
255
269
|
while len(used_relations) < len(relevant_positive):
|
|
256
270
|
for source_name, target_name, _ in positive_joins:
|
|
257
|
-
|
|
271
|
+
apc = all_positive_conditions[target_name]
|
|
272
|
+
if len(apc) == 0:
|
|
273
|
+
join_condition = None
|
|
274
|
+
else:
|
|
275
|
+
join_condition = ' AND '.join(apc)
|
|
258
276
|
|
|
259
277
|
if source_name in used_relations and target_name not in used_relations:
|
|
260
278
|
sorted_positive_joins.append((source_name, target_name, join_condition))
|
|
@@ -308,7 +326,10 @@ class ConditionalSet:
|
|
|
308
326
|
sql_tables = table_statements[relevant_positive[0][0]]
|
|
309
327
|
for _, target_name, join_condition in sorted_positive_joins:
|
|
310
328
|
target_table_stmt = table_statements[target_name]
|
|
311
|
-
|
|
329
|
+
if join_condition is None:
|
|
330
|
+
sql_tables += f' CROSS JOIN {target_table_stmt}'
|
|
331
|
+
else:
|
|
332
|
+
sql_tables += f' JOIN {target_table_stmt} ON {join_condition}'
|
|
312
333
|
for _, target_name, join_condition, _ in sorted_negative_joins:
|
|
313
334
|
target_table_stmt = table_statements[target_name]
|
|
314
335
|
sql_tables += f' LEFT JOIN {target_table_stmt} ON {join_condition}'
|
|
@@ -30,6 +30,23 @@ def test_simple_queries():
|
|
|
30
30
|
]
|
|
31
31
|
|
|
32
32
|
|
|
33
|
+
def test_asterisk_projection():
|
|
34
|
+
with Connection() as con:
|
|
35
|
+
root = DCParser.parse_query('{ * | users(id, _) }')
|
|
36
|
+
assert con.execute_dc(root) == [
|
|
37
|
+
(1,),
|
|
38
|
+
(2,),
|
|
39
|
+
(3,)
|
|
40
|
+
]
|
|
41
|
+
|
|
42
|
+
root = DCParser.parse_query('{ * | users(id, name) }')
|
|
43
|
+
assert con.execute_dc(root) == [
|
|
44
|
+
(1, 'Alice'),
|
|
45
|
+
(2, 'Bob'),
|
|
46
|
+
(3, 'Charlie')
|
|
47
|
+
]
|
|
48
|
+
|
|
49
|
+
|
|
33
50
|
def test_conditions():
|
|
34
51
|
with Connection() as con:
|
|
35
52
|
for query in [
|
|
@@ -135,6 +152,24 @@ def test_joins():
|
|
|
135
152
|
('Show 2', 'Actor F')
|
|
136
153
|
]
|
|
137
154
|
|
|
155
|
+
# cross join
|
|
156
|
+
root = DCParser.parse_query('{ sename | shows(shid1, shname) ∧ seasons(senum, shid2, sename) ∧ shid1 = shid2 }')
|
|
157
|
+
assert con.execute_dc(root) == [
|
|
158
|
+
('Show 1 / Season 1',),
|
|
159
|
+
('Show 1 / Season 2',),
|
|
160
|
+
('Show 2 / Season 1',),
|
|
161
|
+
('Show 2 / Season 2',)
|
|
162
|
+
]
|
|
163
|
+
|
|
164
|
+
for query in [
|
|
165
|
+
'{ s2,c5 | shows(sa1,s2) ∧ episodes(e1,e2,sb1,e4) ∧ characters(c1,e1,c3,sb1,c5) ∧ sa1=2 ∧ sa1 = sb1 ∧ e4="Show 2 / Season 1 / Episode 2" }',
|
|
166
|
+
'{ s2,c5 | shows(sa1,s2) ∧ episodes(e1,e2,sb1,e4) ∧ characters(c1,e1,c3,sc1,c5) ∧ sa1=2 ∧ sa1 = sb1 ∧ sb1 = sc1 ∧ e4="Show 2 / Season 1 / Episode 2" }'
|
|
167
|
+
]:
|
|
168
|
+
root = DCParser.parse_query(query)
|
|
169
|
+
assert con.execute_dc(root) == [
|
|
170
|
+
('Show 2', 'Actor F')
|
|
171
|
+
]
|
|
172
|
+
|
|
138
173
|
|
|
139
174
|
def test_underscores():
|
|
140
175
|
with Connection() as con:
|
|
@@ -7,6 +7,31 @@ from duckdb_kernel.parser.elements import RAOperand, LogicElement
|
|
|
7
7
|
from . import Connection
|
|
8
8
|
|
|
9
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
|
+
assert con.execute_ra(root) == [
|
|
29
|
+
(1, 'Alice'),
|
|
30
|
+
(2, 'Bob'),
|
|
31
|
+
(3, 'Charlie')
|
|
32
|
+
]
|
|
33
|
+
|
|
34
|
+
|
|
10
35
|
def test_binary_operator_cross():
|
|
11
36
|
for query in (
|
|
12
37
|
r'shows x seasons',
|
|
File without changes
|
|
File without changes
|
{jupyter-duckdb-0.9.2.1.dev202311171355 → jupyter-duckdb-0.9.2.2}/src/duckdb_kernel/__init__.py
RENAMED
|
File without changes
|
{jupyter-duckdb-0.9.2.1.dev202311171355 → jupyter-duckdb-0.9.2.2}/src/duckdb_kernel/__main__.py
RENAMED
|
File without changes
|
{jupyter-duckdb-0.9.2.1.dev202311171355 → jupyter-duckdb-0.9.2.2}/src/duckdb_kernel/db/Column.py
RENAMED
|
File without changes
|
{jupyter-duckdb-0.9.2.1.dev202311171355 → jupyter-duckdb-0.9.2.2}/src/duckdb_kernel/db/Connection.py
RENAMED
|
File without changes
|
{jupyter-duckdb-0.9.2.1.dev202311171355 → jupyter-duckdb-0.9.2.2}/src/duckdb_kernel/db/Constraint.py
RENAMED
|
File without changes
|
|
File without changes
|
{jupyter-duckdb-0.9.2.1.dev202311171355 → jupyter-duckdb-0.9.2.2}/src/duckdb_kernel/db/ForeignKey.py
RENAMED
|
File without changes
|
{jupyter-duckdb-0.9.2.1.dev202311171355 → jupyter-duckdb-0.9.2.2}/src/duckdb_kernel/db/Table.py
RENAMED
|
File without changes
|
{jupyter-duckdb-0.9.2.1.dev202311171355 → jupyter-duckdb-0.9.2.2}/src/duckdb_kernel/db/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{jupyter-duckdb-0.9.2.1.dev202311171355 → jupyter-duckdb-0.9.2.2}/src/duckdb_kernel/kernel.json
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{jupyter-duckdb-0.9.2.1.dev202311171355 → jupyter-duckdb-0.9.2.2}/src/duckdb_kernel/util/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{jupyter-duckdb-0.9.2.1.dev202311171355 → jupyter-duckdb-0.9.2.2}/test/test_result_comparison.py
RENAMED
|
File without changes
|