jupyter-duckdb 0.9.2.2.dev202401171418__py3-none-any.whl → 0.9.2.3__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.
@@ -1,6 +1,6 @@
1
1
  from typing import Dict, List, Tuple, Any
2
2
 
3
- from . import Table
3
+ from .Table import Table
4
4
 
5
5
 
6
6
  class Connection:
@@ -10,6 +10,17 @@ class Connection:
10
10
  def close(self):
11
11
  pass
12
12
 
13
+ @staticmethod
14
+ def plain_explain() -> bool:
15
+ return False
16
+
17
+ @staticmethod
18
+ def multiple_statements_per_query() -> bool:
19
+ return True
20
+
21
+ def __str__(self) -> str:
22
+ raise NotImplementedError
23
+
13
24
  def execute(self, query: str) -> Tuple[List[str], List[List[Any]]]:
14
25
  raise NotImplementedError
15
26
 
duckdb_kernel/db/Table.py CHANGED
@@ -3,7 +3,7 @@ from typing import List, Optional
3
3
 
4
4
  from . import Column
5
5
  from . import ForeignKey
6
- from .Constraint import Constraint
6
+ from . import Constraint
7
7
 
8
8
 
9
9
  class Table:
@@ -1,12 +1,6 @@
1
- from .DatabaseError import DatabaseError
2
1
  from .Column import Column
2
+ from .Connection import Connection
3
3
  from .Constraint import Constraint
4
+ from .DatabaseError import DatabaseError
4
5
  from .ForeignKey import ForeignKey
5
6
  from .Table import Table
6
-
7
- try:
8
- from .duckdb import Connection
9
- SQLITE_MODE = False
10
- except ImportError:
11
- from .sqlite import Connection
12
- SQLITE_MODE = True
@@ -0,0 +1,5 @@
1
+ from ..DatabaseError import DatabaseError
2
+
3
+
4
+ class EmptyResultError(DatabaseError):
5
+ pass
@@ -0,0 +1 @@
1
+ from .EmptyResultError import EmptyResultError
@@ -2,17 +2,25 @@ from typing import Dict, List, Tuple, Any
2
2
 
3
3
  import duckdb
4
4
 
5
- from .. import DatabaseError, Column, Constraint, ForeignKey, Table
6
- from ..Connection import Connection as Base
5
+ from ... import DatabaseError, Column, Constraint, ForeignKey, Table
6
+ from ...Connection import Connection as Base
7
7
 
8
8
 
9
9
  class Connection(Base):
10
10
  def __init__(self, path: str):
11
+ self.path: str = path
11
12
  self.con: duckdb.DuckDBPyConnection = duckdb.connect(path, read_only=False)
12
13
 
13
14
  def close(self):
14
15
  self.con.close()
15
16
 
17
+ @staticmethod
18
+ def plain_explain() -> bool:
19
+ return True
20
+
21
+ def __str__(self) -> str:
22
+ return f'DuckDB: {self.path}'
23
+
16
24
  def execute(self, query: str) -> Tuple[List[str], List[List[Any]]]:
17
25
  with self.con.cursor() as cursor:
18
26
  try:
