The stabilization release
Ducklink v5.0.0 commits the SQL surface, discovery views, catalog schema, and duckdb:extension@4.0.0 WIT contract as stable through v5.x. Anything you build against a name listed in STABILITY.md is guaranteed to keep working for the life of this MAJOR series.
The design churn that shaped this surface is over. Notebooks, dashboards, pipelines, and other extensions can now depend on ducklink without churning underneath.
Breaking changes since v4.6
- Advanced tier removed. Parser extensions, general optimizer rules, and streaming table-function filter pushdown are gone from every ducklink build. They bound DuckDB's internal C++ ABI, which is not stable across DuckDB releases and could not ship uniformly on Linux / macOS / Windows. Ducklink is now C-API-only on every platform.
- SQL statement forms removed.
DUCKLINK LOAD 'name'→FROM ducklink_load('name', kind => 'wasm'|'native').DUCKLINK PREFIX c: crypto→FROM ducklink_prefix('c', 'crypto')(or the scalar /PREFIX(...)macro shapes).c:hash(x)colon syntax → standard SQLc.hash(x). - Seven catalog entries stripped whose
requires:listed capabilities no host can now satisfy:ggsql,dplyr,prql_parser,sqlitewasm,rtreefns,hnswfns,autocomplete. Catalog is now 193 entries, all compatible on every host. Seedocs/extension-scope.mdfor why the parser-tier extensions in particular don't belong as extensions.
What's new
- Delegating aggregate wrapper. Community-native aggregate aliases now propagate every modifier transparently:
DISTINCT,FILTER (WHERE ...),GROUP BY,OVER (...)window frames of every shape (ROWS/RANGE,PRECEDING/FOLLOWING/CURRENT ROW/UNBOUNDED,EXCLUDE CURRENT ROW/GROUP/TIES), andORDER BYinside the aggregate call. Registered as a real C-APIAggregateFunctionthat delegates to the target via a nested SQL query on a sibling connection. - Three call shapes for
ducklink_prefix. Table function (FROM ducklink_prefix(...)), scalar (SELECT ducklink_prefix(...)), and the shorterPREFIX(alias, namespace)macro. All three share one implementation body — see the "one implementation, N surfaces" invariant in STABILITY.md. - Position docs.
docs/extension-scope.mdstates the principle that extensions compose in the SQL grammar rather than replacing it.docs/visualize-design.mdanddocs/vegalite-plan.mdstake out the ducklink take on visualization (spec emission, not rendering).
Deprecated for removal at next MAJOR
The runtime's parser / optimizer / table-stream WIT interfaces and their worlds stay in the shipping duckdb:extension@4.0.0 contract for backward compatibility with components built against v4.x. They are silent no-ops today; scheduled for removal at the next WIT major bump, at which point ducklink will bump to v6.0.0.
Fixed
Bugs surfaced by the delegating-aggregate stress test:
finalizenow honours itsoffsetparameter so window aggregates split across multiple finalize calls write to the right output slots.- NULL results from the target aggregate (e.g.
sumof an all-null column, empty frames afterEXCLUDE CURRENT ROW) write NULL instead of erroring on a null → i64 coercion. updatedetects DuckDB's shared-state C-API dispatch (sorted-aggregate + full-partitionROWS UNBOUNDED..UNBOUNDEDpaths hand us one initialised state at slot 0 and NULL at slot 1 as a sentinel; probing slots 1..N used to crash on unmapped pages).combineis non-destructive so DuckDB's segment-tree windowing can visit the same source multiple times.- Constant-column degenerate path in
build_delegation_sqlemitsn_rowssynthetic rows so a running frame with repeated values returns the correct sum instead of a single-row aggregate.
Full changelog
https://github.com/tegmentum/ducklink-extension/blob/v5.0.0/CHANGELOG.md