jupyter-duckdb 1.2.0.0__tar.gz → 1.2.0.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-1.2.0.0 → jupyter_duckdb-1.2.0.2}/PKG-INFO +1 -1
- {jupyter_duckdb-1.2.0.0 → jupyter_duckdb-1.2.0.2}/src/duckdb_kernel/db/Table.py +8 -0
- {jupyter_duckdb-1.2.0.0 → jupyter_duckdb-1.2.0.2}/src/duckdb_kernel/db/implementation/duckdb/Connection.py +19 -12
- {jupyter_duckdb-1.2.0.0 → jupyter_duckdb-1.2.0.2}/src/duckdb_kernel/db/implementation/postgres/Connection.py +19 -11
- {jupyter_duckdb-1.2.0.0 → jupyter_duckdb-1.2.0.2}/src/duckdb_kernel/db/implementation/sqlite/Connection.py +4 -2
- {jupyter_duckdb-1.2.0.0 → jupyter_duckdb-1.2.0.2}/src/duckdb_kernel/kernel.py +1 -1
- {jupyter_duckdb-1.2.0.0 → jupyter_duckdb-1.2.0.2}/src/duckdb_kernel/parser/elements/binary/ConditionalSet.py +1 -1
- {jupyter_duckdb-1.2.0.0 → jupyter_duckdb-1.2.0.2}/src/duckdb_kernel/parser/util/RenamableColumn.py +1 -1
- {jupyter_duckdb-1.2.0.0 → jupyter_duckdb-1.2.0.2}/src/jupyter_duckdb.egg-info/PKG-INFO +1 -1
- {jupyter_duckdb-1.2.0.0 → jupyter_duckdb-1.2.0.2}/test/test_dc.py +49 -31
- {jupyter_duckdb-1.2.0.0 → jupyter_duckdb-1.2.0.2}/test/test_ra.py +155 -125
- {jupyter_duckdb-1.2.0.0 → jupyter_duckdb-1.2.0.2}/README.md +0 -0
- {jupyter_duckdb-1.2.0.0 → jupyter_duckdb-1.2.0.2}/setup.cfg +0 -0
- {jupyter_duckdb-1.2.0.0 → jupyter_duckdb-1.2.0.2}/setup.py +0 -0
- {jupyter_duckdb-1.2.0.0 → jupyter_duckdb-1.2.0.2}/src/duckdb_kernel/__init__.py +0 -0
- {jupyter_duckdb-1.2.0.0 → jupyter_duckdb-1.2.0.2}/src/duckdb_kernel/__main__.py +0 -0
- {jupyter_duckdb-1.2.0.0 → jupyter_duckdb-1.2.0.2}/src/duckdb_kernel/db/Column.py +0 -0
- {jupyter_duckdb-1.2.0.0 → jupyter_duckdb-1.2.0.2}/src/duckdb_kernel/db/Connection.py +0 -0
- {jupyter_duckdb-1.2.0.0 → jupyter_duckdb-1.2.0.2}/src/duckdb_kernel/db/Constraint.py +0 -0
- {jupyter_duckdb-1.2.0.0 → jupyter_duckdb-1.2.0.2}/src/duckdb_kernel/db/DatabaseError.py +0 -0
- {jupyter_duckdb-1.2.0.0 → jupyter_duckdb-1.2.0.2}/src/duckdb_kernel/db/ForeignKey.py +0 -0
- {jupyter_duckdb-1.2.0.0 → jupyter_duckdb-1.2.0.2}/src/duckdb_kernel/db/__init__.py +0 -0
- {jupyter_duckdb-1.2.0.0 → jupyter_duckdb-1.2.0.2}/src/duckdb_kernel/db/error/EmptyResultError.py +0 -0
- {jupyter_duckdb-1.2.0.0 → jupyter_duckdb-1.2.0.2}/src/duckdb_kernel/db/error/__init__.py +0 -0
- {jupyter_duckdb-1.2.0.0 → jupyter_duckdb-1.2.0.2}/src/duckdb_kernel/db/implementation/duckdb/__init__.py +0 -0
- {jupyter_duckdb-1.2.0.0 → jupyter_duckdb-1.2.0.2}/src/duckdb_kernel/db/implementation/postgres/__init__.py +0 -0
- {jupyter_duckdb-1.2.0.0 → jupyter_duckdb-1.2.0.2}/src/duckdb_kernel/db/implementation/postgres/util.py +0 -0
- {jupyter_duckdb-1.2.0.0 → jupyter_duckdb-1.2.0.2}/src/duckdb_kernel/db/implementation/sqlite/__init__.py +0 -0
- {jupyter_duckdb-1.2.0.0 → jupyter_duckdb-1.2.0.2}/src/duckdb_kernel/kernel.json +0 -0
- {jupyter_duckdb-1.2.0.0 → jupyter_duckdb-1.2.0.2}/src/duckdb_kernel/magics/MagicCommand.py +0 -0
- {jupyter_duckdb-1.2.0.0 → jupyter_duckdb-1.2.0.2}/src/duckdb_kernel/magics/MagicCommandCallback.py +0 -0
- {jupyter_duckdb-1.2.0.0 → jupyter_duckdb-1.2.0.2}/src/duckdb_kernel/magics/MagicCommandException.py +0 -0
- {jupyter_duckdb-1.2.0.0 → jupyter_duckdb-1.2.0.2}/src/duckdb_kernel/magics/MagicCommandHandler.py +0 -0
- {jupyter_duckdb-1.2.0.0 → jupyter_duckdb-1.2.0.2}/src/duckdb_kernel/magics/__init__.py +0 -0
- {jupyter_duckdb-1.2.0.0 → jupyter_duckdb-1.2.0.2}/src/duckdb_kernel/parser/DCParser.py +0 -0
- {jupyter_duckdb-1.2.0.0 → jupyter_duckdb-1.2.0.2}/src/duckdb_kernel/parser/LogicParser.py +0 -0
- {jupyter_duckdb-1.2.0.0 → jupyter_duckdb-1.2.0.2}/src/duckdb_kernel/parser/RAParser.py +0 -0
- {jupyter_duckdb-1.2.0.0 → jupyter_duckdb-1.2.0.2}/src/duckdb_kernel/parser/__init__.py +0 -0
- {jupyter_duckdb-1.2.0.0 → jupyter_duckdb-1.2.0.2}/src/duckdb_kernel/parser/elements/DCOperand.py +0 -0
- {jupyter_duckdb-1.2.0.0 → jupyter_duckdb-1.2.0.2}/src/duckdb_kernel/parser/elements/LogicElement.py +0 -0
- {jupyter_duckdb-1.2.0.0 → jupyter_duckdb-1.2.0.2}/src/duckdb_kernel/parser/elements/LogicOperand.py +0 -0
- {jupyter_duckdb-1.2.0.0 → jupyter_duckdb-1.2.0.2}/src/duckdb_kernel/parser/elements/LogicOperator.py +0 -0
- {jupyter_duckdb-1.2.0.0 → jupyter_duckdb-1.2.0.2}/src/duckdb_kernel/parser/elements/RABinaryOperator.py +0 -0
- {jupyter_duckdb-1.2.0.0 → jupyter_duckdb-1.2.0.2}/src/duckdb_kernel/parser/elements/RAElement.py +0 -0
- {jupyter_duckdb-1.2.0.0 → jupyter_duckdb-1.2.0.2}/src/duckdb_kernel/parser/elements/RAOperand.py +0 -0
- {jupyter_duckdb-1.2.0.0 → jupyter_duckdb-1.2.0.2}/src/duckdb_kernel/parser/elements/RAOperator.py +0 -0
- {jupyter_duckdb-1.2.0.0 → jupyter_duckdb-1.2.0.2}/src/duckdb_kernel/parser/elements/RAUnaryOperator.py +0 -0
- {jupyter_duckdb-1.2.0.0 → jupyter_duckdb-1.2.0.2}/src/duckdb_kernel/parser/elements/__init__.py +0 -0
- {jupyter_duckdb-1.2.0.0 → jupyter_duckdb-1.2.0.2}/src/duckdb_kernel/parser/elements/binary/Add.py +0 -0
- {jupyter_duckdb-1.2.0.0 → jupyter_duckdb-1.2.0.2}/src/duckdb_kernel/parser/elements/binary/And.py +0 -0
- {jupyter_duckdb-1.2.0.0 → jupyter_duckdb-1.2.0.2}/src/duckdb_kernel/parser/elements/binary/ArrowLeft.py +0 -0
- {jupyter_duckdb-1.2.0.0 → jupyter_duckdb-1.2.0.2}/src/duckdb_kernel/parser/elements/binary/Cross.py +0 -0
- {jupyter_duckdb-1.2.0.0 → jupyter_duckdb-1.2.0.2}/src/duckdb_kernel/parser/elements/binary/Difference.py +0 -0
- {jupyter_duckdb-1.2.0.0 → jupyter_duckdb-1.2.0.2}/src/duckdb_kernel/parser/elements/binary/Divide.py +0 -0
- {jupyter_duckdb-1.2.0.0 → jupyter_duckdb-1.2.0.2}/src/duckdb_kernel/parser/elements/binary/Division.py +0 -0
- {jupyter_duckdb-1.2.0.0 → jupyter_duckdb-1.2.0.2}/src/duckdb_kernel/parser/elements/binary/Equal.py +0 -0
- {jupyter_duckdb-1.2.0.0 → jupyter_duckdb-1.2.0.2}/src/duckdb_kernel/parser/elements/binary/GreaterThan.py +0 -0
- {jupyter_duckdb-1.2.0.0 → jupyter_duckdb-1.2.0.2}/src/duckdb_kernel/parser/elements/binary/GreaterThanEqual.py +0 -0
- {jupyter_duckdb-1.2.0.0 → jupyter_duckdb-1.2.0.2}/src/duckdb_kernel/parser/elements/binary/Intersection.py +0 -0
- {jupyter_duckdb-1.2.0.0 → jupyter_duckdb-1.2.0.2}/src/duckdb_kernel/parser/elements/binary/Join.py +0 -0
- {jupyter_duckdb-1.2.0.0 → jupyter_duckdb-1.2.0.2}/src/duckdb_kernel/parser/elements/binary/LessThan.py +0 -0
- {jupyter_duckdb-1.2.0.0 → jupyter_duckdb-1.2.0.2}/src/duckdb_kernel/parser/elements/binary/LessThanEqual.py +0 -0
- {jupyter_duckdb-1.2.0.0 → jupyter_duckdb-1.2.0.2}/src/duckdb_kernel/parser/elements/binary/Minus.py +0 -0
- {jupyter_duckdb-1.2.0.0 → jupyter_duckdb-1.2.0.2}/src/duckdb_kernel/parser/elements/binary/Multiply.py +0 -0
- {jupyter_duckdb-1.2.0.0 → jupyter_duckdb-1.2.0.2}/src/duckdb_kernel/parser/elements/binary/Or.py +0 -0
- {jupyter_duckdb-1.2.0.0 → jupyter_duckdb-1.2.0.2}/src/duckdb_kernel/parser/elements/binary/Unequal.py +0 -0
- {jupyter_duckdb-1.2.0.0 → jupyter_duckdb-1.2.0.2}/src/duckdb_kernel/parser/elements/binary/Union.py +0 -0
- {jupyter_duckdb-1.2.0.0 → jupyter_duckdb-1.2.0.2}/src/duckdb_kernel/parser/elements/binary/__init__.py +0 -0
- {jupyter_duckdb-1.2.0.0 → jupyter_duckdb-1.2.0.2}/src/duckdb_kernel/parser/elements/unary/Not.py +0 -0
- {jupyter_duckdb-1.2.0.0 → jupyter_duckdb-1.2.0.2}/src/duckdb_kernel/parser/elements/unary/Projection.py +0 -0
- {jupyter_duckdb-1.2.0.0 → jupyter_duckdb-1.2.0.2}/src/duckdb_kernel/parser/elements/unary/Rename.py +0 -0
- {jupyter_duckdb-1.2.0.0 → jupyter_duckdb-1.2.0.2}/src/duckdb_kernel/parser/elements/unary/Selection.py +0 -0
- {jupyter_duckdb-1.2.0.0 → jupyter_duckdb-1.2.0.2}/src/duckdb_kernel/parser/elements/unary/__init__.py +0 -0
- {jupyter_duckdb-1.2.0.0 → jupyter_duckdb-1.2.0.2}/src/duckdb_kernel/parser/tokenizer/Token.py +0 -0
- {jupyter_duckdb-1.2.0.0 → jupyter_duckdb-1.2.0.2}/src/duckdb_kernel/parser/tokenizer/Tokenizer.py +0 -0
- {jupyter_duckdb-1.2.0.0 → jupyter_duckdb-1.2.0.2}/src/duckdb_kernel/parser/tokenizer/__init__.py +0 -0
- {jupyter_duckdb-1.2.0.0 → jupyter_duckdb-1.2.0.2}/src/duckdb_kernel/parser/util/RenamableColumnList.py +0 -0
- {jupyter_duckdb-1.2.0.0 → jupyter_duckdb-1.2.0.2}/src/duckdb_kernel/parser/util/__init__.py +0 -0
- {jupyter_duckdb-1.2.0.0 → jupyter_duckdb-1.2.0.2}/src/duckdb_kernel/util/ResultSetComparator.py +0 -0
- {jupyter_duckdb-1.2.0.0 → jupyter_duckdb-1.2.0.2}/src/duckdb_kernel/util/__init__.py +0 -0
- {jupyter_duckdb-1.2.0.0 → jupyter_duckdb-1.2.0.2}/src/duckdb_kernel/util/formatting.py +0 -0
- {jupyter_duckdb-1.2.0.0 → jupyter_duckdb-1.2.0.2}/src/duckdb_kernel/visualization/Drawer.py +0 -0
- {jupyter_duckdb-1.2.0.0 → jupyter_duckdb-1.2.0.2}/src/duckdb_kernel/visualization/RATreeDrawer.py +0 -0
- {jupyter_duckdb-1.2.0.0 → jupyter_duckdb-1.2.0.2}/src/duckdb_kernel/visualization/SchemaDrawer.py +0 -0
- {jupyter_duckdb-1.2.0.0 → jupyter_duckdb-1.2.0.2}/src/duckdb_kernel/visualization/__init__.py +0 -0
- {jupyter_duckdb-1.2.0.0 → jupyter_duckdb-1.2.0.2}/src/jupyter_duckdb.egg-info/SOURCES.txt +0 -0
- {jupyter_duckdb-1.2.0.0 → jupyter_duckdb-1.2.0.2}/src/jupyter_duckdb.egg-info/dependency_links.txt +0 -0
- {jupyter_duckdb-1.2.0.0 → jupyter_duckdb-1.2.0.2}/src/jupyter_duckdb.egg-info/requires.txt +0 -0
- {jupyter_duckdb-1.2.0.0 → jupyter_duckdb-1.2.0.2}/src/jupyter_duckdb.egg-info/top_level.txt +0 -0
- {jupyter_duckdb-1.2.0.0 → jupyter_duckdb-1.2.0.2}/test/test_result_comparison.py +0 -0
|
@@ -14,11 +14,19 @@ class Table:
|
|
|
14
14
|
self.unique_keys: List[Constraint] = []
|
|
15
15
|
self.foreign_keys: List[ForeignKey] = []
|
|
16
16
|
|
|
17
|
+
@staticmethod
|
|
18
|
+
def normalize_name(name: str) -> str:
|
|
19
|
+
return name.lower()
|
|
20
|
+
|
|
17
21
|
@property
|
|
18
22
|
def id(self) -> str:
|
|
19
23
|
name = re.sub(r'[^A-Za-z]', '_', self.name)
|
|
20
24
|
return f'table_{name}'
|
|
21
25
|
|
|
26
|
+
@property
|
|
27
|
+
def normalized_name(self) -> str:
|
|
28
|
+
return self.normalize_name(self.name)
|
|
29
|
+
|
|
22
30
|
def get_column(self, name: str) -> "Column":
|
|
23
31
|
for column in self.columns:
|
|
24
32
|
if column.name == name:
|
|
@@ -59,7 +59,7 @@ class Connection(Base):
|
|
|
59
59
|
WHERE table_type == 'BASE TABLE'
|
|
60
60
|
''').fetchall():
|
|
61
61
|
table = Table(table_name)
|
|
62
|
-
tables[
|
|
62
|
+
tables[table.normalized_name] = table
|
|
63
63
|
|
|
64
64
|
# Get column names and data types for each table.
|
|
65
65
|
for table_name, column_name, data_type, is_nullable in self.con.execute('''
|
|
@@ -71,8 +71,9 @@ class Connection(Base):
|
|
|
71
71
|
FROM information_schema.columns
|
|
72
72
|
ORDER BY ordinal_position ASC
|
|
73
73
|
''').fetchall():
|
|
74
|
-
|
|
75
|
-
|
|
74
|
+
normalized_table_name = Table.normalize_name(table_name)
|
|
75
|
+
if normalized_table_name in tables:
|
|
76
|
+
table = tables[normalized_table_name]
|
|
76
77
|
|
|
77
78
|
column = Column(table, column_name, data_type, is_nullable == 'YES')
|
|
78
79
|
table.columns.append(column)
|
|
@@ -88,10 +89,12 @@ class Connection(Base):
|
|
|
88
89
|
ORDER BY constraint_index ASC
|
|
89
90
|
''').fetchall():
|
|
90
91
|
# get table
|
|
91
|
-
|
|
92
|
+
normalized_table_name = Table.normalize_name(table_name)
|
|
93
|
+
|
|
94
|
+
if normalized_table_name not in tables:
|
|
92
95
|
raise AssertionError(f'unknown table {table_name} for constraint {constraint_index}')
|
|
93
96
|
|
|
94
|
-
table = tables[
|
|
97
|
+
table = tables[normalized_table_name]
|
|
95
98
|
|
|
96
99
|
# store constraint
|
|
97
100
|
if constraint_index in constraints:
|
|
@@ -102,7 +105,7 @@ class Connection(Base):
|
|
|
102
105
|
table,
|
|
103
106
|
tuple(table.get_column(c) for c in constraint_columns)
|
|
104
107
|
)
|
|
105
|
-
constraints[(
|
|
108
|
+
constraints[(normalized_table_name, *constraint_columns)] = constraint
|
|
106
109
|
|
|
107
110
|
# store key
|
|
108
111
|
if table.primary_key is not None:
|
|
@@ -121,10 +124,12 @@ class Connection(Base):
|
|
|
121
124
|
ORDER BY constraint_index ASC
|
|
122
125
|
''').fetchall():
|
|
123
126
|
# get table
|
|
124
|
-
|
|
127
|
+
normalized_table_name = Table.normalize_name(table_name)
|
|
128
|
+
|
|
129
|
+
if normalized_table_name not in tables:
|
|
125
130
|
raise AssertionError(f'unknown table {table_name} for constraint {constraint_index}')
|
|
126
131
|
|
|
127
|
-
table = tables[
|
|
132
|
+
table = tables[normalized_table_name]
|
|
128
133
|
|
|
129
134
|
# store constraint
|
|
130
135
|
if constraint_index in constraints:
|
|
@@ -135,7 +140,7 @@ class Connection(Base):
|
|
|
135
140
|
table,
|
|
136
141
|
tuple(table.get_column(c) for c in constraint_columns)
|
|
137
142
|
)
|
|
138
|
-
constraints[(
|
|
143
|
+
constraints[(normalized_table_name, *constraint_columns)] = constraint
|
|
139
144
|
|
|
140
145
|
# store key
|
|
141
146
|
table.unique_keys.append(constraint)
|
|
@@ -153,13 +158,15 @@ class Connection(Base):
|
|
|
153
158
|
ORDER BY constraint_index ASC
|
|
154
159
|
''').fetchall():
|
|
155
160
|
# get table
|
|
156
|
-
|
|
161
|
+
normalized_table_name = Table.normalize_name(table_name)
|
|
162
|
+
|
|
163
|
+
if normalized_table_name not in tables:
|
|
157
164
|
raise AssertionError(f'unknown table {table_name} for constraint {constraint_index}')
|
|
158
165
|
|
|
159
|
-
table = tables[
|
|
166
|
+
table = tables[normalized_table_name]
|
|
160
167
|
|
|
161
168
|
# lookup constraint
|
|
162
|
-
constraint_key = (referenced_table, *referenced_column_names)
|
|
169
|
+
constraint_key = (Table.normalize_name(referenced_table), *referenced_column_names)
|
|
163
170
|
if constraint_key not in constraints:
|
|
164
171
|
raise AssertionError(f'constraint with key {constraint_key} not discovered previously')
|
|
165
172
|
|
|
@@ -88,7 +88,7 @@ class Connection(Base):
|
|
|
88
88
|
WHERE table_schema='public' AND table_type='BASE TABLE'
|
|
89
89
|
''').fetchall():
|
|
90
90
|
table = Table(table_name)
|
|
91
|
-
tables[
|
|
91
|
+
tables[table.normalized_name] = table
|
|
92
92
|
|
|
93
93
|
# Get column names and data types for each table.
|
|
94
94
|
for table_name, column_name, data_type, is_nullable in self.con.execute('''
|
|
@@ -100,8 +100,9 @@ class Connection(Base):
|
|
|
100
100
|
FROM information_schema.columns
|
|
101
101
|
ORDER BY ordinal_position ASC
|
|
102
102
|
''').fetchall():
|
|
103
|
-
|
|
104
|
-
|
|
103
|
+
normalized_table_name = Table.normalize_name(table_name)
|
|
104
|
+
if normalized_table_name in tables:
|
|
105
|
+
table = tables[normalized_table_name]
|
|
105
106
|
|
|
106
107
|
column = Column(table, column_name, data_type, is_nullable == 'YES')
|
|
107
108
|
table.columns.append(column)
|
|
@@ -126,10 +127,12 @@ class Connection(Base):
|
|
|
126
127
|
|
|
127
128
|
for constraint_name, (table_name, column_names) in constraints_dict.items():
|
|
128
129
|
# get table
|
|
129
|
-
|
|
130
|
+
normalized_table_name = Table.normalize_name(table_name)
|
|
131
|
+
|
|
132
|
+
if normalized_table_name not in tables:
|
|
130
133
|
raise AssertionError(f'unknown table {table_name} for constraint {constraint_index}')
|
|
131
134
|
|
|
132
|
-
table = tables[
|
|
135
|
+
table = tables[normalized_table_name]
|
|
133
136
|
|
|
134
137
|
# store constraint
|
|
135
138
|
constraint = Constraint(
|
|
@@ -166,10 +169,12 @@ class Connection(Base):
|
|
|
166
169
|
|
|
167
170
|
for constraint_name, (table_name, column_names) in constraints_dict.items():
|
|
168
171
|
# get table
|
|
169
|
-
|
|
172
|
+
normalized_table_name = Table.normalize_name(table_name)
|
|
173
|
+
|
|
174
|
+
if normalized_table_name not in tables:
|
|
170
175
|
raise AssertionError(f'unknown table {table_name} for constraint {constraint_index}')
|
|
171
176
|
|
|
172
|
-
table = tables[
|
|
177
|
+
table = tables[normalized_table_name]
|
|
173
178
|
|
|
174
179
|
# store constraint
|
|
175
180
|
constraint = Constraint(
|
|
@@ -197,20 +202,23 @@ class Connection(Base):
|
|
|
197
202
|
raise AssertionError(f'could not parse foreign key definitions for table {source_table_name}')
|
|
198
203
|
|
|
199
204
|
source_table_name = strip_delimiters(source_table_name)
|
|
205
|
+
normalized_source_table_name = Table.normalize_name(source_table_name)
|
|
200
206
|
source_table_column_names = [strip_delimiters(c) for c in match.group(1).split(',')]
|
|
207
|
+
|
|
201
208
|
target_table_name = strip_delimiters(match.group(2))
|
|
209
|
+
normalized_target_table_name = Table.normalize_name(target_table_name)
|
|
202
210
|
target_table_column_names = [strip_delimiters(c) for c in match.group(3).split(',')]
|
|
203
211
|
|
|
204
212
|
# get tables
|
|
205
|
-
if
|
|
213
|
+
if normalized_source_table_name not in tables:
|
|
206
214
|
raise AssertionError(f'unknown table {source_table_name} for foreign key {fk_name}')
|
|
207
215
|
|
|
208
|
-
source_table = tables[
|
|
216
|
+
source_table = tables[normalized_source_table_name]
|
|
209
217
|
|
|
210
|
-
if
|
|
218
|
+
if normalized_target_table_name not in tables:
|
|
211
219
|
raise AssertionError(f'unknown table {target_table_name} for foreign key {fk_name}')
|
|
212
220
|
|
|
213
|
-
target_table = tables[
|
|
221
|
+
target_table = tables[normalized_target_table_name]
|
|
214
222
|
|
|
215
223
|
# store constraint
|
|
216
224
|
constraint = Constraint(
|
|
@@ -61,7 +61,7 @@ class Connection(Base):
|
|
|
61
61
|
WHERE type ='table' AND name NOT LIKE 'sqlite_%';
|
|
62
62
|
''').fetchall():
|
|
63
63
|
table = Table(table_name)
|
|
64
|
-
tables[
|
|
64
|
+
tables[table.normalized_name] = table
|
|
65
65
|
|
|
66
66
|
# Get column names and data types for each table.
|
|
67
67
|
for table_name, table in tables.items():
|
|
@@ -174,8 +174,10 @@ class Connection(Base):
|
|
|
174
174
|
current_targets = []
|
|
175
175
|
|
|
176
176
|
# add columns to parse later
|
|
177
|
+
normalized_to_table_name = Table.normalize_name(to_table_name)
|
|
178
|
+
|
|
177
179
|
current_sources.append(table.get_column(from_col))
|
|
178
|
-
current_targets.append(tables[
|
|
180
|
+
current_targets.append(tables[normalized_to_table_name].get_column(to_col))
|
|
179
181
|
|
|
180
182
|
if len(current_sources) > 0:
|
|
181
183
|
store()
|
|
@@ -116,7 +116,7 @@ class ConditionalSet:
|
|
|
116
116
|
underscore_regex = re.compile(r'_{1,}')
|
|
117
117
|
|
|
118
118
|
for operand_i, operand in enumerate(dc_operands):
|
|
119
|
-
source_columns = tables[operand.relation].columns
|
|
119
|
+
source_columns = tables[Table.normalize_name(operand.relation)].columns
|
|
120
120
|
|
|
121
121
|
# Raise an exception if the given number of operands does not match
|
|
122
122
|
# the number of attributes in the relation.
|
{jupyter_duckdb-1.2.0.0 → jupyter_duckdb-1.2.0.2}/src/duckdb_kernel/parser/util/RenamableColumn.py
RENAMED
|
@@ -13,7 +13,7 @@ class RenamableColumn(Column):
|
|
|
13
13
|
return f'{self.table.name}.{self.name}'
|
|
14
14
|
|
|
15
15
|
def matches(self, name: str) -> bool:
|
|
16
|
-
return self.name == name or self.full_name == name
|
|
16
|
+
return self.name.lower() == name.lower() or self.full_name.lower() == name.lower()
|
|
17
17
|
|
|
18
18
|
def rename(self):
|
|
19
19
|
old_name = self.current_name
|
|
@@ -2,14 +2,32 @@ from duckdb_kernel.parser import DCParser
|
|
|
2
2
|
from . import Connection
|
|
3
3
|
|
|
4
4
|
|
|
5
|
+
def test_case_insensitivity():
|
|
6
|
+
for query in (
|
|
7
|
+
'{ username | users(id, username) }',
|
|
8
|
+
'{ username | Users(id, username) }',
|
|
9
|
+
'{ username | USERS(id, username) }',
|
|
10
|
+
'{ username | uSers(id, username) }'
|
|
11
|
+
):
|
|
12
|
+
root = DCParser.parse_query(query)
|
|
13
|
+
|
|
14
|
+
# execute to test case insensitivity
|
|
15
|
+
with Connection() as con:
|
|
16
|
+
assert con.execute_dc(root) == [
|
|
17
|
+
('Alice',),
|
|
18
|
+
('Bob',),
|
|
19
|
+
('Charlie',)
|
|
20
|
+
]
|
|
21
|
+
|
|
22
|
+
|
|
5
23
|
def test_simple_queries():
|
|
6
24
|
with Connection() as con:
|
|
7
25
|
for query in [
|
|
8
|
-
'{ id |
|
|
9
|
-
'{ id |
|
|
10
|
-
'{ id |
|
|
11
|
-
'{id|
|
|
12
|
-
'id |
|
|
26
|
+
'{ id | Users(id, _) }',
|
|
27
|
+
'{ id | Users (id, _) }',
|
|
28
|
+
'{ id | Users id,_ }',
|
|
29
|
+
'{id|Users(id,_)}',
|
|
30
|
+
'id | Users (id ,_)',
|
|
13
31
|
]:
|
|
14
32
|
root = DCParser.parse_query(query)
|
|
15
33
|
assert con.execute_dc(root) == [
|
|
@@ -19,8 +37,8 @@ def test_simple_queries():
|
|
|
19
37
|
]
|
|
20
38
|
|
|
21
39
|
for query in [
|
|
22
|
-
'{ id, name |
|
|
23
|
-
'{ id,name |
|
|
40
|
+
'{ id, name | Users(id, name) }',
|
|
41
|
+
'{ id,name | Users(id, name) }'
|
|
24
42
|
]:
|
|
25
43
|
root = DCParser.parse_query(query)
|
|
26
44
|
assert con.execute_dc(root) == [
|
|
@@ -32,14 +50,14 @@ def test_simple_queries():
|
|
|
32
50
|
|
|
33
51
|
def test_asterisk_projection():
|
|
34
52
|
with Connection() as con:
|
|
35
|
-
root = DCParser.parse_query('{ * |
|
|
53
|
+
root = DCParser.parse_query('{ * | Users(id, _) }')
|
|
36
54
|
assert con.execute_dc(root) == [
|
|
37
55
|
(1,),
|
|
38
56
|
(2,),
|
|
39
57
|
(3,)
|
|
40
58
|
]
|
|
41
59
|
|
|
42
|
-
root = DCParser.parse_query('{ * |
|
|
60
|
+
root = DCParser.parse_query('{ * | Users(id, name) }')
|
|
43
61
|
assert con.execute_dc(root) == [
|
|
44
62
|
(1, 'Alice'),
|
|
45
63
|
(2, 'Bob'),
|
|
@@ -50,9 +68,9 @@ def test_asterisk_projection():
|
|
|
50
68
|
def test_conditions():
|
|
51
69
|
with Connection() as con:
|
|
52
70
|
for query in [
|
|
53
|
-
'{ name |
|
|
54
|
-
'{ name |
|
|
55
|
-
'{ name |
|
|
71
|
+
'{ name | Users(id, name) ∧ id > 1 }',
|
|
72
|
+
'{ name | Users(id, name) ∧ id ≠ 1 }',
|
|
73
|
+
'{ name | Users(id, name) ∧ (id = 2 ∨ id = 3) }'
|
|
56
74
|
]:
|
|
57
75
|
root = DCParser.parse_query(query)
|
|
58
76
|
assert con.execute_dc(root) == [
|
|
@@ -61,7 +79,7 @@ def test_conditions():
|
|
|
61
79
|
]
|
|
62
80
|
|
|
63
81
|
for query in [
|
|
64
|
-
'{ id |
|
|
82
|
+
'{ id | Users(id, name) ∧ name > "B" ∧ name < "C" }'
|
|
65
83
|
]:
|
|
66
84
|
root = DCParser.parse_query(query)
|
|
67
85
|
assert con.execute_dc(root) == [
|
|
@@ -73,7 +91,7 @@ def test_shortcut_conditions():
|
|
|
73
91
|
with Connection() as con:
|
|
74
92
|
# single shortcut conditions
|
|
75
93
|
for query in [
|
|
76
|
-
'{ name |
|
|
94
|
+
'{ name | Users(1, name) }'
|
|
77
95
|
]:
|
|
78
96
|
root = DCParser.parse_query(query)
|
|
79
97
|
assert con.execute_dc(root) == [
|
|
@@ -81,7 +99,7 @@ def test_shortcut_conditions():
|
|
|
81
99
|
]
|
|
82
100
|
|
|
83
101
|
for query in [
|
|
84
|
-
'{ season_name |
|
|
102
|
+
'{ season_name | Seasons(1, 1, season_name) }'
|
|
85
103
|
]:
|
|
86
104
|
root = DCParser.parse_query(query)
|
|
87
105
|
assert con.execute_dc(root) == [
|
|
@@ -90,7 +108,7 @@ def test_shortcut_conditions():
|
|
|
90
108
|
|
|
91
109
|
# multiple shortcut conditions
|
|
92
110
|
for query in [
|
|
93
|
-
'{ sname, ename |
|
|
111
|
+
'{ sname, ename | Seasons(snum, 2, sname) ∧ Episodes(enum, snum, 2, ename) }'
|
|
94
112
|
]:
|
|
95
113
|
root = DCParser.parse_query(query)
|
|
96
114
|
assert con.execute_dc(root) == [
|
|
@@ -108,7 +126,7 @@ def test_joins():
|
|
|
108
126
|
with Connection() as con:
|
|
109
127
|
# with one attribute
|
|
110
128
|
for query in [
|
|
111
|
-
'{ sename |
|
|
129
|
+
'{ sename | Shows(shid, shname) ∧ Seasons(senum, shid, sename) }'
|
|
112
130
|
]:
|
|
113
131
|
root = DCParser.parse_query(query)
|
|
114
132
|
assert con.execute_dc(root) == [
|
|
@@ -119,8 +137,8 @@ def test_joins():
|
|
|
119
137
|
]
|
|
120
138
|
|
|
121
139
|
for query in [
|
|
122
|
-
'{ sename |
|
|
123
|
-
'{ sename |
|
|
140
|
+
'{ sename | Shows(shid, shname) ∧ Seasons(senum, shid, sename) ∧ shname = "Show 1" }',
|
|
141
|
+
'{ sename | Seasons(senum, shid, sename) ∧ Shows(shid, "Show 1") }'
|
|
124
142
|
]:
|
|
125
143
|
root = DCParser.parse_query(query)
|
|
126
144
|
assert con.execute_dc(root) == [
|
|
@@ -130,7 +148,7 @@ def test_joins():
|
|
|
130
148
|
|
|
131
149
|
# with multiple attributes
|
|
132
150
|
for query in [
|
|
133
|
-
'{ sname, ename |
|
|
151
|
+
'{ sname, ename | Seasons(snum, shid, sname) ∧ Episodes(enum, snum, shid, ename) ∧ shid = 2 }'
|
|
134
152
|
]:
|
|
135
153
|
root = DCParser.parse_query(query)
|
|
136
154
|
assert con.execute_dc(root) == [
|
|
@@ -145,7 +163,7 @@ def test_joins():
|
|
|
145
163
|
|
|
146
164
|
# join three relations
|
|
147
165
|
for query in [
|
|
148
|
-
'{ s2,c5 |
|
|
166
|
+
'{ s2,c5 | Shows(s1,s2) ∧ Episodes(e1,e2,s1,e4) ∧ Characters(c1,e1,c3,s1,c5) ∧ s1=2 ∧ e4="Show 2 / Season 1 / Episode 2" }'
|
|
149
167
|
]:
|
|
150
168
|
root = DCParser.parse_query(query)
|
|
151
169
|
assert con.execute_dc(root) == [
|
|
@@ -153,7 +171,7 @@ def test_joins():
|
|
|
153
171
|
]
|
|
154
172
|
|
|
155
173
|
# cross join
|
|
156
|
-
root = DCParser.parse_query('{ sename |
|
|
174
|
+
root = DCParser.parse_query('{ sename | Shows(shid1, shname) ∧ Seasons(senum, shid2, sename) ∧ shid1 = shid2 }')
|
|
157
175
|
assert con.execute_dc(root) == [
|
|
158
176
|
('Show 1 / Season 1',),
|
|
159
177
|
('Show 1 / Season 2',),
|
|
@@ -162,8 +180,8 @@ def test_joins():
|
|
|
162
180
|
]
|
|
163
181
|
|
|
164
182
|
for query in [
|
|
165
|
-
'{ s2,c5 |
|
|
166
|
-
'{ s2,c5 |
|
|
183
|
+
'{ 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" }',
|
|
184
|
+
'{ 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
185
|
]:
|
|
168
186
|
root = DCParser.parse_query(query)
|
|
169
187
|
assert con.execute_dc(root) == [
|
|
@@ -175,10 +193,10 @@ def test_underscores():
|
|
|
175
193
|
with Connection() as con:
|
|
176
194
|
# distinct underscores
|
|
177
195
|
for query in [
|
|
178
|
-
'{ ename |
|
|
179
|
-
'{ ename |
|
|
180
|
-
'{ ename |
|
|
181
|
-
'{ ename |
|
|
196
|
+
'{ ename | Seasons(snum, shid, sname) ∧ Episodes(_, snum, shid, ename) ∧ shid = 2 }',
|
|
197
|
+
'{ ename | Seasons(snum, shid, sname) ∧ Episodes(enum, _, shid, ename) ∧ shid = 2 }',
|
|
198
|
+
'{ ename | Seasons(snum, shid, sname) ∧ Episodes(__, snum, shid, ename) ∧ shid = 2 }',
|
|
199
|
+
'{ ename | Seasons(snum, shid, sname) ∧ Episodes(_, __, shid, ename) ∧ shid = 2 }'
|
|
182
200
|
]:
|
|
183
201
|
root = DCParser.parse_query(query)
|
|
184
202
|
assert con.execute_dc(root) == [
|
|
@@ -193,7 +211,7 @@ def test_underscores():
|
|
|
193
211
|
|
|
194
212
|
# reused underscores in a single relation
|
|
195
213
|
for query in [
|
|
196
|
-
'{ ename |
|
|
214
|
+
'{ ename | Seasons(snum, shid, sname) ∧ Episodes(_, _, shid, ename) ∧ shid = 2 }'
|
|
197
215
|
]:
|
|
198
216
|
root = DCParser.parse_query(query)
|
|
199
217
|
assert con.execute_dc(root) == [
|
|
@@ -208,8 +226,8 @@ def test_underscores():
|
|
|
208
226
|
|
|
209
227
|
# reused underscores in two different relations
|
|
210
228
|
for query in [
|
|
211
|
-
'{ ename |
|
|
212
|
-
'{ ename |
|
|
229
|
+
'{ ename | Seasons(_, shid, _) ∧ Episodes(_, _, shid, ename) ∧ shid = 2 }',
|
|
230
|
+
'{ ename | Seasons(_, shid, __) ∧ Episodes(_, __, shid, ename) ∧ shid = 2 }'
|
|
213
231
|
]:
|
|
214
232
|
root = DCParser.parse_query(query)
|
|
215
233
|
assert con.execute_dc(root) == [
|