Skip to content

Releases: singhpratech/duckbridge

DuckBridge 0.1.1: safe, large, production-grade loads

Choose a tag to compare

@github-actions github-actions released this 21 Oct 03:09

DuckBridge 0.1.1 makes loads into a shared SQL Server safe and lets a 1 bn-row table go into production DDL in parallel.

Safety (R1, R8)

  • A safety guard owns every database-level statement. CREATE/DROP/ALTER DATABASE are allowed only for databases matching --disposable-db-pattern (env DUCKBRIDGE_DISPOSABLE_DB_PATTERN, default ^_). No ROLLBACK IMMEDIATE anywhere: a drop refuses while other sessions are connected and lists them. Compatibility level and recovery model are never changed unless --compat-level / --recovery are given. Live loads no longer create databases implicitly (--create-database).
  • --plan prints every statement and bulk job without executing; --log, --summary, --progress-seconds. Exit codes: 0 ok, 1 check failed, 2 could not run, 3 guard.

Loads into existing production tables (R2–R5, R9)

  • --into-existing: the target DDL is the contract. Columns are mapped by name; one pre-flight query per table checks lengths, code page, NULLs, integer/decimal ranges and scale, bit, date ranges, PK duplicates (--check-pk) and case/trailing-space collisions before any data moves. --check-only, --ignore-extra-columns, --allow-rescale.
  • --split table=column:<col>|files:<glob>|hash:<cols>:<n>|range:<col>:<n> and --strategy table=switch|heap-then-index|serial. switch loads each partition value into a staging table built from the target's own metadata and ALTER TABLE ... SWITCHes it in (invisible to readers until then); heap-then-index captures and recreates the indexes. --state-dir makes a killed run resumable; --replace-partitions, --drop-old, --max-jobs-per-table, --source-parquet table=glob.
  • New bulk path: per-column converters built once, exact DECIMAL from the DuckDB mantissa, Arrow reader thread with a bounded channel. ~1.2 M rows/s conversion, ~650 k rows/s per session on the dev container (was ~500 k). Bulk copies now check constraints so they stay trusted.
  • --verify counts|checksum|except --sample n: row counts per table/partition always; MD5 column checksums computed identically in both engines; differing rows on request; index completeness after switch/heap-then-index.
  • Create mode: --string-type varchar|nvarchar|auto, --string-sizes from-data|max|<csv>; strings above 2000 characters become NVARCHAR(MAX).

Safe reads (R6)

  • Every import connection sets LOCK_TIMEOUT (1000 ms), DEADLOCK_PRIORITY LOW and the chosen --isolation; --lock-check/--lock-wait/--on-lock before each table; fingerprints before and after with bounded re-reads (--max-rereads); --manifest CSV+JSON; --readonly intent; --wait-for gate; the source connection refuses write statements.

Translator (R7)

  • Warnings carry codes and positions (W-DIV-DECIMAL, W-ROUND-TRUNC, W-FORMAT-NUM, W-TRYCAST-EMPTY, W-CI-COMPARE, W-TRAILING-SPACE, W-PROCEDURAL, W-POWER-DOUBLE); --strict stops before executing anything.
  • --nocase rewrite (new default) rewrites comparisons per literal instead of a global nocase collation (--nocase global still available; it is slow on big GROUP BY/DISTINCT). duckbridge audit-ci shows where it matters.
  • --mssql-math: exact mssql_div, mssql_round, mssql_round_trunc, mssql_try_int, mssql_format_pct macros in HUGEINT arithmetic, verified against SQL Server 2019 on 3000 random cases; duckbridge verify-math reruns that check against your server.

Cut-over (R10)

  • duckbridge swap --pairs new=live,...: all-or-nothing rename in one lock-timed transaction, refuses schema-bound views and incoming FKs, keeps <live>__old_<timestamp>; duckbridge drop-old --before.

DuckDB extension

  • bridge_import / bridge_export / bridge_run expose all of the above as named parameters (see README). parallel is capped at 32 inside the extension. bridge_prelude(true) returns the 3-line rewrite-mode prelude.

Fixes

  • tiberius' 30 s response stall timeout is disabled (long index builds, SWITCH waits, backups and checksums no longer abort).
  • The old per-value loader could wrap tinyint values and sent datetimeoffset text as local time; both are gone.

Tested: 94 library + 81 translator unit tests, 45 CLI and 33 extension end-to-end checks, and the new 118-check large-load suite (2 M-row table in 25 partitions with PAGE compression, a 10-column varchar PK and a filtered index; kill and resume; lock contention; snapshot reads; swap) against SQL Server 2019.

v0.1.0

Choose a tag to compare

@github-actions github-actions released this 18 Oct 15:27
DuckBridge v0.1.0: SQL Server <-> DuckDB bridge CLI and DuckDB extension