@@ -0,0 +1,226 @@
1
+ import contextlib
2
+ import re
3
+ from typing import Tuple, List, Any, Optional, Dict
4
+ from uuid import uuid4
5
+
6
+ import psycopg
7
+
8
+ from ... import DatabaseError, Column, Constraint, ForeignKey, Table
9
+ from ...Connection import Connection as Base
10
+ from ...error import EmptyResultError
11
+
12
+
13
+ class Connection(Base):
14
+ def __init__(self,
15
+ host: str, port: int,
16
+ username: Optional[str], password: Optional[str],
17
+ database_name: Optional[str]):
18
+ self.host: str = host
19
+ self.port: int = port
20
+ self.username: Optional[str] = username
21
+
22
+ options = {
23
+ 'host': host,
24
+ 'port': port,
25
+ 'user': username,
26
+ 'password': password,
27
+ 'autocommit': True
28
+ }
29
+
30
+ # If not database name is provided we create one.
31
+ if database_name is None:
32
+ # connect to the server without a database name
33
+ with contextlib.closing(psycopg.connect(**options, dbname='postgres')) as temp_con:
34
+ # create a database to use
35
+ database_name: str = 'db_' + str(uuid4()).replace('-', '')
36
+ temp_con.execute(f'CREATE DATABASE {database_name}')
37
+
38
+ # Finally the "real" connection is created using the database name.
39
+ self.con = psycopg.connect(**options, dbname=database_name)
40
+ self.database_name: str = database_name
41
+
42
+ def close(self):
43
+ self.con.close()
44
+
45
+ def __str__(self) -> str:
46
+ user = f'{self.username}@' if self.username is not None else ''
47
+ return f'PostgreSQL: {user}{self.host}:{self.port}/{self.database_name}'
48
+
49
+ def execute(self, query: str) -> Tuple[List[str], List[List[Any]]]:
50
+ with self.con.cursor() as cursor:
51
+ try:
52
+ cursor.execute(query)
53
+ except Exception as e:
54
+ if isinstance(e, psycopg.Error):
55
+ text = str(e)
56
+ raise DatabaseError(text)
57
+ else:
58
+ raise e
59
+
60
+ # get rows
61
+ try:
62
+ rows = cursor.fetchall()
63
+ except psycopg.ProgrammingError as e:
64
+ text = str(e)
65
+ if text == "the last operation didn't produce a result":
66
+ raise EmptyResultError()
67
+ else:
68
+ raise e
69
+
70
+ # get columns
71
+ if cursor.description is None:
72
+ columns = []
73
+ else:
74
+ columns = [e[0] for e in cursor.description]
75
+
76
+ return columns, rows
77
+
78
+ def analyze(self) -> Dict[str, Table]:
79
+ tables: Dict[str, Table] = {}
80
+ constraints: Dict[str, Constraint] = {}
81
+ constraint_index: int = 0
82
+
83
+ # First, receive the table names.
84
+ for table_name, in self.con.execute('''
85
+ SELECT table_name
86
+ FROM information_schema.tables
87
+ WHERE table_schema='public' AND table_type='BASE TABLE'
88
+ ''').fetchall():
89
+ table = Table(table_name)
90
+ tables[table_name] = table
91
+
92
+ # Get column names and data types for each table.
93
+ for table_name, column_name, data_type in self.con.execute('''
94
+ SELECT
95
+ table_name,
96
+ column_name,
97
+ data_type
98
+ FROM information_schema.columns
99
+ ORDER BY ordinal_position ASC
100
+ ''').fetchall():
101
+ if table_name in tables:
102
+ table = tables[table_name]
103
+
104
+ column = Column(table, column_name, data_type)
105
+ table.columns.append(column)
106
+
107
+ # Find primary keys.
108
+ constraints_dict = {}
109
+
110
+ for constraint_name, table_name, column_name in self.con.execute('''
111
+ SELECT tc.constraint_name, tc.table_name, c.column_name
112
+ FROM information_schema.table_constraints tc
113
+ JOIN information_schema.constraint_column_usage AS ccu
114
+ USING (constraint_schema, constraint_name)
115
+ JOIN information_schema.columns AS c
116
+ ON c.table_schema = tc.constraint_schema AND tc.table_name = c.table_name AND ccu.column_name = c.column_name
117
+ WHERE tc.table_schema = 'public' AND tc.constraint_type = 'PRIMARY KEY'
118
+ ORDER BY tc.table_name, c.ordinal_position
119
+ '''):
120
+ if constraint_name not in constraints_dict:
121
+ constraints_dict[constraint_name] = (table_name, [])
122
+
123
+ constraints_dict[constraint_name][1].append(column_name)
124
+
125
+ for constraint_name, (table_name, column_names) in constraints_dict.items():
126
+ # get table
127
+ if table_name not in tables:
128
+ raise AssertionError(f'unknown table {table_name} for constraint {constraint_index}')
129
+
130
+ table = tables[table_name]
131
+
132
+ # store constraint
133
+ constraint = Constraint(
134
+ constraint_index,
135
+ table,
136
+ tuple(table.get_column(c) for c in column_names)
137
+ )
138
+
139
+ constraint_index += 1
140
+
141
+ # store key
142
+ if table.primary_key is not None:
143
+ raise AssertionError(f'discovered second primary key for table {table_name}')
144
+
145
+ table.primary_key = constraint
146
+
147
+ # Find unqiue keys.
148
+ constraints_dict = {}
149
+
150
+ for constraint_name, table_name, column_name in self.con.execute('''
151
+ SELECT tc.constraint_name, tc.table_name, c.column_name
152
+ FROM information_schema.table_constraints tc
153
+ JOIN information_schema.constraint_column_usage AS ccu
154
+ USING (constraint_schema, constraint_name)
155
+ JOIN information_schema.columns AS c
156
+ ON c.table_schema = tc.constraint_schema AND tc.table_name = c.table_name AND ccu.column_name = c.column_name
157
+ WHERE tc.table_schema = 'public' AND tc.constraint_type = 'UNIQUE'
158
+ ORDER BY tc.table_name, c.ordinal_position
159
+ '''):
160
+ if constraint_name not in constraints_dict:
161
+ constraints_dict[constraint_name] = (table_name, [])
162
+
163
+ constraints_dict[constraint_name][1].append(column_name)
164
+
165
+ for constraint_name, (table_name, column_names) in constraints_dict.items():
166
+ # get table
167
+ if table_name not in tables:
168
+ raise AssertionError(f'unknown table {table_name} for constraint {constraint_index}')
169
+
170
+ table = tables[table_name]
171
+
172
+ # store constraint
173
+ constraint = Constraint(
174
+ constraint_index,
175
+ table,
176
+ tuple(table.get_column(c) for c in column_names)
177
+ )
178
+
179
+ constraint_index += 1
180
+
181
+ # store key
182
+ table.unique_keys.append(constraint)
183
+
184
+ # Find foreign keys.
185
+ for source_table_name, fk_name, fk_def in self.con.execute('''
186
+ SELECT conrelid::regclass, conname, pg_get_constraintdef(oid)
187
+ FROM pg_constraint
188
+ WHERE contype = 'f'
189
+ AND connamespace = 'public'::regnamespace
190
+ ORDER BY conrelid::regclass::text, contype DESC
191
+ '''):
192
+ # extract information
193
+ match = re.match(r'^FOREIGN KEY \((.*?)\) REFERENCES (.*?)\((.*?)\)', fk_def, re.IGNORECASE)
194
+ if match is None:
195
+ raise AssertionError(f'could not parse foreign key definitions for table {source_table_name}')
196
+
197
+ source_table_column_names = [c.strip() for c in match.group(1).split(',')]
198
+ target_table_name = match.group(2).strip()
199
+ target_table_column_names = [c.strip() for c in match.group(3).split(',')]
200
+
201
+ # get tables
202
+ if source_table_name not in tables:
203
+ raise AssertionError(f'unknown table {source_table_name} for foreign key {fk_name}')
204
+
205
+ source_table = tables[source_table_name]
206
+
207
+ if target_table_name not in tables:
208
+ raise AssertionError(f'unknown table {target_table_name} for foreign key {fk_name}')
209
+
210
+ target_table = tables[target_table_name]
211
+
212
+ # store constraint
213
+ constraint = Constraint(
214
+ constraint_index,
215
+ target_table,
216
+ tuple(target_table.get_column(c) for c in target_table_column_names)
217
+ )
218
+
219
+ constraint_index += 1
220
+
221
+ # store key
222
+ key = ForeignKey(tuple(source_table.get_column(c) for c in source_table_column_names), constraint)
223
+ source_table.foreign_keys.append(key)
224
+
225
+ # return result
226
+ return tables
@@ -2,8 +2,8 @@ import sqlite3
2
2
  from contextlib import closing
