Changelog¶
All notable changes to DecentDB will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
UNRELEASED¶
[2.16.1] - [2026-07-01]¶
Changed¶
- Accelerated CRM benchmark revenue aggregation by adding strict engine fast paths for the raw joined revenue aggregate and revenue-summary
INSERT ... SELECTworkload shapes, using covering invoice revenue payloads and dense company-id accumulation to avoid generic join/group execution. - Updated the .NET CRM comparison benchmark to use a DecentDB covering
invoices(company_id) INCLUDE (total)index for revenue aggregation and to measure summary-build work separately from explicit WAL checkpoint maintenance.
Fixed¶
- Fixed benchmark-shaped invoice update planning so the DecentDB CRM workload no longer pays for an unnecessary
(paid, total)index during the paid invoice update scenario. - Improved DML range matching with bounded compound B-tree scans and single-column range index support for predicate-driven updates.
[2.16.0] - [2026-07-01]¶
Added¶
- Added BOOLEAN support to the C ABI typed batch signature, including the documented ADR 0201 compatibility decision and refreshed public C headers for downstream bindings.
- Added .NET ADO.NET batch/prepared-statement performance coverage, including typed batch tests, ADO.NET microbenchmarks, CRM comparison benchmarks, benchmark matrix scripts, and a GitHub workflow for CRM benchmark runs.
- Added the
design/2026-06-30_PERF_PLAN.mdimplementation plan covering the completed binding and DML performance work.
Changed¶
- Improved .NET ADO.NET command, connection, and data-reader hot paths with prepared-statement reuse, typed batch execution, cached result metadata, and expanded API documentation.
- Optimized DML execution for boolean updates and benchmark-shaped prepared write paths while preserving index maintenance and transaction semantics.
- Expanded CRM and benchmark documentation with allocation telemetry, matrix comparison output, and updated benchmark result artifacts.
Fixed¶
- Fixed prepared B-tree index handling to resolve index column names with normal SQL identifier case-insensitivity, matching SQLite-compatible quoted-column behavior in .NET tests.
- Fixed paged-row append persistence so modified chunk payloads invalidate stale persisted chunk metadata before locator caches and persistent primary-key locators are rebuilt.
- Fixed deferred filtered
COUNT(*)execution so filtered counts fall back to predicate-aware evaluation instead of returning total persisted row counts.
[2.15.0] - [2026-06-29]¶
Added¶
- Added named database profile configuration across the C ABI and .NET connection-string surfaces, including profile documentation for C/C++, .NET, and general configuration users.
- Added UUID handling for prepared statements, runtime indexes, and Python result decoding paths, with API coverage and SQL regression tests.
- Added
scripts/benchmark_runner.py, expanded complex/movie workload benchmark coverage, and checked in the latest rust-baseline benchmark result artifacts. - Added ADR 0200 and format-14 resident table delete tombstones, including the v13-to-v14 migration parser path and DELETE_BATCH design documentation.
- Added a
DecentDB vs Turso Databaseuser-guide comparison that distinguishes Turso Database, libSQL, and Turso Cloud while positioning DecentDB's local durability, branch, sync, policy, and SQL tradeoffs. - Added detailed
DecentDB vs libSQL,DecentDB vs PGlite,DecentDB vs H2,DecentDB vs LiteDB, andDecentDB vs Firebird Embeddedcomparison guides, and expanded the comparison overview/navigation so users can evaluate DecentDB against more embedded database alternatives.
Changed¶
- Improved SQL execution fast paths for residual predicates, filtered projections, indexed range/order queries, grouped and distinct aggregates, left-join aggregate lookups, and set-operation workloads.
- Enhanced full-text search scoring, ranking, document deletion handling, and movie-query coverage.
- Aligned WAL sync benchmarking behavior with SQLite semantics and documented the benchmark-driven performance work in the design notes.
- Accelerated resident-storage cascade deletes with logical
TableDatatombstones, tombstone-aware runtime index overlays, sparse resident overflow patching, and CRC32C byte-patch updates. The MovieDB scratch cascade-delete metric now beats SQLite in the benchmark runner. - Accelerated Showdown bulk deletes on resident tables by avoiding redundant SQL parser work, deleting runtime index entries by row id, applying logical full-text/trigram delete overlays, and patching resident overflow payloads in place.
- Removed the DecentDB native-defaults Showdown run from
scripts/benchmark_runner.pycomparison profiles so SQLite gap rankings compare like-for-like benchmark configurations. - Made the Showdown search-index benchmark compare full-text index setup against SQLite FTS5 setup by removing the DecentDB-only trigram build from that timed step and enabling matching SQLite FTS prefix indexes.
- Accelerated runtime full-text/trigram search index builds with bulk full-text construction, lower-allocation ASCII token handling, vector-backed full-text postings, and flatter trigram postings.
- Accelerated Showdown read-query metrics by routing top-level BM25 full-text
ORDER BY ... LIMITqueries through the existing top-k full-text fast path and adding strict fast paths for simpleRANK/DENSE_RANK,ROW_NUMBER/LAG, and rollingAVGwindow query shapes. - Improved Showdown DML/query hot paths with arithmetic
UPDATE ... RETURNINGfast paths, cheaper row-id range matching, incremental runtime B-tree row-id moves, resident in-transaction update/revert dirty-state cleanup, no-op row-id UPSERT checks, paged-manifest chunk metadata reuse, a strict integer-series recursive CTE fast path, and a direct literal substringLIKEprojection path. - Archived the completed metric-improvement tracker and folded the remaining diagnostic rust-baseline view/fixed-overhead gaps into
design/WIN_PERFORMANCE_IMPROVEMENTS_01.md. - Reprioritized
design/FUTURE_WINS.mdaround the next adoption-critical backlog: core read/query performance, cross-binding cursor parity, Postgres-backed local-first sync, migration workflow, Doctor/advisors, JSONB, hybrid search, and packaging/ORM adoption work. - Improved deferred SQL view execution for paged row storage by caching parsed view queries, pruning decoded base-table columns for view filter/LIMIT paths, streaming indexed view joins without materializing intermediate row vectors, trimming proven join columns from projected deferred rows, lowering the small-scale deferred-view LIMIT fast-path threshold, bounding grouped Top-N postprocessing, exposing expanded-view pushdown metadata in
EXPLAIN, and reducing inactive faulty-VFS wrapper overhead. - Trimmed row-id alias join keys from deferred SQL view projected reads so a three-table inner-join view chain no longer decodes the join key column when it equals the previous row's stored row id. The linear and generic deferred view walkers now synthesize the join key from the row id directly, shrinking per-table projections for
v_artist_songs-style view shapes. This is a general optimization, not a schema or view-name specific shortcut. - Fixed a planner index-detection gap where explicit
JOIN ... ONsyntax never recognized usable join indexes, so cost-basedIndexedJoinis now selected for explicit inner equi-joins when a useful B-tree index exists (previously such joins always fell back toHashJoin).EXPLAINnow surfaces the chosenIndexedJoinoperator with estimates for these shapes. - Added planner
EXPLAINregression tests for indexed-join selection, hash-join selection without a useful index, and estimated rows/cost surfacing. - Completed the WIN01 read/query performance closeout: public
embedded_compareguardrails now pass for balanced, low-memory, and tuned durable DecentDB profiles; rust-baseline full/huge peak RSS drops by more than 25%; and the full/huge view-query gates exceed 2x improvement without weakening WAL sync or durability semantics. - Accelerated the public prepared-insert and read hot paths with transaction-local next-row-id caching, fewer redundant catalog writes, append-only unique-index tombstone-cleanup avoidance, resident prepared point/range reads, direct projected row-id/range result construction, and narrow
SmallVecquery rows. - Updated the Future Wins roadmap so WIN01 is recorded as delivered context instead of active backlog, leaving cross-binding cursor/row-view parity as the next top-priority performance-adjacent roadmap item.
Fixed¶
- Prevented paged-row snapshot reads from mixing cached main-db pages with WAL-pinned snapshots under rapid same-process open/close churn, and made open-time paged-storage backfill abandon stale writes when another writer advances the WAL first.
- Preserved non-updated wide-row columns during arithmetic updates.
- Improved checkpoint and runtime-index refresh behavior used by prepared statements and benchmark-heavy read paths.
- Simplified resident read checks by removing stale
SingleProcessUnsafegating from the relevant read-path logic. - Kept tombstone-aware runtime indexes from returning stale rows after delete/update/reinsert sequences while preserving resident checkpoint and compaction fallbacks.
[2.14.0] - [2026-06-19]¶
Added¶
- Added Go direct binding branch helpers backed by existing C ABI functions:
CreateBranch,ListBranches,DeleteBranch,ExecuteOnBranch, andQueryOnBranchInt64, with package tests and README examples. - Added a binding compatibility matrix covering Rust, C ABI, Python, Go, Java, Node.js, Dart, .NET, and Web/WASM support status across core embedding capabilities.
- Added targeted WAL/VFS, extension trust, local security, TDE, error taxonomy, record/value, B+Tree, SQL robustness, and spatial/EWKB tests from the implementation review.
- Documented browser/WASM row ownership and added browser smoke coverage proving prepared-statement rows remain usable after advancing and closing the statement.
Changed¶
- Split large executor and database helper code into smaller internal Rust modules without changing public API, SQL behavior, C ABI behavior, or on-disk formats.
- Moved large
db.rsandexec/mod.rsin-file test modules into sibling test modules for easier navigation. - Optimized aggregate read paths used by issue-tracker style reporting workloads. Simple
GROUP BY <column>, COUNT(*)queries can now answer from fresh single-column B-tree index cardinalities, including deferred paged-table snapshots without a resident row source, and status-reportLEFT JOINaggregates can use the child join index instead of scanning the full child table.
Fixed¶
- Kept deferred read execution paths pinned to one WAL snapshot through final statement execution. This prevents concurrent writer/checkpoint activity from mixing runtime metadata with pages from a different snapshot, which could surface as intermittent overflow payload length mismatch errors under writer/reader stress.
- Preserved hot same-handle paged-table runtime metadata across explicit WAL checkpoint folds while still reloading after background or cross-connection post-checkpoint WAL commits. Bulk-load-then-read workloads now keep deferred row-count metadata and locator/index caches available after
checkpoint_wal(), restoring rust-baseline count, grouped-join, and view-query performance. - Replaced selected production panic-like executor paths with typed SQL/internal errors or explicit invariants, with regression tests for those error paths.
[2.13.1] - [2026-06-15]¶
Fixed¶
- Prevented an overflow payload length mismatch during concurrent connection churn.
runtime_table_row_countpreviously created a new snapshot reader viaPagerReadStore::new, which could observe a different WAL snapshot than the outerSELECT COUNT(*)operation. When the writer committed new overflow pages between the two snapshot acquisitions, the overflow chain walk decoded a payload length that diverged from theOverflowPointer.logical_lenstored in the catalog snapshot.PagerReadStorenow accepts an explicit snapshot LSN so that the overflow chain, catalog pointer, and external reader guard all observe the same consistent snapshot. - Kept deferred-table database open lazy while avoiding repeated secondary index rebuilds across short-lived connections in the same process. The first query for a specific deferred B-tree index may hydrate that one runtime index, then a bounded process cache reuses the runtime index and paged row locator cache for subsequent handles with the same persisted table snapshot. This fixes Melodee's checkpointed MusicBrainz DDB-002/DDB-003 timeout pattern without moving all multi-million-row index rebuild work into every
Db::open.
[2.13.0] - [2026-06-15]¶
Added¶
- Added the default-on connection-local plan cache (ADR 0190-0194). It reuses parsed parameterized statements and prepared-plan bundles across calls within a
Dbhandle, keyed by(sql_text, parameter_shape, persistent_schema_cookie, temp_schema_cookie, policy_mask_generation). Diagnostics are exposed throughsys.plan_cache,sys.plan_cache_summary,sys.doctor_findings,PRAGMA flush_plan_cache, C ABIddb_plan_cache_summary/ddb_plan_cache_flush, anddecentdb plan-cache stats|list|reset. C ABI open optionsplan_cache_enabledandplan_cache_max_bytesare additive and do not bump the C ABI version. - Added
cargo bench -p decentdb --bench plan_cacheandbenchmarks/rust-baseline --plan-cache-benchmarkguardrail benchmarks. Local validation showed repeated point-lookup preparation at 643K ops/s with the cache enabled vs 188K ops/s disabled, one-shot query throughput within the guardrail at 435 ops/s enabled vs 442 ops/s disabled, and warm churn preparation at 100K ops/s enabled vs 43K ops/s disabled. - Added cost and cardinality estimates to rendered physical plans, including explicit
HashJoin,IndexedJoin,StreamingAggregate,ViewScan, andExpandedViewplan nodes for planner diagnostics.EXPLAINnow surfaces estimated rows and relative cost for planned read operators, and the EXPLAIN planner can use persistedANALYZEstatistics to compare table scans, row-id lookups, index seeks, and simple inner-join alternatives.
Changed¶
- Improved prepared read hot paths for row-id, row-id range, and simple row-id join projections by reusing bounded resident paged row sources when the runtime snapshot is current. This avoids repeated deferred-table row-source reloads for medium-sized prepared lookup workloads while preserving the existing deferred-table memory cap and re-defer behavior.
- Reduced unnecessary row materialization in simple projection paths by reading projected values directly for row-id lookups and by applying unordered
LIMIT/OFFSETwhile scanning simple table and filtered projection fast paths. - Switched the in-process reader registry from a hash map to reusable reader slots so repeated reader registration avoids avoidable hot-path overhead.
- Regenerated the native benchmark summary and README benchmark chart assets from the latest
embedded_comparerun.
Fixed¶
- Protected one-shot literal SQL from plan-cache churn by bypassing the generalized parsed cache for zero-parameter execution and using second-use admission for parameterized parsed statements.
- Eagerly hydrate all B-tree indexes for deferred tables on database open when
defer_table_materializationis enabled. Previously, each secondary index was lazily hydrated on first query, causing multi-second delays (12+ seconds for 1M row tables) on the first query for each index. Now all indexes are loaded during open, ensuring sub-millisecond query performance from the first execution. This trades slightly slower database open time for consistently fast query performance, which is critical for request-path workloads like Melodee's MusicBrainz lookups.
[2.12.0] - [2026-06-13]¶
Added¶
- Added a deferred-table fast path for simple
ORDER BY <INT64 primary key> LIMIT/OFFSETprojections. DecentDB now plans these as ordered row-id scans, lazily backfills only the target table's persistent primary-key locator when needed, refreshes the read snapshot after that metadata backfill, and uses the persisted locator instead of falling through to full paged-table scans.
Changed¶
- Kept persistent primary-key locator indexes opt-in behind
DbConfig::persistent_pk_indexso the default rust-baseline write path preserves its low-write-amplification profile while large deferred lookup workloads can still enable durable locators explicitly.
Fixed¶
- Corrected deferred paged-table projections that order by an
INT64primary key column that is not part of the projection, including mixed update-and-append transactions where the updated row is stored in an overlay chunk. - Kept cold secondary btree equality lookups on deferred paged tables from materializing the table by lazily hydrating only the required runtime index and then preserving deferred row storage.
- Improved B+Tree corruption diagnostics by including the page id when page decoding fails during read traversal.
- Hardened the sync relay websocket checkpoint test with socket timeouts so failed handshakes cannot hang the test process, and preserved frame bytes already buffered while reading the HTTP upgrade headers.
- Kept memory-safety nightly useful under AddressSanitizer by preserving the indexed checkpointed-table correctness and plan-shape checks while reserving strict wall-clock performance assertions for non-sanitized runs.
- Bounded the release workflow validation job and workspace-check step so a hung test reports a targeted timeout instead of consuming the full six-hour GitHub Actions job window.
[2.11.0] - [2026-06-12]¶
Fixed¶
- Removed the 250,000-row limit on the paged row locator cache that caused indexed equality lookups on large checkpointed tables to degrade to O(manifest_size) per-row linear scans. The cache is now built for all tables with btree indexes or row_id alias columns, regardless of row count. This fixes multi-second indexed lookups observed on tables with millions of rows (Melodee DDB-002/DDB-003).
- Refreshed reader and prepared-statement checkpoint handling so same-handle and FFI callers continue to read and commit correctly after WAL checkpoint truncation.
- Hardened faulty-VFS write handling used by WAL recovery tests so injected partial-write failures preserve the expected file state.
- Kept the Miri smoke binary compatible with default Miri isolation by using a deterministic runtime-tracing timestamp under
cfg(miri).
Added¶
- Added executor support for bounded indexed range seeks with optional limits, expanding the fast path beyond exact equality probes.
- Added regression tests for indexed seek performance on checkpointed/paged tables with 300K+ rows, verifying bounded lookup time after checkpoint and reopen.
- Added the now-archived
design/_archive/METRIC_IMPROVEMENTS_PLAN.mdto track DecentDB's benchmark standing against SQLite and the priority order for closing or exceeding each public-facing metric. - Added
benchmarks/rust-baseline --benchmark, which runssmoke,medium,full, andhugescales in order for the selected engine/profile and then generates the HTML report.
Changed¶
- Optimized Rust query result and row projection paths by sharing column metadata with
Arcand improving fast projection decoding for point-lookups. - Updated the rust-baseline benchmark to measure reads from a checkpointed post-seed state for both engines: DecentDB uses
Db::checkpoint_wal()and SQLite usesPRAGMA wal_checkpoint(TRUNCATE). The newcheckpoint_after_seedstep records duration plus WAL/database bytes before and after checkpointing.
[2.10.0] - [2026-06-10]¶
Fixed¶
- Kept simple indexed equality projections on the native fast path when they include provider-generated
ORDER BY,LIMIT, orOFFSETclauses. This covers EF Core shapes such asWhere(...).OrderBy(...).Take(...)for indexed string lookups.
Added¶
- Added .NET ADO.NET
DecentDBMaintenance.RebuildIndexAsync(...)andRebuildIndexesAsync(...)helpers so applications can rebuild runtime index structures through the binding without invoking the CLI. - Added native and .NET regression coverage for Melodee-style ordered indexed string equality lookups.
- Runtime tracing subsystem (
RuntimeTraceState,RuntimeTracingConfig) with open-time configuration viaDbConfig::tracing. Disabled by default; the disabled path adds no allocation, no SQL normalization, and no extra locks. - Slow query tracing: per-statement fingerprinting, redaction, bounded ring buffer (
sys.slow_queries), andSqlTextMode::None(default) vsFull. - Lock-wait tracing: records
sql_write_lockwaits and process-coordination lock waits (sys.lock_waits). - Index-usage aggregates: read/write counters per index (
sys.index_usage). - Advisor engine (
AdvisorEngine) with four advisor categories:Query,Index,Contention,Storage. Produces findings with severity, confidence, evidence, and optional safe fix plans. - Doctor integration:
sys.doctor_findingsmerges staticsync_operational_doctor_reportfindings with runtime advisor findings;sys.fix_planexposes safe-to-apply plans. - C ABI:
ddb_runtime_tracing_snapshotandddb_runtime_tracing_resetfor all trace views. - CLI: new
decentdb tracing --view <view>command supporting JSON/Table/Markdown output and--resetoption. - Integration tests covering disabled-by-default, slow query capture, redaction, full-mode SQL text, sessions view, lock-wait capture, and empty-buffer reset.
[2.9.0] - [2026-06-09]¶
Fixed¶
- Fixed Memory Safety Nightly Valgrind failures by releasing retained capacity from the process-local WAL reader-slot registry after the final local reader slot is removed.
Added¶
- Added .NET ADO.NET maintenance helpers for WAL status snapshots, binding-native checkpoints, compact save-as copies, and in-process vacuum without requiring an external executable.
- Added a .NET ADO.NET
ExplainQueryhelper forEXPLAINandEXPLAIN ANALYZEdiagnostics. - Added .NET EF Core regression coverage for exact equality on large indexed string columns modeled after Melodee's MusicBrainz lookup workload.
Changed¶
- Improved .NET ADO.NET open failures for unsupported database format versions with guidance to use a compatible engine, run
decentdb-migratewhen available, or rebuild/export with the current engine.
[2.8.0] - [2026-05-28]¶
Added¶
- Added local data security v1: transparent data encryption for database, WAL, and sync-journal files via
DbConfig::encryptionand C ABI open options; durableCREATE/ALTER/DROP POLICY; durableCREATE/ALTER/DROP MASK; connection-local audit context through Rust, SQL, and C ABI APIs; audit context SQL functions;sys_audit_context; and security DDL audit events. - Added ADR 0174 documenting the TDE, policy, masking, audit-context, C ABI, and follow-up security boundaries.
- Added native full-text search with
USING fulltextindexes, persisted analyzer options,fulltext_match,bm25ranking, phrase and prefix queries, write-path maintenance,ALTER INDEX ... VERIFY,ALTER INDEX ... REBUILD, tooling metadata, and SQL/user documentation. - Added Python, Dart, and .NET binding showcase tests for native full-text search, parameterized
fulltext_matchqueries, prefix search, andbm25ranking through each binding's public API. - Added cross-process WAL coordination for local on-disk databases: VFS byte-range locks on native platforms, a rebuildable
.coordsidecar with database identity checks, cross-process writer/checkpoint serialization, reader-slot WAL retention, external WAL refresh, stale-slot cleanup, andsys.process_coordination,sys.process_readers, andsys.process_lock_metricsdiagnostics. - Added Rust, C ABI open-option, Python, Dart, and .NET surfaces for
process_coordination=auto|required|single_process_unsafeandprocess_coordination_timeout_ms, plus binding smoke coverage for the new diagnostics. - Added
@decentdb/webbrowser parity hardening:browser-app-v2SQL profile metadata, stable browser SQL error codes, protocol/capability metadata, transaction/savepoint helpers, prepared statement reset/clear/page/async iteration, explicit closed-handle/import lifecycle errors, OPFS checkpoint/ export/import diagnostics, browser sync apply-before-ack helpers, framework recipes, a checked-in SQL parity corpus, and expanded browser benchmark guardrails. - Added Flutter mobile production-runtime hardening with a new
decentdb_flutterpackage shell, Android/iOS native artifact build scripts, unsigned mobile GitHub Actions artifact workflow, app-private path and database-set helpers, mobile key-provider wiring, redacted open-option diagnostics, a reference Flutter app, and mobile package tests. - Added Dart sync JSON/public changeset wrappers, including status/init, changeset create/inspect/apply/invert, and
applyBeforeAckordering for relay clients. - Added default-fast benchmark/profile assets: canonical
decentdb_balanced_durable,decentdb_low_memory_durable,decentdb_tuned_durable, andduckdb_engine_defaultlabels; storage split fields; cold-state metadata; H2/HSQLDB partial labeling; and Python binding prepared-statement/result-materialization benchmark slices. - Added prepared INSERT fast-path coverage for supported direct/default write shapes, including routing that avoids unnecessary covering-index payload work, deferred table materialization that preserves valid index state, and scalar integer aggregate support that scans persisted payload columns without forcing full row materialization.
- Added parser-bypass fast paths for plain persistent-table
COUNT(*)reads and integer primary-key projection reads so default rust-baseline count and single-row lookup slices stay on metadata/row-id lookup paths. - Added runtime-only covering-index execution for safe B+Tree
INCLUDE (...)projections, includingEXPLAINreporting and conservative fallback when projections are not covered or security rules are active. - Added
SqlTransaction::prepared_batchandPreparedStatementBatchfor Rust callers that repeatedly execute one prepared statement inside an exclusive transaction; simple positional INSERT batches validate and resolve the fast path once, then refill a mutable parameter buffer per row. - Added rich structured error diagnostics across Rust, the C ABI, CLI/HTTP JSON, WASM/browser errors, and maintained bindings, including
ddb_last_error_json, stablesubcode/retryable/permanentfields, SQLSTATE/doc anchors where applicable, redacted context, binding smoke coverage, compatibility guidance, and a dedicatederror-diagnosticstroubleshooting page.
Changed¶
- Kept release-facing benchmark charts on the controlled 2026-05-22 snapshot while the new profile-aware benchmark harness is staged; local diagnostic runs no longer replace the checked-in comparison asset, and H2/HSQLDB read-only partial comparison rows remain visible in the chart.
- Bumped the C ABI version to 6 for the new audit-context entry points and TDE open options, and updated the Dart ABI expectation/header copies.
- Extended the Rust library crate outputs with
staticlibfor iOS XCFramework packaging and added Dart default native loading for Android and iOS package layouts. - Bumped the database format version to 12 for full-text index metadata and added
decentdb-migratesupport for format-11 databases. - Bumped the database format version to 13 to add a non-secret database identity used by coordination sidecars, and added
decentdb-migratesupport for format-12 databases. - Tightened checkpoint safety so explicit checkpoints skip main-file copyback while local snapshots, named snapshot retention, unreadable reader slots, or cross-process reader slots are active; reader-free checkpoints still copy back and truncate normally.
- Improved large-table read performance for common
LIKEpredicates and deferred paged row-id point lookups, including allocation-lightLIKEmatching, trigram candidate pushdown for safe substring searches, bulk trigram index construction, and chunk-targetedINTEGER PRIMARY KEYlookups that avoid reconstructing a full paged table manifest. - Kept the default durable cache at the historical 4 MiB after executor fast-path fixes recovered read headroom without raising the default cache, added explicit
DbConfig::balanced()(16 MiB),DbConfig::low_memory()(4 MiB), andDbConfig::tuned_durable()helpers, and stopped the CLIexeccommand from overriding caller-selected cache options. - Reduced default open and commit overhead by lazily starting the background checkpoint worker, lazily creating reactive subscription hubs, treating the coordination sidecar as rebuildable metadata during create/open, keeping writer-owner diagnostics in memory for default
autocoordination, and avoiding redundant coordination-header reads/locks after publish operations, plus skipping no-op backfill/snapshot-retention maintenance when a newly created database still has schema cookie0, while preserving the byte-range process lock. - Tightened the Rust rust-baseline benchmark runner so schema setup uses one explicit durable transaction for the same DDL, seed slices use mutable prepared insert buffers through transaction-scoped prepared batches without prepare time in the measured section, unused seed-walk payloads are not constructed, and release builds use full LTO, stripped symbols, and abort-on-panic. The final smoke/medium/full/huge comparison against
benchmarks/rust-baseline/resultsis green across every recorded step, total runtime, peak RSS, database size, and WAL size metric. - Promoted the default-fast performance/storage-efficiency Future Win from the roadmap to delivered context; follow-on performance work is now scoped to measured evidence outside this completed baseline.
- Promoted the browser Future Win from roadmap item to delivered context in
design/FUTURE_WINS.md; follow-on browser work is now scoped to measured parser breadth, security key handling, branch workflows, or performance. - Promoted the mobile Future Win from roadmap item to delivered context in
design/FUTURE_WINS.md; follow-on mobile work is now scoped to measured device matrices, direct native SDKs, watch lifecycle guarantees, and key rotation rather than first-class Flutter package hardening. - Bumped the C ABI version to 7 for structured diagnostic JSON and added release guardrail documentation for first-slice subcode projection across bindings.
Fixed¶
- Fixed Windows native release builds by making the process-coordination byte-range lock guard explicitly
Send/Syncunder the documented Windows handle lifetime invariant. - Fixed Windows GitHub release artifact builds by linking the Java JNI bridge against the DecentDB cdylib/import library before falling back to the Rust static library, avoiding MinGW/MSVC runtime symbol mismatches.
- Fixed mobile native artifact release builds by passing Android NDK compiler, archiver, C flag, and bindgen sysroot settings through to C build scripts, using shell-safe multi-line workflow commands, and avoiding Bash associative arrays in the iOS artifact script on macOS runners.
- Fixed mobile native artifact uploads so workflow-dispatch packaging writes zip files to explicit runner-temp paths accepted by
actions/upload-artifactinstead of parent-relative paths. - Fixed the native release benchmark lane so DecentDB README chart profiles explicitly run as single-process embedded comparisons with
process_coordination=single_process_unsafe, while keeping durableWalSyncMode::Fulland documenting that cross-process coordination is validated separately. - Added a release benchmark narrative guard to the benchmark-assets workflow: it now runs the raw rust-baseline full-scale cross-check, uploads the compare report, and fails before publishing README chart assets if the tuned durable chart row and raw-engine baseline tell conflicting performance stories.
- Fixed legacy database migrations to seed the v13 coordination identity for all upgraded source formats and to keep copied WAL header-page frames aligned with the migrated main header identity.
- Fixed opening current-format databases produced by earlier v13 migration builds by repairing an empty coordination identity before initializing the coordination sidecar.
- Fixed non-ANALYZE
EXPLAINso it renders from catalog metadata without materializing deferred paged row sources, reportsRowIdLookupfor row-id primary-key predicates, and matches index columns with normal SQL identifier equality instead of case-sensitive string equality. - Fixed trigram
LIKEplanning to avoid unsafe index use forNOT LIKEand escaped patterns while ignoring wildcard characters when deriving required trigram tokens. - Fixed same-handle reader snapshots so refreshing to an older retained WAL LSN reloads the runtime catalog/table metadata instead of reusing newer deferred paged-table overflow pointers.
[2.7.0] - [2026-05-22]¶
Added¶
- Added ABI v5 with the stable C ABI
ddb_db_execute_on_branchentry point plus DartDatabase.branchWorkflowAPIs for named snapshots, branch create/list/ delete/rename/commit/log/diff/restore/merge, and branch-local SQL execution with typed positional parameters.
Fixed¶
- Fixed canonical
sys.*inspection query execution through prepared statements, includingsys.wal_metrics,sys.storage_metrics,sys.write_queue_metrics,sys.sync_status,sys.sync_retention,sys.sync_peer_lag,sys.sync_relay_status,sys.reactive_metrics,sys.reactive_subscriptions,sys.extensions,sys.extension_functions,sys.extension_collations,sys.extension_dependencies, andsys.extension_validation.
[2.6.0] - 2026-05-21¶
Added¶
- Added
decentdb serve, a CLI-hosted local HTTP API and lightweight Web Console with embedded offline assets, transparent localhost auth, read-only mode, schema/table/index/view/trigger inspection, SQL and EXPLAIN execution, result limits, request limits, query history, CSV export, optional CORS, JSON request logging, and remote-bind safety checks. - Enhanced
decentdb describeand the REPL.d <table>command to show foreign key references, including table-level foreign key constraints. - Completed the interactive SQL shell ergonomics roadmap slice with a version banner,
help/quit aliases, topic-specific help, schema inspection commands (.tables,.dt,.d <table>,.schema,.indexes,.views), function listing (.df), output controls (.mode,.headers,.nullvalue,.width,.timer), file workflows (.read,.output,.once,.import,.export), explain helpers (.explain,.plan,.explain-analyze), positional parameter helpers (.param), repeat-last-SQL (.g), session history (.s), and branch creation/checkout helpers. - Added WASM/browser support: the
decentdbcrate now checks forwasm32-unknown-unknown, exposes wasm-bindgen browser exports, and includes an OPFS-backed VFS intended for Dedicated Worker use. - Added the
@decentdb/webTypeScript binding with an async worker-owned API, OPFS host bridge, explicitwasmUrlloading,exec/query/prepare, binary result transport, checkpoint, import/export, persistence helper, worker metrics, automated Chromium OPFS browser smoke coverage, and scheduled browser transport benchmark coverage. - Added ADR 0161 documenting the browser WASM/OPFS runtime and its one-worker ownership model.
- Added the WASM / Browser API documentation page.
- Completed the production browser runtime phase with ADR 0165,
probeRuntime(), stable browser error codes, Dedicated Worker owner coordination through Web Locks and BroadcastChannel, multi-tab owner routing and recovery coverage, explicit service-worker exclusion, owner/quota/persistence diagnostics throughmetrics()andsys.browser_*views, tagged browser parameters, an expandedbrowser-app-v1SQL profile, and tier/candidate Playwright browser matrix scripts. - Added concurrent-write benchmark coverage: native benchmark hooks for direct single-writer and read-under-write regression slices, executable queued-write single-writer and reader-under-writer scenarios, a shared cross-binding concurrent-write scenario definition, a grouped-commit fault-injection test plan, and pre-commit check keys for the new slices.
- Added the engine-owned queued write path with strict durable group commit, bounded admission, timeout and cancellation-before-run errors, Rust and C ABI queue metrics, C ABI status codes and execution entry points, and ADR 0162.
- Added the Write Concurrency user guide and C ABI documentation for queued writes, queue configuration, queue metrics, and the distinction between strict group commit and async commit.
- Added queued-write binding coverage across Python, Go, Dart, Node, .NET native, Java/JDBC status/config mapping, Knex unbound writes, and C ABI smoke tests for maintained binding surfaces.
- Added built-in operational metrics
sys.*inspection views:sys.wal_metrics,sys.write_queue_metrics,sys.storage_metrics, and canonicalsys.sync_statuswhile preservingsys_sync_*compatibility inspection names. Added deterministic Rust regression tests and SQL API documentation plus ADR 0163 covering column contracts, metric snapshots, and lifecycle semantics. - Added in-process reactive subscriptions and change streams with Rust watch handles, table/range/query/change-stream watch kinds, bounded lag reporting, post-commit LSN events, queued/sync/branch source tagging, C ABI JSON watch handles, Python and Go direct watch helpers,
sys.reactive_metrics,sys.reactive_subscriptions, ADR 0164, and a full implementation spec for the reactive contract. - Added the production sync relay and public changeset surface: Rust changeset create/inspect/apply/invert APIs, C ABI JSON entry points,
decentdb sync changeset, authenticateddecentdb relay servev2 HTTP and WebSocket routes, sync shapes backed by scopes, durable shape acks and retention blockers, relay/shape/changesetsys.*diagnostics, browser relay helpers, .NET JSON helpers, user docs, and ADR 0166-0168 delivery context. - Completed the SQL and PRAGMA compatibility quick-wins roadmap item with safe SQLite-style PRAGMA probes and assignments, durable transactional
user_version/application_idmetadata, extended schema-introspection PRAGMAs, PRAGMA table functions, read-onlysqlite_schemaand minimalinformation_schemaviews,generate_series, narrowmain./temp.qualifiers, query-timeBINARY/NOCASE/RTRIMcollations, scalar compatibility helpers, docs, and CLI smoke coverage. - Added the sandboxed Lua extension runtime and package model: manifest validation, stable package hashing, Ed25519 signature verification, database-owned package catalogs, explicit install/enable/disable/purge lifecycle, connection-level content-hash trust, development-only unsigned overrides, scalar functions, table-valued functions, aggregate functions, query-time Lua collations, runtime resource limits,
sys.extension_*inspection views, Rust APIs,decentdb extensionCLI commands, C ABI JSON lifecycle bridges, docs, and a full example extension package.
Changed¶
- Gated the native C-backed
pg_queryparser out ofwasm32-unknown-unknownbuilds and added a documented wasm parser for the browser v1 SQL subset.
Fixed¶
- Fixed
decentdb-migratev10 → v11 upgrades for databases with an existing<db>.walsidecar by standardizing migration tooling on the engine's append-.walsidecar convention, copying the v10 WAL forward, and upgrading any page-1 database-header frames inside the copied WAL so a later checkpoint cannot restore a legacy v10 header. - Fixed production relay shape HTTP endpoints to authorize by shape ACL/allowlist for shape-based streams and snapshots, avoiding a false
SCOPE_UNAUTHORIZEDrejection when callers present valid shape permissions but no explicit scope list.
[2.5.1] - 2026-05-19¶
Changed¶
- Updated the .NET benchmark harness to use the same tuned durable read profile as the native benchmark (
64MBcache, resident row sources after commit, paged row storage disabled, and WAL auto-checkpoint disabled), primary-key point-read schema parity for SQLite and DecentDB, parameterized batched Dapper inserts, larger EF CoreSaveChangesbatches, and only like-for-like paired provider comparisons.
Fixed¶
- Fixed .NET
Cache Sizeand related native connection options so they are passed through the C ABI at open time instead of being parsed and ignored by the managed binding. - Fixed C ABI owned-value disposal for native
GEOMETRYandGEOGRAPHYresult values so sanitizer runs no longer report leaked copied spatial cells. - Fixed the Node Knex lifecycle tests to always close pools after success or failure and clean up DecentDB WAL sidecar files between tests, avoiding hung nightly binding lifecycle runs after transaction failures.
[2.5.0] - 2026-05-18¶
Changed¶
- Extracted CTE and query-scope utility functions from
exec/mod.rsintoexec/cte.rs(~470 lines), improving module cohesion.
Fixed¶
- Fixed single-row
ENUMinserts and updates after reopen so column label metadata is used during write coercion instead of falling through to the metadata-free generic cast path. - Removed three stale
#[ignore]test annotations: the zero-byte WAL design-choice test, theINSERT DEFAULT VALUESmissing-feature test, and the decimal negative-precision ordering test (the underlying sortable encoding was already correct, validated by the now-active test).
Added¶
- Stable schema and query-contract metadata for tooling: added
Db::get_tooling_metadata(),Db::describe_query_contract(sql), C ABI JSON helpers, deterministic schema fingerprints, native type metadata, query parameter/result-column contracts, and binding exposure across Python, Go, .NET, Node.js, Java/JDBC, and Dart. - C ABI open-with-options entry points (
ddb_db_create_with_options,ddb_db_open_with_options, andddb_db_open_or_create_with_options) for open-time tuning from bindings, including cache size, paged row-source residency, paged row storage, persistent primary-key index, and WAL auto-checkpoint thresholds. - Binding-native semantic data types: added compact native storage and C ABI value tags for
ENUM,IPADDR/INET,CIDR,DATE,TIME,TIMESTAMPTZ,INTERVAL, andMACADDR/MACADDR8, including SQL casts, format-version migration support, dump/sync/tooling metadata coverage, and typed result decoding across Python, Go, .NET, Node.js, Java/JDBC, and Dart.ENUMstores stable label ids plus persisted catalog label metadata so row values are not tied to mutable label strings. - Native geospatial types and spatial indexes: added
GEOMETRYandGEOGRAPHYcolumn types with EWKB-backed storage, WKB/WKT/GeoJSON conversion functions, coreST_*accessors/predicates/measurements, indexed spatial filters, distance ordering via<->, point-in-polygon spatial joins, C ABI bind/read support, and binding updates across Python, Go, .NET, Node.js, Java JNI, and Dart. - Branch, diff, restore, and time-travel workflows: added named snapshots, read-only historical execution, branch metadata, branch-local writes, branch commit/log markers, primary-key row diffs, guarded restore, constrained merge, CLI and REPL support, Rust APIs, and a C ABI JSON bridge.
- 12 proptest-based property tests for WAL delta encoding (roundtrip, no-op, size bounds, determinism, corruption rejection) and WAL frame format (page/commit/checkpoint roundtrips, header identity, invalid frame types, encoded-len consistency).
- 4 crash-recovery edge-case tests: checkpoint survival, uncommitted transaction discard, WAL growth-and-truncation cycle, and SQL-level transaction isolation.
wal_fuzzstandalone binary exercising 6 WAL-corruption strategies across 75+ DB states to verify recovery never panics.
[2.4.2] - 2026-05-04¶
Fixed¶
- Fixed shutdown-time ownership that caused the nightly memory-safety Valgrind workflow to report possible leaks after C ABI and Python open/query/close probes. In-memory database drop now runs its final checkpoint synchronously so
ddb_db_freedoes not return while a drop checkpoint thread still owns WAL and pager state. - Pruned stale weak entries from the database open-lock and OS VFS path-lock registries as handles close, avoiding process-lifetime registry allocations being reported as possible leaks by Memcheck.
- Hardened background checkpoint worker shutdown so worker-context teardown cannot attempt to join its own thread.
[2.4.1] - 2026-04-30¶
Fixed¶
- Fixed deferred paged-row UPDATE validation so all foreign-key parent tables needed by row validation are materialized, including unchanged FK columns. This resolves the DecentDB.EntityFrameworkCore regression seen by downstream apps merge workflows after upgrading to 2.4.0.
- Improved .NET EF Core modification-batch diagnostics by surfacing the native DecentDB statement error instead of replacing it with a generic
Step failedmessage. - Fixed aggregate SELECTs over joins, including Entity Framework Core
COUNT(*)join queries, so aggregate projections fall through to grouped evaluation instead of the non-aggregate join fast paths. - Fixed base-table join filtering so
WHEREpredicates are evaluated against the full join scope before projection. This resolves filtered joins whose predicate references columns not present in the final projection. - Fixed deferred DELETE dependency analysis for transitive self-referential
ON DELETE CASCADErelationships so dependency traversal terminates and loads each affected table once. - Fixed shared file-backed WAL checkpoint races that could corrupt paged table manifests or overflow payload reads during concurrent writer plus rapid open/close reader workloads. Implicit automatic, on-open, and drop-time checkpoints are now skipped for shared WAL handles until cross-handle pager-cache invalidation is coordinated; explicit checkpoints remain available.
- Fixed large WAL checkpointing so exact VFS reads and writes retry legal partial I/O results instead of treating them as fatal short reads/writes. CLI maintenance paths (
checkpoint,exec --checkpoint,import,bulk-load,save-as,vacuum, anddoctor --fix) now perform pure WAL flushes without running the optional pre-checkpoint payload compaction pass, avoiding multi-GB compaction appends during maintenance flushes. - Fixed deferred-table index freshness reporting so
rebuild-indexespersists fresh catalog metadata and subsequentlist-indexes/doctorruns do not report rebuilt indexes as stale simply because table row payloads are still lazily materialized. - Fixed PostgreSQL dump overwrite imports in the Python tools by evicting any shared WAL registry entry and removing the
.walsidecar before recreating the destination database.
[2.4.0] - 2026-04-30¶
Added¶
- Expanded .NET regression coverage with new ADO.NET and EF Core suites targeting common provider failure modes: parameter-collection shape/errors, maintenance path resolution and cleanup behavior, design-time model-factory metadata extraction, window/sql-expression translator contracts, modification-batch bind/execute fallback paths, and broad SaveChanges type-matrix binding coverage.
- Background incremental checkpoint worker (ADR 0058): auto-checkpoint work moved off the writer commit hot path onto a dedicated
decentdb-checkpointthread. Writers signal the worker via aCondvar; the worker also wakes on a periodic timeout to drain WAL even for workloads that just barely cross a threshold and then go idle. Opt-in viaDbConfig::background_checkpoint_worker(defaulttruewhen any auto-checkpoint threshold is configured). - Per-engine allocator scaffold (ADR 0142): new
crates/decentdb/src/alloc.rsintroduces a per-engine allocator forwarder defaulting to the global allocator. Provides the abstraction needed for future per-database arena/jemalloc integration without changing call sites. - Paged on-disk WAL index sidecar scaffold (ADR 0141): new
wal/index_sidecar.rsand supportingWalVersionPayloadenum (Resident/OnDisk) introduce the type machinery required to spill WAL-resident page versions to a sidecar file. Currently always-resident; spill path will be wired in a follow-up. - Storage-state memory instrumentation (ADR 0143 Phase A):
Db::inspect_storage_state_jsonnow reports four new fields —tables_in_memory_bytes,rows_in_memory_count,loaded_table_count, anddeferred_table_count— sourced from new helpersEngineRuntime::table_memory_totals,TableData::approximate_heap_bytes, andValue::approximate_heap_bytes. Enables external memory probes without parsing platform-specific RSS. - Per-commit delta payload recycler (M6) and
SmallVecWAL index (M7): writer-side commit path reuses encoded-delta scratch buffers across commits, andWalIndexnow stores per-page version chains in aSmallVecto avoid heap allocations for the common single-version case. - Linux heap-release hook (ADR 0138): opt-in
DbConfig::release_freed_after_checkpointcallsmalloc_trimon glibc Linux after a successful checkpoint to return freed arena pages to the OS. No-op on non-glibc/non-Linux targets. - New helper
Value::approximate_heap_bytes()returns a best-effort byte estimate of heap-allocated payload (Text,Blob,Json, etc.) for memory-accounting callers. - Per-table on-demand loading scaffold (ADR 0143 Phase B): New
materialize_deferred_tables_with_storenow accepts an optionalfilter: Option<&BTreeSet<String>>parameter to materialize only specified tables instead of all deferred tables. Addedload_deferred_tables_filteredfor targeted loading. Statement-target analysis viastatement_referenced_tables()extracts table names fromSELECT/INSERT/UPDATE/DELETEstatements. Targeted index rebuild viamark_indexes_stale_for_table+rebuild_stale_indexesafter per-table load. - Deferred table materialization is now the default (ADR 0143 Phase B follow-up): the per-table loader remains wired through the strict whitelist analyzer
safe_referenced_tables(crates/decentdb/src/sql/ast.rs), but the old concurrent-checkpoint race is now closed by pinning one WAL snapshot across the runtime refresh and first-use overflow payload reads. PlainSELECT/UPDATE/DELETE/INSERT … VALUESstatements whose table set is provably exhaustive load only the referenced tables; CTEs, set operations,INSERT … SELECT, FROM-subqueries/functions, view/CTE references, and any expression-level subquery (InSubquery/CompareSubquery/ScalarSubquery/Exists) still conservatively fall back toensure_all_tables_loaded. SetDbConfig::defer_table_materialization = falseto restore eager-at-open loading. - Persistent primary-key locator index (ADR 0144, soak-flagged): new
DbConfig::persistent_pk_indexpersists a row-id locator B+Tree (pk_index_root) per table so deferredWHERE id = ?reads can decode one row directly from the overflow payload instead of materializingVec<StoredRow>for the whole table. The format version is now 9, checkpoint compaction skips payloads with live locator roots, anddecentdb-migratebackfills missing roots during format-8 → format-9 upgrades. - Phase D row-source seam + streamed paged deferred scan slice (ADR 0145):
EngineRuntime.tablesnow stores aTableRowSourceabstraction instead of exposingArc<TableData>directly, the executor has aTableRowIter/ visible-row-source layer for several simple scan, join, and runtime-index read paths, and non-transaction deferred reads can now answer plainCOUNT(*), groupedCOUNT(*), paged deferredMIN/MAX, plainSELECT */alias.*sequential scans, the simplest filtered-projection queries, single-table expression projections withORDER BY/LIMIT, and the narrow grouped numeric aggregate fast path from persisted table bytes without promoting the table to residentVec<StoredRow>. The latest follow-up streams grouped-count / grouped-sum / projection fast paths chunk-by-chunk from persisted state instead of hydrating all paged chunk payloads up front; legacy deferredMIN/MAXnow deliberately falls back to the safer snapshot-pinned load path until the broader iterator path is hardened. Broader scan/aggregate migration is still follow-up work. - Phase D paged-persistence follow-up (ADR 0145): format 10 now introduces a table-level paged manifest behind
DbConfig::paged_row_storage(defaulttrue). Existing legacy tables can be backfilled into that manifest on open, dirty tables written under the flag now persist behind bounded multi-chunk paged manifests, paged tables retain deferred primary-key point lookups through chunk-aware locator roots, pure insert growth on already-paged tables appends new chunks without rewriting existing chunk payloads, update/delete persistence now rewrites only changed chunks while preserving untouched chunk pointers, checkpoint compaction now rewrites large paged chunk payloads without breaking chunk-aware locator roots, anddecentdb-migratecan copy v9 databases forward to the new format. True tombstones and fully streaming paged mutation semantics are still follow-up work. - Auto-checkpoint on open (ADR 0143): new
DbConfig::auto_checkpoint_on_open_mb(default16MB). When the on-disk WAL exceeds the threshold atDb::open, the engine performs a synchronous checkpoint immediately afterWalHandle::acquireand beforeEngineRuntime::load_from_storage. This drops the resident WAL page-version index — which can be hundreds of MB on a large uncheckpointed WAL — before the runtime is loaded, dramatically reducing post-open RSS. Validated via.tmp/decentdb_memory_reopen_probe.py: at scale 5 (~321 MB DB + ~384 MB WAL), open Δ dropped from ~775 MB to ~6 MB and peak RSS from ~1089 MB to ~662 MB. - Doctor / Advisor / Introspection v1: new
decentdb doctorcommand and Rust report model produce deterministic Markdown or JSON health reports covering header/open compatibility, storage/WAL state, fragmentation, schema/index metadata, optional logical index verification, CI-friendly--fail-onthresholds, path redaction modes, recommendation suppression, and constrained--fixactions for safe checkpoint and index-rebuild maintenance.
Fixed¶
- .NET SQL parameter rewriting for EF-style multi-row parameter names (for example
@p0_0,@p1_1,@p10_11) so provider-generated names bind correctly without false positional rewrites. - .NET prepared-command reuse now consistently resets and clears bindings after successful non-query execution, reducing native statement-retention pressure in repeated prepared insert/update workloads.
- .NET native text binding path now uses pooled/stack-based UTF-8 encoding buffers instead of per-call byte-array allocations, reducing allocation churn on high-frequency bind paths.
- WAL writer / background-checkpoint race (regression introduced by ADR 0058):
commit_pages_if_latestnow distinguishes a benign WAL-end-LSN advance caused by the background checkpoint worker (which bumpsWalShared::checkpoint_epochand may truncatewal_end_lsnto0) from a real concurrent writer commit. Previously, a long-running write transaction whose commit happened to land just after a background checkpoint truncated the WAL would spuriously fail withtransaction conflict: WAL advanced from N to 0. The OCC guard for true multi-connection writer conflicts (ADR 0023) is preserved by checking the checkpoint epoch alongside the WAL end LSN. - Active-reader checkpoint safety for deferred scans: checkpoint now retains snapshot-visible WAL versions while readers are active instead of pruning them mid-flight, and legacy deferred
SELECT MIN/MAX(...)falls back to the safer snapshot-pinned load path. This removes the remaining parallel pre-commitoverflow payload length mismatchfailure seen in the Python writer/reader interleave stress test.
Documentation¶
- New ADRs: 0058 (background incremental checkpoint worker), 0138 (Linux heap-release on checkpoint), 0141 (paged on-disk WAL index), 0142 (per-engine allocator), 0143 (on-disk row-scan executor, phased plan).
[2.3.0] - 2026-04-20¶
Added¶
- WAL group-commit mode (
WalSyncMode::AsyncCommit { interval_ms }): commits return as soon as the WAL frame is written, while a per-WAL background thread fsyncs on the configured interval. DefaultWalSyncMode::Fullis unchanged. NewDb::sync()provides an explicit durability barrier (no-op for non-AsyncCommit modes). Trades a bounded recovery window (lastinterval_msof acked commits may be lost on crash) for higher write throughput. See ADR 0135.
Added (Dart/Flutter binding)¶
- UUID bind (
UuidValue):Statement.bindAllandStatement.bindUuidacceptUuidValueand bind it via the native UUID path instead of a generic BLOB. inspectStorageState:Database.inspectStorageState()exposes WAL and cache metrics without requiring a snapshot handle.- Savepoint helpers:
Database.savepoint(),Database.releaseSavepoint(), andDatabase.rollbackToSavepoint()with atransaction()overload that wraps work in a named savepoint instead of a bare BEGIN/COMMIT. - LRU prepared-statement cache:
Database.prepare()now returns a cachedStatementkeyed by SQL (capacity configurable viastmtCacheCapacityon all factory methods, default 128).stmtCacheStats,clearStmtCache(), andonPerformanceWarningallow observability and tuning. PerformanceWarningexception class fires (at most once per database) when the statement-cache hit rate falls below 50 % after 100 prepares.- Zero-copy batch binding:
executeBatchTyped,executeBatchInt64, andexecuteBatchI64TextF64usemallocfor write-only bulk arrays instead of zero-filling withcalloc. - Single-pass
executeBatchTyped: rewrote from multi-pass type-probe to single-pass dispatch, reducing FFI call count for mixed-type bulk inserts. - Column-metadata caching:
Statement._loadColumnMetadatais called at most once per prepared statement; the result is reused across resets and rebinds (eliminates ~30k redundant FFI calls in point-read workloads). - Unmodifiable result views:
columnNamesandquery()returnUnmodifiableListViewto prevent accidental mutation. Statementfinalizer: adart:coreFinalizer<_StmtToken>callsstmtFreeon GC'd statements;dispose()detaches it to prevent double-free.isDisposedgetter onStatementfor safe cache-lookup checks.rows()streaming:Statement.rows({int pageSize = 100})returns a lazyStream<Row>backed bynextPage, suitable for large result sets.AsyncDatabaseandAsyncStatement: an isolate-backed wrapper that moves all FFI calls to a dedicated worker isolate, keeping the caller's event loop unblocked.
Fixed¶
- Made WAL page versions cheaply shareable with
Arc<[u8]>so snapshot reads stop cloning full WAL-resident page buffers on every access. - Eliminated repeated base-page materialization during WAL recovery by reusing per-page pending reconstruction state across long delta chains.
- Stopped deep-cloning read-mostly execution runtime state by Arc-sharing catalog, table, temp-table, and runtime-index maps with copy-on-write mutation.
- Eliminated cross-table COW contamination on UPDATE/DELETE/INSERT by wrapping each table's
TableDatain its ownArc, so the first write in a transaction now clones only the targeted table's row vector instead of every table's rows. Yields ~3× faster DELETE p50 (132 µs → 42 µs) and ~1.3× faster UPDATE p50 (116 µs → 87 µs) on the Pythonbench_complexworkload, with a 44× speedup on a worst-case micro-probe (mutating a small table while a large unrelated table sits in the catalog). - Extended the per-entry
Arccopy-on-write pattern to the runtime index map so the first write to an indexed column in a transaction clones only the targeted index instead of everyRuntimeIndex(BTREE keys + trigram postings) in the database. Closes a latent regression that would have appeared on workloads updating indexed columns on databases with many or large secondary indexes. - ADR 0136 (proposed): chunked row storage for finer-grained copy-on-write, targeting the remaining UPDATE-latency gap to SQLite by reducing per-transaction first-write cloning from O(rows in mutated table) to O(rows in mutated chunk).
- Avoided full dataset clones on CTE alias resolution by sharing dataset row storage and rewriting only column-binding metadata.
- Bounded the per-session cached payload map with an LRU cap from
DbConfigand Arc-shared temp schema state to avoid repeated deep clones across statements. - Documented C ABI ownership and free responsibilities for database, statement, and result handles in both the public header and Rust rustdoc.
- Fixed the Go binding BLOB bind path to satisfy cgo pointer rules by pinning Go byte slices during the native call, with a large-blob regression test and strict cgo validation guidance.
- Made Go
DB.Close()idempotent and detached finalizers on explicit close to prevent double-free races, with direct regression coverage. - Added Python statement-cache hit/miss stats, a close-time
PerformanceWarningfor low cache hit rates, and documented the new observability surface. CREATE VIEWno longer executes the SELECT body to derive output column names. A syntactic resolver walks the projection AST instead, falling back to execution only for*/tbl.*wildcards. Eliminates the cost of running large JOIN/aggregate view bodies during DDL (~94 % faster for the Dartconsole_complexview-creation step) and avoids unintended side effects of the SELECT during view definition.
[2.2.1] - 2026-04-19¶
Fixed¶
- .NET GUID/UUID parameter binding so native prepared statements, ADO.NET commands, and EF Core modification batches preserve UUID semantics instead of binding GUID values as raw blobs.
- Mixed-case identifier handling across Rust execution/runtime paths used by EF-created schemas, including raw SQL DML resolution and dirty-table persistence tracking after append-only and row-update writes.
- Planner/executor now uses the indexed equi-join fast path for
LEFT JOINon an indexed (or rowid-alias) right-side column, not onlyINNER JOIN. Previously LEFT JOINs with a valid B-tree or rowid probe fell back to an O(n·m) nested loop, causing multi-second regressions on mid-sized joined workloads. NULL-extended row semantics are preserved for non-matching left rows and for left rows whose join key is NULL.
Added¶
- Regression coverage for typed UUID binding through the C ABI plus ADO.NET and EF Core indexed GUID equality queries.
- Regression coverage for mixed-case EF-created tables remaining reachable from unquoted raw SQL after
EnsureCreated(). - Regression coverage for the indexed
LEFT JOINfast path: a scaling/perf guard (indexed_left_join_scales_linearly_not_quadratically) plus correctness tests covering NULL-extended non-matches (indexed_left_join_preserves_null_extended_rows) and multi-row right-side matches (indexed_left_join_handles_multi_match_right_side).
[2.2.0] - 2026-04-18¶
Fixed¶
- EF Core literal generation and
HasDatacoverage for provider-converted types, includingDateTime,DateTimeOffset,DateOnly,TimeOnly,TimeSpan,decimalscale normalization, and NodaTime literal mappings. - ADO.NET parameter and reader behavior for additional scalar types (
sbyte,char, unsigned integer overflow guards), with explicit fail-fast behavior where DecentDB SQL literal syntax is not yet available (BLOBHasDataliterals).
Added¶
- Expanded .NET regression coverage for literal executability contracts, comprehensive
HasDatamatrix scenarios (including nullable cases), and 4 MB BLOB round-trip verification. - ADR 0134 documenting the engine-level BLOB literal parsing gap and a proposed parser function path.
[2.1.0] - 2026-04-01¶
Fixed¶
- Decimal
MIN/MAXaggregate ordering in the Rust engine now comparesDECIMALvalues natively during aggregate-extreme evaluation, including mixed decimal scales. - EF Core decimal aggregate regression for grouped
Max(decimal)projection shapes by aligning provider behavior with native engine decimal comparison support. - .NET decimal parameter scale handling during command binding and EF modification batching so configured scale metadata is applied consistently before native decimal binding.
- Foreign key DDL validation for self-referencing and composite-key EF Core schemas so
CREATE TABLEand migration-generated constraints now validate correctly. - EF Core migration SQL generation for rename-table, rename-column, alter-column-type, and drop-index operations, plus explicit
NotSupportedExceptionsavepoint behavior instead of leaking later SQL execution errors. - Rust engine decimal comparison and
SUM/AVGaggregate paths so mixed numeric comparisons and decimal aggregates execute without the earlier EF Core showcase workarounds. - EF Core translation for
DateTime,DateOnly, andTimeOnlymember access in predicates, including nullable member-access shapes used by the showcase. - Fault-injection WAL write classification for compound page-frame plus commit-frame appends so
wal.write_commitfailpoints and crash/reopen coverage continue to target the durable publish boundary after the write-path batching optimization. - Rust table-payload append-only overflow persistence after checkpoint compaction now patches the on-disk row-count header before appending, preventing duplicate primary-key rows and the overnight memory-safety corruption failure on reopen.
Added¶
- Dedicated standalone
decentdb-migrateCLI tool to seamlessly upgrade databases from unsupported legacy format versions (e.g., Nim-era v3) to the current format. decentdb-clinow detects legacy format versions and provides a helpful message directing the user to thedecentdb-migratetool.- Exported
DB_FORMAT_VERSIONfrom the core engine to identify the target database version. - Added structured error code
DDB_ERR_UNSUPPORTED_FORMAT_VERSION(8) to the C ABI and mapped it across all language bindings (Dart, Java, Python, Go, Node.js, .NET). - Provider-specific EF Core window-function LINQ support via
EF.Functions, covering ranking functions and value window functions rendered asOVER (...)SQL. - Expanded .NET showcase coverage for temporal member predicates, composite foreign keys, and window functions so the sample now exercises the newly supported EF Core surface directly.
- Expanded .NET EF Core validation and docs for server-side set operations,
ExecuteUpdateAsync,ExecuteDeleteAsync,AsAsyncEnumerable(), and explicit constraint/savepoint failure contracts. - EF Core
UseDecentDB(DecentDBConnectionStringBuilder)overloads so typed connection-string setup can be shared directly between ADO.NET and EF Core configuration. - Lightweight .NET performance-sanity coverage and showcase guidance for projection-vs-tracked reads,
AsNoTracking, split-query includes, keyset pagination, async streaming, and bulk mutation rowcount checks. - Fast Rust regression coverage for the checkpointed append-only overflow primary-key corruption path, wired into
scripts/do-pre-commit-checks.py. - Dart binding rich schema snapshot:
Schema.getSchemaSnapshot()returns a typed model layer covering tables, views, indexes, triggers, check constraints, foreign keys, generated columns, temp-object metadata, and canonical DDL in one call. - Rust engine rich schema snapshot model (
SchemaSnapshotand related structs inmetadata.rs) with a single authoritative builder path indb.rsand deterministic name-ordered collections. - C ABI function
ddb_db_get_schema_snapshot_jsonfor one-shot schema snapshot JSON retrieval over the stable ABI. - Dart binding streaming statement refactor:
step()andnextPage()now stream from native row-view buffers without materializing the full result set in Dart.query()internally chunks at 256 rows via the streaming path. - Dart binding fast-path wrappers:
executeBatchInt64,executeBatchI64TextF64,executeBatchTyped,rebindInt64Execute,rebindTextInt64Execute,rebindInt64TextExecute,Database.evictSharedWal, and fused bind+step helpersbindInt64StepandbindInt64StepI64TextF64. - Dart binding test suite expanded with
schema_snapshot_test.dart,statement_streaming_test.dart, andfast_paths_test.dartcovering rich schema, streaming semantics, and batch/re-execute fast paths. - Dart benchmark (
bench_fetch.dart) updated to measure streamingstep()andnextPage()paths instead of the old hidden full-fetch implementation. - Regression coverage for decimal aggregate correctness:
- Rust SQL test coverage for
MIN/MAXoverDECIMAL. - EF Core query-shape coverage for grouped decimal aggregate projections.
- EF Core aggregate-shape coverage across grouped and ungrouped projections for core scalar types.
- EF Core nullable aggregate-shape coverage, including mixed-null and all-null aggregate inputs.
Changed¶
- Decent Bench (
decent-bench) now uses the rich upstream schema snapshot API instead of narrow v2 types, resolving the metadata regression from the v1-to-v2 migration. - Decent Bench native library resolver now looks for Rust v2 library names (
libdecentdb.so,libdecentdb.dylib,decentdb.dll). - Dart binding examples updated to demonstrate
executeBatchTypedfor bulk inserts instead of manual per-row bind/execute loops. - Design and binding review documentation updated to reflect the completed Dart binding v2 surface.
- Rust durable-write hot paths now avoid eager post-commit transaction-state cloning, skip redundant explicit-transaction stale-index rebuilds on prepared fast-path writes, batch WAL page frames with the commit control frame, and move owned page buffers into write-transaction staging to reduce extra copy overhead during overflow and root persistence.
[2.0.1] - 2026-03-28¶
Fixed¶
- Python binding cursor semantics:
Connection.execute(...)once again returns a fresh cursor per call instead of mutating a single shared cursor object across successive executions on the same connection. - Release automation validation for the Python binding suite and Java FFM smoke path so the GitHub release workflow matches the supported dependency/toolchain setup.
- Memory-safety nightly stress coverage to use valid SQL, fail fast on unexpected database errors, and keep the working set bounded with periodic checkpoints instead of drifting into self-inflicted I/O failures.
- Benchmark asset refresh automation on protected
mainbranches by pushing the generated asset commit toautomation/benchmark-assetsand opening/updating a PR (or surfacing a manual PR URL) instead of attempting a direct protected-branch push.
Changed¶
- Docs deployment now publishes from docs changes merged to
main, which keeps benchmark-asset refreshes compatible with pull-request-only repository rules without reintroducing the earlier double-publish path.
[2.0.0] - 2026-03-28¶
v2.0.0 marks the first release of the Rust-native DecentDB engine. The original DecentDB engine was written in Nim. For v2.0.0 the engine core was rewritten from scratch in Rust, delivering substantially improved memory safety, ACID durability guarantees, a stable C ABI (
include/decentdb.h), and a fully updated binding ecosystem (.NET, Python, Go, Java/JDBC/DBeaver, Node.js, Dart). The v1.x Nim-era releases are preserved in repository history but are no longer maintained.
Added¶
- SQL window enhancements:
NTILE,PERCENT_RANK,CUME_DIST, aggregate window functions, and frame-aware execution forROWSand supportedRANGEbounds. - Statistical and ordered-set aggregates:
ARRAY_AGG,MEDIAN,PERCENTILE_CONT ... WITHIN GROUP, andPERCENTILE_DISC ... WITHIN GROUP. - Trigonometric math functions:
SIN,COS,TAN,ASIN,ACOS,ATAN,ATAN2,PI,DEGREES,RADIANS, andCOT. - Conditional scalar functions:
GREATEST,LEAST, andIIF. - DML enhancements:
UPDATE ... RETURNING,DELETE ... RETURNING, andTRUNCATE TABLEwithRESTART IDENTITY,CONTINUE IDENTITY, andCASCADE. - Subquery comparison operators:
expr op ANY/SOME (subquery)andexpr op ALL (subquery). - Regex comparison operators:
~,~*,!~,!~*. - Extended date/time functions:
DATE_TRUNC,DATE_PART,DATE_DIFF,LAST_DAY,NEXT_DAY,MAKE_DATE,MAKE_TIMESTAMP,TO_TIMESTAMP,AGE, and timestampINTERVALarithmetic. - Extended string functions:
CONCAT,CONCAT_WS,POSITION,INITCAP,ASCII,REGEXP_REPLACE,SPLIT_PART,STRING_TO_ARRAY,QUOTE_IDENT,QUOTE_LITERAL,MD5, andSHA256. - Query features slice (S9): standalone
VALUESquery bodies,VALUEStable sources with alias column naming,CREATE TABLE ... AS SELECT(includingWITH NO DATAandIF NOT EXISTS), row-valueIN (VALUES ...), andLATERALsubqueries/table-function joins. - DDL enhancements slice (S11):
ALTER TABLE ... RENAME TO ...andALTER TABLE ADD/DROP CONSTRAINTfor namedCHECK, namedFOREIGN KEY, and namedUNIQUEconstraints with existing-row validation. - Utility commands slice (S12): SQL-level
PRAGMAsupport forpage_size,cache_size,integrity_check,database_list, andtable_info(table)with read/query behavior and constrained assignment semantics. - DDL enhancements slice (S11) completion:
GENERATED ALWAYS AS (...) VIRTUALcolumns with parser support, read-time computation semantics, persistence metadata support, andtable_ddlrendering ofVIRTUALvsSTORED. - S13 increment: covering index syntax
CREATE INDEX ... INCLUDE (...)for BTREE key-column indexes, including parser normalization, catalog persistence, metadata APIs, and SQL dump rendering. - S13 increment:
CREATE SCHEMAwith catalog namespace registration,IF NOT EXISTSsemantics, and persistence across restart/checkpoint.
Changed¶
- Refreshed repository documentation to present DecentDB as the current Rust engine and binding ecosystem.
- Clarified release/versioning docs around the current public
v2.xrelease line.