duckrun 0.3.17.dev4__tar.gz → 0.3.17.dev5__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.
- {duckrun-0.3.17.dev4/duckrun.egg-info → duckrun-0.3.17.dev5}/PKG-INFO +1 -1
- duckrun-0.3.17.dev5/dbt/adapters/duckrun/__version__.py +1 -0
- {duckrun-0.3.17.dev4 → duckrun-0.3.17.dev5}/dbt/adapters/duckrun/delta_dml.py +30 -7
- {duckrun-0.3.17.dev4 → duckrun-0.3.17.dev5}/dbt/adapters/duckrun/engine.py +17 -0
- {duckrun-0.3.17.dev4 → duckrun-0.3.17.dev5/duckrun.egg-info}/PKG-INFO +1 -1
- {duckrun-0.3.17.dev4 → duckrun-0.3.17.dev5}/pyproject.toml +1 -1
- duckrun-0.3.17.dev4/dbt/adapters/duckrun/__version__.py +0 -1
- {duckrun-0.3.17.dev4 → duckrun-0.3.17.dev5}/LICENSE +0 -0
- {duckrun-0.3.17.dev4 → duckrun-0.3.17.dev5}/MANIFEST.in +0 -0
- {duckrun-0.3.17.dev4 → duckrun-0.3.17.dev5}/README.md +0 -0
- {duckrun-0.3.17.dev4 → duckrun-0.3.17.dev5}/dbt/adapters/duckrun/__init__.py +0 -0
- {duckrun-0.3.17.dev4 → duckrun-0.3.17.dev5}/dbt/adapters/duckrun/credentials.py +0 -0
- {duckrun-0.3.17.dev4 → duckrun-0.3.17.dev5}/dbt/adapters/duckrun/delta_plugin.py +0 -0
- {duckrun-0.3.17.dev4 → duckrun-0.3.17.dev5}/dbt/adapters/duckrun/environment.py +0 -0
- {duckrun-0.3.17.dev4 → duckrun-0.3.17.dev5}/dbt/adapters/duckrun/impl.py +0 -0
- {duckrun-0.3.17.dev4 → duckrun-0.3.17.dev5}/dbt/adapters/duckrun/remote.py +0 -0
- {duckrun-0.3.17.dev4 → duckrun-0.3.17.dev5}/dbt/adapters/duckrun/secret.py +0 -0
- {duckrun-0.3.17.dev4 → duckrun-0.3.17.dev5}/dbt/include/duckrun/__init__.py +0 -0
- {duckrun-0.3.17.dev4 → duckrun-0.3.17.dev5}/dbt/include/duckrun/dbt_project.yml +0 -0
- {duckrun-0.3.17.dev4 → duckrun-0.3.17.dev5}/dbt/include/duckrun/macros/catalog.sql +0 -0
- {duckrun-0.3.17.dev4 → duckrun-0.3.17.dev5}/dbt/include/duckrun/macros/materializations/_delta_core.sql +0 -0
- {duckrun-0.3.17.dev4 → duckrun-0.3.17.dev5}/dbt/include/duckrun/macros/materializations/delta.sql +0 -0
- {duckrun-0.3.17.dev4 → duckrun-0.3.17.dev5}/dbt/include/duckrun/macros/materializations/incremental.sql +0 -0
- {duckrun-0.3.17.dev4 → duckrun-0.3.17.dev5}/dbt/include/duckrun/macros/materializations/snapshot.sql +0 -0
- {duckrun-0.3.17.dev4 → duckrun-0.3.17.dev5}/dbt/include/duckrun/macros/materializations/table.sql +0 -0
- {duckrun-0.3.17.dev4 → duckrun-0.3.17.dev5}/duckrun/__init__.py +0 -0
- {duckrun-0.3.17.dev4 → duckrun-0.3.17.dev5}/duckrun/auth.py +0 -0
- {duckrun-0.3.17.dev4 → duckrun-0.3.17.dev5}/duckrun/delta_table.py +0 -0
- {duckrun-0.3.17.dev4 → duckrun-0.3.17.dev5}/duckrun/session.py +0 -0
- {duckrun-0.3.17.dev4 → duckrun-0.3.17.dev5}/duckrun.egg-info/SOURCES.txt +0 -0
- {duckrun-0.3.17.dev4 → duckrun-0.3.17.dev5}/duckrun.egg-info/dependency_links.txt +0 -0
- {duckrun-0.3.17.dev4 → duckrun-0.3.17.dev5}/duckrun.egg-info/requires.txt +0 -0
- {duckrun-0.3.17.dev4 → duckrun-0.3.17.dev5}/duckrun.egg-info/top_level.txt +0 -0
- {duckrun-0.3.17.dev4 → duckrun-0.3.17.dev5}/setup.cfg +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
version = "0.3.17.dev5"
|
|
@@ -30,8 +30,11 @@ view`` (not ``table``), so they pass through too.
|
|
|
30
30
|
|
|
31
31
|
Supported / unsupported (what reaches delta_rs):
|
|
32
32
|
|
|
33
|
-
create [or replace] table x [if not exists] as <query> Delta
|
|
34
|
-
|
|
33
|
+
create [or replace] table x [if not exists] as <query> Delta CTAS (query: select/with/(…)); a
|
|
34
|
+
plain create errors if x is live, `or
|
|
35
|
+
replace` overwrites, `if not exists` no-ops
|
|
36
|
+
create [or replace] table x [if not exists] (<col defs>) empty Delta table (connection API only);
|
|
37
|
+
logs a CREATE TABLE op, same exists rules
|
|
35
38
|
create temp/temporary table … native DuckDB (pass through) ── invariant:
|
|
36
39
|
create view … native DuckDB (pass through) ── only TEMP
|
|
37
40
|
and VIEW are
|
|
@@ -91,7 +94,7 @@ _CREATE_AS = re.compile(
|
|
|
91
94
|
# `create [or replace] table [if not exists] <rel> (<col defs>)` — no `as`. Connection-API only
|
|
92
95
|
# (see _create_coldefs): materializes an EMPTY Delta table so `CREATE TABLE` is always Delta-backed.
|
|
93
96
|
_CREATE_COLDEFS = re.compile(
|
|
94
|
-
r"\s*create\s+(
|
|
97
|
+
r"\s*create\s+(?P<orrep>or\s+replace\s+)?table\s+(?P<ine>if\s+not\s+exists\s+)?"
|
|
95
98
|
r"(?P<rel>.+?)\s*\((?P<defs>.+)\)\s*;?\s*",
|
|
96
99
|
re.I | re.S,
|
|
97
100
|
)
|
|
@@ -293,10 +296,18 @@ class _DeltaDML:
|
|
|
293
296
|
m.group("orrep") or not re.match(r"select\b", m.group("body").lstrip(), re.I)
|
|
294
297
|
):
|
|
295
298
|
return False
|
|
299
|
+
live = self._exists(loc) and not is_dropped(self.cursor, loc, self.so)
|
|
296
300
|
# `if not exists` over a live (non-tombstone) table is a no-op — just (re)surface the view.
|
|
297
|
-
if m.group("ine") and
|
|
301
|
+
if m.group("ine") and live:
|
|
298
302
|
self._refresh_view(rel, schema, loc)
|
|
299
303
|
return True
|
|
304
|
+
# Connection API: a plain `create table` must NOT silently clobber a live table — that's what
|
|
305
|
+
# `or replace` is for. (The dbt/cursor path keeps overwriting: dbt owns idempotent re-runs.)
|
|
306
|
+
if self.default_schema is not None and live and not m.group("orrep"):
|
|
307
|
+
raise ValueError(
|
|
308
|
+
f"table {schema}.{identifier} already exists — "
|
|
309
|
+
f"use CREATE OR REPLACE TABLE to replace it"
|
|
310
|
+
)
|
|
300
311
|
data = self.cursor.sql(m.group("body"))
|
|
301
312
|
# overwrite_schema so this replaces a prior table (or a drop-tombstone) wholesale — a live
|
|
302
313
|
# table is recreated with the real schema, clearing any tombstone marker.
|
|
@@ -316,15 +327,27 @@ class _DeltaDML:
|
|
|
316
327
|
schema, identifier, loc = self._resolve(rel)
|
|
317
328
|
if not loc:
|
|
318
329
|
return False
|
|
330
|
+
live = self._exists(loc) and not is_dropped(self.cursor, loc, self.so)
|
|
331
|
+
if m.group("ine") and live: # IF NOT EXISTS over a live table → no-op
|
|
332
|
+
self._refresh_view(rel, schema, loc)
|
|
333
|
+
return True
|
|
334
|
+
if live and not m.group("orrep"): # plain CREATE over a live table → error
|
|
335
|
+
raise ValueError(
|
|
336
|
+
f"table {schema}.{identifier} already exists — "
|
|
337
|
+
f"use CREATE OR REPLACE TABLE to replace it"
|
|
338
|
+
)
|
|
319
339
|
# Let DuckDB parse the column defs (types, constraints, nested parens) by building the table
|
|
320
|
-
# as a TEMP, then take
|
|
340
|
+
# as a TEMP, then take its Arrow schema and create an EMPTY Delta table from it. DeltaTable.create
|
|
341
|
+
# logs a CREATE TABLE operation (not a WRITE/Overwrite). A live table or a drop-tombstone already
|
|
342
|
+
# has files at ``loc``, so it must be replaced (overwrite); otherwise create-if-absent (error).
|
|
321
343
|
tmp = f"__duckrun_empty_{abs(hash((schema, identifier))) & 0xFFFFFFFF}"
|
|
322
344
|
self.cursor.execute(f'create or replace temp table "{tmp}" ({m.group("defs")})')
|
|
323
345
|
try:
|
|
324
|
-
|
|
325
|
-
engine.write_delta(loc, empty, "overwrite", overwrite_schema=True, storage_options=self.so)
|
|
346
|
+
arrow_schema = self.cursor.sql(f'select * from "{tmp}" limit 0').arrow().schema
|
|
326
347
|
finally:
|
|
327
348
|
self.cursor.execute(f'drop table if exists "{tmp}"')
|
|
349
|
+
mode = "overwrite" if self._exists(loc) else "error"
|
|
350
|
+
engine.create_empty_delta(loc, arrow_schema, mode=mode, storage_options=self.so)
|
|
328
351
|
self._refresh_view(rel, schema, loc)
|
|
329
352
|
return True
|
|
330
353
|
|
|
@@ -732,6 +732,23 @@ def write_delta(
|
|
|
732
732
|
_maintain(dt, compaction_threshold)
|
|
733
733
|
|
|
734
734
|
|
|
735
|
+
def create_empty_delta(
|
|
736
|
+
path: str,
|
|
737
|
+
schema,
|
|
738
|
+
*,
|
|
739
|
+
mode: str = "error",
|
|
740
|
+
storage_options: Optional[Dict[str, str]] = None,
|
|
741
|
+
) -> None:
|
|
742
|
+
"""Create an EMPTY Delta table at ``path`` from an Arrow ``schema`` (no data files).
|
|
743
|
+
|
|
744
|
+
Used by the connection API's bare ``CREATE TABLE (col defs)``: it logs a ``CREATE TABLE``
|
|
745
|
+
operation rather than a ``WRITE``/``Overwrite``, which is what a create — not an overwrite —
|
|
746
|
+
should record. ``mode`` follows delta-rs: ``error`` (fail if the table exists), ``overwrite``
|
|
747
|
+
(replace an existing table or drop-tombstone), or ``ignore`` (no-op if it exists).
|
|
748
|
+
"""
|
|
749
|
+
DeltaTable.create(path, schema, mode=mode, storage_options=storage_options)
|
|
750
|
+
|
|
751
|
+
|
|
735
752
|
def append_if_unchanged(
|
|
736
753
|
path: str,
|
|
737
754
|
data,
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "duckrun"
|
|
7
|
-
version = "0.3.17.
|
|
7
|
+
version = "0.3.17.dev5"
|
|
8
8
|
description = "A dbt adapter that runs SQL in DuckDB and materializes to Delta Lake (delta_rs)."
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
license = {text = "MIT"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
version = "0.3.17.dev4"
|
|
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
|
{duckrun-0.3.17.dev4 → duckrun-0.3.17.dev5}/dbt/include/duckrun/macros/materializations/delta.sql
RENAMED
|
File without changes
|
|
File without changes
|
{duckrun-0.3.17.dev4 → duckrun-0.3.17.dev5}/dbt/include/duckrun/macros/materializations/snapshot.sql
RENAMED
|
File without changes
|
{duckrun-0.3.17.dev4 → duckrun-0.3.17.dev5}/dbt/include/duckrun/macros/materializations/table.sql
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
|