3
3
  from typing import Dict, List, Tuple, Any
4
4
 
5
- from .. import DatabaseError, Column, Constraint, ForeignKey, Table
6
- from ..Connection import Connection as Base
5
+ from ... import DatabaseError, Column, Constraint, ForeignKey, Table
6
+ from ...Connection import Connection as Base
7
7
 
8
8
 
9
9
  class Connection(Base):
@@ -14,6 +14,13 @@ class Connection(Base):
14
14
  def close(self):
15
15
  self.con.close()
16
16
 
17
+ @staticmethod
18
+ def multiple_statements_per_query() -> bool:
19
+ return False
20
+
21
+ def __str__(self) -> str:
22
+ return f'SQLite: {self.path}'
23
+
17
24
  def execute(self, query: str) -> Tuple[List[str], List[List[Any]]]:
18
25
  with closing(self.con.cursor()) as cursor:
19
26
  try:
@@ -0,0 +1 @@
1
+ from .Connection import Connection
duckdb_kernel/kernel.py CHANGED
@@ -8,7 +8,8 @@ from typing import Optional, Dict, List, Tuple
8
8
 
9
9
  from ipykernel.kernelbase import Kernel
10
10
 
11
- from .db import Connection, DatabaseError, SQLITE_MODE
11
+ from .db import Connection, DatabaseError
12
+ from .db.error import *
12
13
  from .magics import *
