jupyter-duckdb 1.4.0__tar.gz → 1.4.105__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-1.4.0 → jupyter_duckdb-1.4.105}/PKG-INFO +5 -3
- {jupyter_duckdb-1.4.0 → jupyter_duckdb-1.4.105}/README.md +3 -1
- {jupyter_duckdb-1.4.0 → jupyter_duckdb-1.4.105}/setup.py +2 -2
- {jupyter_duckdb-1.4.0 → jupyter_duckdb-1.4.105}/src/duckdb_kernel/kernel.py +9 -5
- {jupyter_duckdb-1.4.0 → jupyter_duckdb-1.4.105}/src/duckdb_kernel/parser/RAParser.py +5 -0
- {jupyter_duckdb-1.4.0 → jupyter_duckdb-1.4.105}/src/duckdb_kernel/parser/elements/RAElement.py +4 -1
- {jupyter_duckdb-1.4.0 → jupyter_duckdb-1.4.105}/src/duckdb_kernel/parser/elements/binary/ConditionalSet.py +7 -1
- jupyter_duckdb-1.4.105/src/duckdb_kernel/parser/util/QuerySplitter.py +87 -0
- {jupyter_duckdb-1.4.0 → jupyter_duckdb-1.4.105}/src/duckdb_kernel/tests/__init__.py +2 -2
- {jupyter_duckdb-1.4.0 → jupyter_duckdb-1.4.105}/src/duckdb_kernel/tests/test_ra.py +23 -0
- {jupyter_duckdb-1.4.0 → jupyter_duckdb-1.4.105}/src/jupyter_duckdb.egg-info/PKG-INFO +5 -3
- {jupyter_duckdb-1.4.0 → jupyter_duckdb-1.4.105}/src/jupyter_duckdb.egg-info/SOURCES.txt +1 -0
- {jupyter_duckdb-1.4.0 → jupyter_duckdb-1.4.105}/src/jupyter_duckdb.egg-info/requires.txt +1 -1
- {jupyter_duckdb-1.4.0 → jupyter_duckdb-1.4.105}/setup.cfg +0 -0
- {jupyter_duckdb-1.4.0 → jupyter_duckdb-1.4.105}/src/duckdb_kernel/__init__.py +0 -0
- {jupyter_duckdb-1.4.0 → jupyter_duckdb-1.4.105}/src/duckdb_kernel/__main__.py +0 -0
- {jupyter_duckdb-1.4.0 → jupyter_duckdb-1.4.105}/src/duckdb_kernel/db/Column.py +0 -0
- {jupyter_duckdb-1.4.0 → jupyter_duckdb-1.4.105}/src/duckdb_kernel/db/Connection.py +0 -0
- {jupyter_duckdb-1.4.0 → jupyter_duckdb-1.4.105}/src/duckdb_kernel/db/Constraint.py +0 -0
- {jupyter_duckdb-1.4.0 → jupyter_duckdb-1.4.105}/src/duckdb_kernel/db/DatabaseError.py +0 -0
- {jupyter_duckdb-1.4.0 → jupyter_duckdb-1.4.105}/src/duckdb_kernel/db/ForeignKey.py +0 -0
- {jupyter_duckdb-1.4.0 → jupyter_duckdb-1.4.105}/src/duckdb_kernel/db/Table.py +0 -0
- {jupyter_duckdb-1.4.0 → jupyter_duckdb-1.4.105}/src/duckdb_kernel/db/__init__.py +0 -0
- {jupyter_duckdb-1.4.0 → jupyter_duckdb-1.4.105}/src/duckdb_kernel/db/error/EmptyResultError.py +0 -0
- {jupyter_duckdb-1.4.0 → jupyter_duckdb-1.4.105}/src/duckdb_kernel/db/error/__init__.py +0 -0
- {jupyter_duckdb-1.4.0 → jupyter_duckdb-1.4.105}/src/duckdb_kernel/db/implementation/duckdb/Connection.py +0 -0
- {jupyter_duckdb-1.4.0 → jupyter_duckdb-1.4.105}/src/duckdb_kernel/db/implementation/duckdb/__init__.py +0 -0
- {jupyter_duckdb-1.4.0 → jupyter_duckdb-1.4.105}/src/duckdb_kernel/db/implementation/postgres/Connection.py +0 -0
- {jupyter_duckdb-1.4.0 → jupyter_duckdb-1.4.105}/src/duckdb_kernel/db/implementation/postgres/__init__.py +0 -0
- {jupyter_duckdb-1.4.0 → jupyter_duckdb-1.4.105}/src/duckdb_kernel/db/implementation/postgres/util.py +0 -0
- {jupyter_duckdb-1.4.0 → jupyter_duckdb-1.4.105}/src/duckdb_kernel/db/implementation/sqlite/Connection.py +0 -0
- {jupyter_duckdb-1.4.0 → jupyter_duckdb-1.4.105}/src/duckdb_kernel/db/implementation/sqlite/__init__.py +0 -0
- {jupyter_duckdb-1.4.0 → jupyter_duckdb-1.4.105}/src/duckdb_kernel/kernel.json +0 -0
- {jupyter_duckdb-1.4.0 → jupyter_duckdb-1.4.105}/src/duckdb_kernel/magics/MagicCommand.py +0 -0
- {jupyter_duckdb-1.4.0 → jupyter_duckdb-1.4.105}/src/duckdb_kernel/magics/MagicCommandCallback.py +0 -0
- {jupyter_duckdb-1.4.0 → jupyter_duckdb-1.4.105}/src/duckdb_kernel/magics/MagicCommandException.py +0 -0
- {jupyter_duckdb-1.4.0 → jupyter_duckdb-1.4.105}/src/duckdb_kernel/magics/MagicCommandHandler.py +0 -0
- {jupyter_duckdb-1.4.0 → jupyter_duckdb-1.4.105}/src/duckdb_kernel/magics/MagicState.py +0 -0
- {jupyter_duckdb-1.4.0 → jupyter_duckdb-1.4.105}/src/duckdb_kernel/magics/__init__.py +0 -0
- {jupyter_duckdb-1.4.0 → jupyter_duckdb-1.4.105}/src/duckdb_kernel/parser/DCParser.py +0 -0
- {jupyter_duckdb-1.4.0 → jupyter_duckdb-1.4.105}/src/duckdb_kernel/parser/LogicParser.py +0 -0
- {jupyter_duckdb-1.4.0 → jupyter_duckdb-1.4.105}/src/duckdb_kernel/parser/ParserError.py +0 -0
- {jupyter_duckdb-1.4.0 → jupyter_duckdb-1.4.105}/src/duckdb_kernel/parser/__init__.py +0 -0
- {jupyter_duckdb-1.4.0 → jupyter_duckdb-1.4.105}/src/duckdb_kernel/parser/elements/DCOperand.py +0 -0
- {jupyter_duckdb-1.4.0 → jupyter_duckdb-1.4.105}/src/duckdb_kernel/parser/elements/LogicElement.py +0 -0
- {jupyter_duckdb-1.4.0 → jupyter_duckdb-1.4.105}/src/duckdb_kernel/parser/elements/LogicOperand.py +0 -0
- {jupyter_duckdb-1.4.0 → jupyter_duckdb-1.4.105}/src/duckdb_kernel/parser/elements/LogicOperator.py +0 -0
- {jupyter_duckdb-1.4.0 → jupyter_duckdb-1.4.105}/src/duckdb_kernel/parser/elements/RABinaryOperator.py +0 -0
- {jupyter_duckdb-1.4.0 → jupyter_duckdb-1.4.105}/src/duckdb_kernel/parser/elements/RAOperand.py +0 -0
- {jupyter_duckdb-1.4.0 → jupyter_duckdb-1.4.105}/src/duckdb_kernel/parser/elements/RAOperator.py +0 -0
- {jupyter_duckdb-1.4.0 → jupyter_duckdb-1.4.105}/src/duckdb_kernel/parser/elements/RAUnaryOperator.py +0 -0
- {jupyter_duckdb-1.4.0 → jupyter_duckdb-1.4.105}/src/duckdb_kernel/parser/elements/__init__.py +0 -0
- {jupyter_duckdb-1.4.0 → jupyter_duckdb-1.4.105}/src/duckdb_kernel/parser/elements/binary/Add.py +0 -0
- {jupyter_duckdb-1.4.0 → jupyter_duckdb-1.4.105}/src/duckdb_kernel/parser/elements/binary/And.py +0 -0
- {jupyter_duckdb-1.4.0 → jupyter_duckdb-1.4.105}/src/duckdb_kernel/parser/elements/binary/ArrowLeft.py +0 -0
- {jupyter_duckdb-1.4.0 → jupyter_duckdb-1.4.105}/src/duckdb_kernel/parser/elements/binary/Cross.py +0 -0
- {jupyter_duckdb-1.4.0 → jupyter_duckdb-1.4.105}/src/duckdb_kernel/parser/elements/binary/Difference.py +0 -0
- {jupyter_duckdb-1.4.0 → jupyter_duckdb-1.4.105}/src/duckdb_kernel/parser/elements/binary/Divide.py +0 -0
- {jupyter_duckdb-1.4.0 → jupyter_duckdb-1.4.105}/src/duckdb_kernel/parser/elements/binary/Division.py +0 -0
- {jupyter_duckdb-1.4.0 → jupyter_duckdb-1.4.105}/src/duckdb_kernel/parser/elements/binary/Equal.py +0 -0
- {jupyter_duckdb-1.4.0 → jupyter_duckdb-1.4.105}/src/duckdb_kernel/parser/elements/binary/FullOuterJoin.py +0 -0
- {jupyter_duckdb-1.4.0 → jupyter_duckdb-1.4.105}/src/duckdb_kernel/parser/elements/binary/GreaterThan.py +0 -0
- {jupyter_duckdb-1.4.0 → jupyter_duckdb-1.4.105}/src/duckdb_kernel/parser/elements/binary/GreaterThanEqual.py +0 -0
- {jupyter_duckdb-1.4.0 → jupyter_duckdb-1.4.105}/src/duckdb_kernel/parser/elements/binary/Intersection.py +0 -0
- {jupyter_duckdb-1.4.0 → jupyter_duckdb-1.4.105}/src/duckdb_kernel/parser/elements/binary/Join.py +0 -0
- {jupyter_duckdb-1.4.0 → jupyter_duckdb-1.4.105}/src/duckdb_kernel/parser/elements/binary/LeftOuterJoin.py +0 -0
- {jupyter_duckdb-1.4.0 → jupyter_duckdb-1.4.105}/src/duckdb_kernel/parser/elements/binary/LessThan.py +0 -0
- {jupyter_duckdb-1.4.0 → jupyter_duckdb-1.4.105}/src/duckdb_kernel/parser/elements/binary/LessThanEqual.py +0 -0
- {jupyter_duckdb-1.4.0 → jupyter_duckdb-1.4.105}/src/duckdb_kernel/parser/elements/binary/Minus.py +0 -0
- {jupyter_duckdb-1.4.0 → jupyter_duckdb-1.4.105}/src/duckdb_kernel/parser/elements/binary/Multiply.py +0 -0
- {jupyter_duckdb-1.4.0 → jupyter_duckdb-1.4.105}/src/duckdb_kernel/parser/elements/binary/Or.py +0 -0
- {jupyter_duckdb-1.4.0 → jupyter_duckdb-1.4.105}/src/duckdb_kernel/parser/elements/binary/RightOuterJoin.py +0 -0
- {jupyter_duckdb-1.4.0 → jupyter_duckdb-1.4.105}/src/duckdb_kernel/parser/elements/binary/Unequal.py +0 -0
- {jupyter_duckdb-1.4.0 → jupyter_duckdb-1.4.105}/src/duckdb_kernel/parser/elements/binary/Union.py +0 -0
- {jupyter_duckdb-1.4.0 → jupyter_duckdb-1.4.105}/src/duckdb_kernel/parser/elements/binary/__init__.py +0 -0
- {jupyter_duckdb-1.4.0 → jupyter_duckdb-1.4.105}/src/duckdb_kernel/parser/elements/unary/Not.py +0 -0
- {jupyter_duckdb-1.4.0 → jupyter_duckdb-1.4.105}/src/duckdb_kernel/parser/elements/unary/Projection.py +0 -0
- {jupyter_duckdb-1.4.0 → jupyter_duckdb-1.4.105}/src/duckdb_kernel/parser/elements/unary/Rename.py +0 -0
- {jupyter_duckdb-1.4.0 → jupyter_duckdb-1.4.105}/src/duckdb_kernel/parser/elements/unary/Selection.py +0 -0
- {jupyter_duckdb-1.4.0 → jupyter_duckdb-1.4.105}/src/duckdb_kernel/parser/elements/unary/__init__.py +0 -0
- {jupyter_duckdb-1.4.0 → jupyter_duckdb-1.4.105}/src/duckdb_kernel/parser/tokenizer/Token.py +0 -0
- {jupyter_duckdb-1.4.0 → jupyter_duckdb-1.4.105}/src/duckdb_kernel/parser/tokenizer/Tokenizer.py +0 -0
- {jupyter_duckdb-1.4.0 → jupyter_duckdb-1.4.105}/src/duckdb_kernel/parser/tokenizer/__init__.py +0 -0
- {jupyter_duckdb-1.4.0 → jupyter_duckdb-1.4.105}/src/duckdb_kernel/parser/util/RenamableColumn.py +0 -0
- {jupyter_duckdb-1.4.0 → jupyter_duckdb-1.4.105}/src/duckdb_kernel/parser/util/RenamableColumnList.py +0 -0
- {jupyter_duckdb-1.4.0 → jupyter_duckdb-1.4.105}/src/duckdb_kernel/parser/util/__init__.py +0 -0
- {jupyter_duckdb-1.4.0 → jupyter_duckdb-1.4.105}/src/duckdb_kernel/tests/test_dc.py +0 -0
- {jupyter_duckdb-1.4.0 → jupyter_duckdb-1.4.105}/src/duckdb_kernel/tests/test_result_comparison.py +0 -0
- {jupyter_duckdb-1.4.0 → jupyter_duckdb-1.4.105}/src/duckdb_kernel/tests/test_sql.py +0 -0
- {jupyter_duckdb-1.4.0 → jupyter_duckdb-1.4.105}/src/duckdb_kernel/util/ResultSetComparator.py +0 -0
- {jupyter_duckdb-1.4.0 → jupyter_duckdb-1.4.105}/src/duckdb_kernel/util/SQL.py +0 -0
- {jupyter_duckdb-1.4.0 → jupyter_duckdb-1.4.105}/src/duckdb_kernel/util/TestError.py +0 -0
- {jupyter_duckdb-1.4.0 → jupyter_duckdb-1.4.105}/src/duckdb_kernel/util/__init__.py +0 -0
- {jupyter_duckdb-1.4.0 → jupyter_duckdb-1.4.105}/src/duckdb_kernel/util/formatting.py +0 -0
- {jupyter_duckdb-1.4.0 → jupyter_duckdb-1.4.105}/src/duckdb_kernel/visualization/Drawer.py +0 -0
- {jupyter_duckdb-1.4.0 → jupyter_duckdb-1.4.105}/src/duckdb_kernel/visualization/Plotly.py +0 -0
- {jupyter_duckdb-1.4.0 → jupyter_duckdb-1.4.105}/src/duckdb_kernel/visualization/RATreeDrawer.py +0 -0
- {jupyter_duckdb-1.4.0 → jupyter_duckdb-1.4.105}/src/duckdb_kernel/visualization/SchemaDrawer.py +0 -0
- {jupyter_duckdb-1.4.0 → jupyter_duckdb-1.4.105}/src/duckdb_kernel/visualization/__init__.py +0 -0
- {jupyter_duckdb-1.4.0 → jupyter_duckdb-1.4.105}/src/duckdb_kernel/visualization/lib/__init__.py +0 -0
- {jupyter_duckdb-1.4.0 → jupyter_duckdb-1.4.105}/src/duckdb_kernel/visualization/lib/plotly-3.0.1.min.js +0 -0
- {jupyter_duckdb-1.4.0 → jupyter_duckdb-1.4.105}/src/duckdb_kernel/visualization/lib/ra.css +0 -0
- {jupyter_duckdb-1.4.0 → jupyter_duckdb-1.4.105}/src/duckdb_kernel/visualization/lib/ra.js +0 -0
- {jupyter_duckdb-1.4.0 → jupyter_duckdb-1.4.105}/src/jupyter_duckdb.egg-info/dependency_links.txt +0 -0
- {jupyter_duckdb-1.4.0 → jupyter_duckdb-1.4.105}/src/jupyter_duckdb.egg-info/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: jupyter-duckdb
|
|
3
|
-
Version: 1.4.
|
|
3
|
+
Version: 1.4.105
|
|
4
4
|
Summary: a basic wrapper kernel for DuckDB
|
|
5
5
|
Home-page: https://github.com/erictroebs/jupyter-duckdb
|
|
6
6
|
Author: Eric Tröbs
|
|
@@ -14,7 +14,7 @@ Description-Content-Type: text/markdown
|
|
|
14
14
|
Requires-Dist: jupyter
|
|
15
15
|
Requires-Dist: graphviz==0.21
|
|
16
16
|
Requires-Dist: checkmarkandcross
|
|
17
|
-
Requires-Dist: duckdb==1.4.
|
|
17
|
+
Requires-Dist: duckdb==1.4.1
|
|
18
18
|
Dynamic: author
|
|
19
19
|
Dynamic: author-email
|
|
20
20
|
Dynamic: classifier
|
|
@@ -45,6 +45,7 @@ There are some magic commands that make teaching easier with this kernel.
|
|
|
45
45
|
- [Ship Tests With Your Notebook](#ship-tests-with-your-notebooks)
|
|
46
46
|
- [Relational Algebra](#relational-algebra)
|
|
47
47
|
- [Domain Calculus](#domain-calculus)
|
|
48
|
+
- [Automated Parser Selection](#automated-parser-selection)
|
|
48
49
|
|
|
49
50
|
## Setup
|
|
50
51
|
|
|
@@ -281,6 +282,8 @@ The supported operations are:
|
|
|
281
282
|
The optional flag `ANALYZE` can be used to add an execution diagram to the
|
|
282
283
|
output.
|
|
283
284
|
|
|
285
|
+
You can also add comments to queries using `--` or `/* */`, just like in SQL.
|
|
286
|
+
|
|
284
287
|
The Dockerfile also installs the Jupyter Lab plugin
|
|
285
288
|
[jupyter-ra-extension](https://pypi.org/project/jupyter-ra-extension/). It adds
|
|
286
289
|
the symbols mentioned above and some other supported symbols to the toolbar for
|
|
@@ -304,4 +307,3 @@ executed cells.
|
|
|
304
307
|
If the magic command `%AUTO_PARSER` is added to a cell, a parser is
|
|
305
308
|
automatically selected. If `%GUESS_PARSER` is executed, the parser is
|
|
306
309
|
automatically selected for all subsequent cells.
|
|
307
|
-
|
|
@@ -17,6 +17,7 @@ There are some magic commands that make teaching easier with this kernel.
|
|
|
17
17
|
- [Ship Tests With Your Notebook](#ship-tests-with-your-notebooks)
|
|
18
18
|
- [Relational Algebra](#relational-algebra)
|
|
19
19
|
- [Domain Calculus](#domain-calculus)
|
|
20
|
+
- [Automated Parser Selection](#automated-parser-selection)
|
|
20
21
|
|
|
21
22
|
## Setup
|
|
22
23
|
|
|
@@ -253,6 +254,8 @@ The supported operations are:
|
|
|
253
254
|
The optional flag `ANALYZE` can be used to add an execution diagram to the
|
|
254
255
|
output.
|
|
255
256
|
|
|
257
|
+
You can also add comments to queries using `--` or `/* */`, just like in SQL.
|
|
258
|
+
|
|
256
259
|
The Dockerfile also installs the Jupyter Lab plugin
|
|
257
260
|
[jupyter-ra-extension](https://pypi.org/project/jupyter-ra-extension/). It adds
|
|
258
261
|
the symbols mentioned above and some other supported symbols to the toolbar for
|
|
@@ -276,4 +279,3 @@ executed cells.
|
|
|
276
279
|
If the magic command `%AUTO_PARSER` is added to a cell, a parser is
|
|
277
280
|
automatically selected. If `%GUESS_PARSER` is executed, the parser is
|
|
278
281
|
automatically selected for all subsequent cells.
|
|
279
|
-
|
|
@@ -13,6 +13,7 @@ from .db import Connection, DatabaseError, Table
|
|
|
13
13
|
from .db.error import *
|
|
14
14
|
from .magics import *
|
|
15
15
|
from .parser import RAParser, DCParser, ParserError
|
|
16
|
+
from .parser.util.QuerySplitter import split_queries, get_last_query
|
|
16
17
|
from .util.ResultSetComparator import ResultSetComparator
|
|
17
18
|
from .util.SQL import SQL_KEYWORDS
|
|
18
19
|
from .util.TestError import TestError
|
|
@@ -27,9 +28,11 @@ class DuckDBKernel(Kernel):
|
|
|
27
28
|
implementation_version = '1.0'
|
|
28
29
|
banner = 'DuckDB Kernel'
|
|
29
30
|
language_info = {
|
|
30
|
-
'name': '
|
|
31
|
-
'mimetype': 'application/sql',
|
|
31
|
+
'name': 'sql',
|
|
32
32
|
'file_extension': '.sql',
|
|
33
|
+
'mimetype': 'text/x-sql',
|
|
34
|
+
'codemirror_mode': 'sql',
|
|
35
|
+
'pygments_lexer': 'sql',
|
|
33
36
|
}
|
|
34
37
|
|
|
35
38
|
def __init__(self, **kwargs):
|
|
@@ -166,7 +169,9 @@ class DuckDBKernel(Kernel):
|
|
|
166
169
|
# print result if not silent
|
|
167
170
|
if not silent:
|
|
168
171
|
# print EXPLAIN queries as raw text if using DuckDB
|
|
169
|
-
|
|
172
|
+
last_query = get_last_query(query, remove_comments=True).strip()
|
|
173
|
+
|
|
174
|
+
if last_query.startswith('EXPLAIN') and state.db.plain_explain():
|
|
170
175
|
for ekey, evalue in rows:
|
|
171
176
|
html = f'<b>{ekey}</b><br><pre>{evalue}</pre>'
|
|
172
177
|
break
|
|
@@ -273,8 +278,7 @@ class DuckDBKernel(Kernel):
|
|
|
273
278
|
|
|
274
279
|
# You can only execute one statement at a time using SQLite.
|
|
275
280
|
if not state.db.multiple_statements_per_query():
|
|
276
|
-
|
|
277
|
-
for statement in statements:
|
|
281
|
+
for statement in split_queries(content):
|
|
278
282
|
try:
|
|
279
283
|
state.db.execute(statement)
|
|
280
284
|
except EmptyResultError:
|
|
@@ -2,6 +2,7 @@ from .LogicParser import LogicParser
|
|
|
2
2
|
from .ParserError import RAParserError
|
|
3
3
|
from .elements import *
|
|
4
4
|
from .tokenizer import *
|
|
5
|
+
from .util.QuerySplitter import get_last_query
|
|
5
6
|
|
|
6
7
|
|
|
7
8
|
# Instead of multiple nested loops, a tree with rotation can
|
|
@@ -10,6 +11,10 @@ from .tokenizer import *
|
|
|
10
11
|
class RAParser:
|
|
11
12
|
@staticmethod
|
|
12
13
|
def parse_query(query: str) -> RAElement:
|
|
14
|
+
# remove comments from query
|
|
15
|
+
query = get_last_query(query, split_at=None, remove_comments=True)
|
|
16
|
+
|
|
17
|
+
# parse query
|
|
13
18
|
initial_token = Token(query)
|
|
14
19
|
return RAParser.parse_tokens(initial_token, depth=0)
|
|
15
20
|
|
{jupyter_duckdb-1.4.0 → jupyter_duckdb-1.4.105}/src/duckdb_kernel/parser/elements/RAElement.py
RENAMED
|
@@ -36,10 +36,13 @@ class RAElement:
|
|
|
36
36
|
# if all columns are from the same relation we can skip the relation name
|
|
37
37
|
if len(set(c.table for c in columns)) == 1:
|
|
38
38
|
column_names = ', '.join(f'{c.current_name} AS "{c.name}"' for c in columns)
|
|
39
|
+
order_names = ', '.join(f'"{c.name}" ASC' for c in columns)
|
|
39
40
|
else:
|
|
40
41
|
column_names = ', '.join(f'{c.current_name} AS "{c.full_name}"' for c in columns)
|
|
42
|
+
order_names = ', '.join(f'"{c.full_name}" ASC' for c in columns)
|
|
41
43
|
|
|
42
|
-
|
|
44
|
+
# create sql
|
|
45
|
+
return f'SELECT {column_names} FROM ({sql}) {self._name()} ORDER BY {order_names}'
|
|
43
46
|
|
|
44
47
|
def to_sql_with_count(self, tables: Dict[str, Table]) -> str:
|
|
45
48
|
sql, _ = self.to_sql(tables)
|
|
@@ -347,7 +347,13 @@ class ConditionalSet:
|
|
|
347
347
|
sql_join_filters += f' AND {join_filter}'
|
|
348
348
|
|
|
349
349
|
sql_condition = condition.to_sql(joined_columns) if condition is not None else '1=1'
|
|
350
|
-
|
|
350
|
+
|
|
351
|
+
if self.projection == ('*',):
|
|
352
|
+
sql_order = ', '.join(f'{rc.name} ASC' for rcl in rcls for rc in rcl)
|
|
353
|
+
else:
|
|
354
|
+
sql_order = ', '.join(f'{col} ASC' for col in self.projection)
|
|
355
|
+
|
|
356
|
+
sql_query = f'SELECT DISTINCT {sql_select} FROM {sql_tables} WHERE ({sql_join_filters}) AND ({sql_condition}) ORDER BY {sql_order}'
|
|
351
357
|
|
|
352
358
|
# Create a mapping from intermediate column names to constant values.
|
|
353
359
|
column_name_mapping = {
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
from typing import Iterator
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
def split_queries(query: str, split_at: str | None = ';', remove_comments: bool = False) -> Iterator[str]:
|
|
5
|
+
quotes = '\'"`'
|
|
6
|
+
|
|
7
|
+
escaped = False
|
|
8
|
+
in_quotes = None
|
|
9
|
+
in_singleline_comment = False
|
|
10
|
+
in_multiline_comment = False
|
|
11
|
+
|
|
12
|
+
previous = None
|
|
13
|
+
current_query = []
|
|
14
|
+
|
|
15
|
+
for symbol in query:
|
|
16
|
+
keep_symbol = True
|
|
17
|
+
|
|
18
|
+
# escaped symbol
|
|
19
|
+
if escaped:
|
|
20
|
+
escaped = False
|
|
21
|
+
|
|
22
|
+
# backslash (escape)
|
|
23
|
+
elif symbol == '\\':
|
|
24
|
+
escaped = True
|
|
25
|
+
|
|
26
|
+
# if in quotes
|
|
27
|
+
elif in_quotes is not None:
|
|
28
|
+
if symbol == in_quotes:
|
|
29
|
+
in_quotes = False
|
|
30
|
+
|
|
31
|
+
# if in single line comment
|
|
32
|
+
elif in_singleline_comment:
|
|
33
|
+
if symbol == '\n':
|
|
34
|
+
in_singleline_comment = False
|
|
35
|
+
elif remove_comments:
|
|
36
|
+
keep_symbol = False
|
|
37
|
+
|
|
38
|
+
# if in multiline comment
|
|
39
|
+
elif in_multiline_comment:
|
|
40
|
+
if previous == '*' and symbol == '/':
|
|
41
|
+
in_multiline_comment = False
|
|
42
|
+
|
|
43
|
+
if remove_comments:
|
|
44
|
+
keep_symbol = False
|
|
45
|
+
|
|
46
|
+
# start of quotes
|
|
47
|
+
elif symbol in quotes:
|
|
48
|
+
in_quotes = symbol
|
|
49
|
+
|
|
50
|
+
# start of single line comment
|
|
51
|
+
elif previous == '-' and symbol == '-':
|
|
52
|
+
in_singleline_comment = True
|
|
53
|
+
|
|
54
|
+
if remove_comments:
|
|
55
|
+
keep_symbol = False
|
|
56
|
+
current_query.pop()
|
|
57
|
+
|
|
58
|
+
# start of multiline comment
|
|
59
|
+
elif previous == '/' and symbol == '*':
|
|
60
|
+
in_multiline_comment = True
|
|
61
|
+
|
|
62
|
+
if remove_comments:
|
|
63
|
+
keep_symbol = False
|
|
64
|
+
current_query.pop()
|
|
65
|
+
|
|
66
|
+
# semicolon
|
|
67
|
+
elif split_at is not None and symbol == split_at:
|
|
68
|
+
yield ''.join(current_query)
|
|
69
|
+
|
|
70
|
+
current_query = []
|
|
71
|
+
keep_symbol = False
|
|
72
|
+
|
|
73
|
+
# store symbol
|
|
74
|
+
if keep_symbol:
|
|
75
|
+
current_query.append(symbol)
|
|
76
|
+
|
|
77
|
+
previous = symbol
|
|
78
|
+
|
|
79
|
+
# yield remaining symbols
|
|
80
|
+
yield ''.join(current_query)
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
def get_last_query(query: str, split_at: str | None = ';', remove_comments: bool = False) -> str:
|
|
84
|
+
for query in split_queries(query, split_at, remove_comments):
|
|
85
|
+
pass
|
|
86
|
+
|
|
87
|
+
return query
|
|
@@ -56,7 +56,7 @@ class Connection:
|
|
|
56
56
|
sql = root.to_sql_with_renamed_columns(self.tables)
|
|
57
57
|
cols, rows = self.execute_sql_return_cols(sql)
|
|
58
58
|
|
|
59
|
-
return cols, sorted(rows, key=lambda t: tuple(-1 if x is None else x for x in t))
|
|
59
|
+
return cols, rows # sorted(rows, key=lambda t: tuple(-1 if x is None else x for x in t))
|
|
60
60
|
|
|
61
61
|
def execute_ra(self, root: RAElement) -> List:
|
|
62
62
|
_, rows = self.execute_ra_return_cols(root)
|
|
@@ -66,7 +66,7 @@ class Connection:
|
|
|
66
66
|
sql, cnm = root.to_sql_with_renamed_columns(self.tables)
|
|
67
67
|
cols, rows = self.execute_sql_return_cols(sql)
|
|
68
68
|
|
|
69
|
-
return [cnm.get(c, c) for c in cols], sorted(rows)
|
|
69
|
+
return [cnm.get(c, c) for c in cols], rows # sorted(rows)
|
|
70
70
|
|
|
71
71
|
def execute_dc(self, root: ConditionalSet) -> List:
|
|
72
72
|
_, rows = self.execute_dc_return_cols(root)
|
|
@@ -79,6 +79,29 @@ def test_case_insensitivity():
|
|
|
79
79
|
]
|
|
80
80
|
|
|
81
81
|
|
|
82
|
+
def test_comments():
|
|
83
|
+
for query in (
|
|
84
|
+
# single line
|
|
85
|
+
'Shows -- x Users\n x Seasons',
|
|
86
|
+
'Shows x Seasons -- x Users',
|
|
87
|
+
'Shows x Seasons--',
|
|
88
|
+
'Shows x Seasons--\n',
|
|
89
|
+
# multi line
|
|
90
|
+
'Shows /* x Users */ x Seasons',
|
|
91
|
+
'Shows /* x Users */\n x Seasons',
|
|
92
|
+
'Shows /* x Users\n */ x Seasons',
|
|
93
|
+
'Shows x Seasons/**/',
|
|
94
|
+
'Shows x Seasons/*\n*/',
|
|
95
|
+
'Shows x Seasons\n/**/',
|
|
96
|
+
'Shows x Seasons/* x Users'
|
|
97
|
+
):
|
|
98
|
+
root = RAParser.parse_query(query)
|
|
99
|
+
|
|
100
|
+
assert isinstance(root, BinaryOperators.Cross)
|
|
101
|
+
assert isinstance(root.left, RAOperand) and root.left.name == 'Shows'
|
|
102
|
+
assert isinstance(root.right, RAOperand) and root.right.name == 'Seasons'
|
|
103
|
+
|
|
104
|
+
|
|
82
105
|
def test_binary_operator_cross():
|
|
83
106
|
for query in (
|
|
84
107
|
r'Shows x Seasons',
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: jupyter-duckdb
|
|
3
|
-
Version: 1.4.
|
|
3
|
+
Version: 1.4.105
|
|
4
4
|
Summary: a basic wrapper kernel for DuckDB
|
|
5
5
|
Home-page: https://github.com/erictroebs/jupyter-duckdb
|
|
6
6
|
Author: Eric Tröbs
|
|
@@ -14,7 +14,7 @@ Description-Content-Type: text/markdown
|
|
|
14
14
|
Requires-Dist: jupyter
|
|
15
15
|
Requires-Dist: graphviz==0.21
|
|
16
16
|
Requires-Dist: checkmarkandcross
|
|
17
|
-
Requires-Dist: duckdb==1.4.
|
|
17
|
+
Requires-Dist: duckdb==1.4.1
|
|
18
18
|
Dynamic: author
|
|
19
19
|
Dynamic: author-email
|
|
20
20
|
Dynamic: classifier
|
|
@@ -45,6 +45,7 @@ There are some magic commands that make teaching easier with this kernel.
|
|
|
45
45
|
- [Ship Tests With Your Notebook](#ship-tests-with-your-notebooks)
|
|
46
46
|
- [Relational Algebra](#relational-algebra)
|
|
47
47
|
- [Domain Calculus](#domain-calculus)
|
|
48
|
+
- [Automated Parser Selection](#automated-parser-selection)
|
|
48
49
|
|
|
49
50
|
## Setup
|
|
50
51
|
|
|
@@ -281,6 +282,8 @@ The supported operations are:
|
|
|
281
282
|
The optional flag `ANALYZE` can be used to add an execution diagram to the
|
|
282
283
|
output.
|
|
283
284
|
|
|
285
|
+
You can also add comments to queries using `--` or `/* */`, just like in SQL.
|
|
286
|
+
|
|
284
287
|
The Dockerfile also installs the Jupyter Lab plugin
|
|
285
288
|
[jupyter-ra-extension](https://pypi.org/project/jupyter-ra-extension/). It adds
|
|
286
289
|
the symbols mentioned above and some other supported symbols to the toolbar for
|
|
@@ -304,4 +307,3 @@ executed cells.
|
|
|
304
307
|
If the magic command `%AUTO_PARSER` is added to a cell, a parser is
|
|
305
308
|
automatically selected. If `%GUESS_PARSER` is executed, the parser is
|
|
306
309
|
automatically selected for all subsequent cells.
|
|
307
|
-
|
|
@@ -73,6 +73,7 @@ src/duckdb_kernel/parser/elements/unary/__init__.py
|
|
|
73
73
|
src/duckdb_kernel/parser/tokenizer/Token.py
|
|
74
74
|
src/duckdb_kernel/parser/tokenizer/Tokenizer.py
|
|
75
75
|
src/duckdb_kernel/parser/tokenizer/__init__.py
|
|
76
|
+
src/duckdb_kernel/parser/util/QuerySplitter.py
|
|
76
77
|
src/duckdb_kernel/parser/util/RenamableColumn.py
|
|
77
78
|
src/duckdb_kernel/parser/util/RenamableColumnList.py
|
|
78
79
|
src/duckdb_kernel/parser/util/__init__.py
|
|
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-1.4.0 → jupyter_duckdb-1.4.105}/src/duckdb_kernel/db/error/EmptyResultError.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{jupyter_duckdb-1.4.0 → jupyter_duckdb-1.4.105}/src/duckdb_kernel/db/implementation/postgres/util.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{jupyter_duckdb-1.4.0 → jupyter_duckdb-1.4.105}/src/duckdb_kernel/magics/MagicCommandCallback.py
RENAMED
|
File without changes
|
{jupyter_duckdb-1.4.0 → jupyter_duckdb-1.4.105}/src/duckdb_kernel/magics/MagicCommandException.py
RENAMED
|
File without changes
|
{jupyter_duckdb-1.4.0 → jupyter_duckdb-1.4.105}/src/duckdb_kernel/magics/MagicCommandHandler.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{jupyter_duckdb-1.4.0 → jupyter_duckdb-1.4.105}/src/duckdb_kernel/parser/elements/DCOperand.py
RENAMED
|
File without changes
|
{jupyter_duckdb-1.4.0 → jupyter_duckdb-1.4.105}/src/duckdb_kernel/parser/elements/LogicElement.py
RENAMED
|
File without changes
|
{jupyter_duckdb-1.4.0 → jupyter_duckdb-1.4.105}/src/duckdb_kernel/parser/elements/LogicOperand.py
RENAMED
|
File without changes
|
{jupyter_duckdb-1.4.0 → jupyter_duckdb-1.4.105}/src/duckdb_kernel/parser/elements/LogicOperator.py
RENAMED
|
File without changes
|
|
File without changes
|
{jupyter_duckdb-1.4.0 → jupyter_duckdb-1.4.105}/src/duckdb_kernel/parser/elements/RAOperand.py
RENAMED
|
File without changes
|
{jupyter_duckdb-1.4.0 → jupyter_duckdb-1.4.105}/src/duckdb_kernel/parser/elements/RAOperator.py
RENAMED
|
File without changes
|
{jupyter_duckdb-1.4.0 → jupyter_duckdb-1.4.105}/src/duckdb_kernel/parser/elements/RAUnaryOperator.py
RENAMED
|
File without changes
|
{jupyter_duckdb-1.4.0 → jupyter_duckdb-1.4.105}/src/duckdb_kernel/parser/elements/__init__.py
RENAMED
|
File without changes
|
{jupyter_duckdb-1.4.0 → jupyter_duckdb-1.4.105}/src/duckdb_kernel/parser/elements/binary/Add.py
RENAMED
|
File without changes
|
{jupyter_duckdb-1.4.0 → jupyter_duckdb-1.4.105}/src/duckdb_kernel/parser/elements/binary/And.py
RENAMED
|
File without changes
|
|
File without changes
|
{jupyter_duckdb-1.4.0 → jupyter_duckdb-1.4.105}/src/duckdb_kernel/parser/elements/binary/Cross.py
RENAMED
|
File without changes
|
|
File without changes
|
{jupyter_duckdb-1.4.0 → jupyter_duckdb-1.4.105}/src/duckdb_kernel/parser/elements/binary/Divide.py
RENAMED
|
File without changes
|
{jupyter_duckdb-1.4.0 → jupyter_duckdb-1.4.105}/src/duckdb_kernel/parser/elements/binary/Division.py
RENAMED
|
File without changes
|
{jupyter_duckdb-1.4.0 → jupyter_duckdb-1.4.105}/src/duckdb_kernel/parser/elements/binary/Equal.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{jupyter_duckdb-1.4.0 → jupyter_duckdb-1.4.105}/src/duckdb_kernel/parser/elements/binary/Join.py
RENAMED
|
File without changes
|
|
File without changes
|
{jupyter_duckdb-1.4.0 → jupyter_duckdb-1.4.105}/src/duckdb_kernel/parser/elements/binary/LessThan.py
RENAMED
|
File without changes
|
|
File without changes
|
{jupyter_duckdb-1.4.0 → jupyter_duckdb-1.4.105}/src/duckdb_kernel/parser/elements/binary/Minus.py
RENAMED
|
File without changes
|
{jupyter_duckdb-1.4.0 → jupyter_duckdb-1.4.105}/src/duckdb_kernel/parser/elements/binary/Multiply.py
RENAMED
|
File without changes
|
{jupyter_duckdb-1.4.0 → jupyter_duckdb-1.4.105}/src/duckdb_kernel/parser/elements/binary/Or.py
RENAMED
|
File without changes
|
|
File without changes
|
{jupyter_duckdb-1.4.0 → jupyter_duckdb-1.4.105}/src/duckdb_kernel/parser/elements/binary/Unequal.py
RENAMED
|
File without changes
|
{jupyter_duckdb-1.4.0 → jupyter_duckdb-1.4.105}/src/duckdb_kernel/parser/elements/binary/Union.py
RENAMED
|
File without changes
|
{jupyter_duckdb-1.4.0 → jupyter_duckdb-1.4.105}/src/duckdb_kernel/parser/elements/binary/__init__.py
RENAMED
|
File without changes
|
{jupyter_duckdb-1.4.0 → jupyter_duckdb-1.4.105}/src/duckdb_kernel/parser/elements/unary/Not.py
RENAMED
|
File without changes
|
|
File without changes
|
{jupyter_duckdb-1.4.0 → jupyter_duckdb-1.4.105}/src/duckdb_kernel/parser/elements/unary/Rename.py
RENAMED
|
File without changes
|
{jupyter_duckdb-1.4.0 → jupyter_duckdb-1.4.105}/src/duckdb_kernel/parser/elements/unary/Selection.py
RENAMED
|
File without changes
|
{jupyter_duckdb-1.4.0 → jupyter_duckdb-1.4.105}/src/duckdb_kernel/parser/elements/unary/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
{jupyter_duckdb-1.4.0 → jupyter_duckdb-1.4.105}/src/duckdb_kernel/parser/tokenizer/Tokenizer.py
RENAMED
|
File without changes
|
{jupyter_duckdb-1.4.0 → jupyter_duckdb-1.4.105}/src/duckdb_kernel/parser/tokenizer/__init__.py
RENAMED
|
File without changes
|
{jupyter_duckdb-1.4.0 → jupyter_duckdb-1.4.105}/src/duckdb_kernel/parser/util/RenamableColumn.py
RENAMED
|
File without changes
|
{jupyter_duckdb-1.4.0 → jupyter_duckdb-1.4.105}/src/duckdb_kernel/parser/util/RenamableColumnList.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{jupyter_duckdb-1.4.0 → jupyter_duckdb-1.4.105}/src/duckdb_kernel/tests/test_result_comparison.py
RENAMED
|
File without changes
|
|
File without changes
|
{jupyter_duckdb-1.4.0 → jupyter_duckdb-1.4.105}/src/duckdb_kernel/util/ResultSetComparator.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{jupyter_duckdb-1.4.0 → jupyter_duckdb-1.4.105}/src/duckdb_kernel/visualization/RATreeDrawer.py
RENAMED
|
File without changes
|
{jupyter_duckdb-1.4.0 → jupyter_duckdb-1.4.105}/src/duckdb_kernel/visualization/SchemaDrawer.py
RENAMED
|
File without changes
|
|
File without changes
|
{jupyter_duckdb-1.4.0 → jupyter_duckdb-1.4.105}/src/duckdb_kernel/visualization/lib/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{jupyter_duckdb-1.4.0 → jupyter_duckdb-1.4.105}/src/jupyter_duckdb.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
|
File without changes
|