13
14
  from .parser import RAParser, DCParser
14
15
  from .util.ResultSetComparator import ResultSetComparator
@@ -20,7 +21,7 @@ class DuckDBKernel(Kernel):
20
21
  DEFAULT_MAX_ROWS = 20
21
22
 
22
23
  implementation = 'DuckDB'
23
- implementation_version = '0.9.2'
24
+ implementation_version = '1.0'
24
25
  banner = 'DuckDB Kernel'
25
26
  language_info = {
26
27
  'name': 'duckdb',
@@ -87,7 +88,41 @@ class DuckDBKernel(Kernel):
87
88
  # database related functions
88
89
  def _load_database(self, path: str):
89
90
  if self._db is None:
90
- self._db: Optional[Connection] = Connection(path)
91
+ # If the provided path looks like a postgres url,
92
+ # we want to use the postgres driver.
93
+ if path.startswith(('postgresql://', 'postgres://', 'pgsql://', 'psql://', 'pg://')):
94
+ # pull data from connection string
95
+ match = re.fullmatch(r'(postgresql|postgres|pgsql|psql|pg)://((.*?)(:(.*?))?@)?(.*?)(:(\d+))?(/(.*))?', path)
96
+
97
+ host = match.group(6)
98
+ port = int(match.group(8)) if match.group(8) is not None else 5432
99
+ username = match.group(3)
100
+ password = match.group(5)
101
+ database_name = match.group(10)
102
+
103
+ # load and create instance
104
+ try:
105
+ from .db.implementation.postgres import Connection as Postgres
106
+ self._db = Postgres(host, port, username, password, database_name)
107
+ except ImportError:
108
+ self.print('psycopg could not be found', name='stderr')
109
+
110
+ # Otherwise the provided path is used to create an
111
+ # in-process instance.
112
+ else:
113
+ # By default, we try to load DuckDB.
114
+ try:
115
+ from .db.implementation.duckdb import Connection as DuckDB
116
+ self._db = DuckDB(path)
117
+
118
+ # If DuckDB is not installed or fails to load,
119
+ # we use SQLite instead.
120
+ except ImportError:
121
+ self.print('DuckDB is not available\n')
122
+
123
+ from .db.implementation.sqlite import Connection as SQLite
124
+ self._db = SQLite(path)
125
+
91
126
  return True
92
127
  else:
93
128
  return False
@@ -107,7 +142,12 @@ class DuckDBKernel(Kernel):
107
142
 
108
143
  # execute query and store start and end timestamp
109
144
  st = time.time()
110
- columns, rows = self._db.execute(query)
145
+
146
+ try:
147
+ columns, rows = self._db.execute(query)
148
+ except EmptyResultError:
149
+ columns, rows = None, None
150
+
111
151
  et = time.time()
112
152
 
113
153
  # return result if silent
@@ -115,7 +155,7 @@ class DuckDBKernel(Kernel):
115
155
  return columns, rows
116
156
 
117
157
  # print EXPLAIN queries as raw text if using DuckDB
118
- if query.strip().startswith('EXPLAIN') and not SQLITE_MODE:
158
+ if query.strip().startswith('EXPLAIN') and self._db.plain_explain():
119
159
  for ekey, evalue in rows:
120
160
  self.print_data(f'<b>{ekey}</b><br><pre>{evalue}</pre>')
121
161
 
@@ -123,34 +163,38 @@ class DuckDBKernel(Kernel):
123
163
 
124
164
  # print every other query as a table
125
165
  else:
126
- # table header
127
- table_header = ''.join(f'<th>{c}</th>' for c in columns)
128
-
129
- # table data
130
- if max_rows is not None and len(rows) > max_rows:
131
- table_data = f'''
132
- {rows_table(rows[:math.ceil(max_rows / 2)])}
133
- <tr>
134
- <td colspan="{len(columns)}"
135
- style="text-align: center"
136
- title="{row_count(len(rows) - max_rows)} omitted">
137
- ...
138
- </td>
139
- </tr>
140
- {rows_table(rows[-math.floor(max_rows // 2):])}
141
- '''
142
- else:
143
- table_data = rows_table(rows)
144
-
145
- # send to client
146
- self.print_data(f'''
147
- <table class="duckdb-query-result">
148
- {table_header}
149
- {table_data}
150
- </table>
151
- ''')
166
+ if columns is not None:
167
+ # table header
168
+ table_header = ''.join(f'<th>{c}</th>' for c in columns)
169
+
170
+ # table data
171
+ if max_rows is not None and len(rows) > max_rows:
172
+ table_data = f'''
173
+ {rows_table(rows[:math.ceil(max_rows / 2)])}
174
+ <tr>
175
+ <td colspan="{len(columns)}"
176
+ style="text-align: center"
177
+ title="{row_count(len(rows) - max_rows)} omitted">
178
+ ...
179
+ </td>
180
+ </tr>
181
+ {rows_table(rows[-math.floor(max_rows // 2):])}
182
+ '''
183
+ else:
184
+ table_data = rows_table(rows)
185
+
186
+ # send to client
187
+ self.print_data(f'''
188
+ <table class="duckdb-query-result">
189
+ {table_header}
190
+ {table_data}
191
+ </table>
192
+ ''')
193
+
194
+ self.print_data(f'{row_count(len(rows))} in {et - st:.3f}s')
152
195
 
153
- self.print_data(f'{row_count(len(rows))} in {et - st:.3f}s')
196
+ else:
197
+ self.print_data(f'statement executed without result in {et - st:.3f}s')
154
198
 
155
199
  return columns, rows
156
200
 
@@ -167,12 +211,8 @@ class DuckDBKernel(Kernel):
167
211
  if not silent:
168
212
  self.print('unloaded database\n')
169
213
 
170
- # print kernel version
171
- if not silent:
172
- if not SQLITE_MODE:
173
- self.print(f'{self.implementation} {self.implementation_version}\n')
174
- else:
175
- self.print('SQLite (DuckDB is not installed)\n')
214
+ # No user cares about the kernel version,
215
+ # so I removed the printing.
176
216
 
177
217
  # clean path
178
218
  if path.startswith(("'", '"')):
@@ -186,7 +226,8 @@ class DuckDBKernel(Kernel):
186
226
 
187
227
  if self._load_database(path):
188
228
  if not silent:
189
- self.print(f'loaded database "{path}"\n')
229
+ # self.print(f'loaded database "{path}"\n')
230
+ self.print(str(self._db))
190
231
 
191
232
  # copy data from source database
192
233
  if of is not None:
@@ -202,12 +243,12 @@ class DuckDBKernel(Kernel):
202
243
  content = file.read()
203
244
 
204
245
  # You can only execute one statement at a time using SQLite.
205
- if SQLITE_MODE:
246
+ if not self._db.multiple_statements_per_query():
206
247
  statements = re.split(r';\r?\n', content)
207
248
  for statement in statements:
208
249
  self._db.execute(statement)
209
250
 
210
- # DuckDB can execute multiple statements at a time.
251
+ # Other DBMS can execute multiple statements at a time.
211
252
  else:
212
253
  self._db.execute(content)
213
254
 
@@ -35,9 +35,9 @@ class RAElement:
35
35
 
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
- column_names = ', '.join(f"{c.current_name} AS '{c.name}'" for c in columns)
38
+ column_names = ', '.join(f'{c.current_name} AS "{c.name}"' for c in columns)
39
39
  else:
40
- column_names = ', '.join(f"{c.current_name} AS '{c.full_name}'" for c in columns)
40
+ column_names = ', '.join(f'{c.current_name} AS "{c.full_name}"' for c in columns)
41
41
 
42
42
  return f'SELECT {column_names} FROM ({sql}) {self._name()}'
43
43
 
@@ -334,10 +334,10 @@ class ConditionalSet:
334
334
  target_table_stmt = table_statements[target_name]
335
335
  sql_tables += f' LEFT JOIN {target_table_stmt} ON {join_condition}'
336
336
 
337
- sql_join_filters = '1'
337
+ sql_join_filters = '1=1'
338
338
  for _, _, _, join_filter in sorted_negative_joins:
339
339
  sql_join_filters += f' AND {join_filter}'
340
340
 
341
- sql_condition = condition.to_sql(joined_columns) if condition is not None else 1
341
+ sql_condition = condition.to_sql(joined_columns) if condition is not None else '1=1'
342
342
 
343
343
  return f'SELECT DISTINCT {sql_select} FROM {sql_tables} WHERE ({sql_join_filters}) AND ({sql_condition})'
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: jupyter-duckdb
3
- Version: 0.9.2.2.dev202401171418
3
+ Version: 0.9.2.3
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
@@ -1,18 +1,22 @@
1
1
  duckdb_kernel/__init__.py,sha256=6auU6zeJrsA4fxPSr2PYamS8fG-SMXTn5YQFXF2cseo,33
2
2
  duckdb_kernel/__main__.py,sha256=Z3GwHEBWoQjNm2Y84ijnbA0Lk66L7nsFREuqhZ_ptk0,165
3
3
  duckdb_kernel/kernel.json,sha256=_7E8Ci2FSdCvnzCjsOaue8QE8AvpS5JLQuxORO5IGtA,127
4
- duckdb_kernel/kernel.py,sha256=NGFdha_cnRh8rGuMOr4diCwpKKfpjpYRK7_Dc32sABQ,16561
4
+ duckdb_kernel/kernel.py,sha256=XjRN0_lPQvGFGJ8r8ZveAu09fLXG2IArIXZvU0-DUqs,18393
5
5
  duckdb_kernel/db/Column.py,sha256=M9VRAaQ0uEWxZMaXjfFyjaDPpHsLuTSlvGaI5NDo6sM,516
6
- duckdb_kernel/db/Connection.py,sha256=gCzcNitLaAIh9CwsqUyS_nd47Doje6nWvDXcnmpnO9s,368
6
+ duckdb_kernel/db/Connection.py,sha256=5pH-CwGh-r9Q2QwJKGSxvoINBU-sqmvZyG4Q1digfeE,599
7
7
  duckdb_kernel/db/Constraint.py,sha256=1YgUHk7s8mHCVedbcuJKyXDykj7_ybbwT3Dk9p2VMis,287
8
8
  duckdb_kernel/db/DatabaseError.py,sha256=43zl8yym1f-fxH_UtGIbWnDnBE_TRwr9aCziY9t40QY,41
9
9
  duckdb_kernel/db/ForeignKey.py,sha256=iurUAXwTwSIpLXsL0B7BA8jqDTfW4_wkeHxoqQbZwiU,470
10
- duckdb_kernel/db/Table.py,sha256=Jv9un_oX-nupx2EqzJDn_UHtAwddgFGSEapho2kIDrY,756
11
- duckdb_kernel/db/__init__.py,sha256=5kEM0lmq3tdvL-sqg_IQuSNYK0FJ-UiXYqCkg4gVVD8,306
12
- duckdb_kernel/db/duckdb/Connection.py,sha256=4B1BUGIQjfD-W0A6_NeZ_WuDTkkCj3-CU6zTdb-Q9D4,5913
13
- duckdb_kernel/db/duckdb/__init__.py,sha256=HKogB1es4wOiQUoh7_eT32xnUFLmzoCyR_0LuY9r8YQ,35
14
- duckdb_kernel/db/sqlite/Connection.py,sha256=0LPjQTEdqSBkNMtLGwO-JvEVP-zSf6fIahXstTguH4E,6662
15
- duckdb_kernel/db/sqlite/__init__.py,sha256=HKogB1es4wOiQUoh7_eT32xnUFLmzoCyR_0LuY9r8YQ,35
10
+ duckdb_kernel/db/Table.py,sha256=6M_CTBV3QlrL_7CdYfu6s9LelXBQ5RdMUAyntE6xcDI,746
11
+ duckdb_kernel/db/__init__.py,sha256=PKQYQDCW7VQYxmzhQK6A0Qloka9FdMfeFQMfY-CjBSA,198
12
+ duckdb_kernel/db/error/EmptyResultError.py,sha256=N9Oxi2HDZBKaRQsfRsWpJJGOYX4BjdQqWOU-XvzUzNY,92
13
+ duckdb_kernel/db/error/__init__.py,sha256=oHfhfbcfyTJ3pAPN835omdQcebvJTauuULFx5gm9rq4,47
14
+ duckdb_kernel/db/implementation/duckdb/Connection.py,sha256=CUpfIv5OVnKv82MsMVB_QEWrxlIDkNGcqxpSpRc9MQU,6086
15
+ duckdb_kernel/db/implementation/duckdb/__init__.py,sha256=HKogB1es4wOiQUoh7_eT32xnUFLmzoCyR_0LuY9r8YQ,35
16
+ duckdb_kernel/db/implementation/postgres/Connection.py,sha256=ztfDIZH34X1XauGATqRNfcKZ81_r-SPfOiPmEgcaOyw,8605
17
+ duckdb_kernel/db/implementation/postgres/__init__.py,sha256=HKogB1es4wOiQUoh7_eT32xnUFLmzoCyR_0LuY9r8YQ,35
18
+ duckdb_kernel/db/implementation/sqlite/Connection.py,sha256=S-cyRlYP0nzITza5yIedXNPMJTM4Z5uY2CP1RPVaycE,6822
19
+ duckdb_kernel/db/implementation/sqlite/__init__.py,sha256=HKogB1es4wOiQUoh7_eT32xnUFLmzoCyR_0LuY9r8YQ,35
16
20
  duckdb_kernel/magics/MagicCommand.py,sha256=OoQ6j4cNtIYjaK4MPVzJyv1eYTNu4_a7qoRx-5G3Hg0,2346
17
21
  duckdb_kernel/magics/MagicCommandCallback.py,sha256=r1kkJyRR7sZnrnlMH3w4bGqDAJL-BVTIB4-Kn66ynlM,764
18
22
  duckdb_kernel/magics/MagicCommandException.py,sha256=MwuWkpA6NoCqz437urdI0RVXhbSbVdziuRoi7slYFPc,49
@@ -27,7 +31,7 @@ duckdb_kernel/parser/elements/LogicElement.py,sha256=YasKHxWLDDP8UdyLIKbXzqIRA8-
27
31
  duckdb_kernel/parser/elements/LogicOperand.py,sha256=B9NvriloQE5eP734dNMZBZwrdaaIfsuAmZlG1t2eMhs,1021
28
32
  duckdb_kernel/parser/elements/LogicOperator.py,sha256=lkM4TAGkXUhsO4w4PLKVA0bgCRGPQQFpNA1FcWWOW9Q,1028
29
33
  duckdb_kernel/parser/elements/RABinaryOperator.py,sha256=XN41stGc1e-a4dZ1AQVtQ3lEgjUGNt3dMfYXp85LEeE,538
30
- duckdb_kernel/parser/elements/RAElement.py,sha256=gFnByFmDR34mo4nJa432c8tCE9AMPv9Gjn2fT3zL7_Y,1468
34
+ duckdb_kernel/parser/elements/RAElement.py,sha256=d6QWO8KlWcwhA4tXtWsf8K4oT3OMMjTvEnUD4yaWQ_c,1468
31
35
  duckdb_kernel/parser/elements/RAOperand.py,sha256=pghnTYCrrT6MkvynJRgVFPRoMvxIGNB3FTjaq-uCpDQ,1078
32
36
  duckdb_kernel/parser/elements/RAOperator.py,sha256=rtqMFBIBBqT-Bwg7Qm4WQwbDrE28Nb74F_7XMeR3ks4,255
33
37
  duckdb_kernel/parser/elements/RAUnaryOperator.py,sha256=XC1nphkSm88JaEu5V_HKnb_8JNoeBfE3EvNL4o0qh2c,654
@@ -35,7 +39,7 @@ duckdb_kernel/parser/elements/__init__.py,sha256=4DA2M43hh9d1fZb5Z6YnTTI-IBkDyhC
35
39
  duckdb_kernel/parser/elements/binary/Add.py,sha256=XGkZMfab01huk9EaI6JUfzkd2STbV1C_-TyC2guKE8I,190
36
40
  duckdb_kernel/parser/elements/binary/And.py,sha256=0jgetTG8yo5TJSeK70Kj-PI9ERyek1eyMQXX5HBxa4Y,274
37
41
  duckdb_kernel/parser/elements/binary/ArrowLeft.py,sha256=u4fZSoyT9lfvWXBwuhUl4DdjVZAOqyVIKmMVbpElLD4,203
38
- duckdb_kernel/parser/elements/binary/ConditionalSet.py,sha256=wTum6yIspWjH3b_IDZBfD1DzG_xwKzpD_To9jBann_A,16643
42
+ duckdb_kernel/parser/elements/binary/ConditionalSet.py,sha256=OKpUsTP3HzsDg0vVkb3JqWZd5AUL1RnZXmF-8qWoRq8,16649
39
43
  duckdb_kernel/parser/elements/binary/Cross.py,sha256=jVY3cvD6qDWZkJ7q74lFUPO2VdDt4aAjdk2YAfg-ZC4,687
40
44
  duckdb_kernel/parser/elements/binary/Difference.py,sha256=2oCdVm2dgd4Xh6ysLqqv1JgfNS_Bjtd8oA-kNBoFLf0,743
41
45
  duckdb_kernel/parser/elements/binary/Divide.py,sha256=d7mzaOeRYSRO1F-2IHsv_C939TuYtLppbf4-5GSRJXs,265
@@ -70,7 +74,7 @@ duckdb_kernel/visualization/Drawer.py,sha256=D0LkiGMvuJ2v6cQSg_axLTGaM4VXAJEQJAy
70
74
  duckdb_kernel/visualization/RATreeDrawer.py,sha256=j-Vy1zpYMzwZ3CsphyfPW-J7ou9a9tM6aXXgAlQTgDI,2128
71
75
  duckdb_kernel/visualization/SchemaDrawer.py,sha256=fkp7tnyfzKQBXVI6X7efAvT8lczi_XlA7Hc_rhP_47s,2955
72
76
  duckdb_kernel/visualization/__init__.py,sha256=5eMJmxJ01XAXcgWDn3t70eSZF2PGaXdNo6GK-x-0H3s,78
73
- jupyter_duckdb-0.9.2.2.dev202401171418.dist-info/METADATA,sha256=DGnAtkYGcLIHWsydwAyXRzJ35jwyT3NzT_8n7Bniu-s,7764
74
- jupyter_duckdb-0.9.2.2.dev202401171418.dist-info/WHEEL,sha256=oiQVh_5PnQM0E3gPdiz09WCNmwiHDMaGer_elqB3coM,92
75
- jupyter_duckdb-0.9.2.2.dev202401171418.dist-info/top_level.txt,sha256=KvRRPMnmkQNuhyBsXoPmwyt26LRDp0O-0HN6u0Dm5jA,14
76
- jupyter_duckdb-0.9.2.2.dev202401171418.dist-info/RECORD,,
77
+ jupyter_duckdb-0.9.2.3.dist-info/METADATA,sha256=bNaTQa_rguAVOoSbK3pWKwq4I2hbBDzZXSARO1yg9p8,7748
78
+ jupyter_duckdb-0.9.2.3.dist-info/WHEEL,sha256=oiQVh_5PnQM0E3gPdiz09WCNmwiHDMaGer_elqB3coM,92
79
+ jupyter_duckdb-0.9.2.3.dist-info/top_level.txt,sha256=KvRRPMnmkQNuhyBsXoPmwyt26LRDp0O-0HN6u0Dm5jA,14
80
+ jupyter_duckdb-0.9.2.3.dist-info/RECORD,,