Changelog
All notable changes to quack-rs, mirrored from
CHANGELOG.md.
The format follows Keep a Changelog. quack-rs adheres to Semantic Versioning.
Unreleased
[0.8.0] — 2026-03-28
Added
LogicalType::from_raw(ptr)— construct from raw handle- Complex type constructors —
decimal,array,array_from_logical,union_type,union_type_from_logical,enum_type _from_logicalvariants —struct_type_from_logical,list_from_logical,map_from_logicalfor nested complex types- 20 introspection methods on
LogicalType—get_type_id,get_alias,set_alias, decimal/enum/list/map/struct/union/array child access TypeId::from_duckdb_type()— reverse conversion from raw C enumextra_infoonScalarFunctionBuilder,ScalarOverloadBuilder,AggregateFunctionBuilderparam_logical/named_param_logicalonTableFunctionBuilderCastFunctionBuilder::new_logical()for complex source/target types- Callback info wrappers —
ScalarFunctionInfo,ScalarBindInfo(duckdb-1-5),ScalarInitInfo(duckdb-1-5),AggregateFunctionInfo,CopyBindInfo(duckdb-1-5),CopyGlobalInitInfo(duckdb-1-5),CopySinkInfo(duckdb-1-5),CopyFinalizeInfo(duckdb-1-5) get_client_context()on all callback info typesBindInfo—get_parameter,get_named_parameter,get_extra_info,get_client_contextInitInfo/FunctionInfo—get_extra_infoArrayVectorhelper withget_child()vector_size()andvector_get_column_type()utilities- Prelude —
StructVector,ListVector,MapVector,ArrayVector,ScalarFunctionInfo,AggregateFunctionInfo
Changed
- Breaking:
CastFunctionBuilder::source()/target()returnOption<TypeId>(wasTypeId) - Breaking:
CastRecord::source/targetfields changed toOption<TypeId>
0.7.1 — 2026-03-27
Added
TypeId::Any— wildcard type for function overload resolution (duckdb-1-5)TypeId::Varint— variable-length arbitrary-precision integer (duckdb-1-5)TypeId::SqlNull— explicit SQL NULL type for bareNULLliterals (duckdb-1-5)TypeId::IntegerLiteral— integer literal type for overload resolution (duckdb-1-5)TypeId::StringLiteral— string literal type for overload resolution (duckdb-1-5)MockVectorReader/MockVectorWritertests — 12 new tests for untested constructors and getters- DuckDB v1.5.1 evaluation — see
docs/duckdb-v1.5.1-evaluation.md
Fixed
- ARM64 / aarch64 build — use
c_charinstead ofi8for cross-platform pointer casts
Changed
- DuckDB v1.5.1 compatibility — documentation updated to explicitly cover
v1.5.1. C API version unchanged (
v1.2.0). Recommend upgrading DuckDB runtime for WAL corruption and ART index fixes.
0.7.0 — 2026-03-22
Added
-
duckdb-1-5feature modules — theduckdb-1-5feature flag is no longer a placeholder. When enabled, it gates five new modules wrapping DuckDB 1.5.0 C Extension API additions:catalog— catalog entry lookup (CatalogEntry,Catalog,CatalogEntryType)client_context— client context access (ClientContext) for retrieving catalogs, config options, and connection IDs from within registered function callbacksconfig_option— extension-defined configuration options (ConfigOptionBuilder,ConfigOptionScope) registered viaSET/RESET/current_setting()copy_function— customCOPY TOhandlers (CopyFunctionBuilder) with bind → global init → sink → finalize lifecycletable_description— table metadata queries (TableDescription) for column count, names, and logical types
-
TypeId::TimeNs— newTIME_NScolumn type variant for nanosecond- precision time of day (DuckDB 1.5.0+, requiresduckdb-1-5feature) -
ScalarFunctionBuilder::varargs()/varargs_logical()— mark a scalar function as accepting variadic arguments (requiresduckdb-1-5) -
ScalarFunctionBuilder::volatile()— mark a scalar function as volatile (re-evaluated for every row even with constant arguments, requiresduckdb-1-5) -
ScalarFunctionBuilder::bind()— set a bind callback invoked once during query planning for per-query state allocation (requiresduckdb-1-5) -
ScalarFunctionBuilder::init()— set an init callback invoked once per thread for per-thread local state allocation (requiresduckdb-1-5)
Changed
-
DuckDB 1.5.0 support — upgraded default
libduckdb-sysfrom 1.4.4 to 1.10500.0 (DuckDB 1.5.0) andduckdbfrom 1.4.4 to 1.10500.0. The version range">=1.4.4, <2"inCargo.tomlis unchanged, preserving backward compatibility with DuckDB 1.4.x. -
CI action updates —
Swatinem/rust-cachev2.8.2→v2.9.1,actions/download-artifactv8.0.0→v8.0.1,actions/cache5.0.3→5.0.4,codecov/codecov-action5.4.3→5.5.3.
Fixed
- COPY format handlers — previously listed as a known limitation (no C API
counterpart). DuckDB 1.5.0 adds
duckdb_create_copy_functionand related symbols; the newcopy_functionmodule wraps them behindduckdb-1-5.
0.6.0 — 2026-03-12
Added
-
InMemoryDbdispatch table initialisation —InMemoryDb::open()now correctly initialises theloadable-extensiondispatch table from bundled DuckDB symbols before opening a connection. Previously, every call panicked with"DuckDB API not initialized"when thebundled-testfeature was enabled incargo test. See Pitfall P9 for the full technical analysis. -
src/testing/bundled_api_init.cpp— thin C++ shim exposing DuckDB's internalCreateAPIv1()as a C-linkage symbol, compiled at build time via thecccrate. Populates all 459AtomicPtrdispatch table slots with real bundled DuckDB function pointers. -
build.rs— Cargo build script that locates thelibduckdb-sysinclude path and compiles the C++ shim when thebundled-testfeature is active. -
CI:
test-bundledjob — new CI job runscargo test --all-targets --features bundled-teston Linux, macOS, and Windows on every PR, closing the gap that allowed this failure to reach the release workflow undetected. -
Pitfall P9 documented — full analysis in
LESSONS.mdand the Pitfall Catalog: root cause,CreateAPIv1()solution, ABI compatibility details, risks of the internal C++ API, and a mitigation table.
Fixed
InMemoryDb::open()no longer panics undercargo test --features bundled-test. This was broken from the initial 0.5.1 release.
Changed
bundled-testfeature documentation updated to describe dispatch table initialisation accurately.
0.5.1 — 2026-03-12
Added
-
Testing primitives (
quack_rs::testing) —MockVectorWriter,MockVectorReader,MockDuckValue,MockRegistrar,CastRecord. -
bundled-testCargo feature — enablesInMemoryDbfor SQL-level assertions incargo test. (Note:InMemoryDb::open()was broken in this release and fixed in 0.6.0.) -
InMemoryDb— wrapsduckdb::Connectionfor SQL-level integration tests; available behind thebundled-testfeature. -
Builder introspection accessors —
name()on all function builders;source()/target()onCastFunctionBuilder.
Security
- Bump
quinn-proto0.11.13 → 0.11.14 (addresses RUSTSEC advisory).
0.5.0 — 2026-03-10
Added
-
param_logical(LogicalType)on all builders — register parameters with complex parameterized types (LIST(BIGINT),MAP(VARCHAR, INTEGER),STRUCT(...)) thatTypeIdalone cannot express. Available onAggregateFunctionBuilder,AggregateFunctionSetBuilder::OverloadBuilder,ScalarFunctionBuilder, andScalarOverloadBuilder. Parameters added viaparam()andparam_logical()are interleaved by position, so the order you call them is the order DuckDB sees them. -
returns_logical(LogicalType)on all builders — set a complex parameterized return type. When bothreturns(TypeId)andreturns_logical(LogicalType)are called, the logical type takes precedence. Available onAggregateFunctionBuilder,AggregateFunctionSetBuilder,ScalarFunctionBuilder, andScalarOverloadBuilder. This eliminates the need for raw FFI when returningLIST(BOOLEAN),LIST(TIMESTAMP),MAP(K, V), or any other parameterized type. -
null_handling(NullHandling)on set overload builders — per-overload NULL handling configuration forAggregateFunctionSetBuilder::OverloadBuilderandScalarOverloadBuilder. Previously only available on single-function builders.
Notes
- Upstream fix:
duckdb-loadable-macrospanic-at-FFI-boundary — the safe entry-point pattern developed inquack-rs(using?/ok_or_elsethroughout instead of.unwrap()) was contributed upstream as duckdb/duckdb-rs#696 and merged 2026-03-09. All users of theduckdb_entrypoint_c_api!macro fromduckdb-loadable-macroswill receive this fix in the nextduckdb-rsrelease.quack-rsusers have always been protected via the safeentry_point!/entry_point_v2!macros provided by this crate.
0.4.0 — 2026-03-09
Added
-
ConnectionandRegistrartrait — version-agnostic extension registration facade.Connectionwraps theduckdb_connectionandduckdb_databasehandles provided at initialization time. TheRegistrartrait provides uniform methods for registering all extension components (scalar, scalar set, aggregate, aggregate set, table, SQL macro, cast), making registration code interchangeable across DuckDB 1.4.x and 1.5.x. -
init_extension_v2— new entry point helper that passes&Connectionto the registration callback instead of a rawduckdb_connection. Prefer this overinit_extensionfor new extensions. -
entry_point_v2!macro — companion macro toentry_point!that generates the#[no_mangle] unsafe extern "C"entry point usinginit_extension_v2. -
duckdb-1-5cargo feature — placeholder feature flag for DuckDB 1.5.0-specific C API wrappers. Currently empty; will be populated whenlibduckdb-sys1.5.0 is published on crates.io.
Changed
- DuckDB version support broadened to 1.4.x and 1.5.x — the
libduckdb-sysdependency requirement was relaxed from an exact pin (=1.4.4) to a range (>=1.4.4, <2). DuckDB v1.5.0 does not change the C API version string (v1.2.0); the existingDUCKDB_API_VERSIONconstant remains correct for both releases. Extension authors can pin their ownlibduckdb-systo either=1.4.4or=1.5.0and resolve cleanly againstquack-rs. The scaffold template and CI workflow template were updated to default to DuckDB v1.5.0.
0.3.0 — 2026-03-08
Added
-
TableFunctionBuilder— type-safe builder for registering DuckDB table functions (SELECT * FROM my_function(args)). Covers the full bind/init/scan lifecycle with ergonomic callbacks;BindInfo,FfiBindData<T>, andFfiInitData<T>eliminate all raw pointer manipulation. Verified end-to-end against DuckDB 1.4.4. See Table Functions. -
ReplacementScanBuilder— builder for registering DuckDB replacement scans (SELECT * FROM 'file.xyz'patterns). 4-method chain handles callback registration, path extraction, and bind-info population. See Replacement Scans. -
StructVector,ListVector,MapVector— safe wrappers for reading and writing nested-type vectors. Eliminate manual offset arithmetic and raw pointer casts over child vector handles. Re-exported fromquack_rs::vector::complex. See Complex Types. -
CastFunctionBuilder— type-safe builder for registering custom type cast functions. Covers explicitCAST(x AS T)and implicit coercions (optionalimplicit_cost).CastFunctionInfoexposescast_mode(),set_error(), andset_row_error()inside callbacks for correctTRY_CAST/CASTerror handling. See Cast Functions. -
DbConfig— RAII wrapper forduckdb_config. Builder-style.set(name, value)?chain with automaticduckdb_destroy_configon drop andflag_count()/get_flag(index)for enumerating all available options. Seequack_rs::config. -
ScalarFunctionSetBuilder— builder for registering scalar function overload sets, mirroringAggregateFunctionSetBuilder. -
NullHandlingenum and.null_handling()builder method — configurable NULL propagation for scalar and aggregate functions. -
TypeIdvariants —Decimal,Struct,Map,UHugeInt,TimeTz,TimestampS,TimestampMs,TimestampNs,Array,Enum,Union,Bit. -
From<TypeId> for LogicalType— idiomatic conversion fromTypeId. -
#[must_use]on builder structs — compile-time warning if a builder is constructed but never consumed. -
VectorWriter::write_interval— writes INTERVAL values to output vectors. -
append_metadatabinary — native Rust replacement for the Python metadata script. Install withcargo install quack-rs --bin append_metadata. -
hello-extcast demo — the example extension now registersCAST(VARCHAR AS INTEGER)andTRY_CAST(VARCHAR AS INTEGER)usingCastFunctionBuilder, demonstrating both error modes with five unit tests. -
preludeadditions —TableFunctionBuilder,BindInfo,FfiBindData,FfiInitData,ReplacementScanBuilder,StructVector,ListVector,MapVector,CastFunctionBuilder,CastFunctionInfo,CastModeadded toquack_rs::prelude.
Not implemented (upstream C API gap)
- Window functions and COPY format handlers are absent from DuckDB's public C extension API and cannot be wrapped. See Known Limitations.
Fixed
hello-extgs_bindcallback — replaced incorrectduckdb_value_int64(param)withduckdb_get_int64(param). All 11 live SQL tests now pass against DuckDB 1.4.4.
Changed
- Bump
criteriondev-dependency from0.5to0.8. - Bump
Swatinem/rust-cacheGitHub Action fromv2.7.5tov2.8.2. - Bump
dtolnay/rust-toolchainCI pin fromv2.7.5to latest SHA. - Bump
actions/attest-build-provenancefromv2tov4. - Bump
actions/configure-pagesto latest SHA (d5606572…). - Bump
actions/upload-pages-artifactfromv3.0.1tov4.0.0.
0.2.0 — 2026-03-07
Added
-
validate::description_ymlmodule — parse and validate a completedescription.ymlmetadata file end-to-end. Includes:DescriptionYmlstruct — structured representation of all required and optional fieldsparse_description_yml(content: &str)— parse and validate in one stepvalidate_description_yml_str(content: &str)— pass/fail validationvalidate_rust_extension(desc: &DescriptionYml)— enforce Rust-specific fields (language: Rust,build: cargo,requires_toolchainsincludesrust)- 25+ unit tests covering all required fields, optional fields, error paths, and edge cases
-
preludemodule — ergonomic glob-import for the most commonly used items.use quack_rs::prelude::*;brings in all builder types, state traits, vector helpers, types, error handling, and the API version constant. Reduces boilerplate for extension authors. -
Scaffold:
extension_config.cmakegeneration — the scaffold generator now producesextension_config.cmake, which is referenced by theEXT_CONFIGvariable in the Makefile and required byextension-ci-toolsfor CI integration. -
Scaffold: SQLLogicTest skeleton —
generate_scaffoldnow producestest/sql/{name}.test, a ready-to-fill SQLLogicTest file withrequiredirective, format comments, and example query/result blocks. E2E tests are required for community extension submission (Pitfall P3). -
Scaffold: GitHub Actions CI workflow —
generate_scaffoldnow produces.github/workflows/extension-ci.yml, a complete cross-platform CI workflow that builds and tests the extension on Linux, macOS, and Windows against a real DuckDB binary. -
validate::validate_excluded_platforms_str— validates theexcluded_platformsfield fromdescription.ymlas a semicolon-delimited string (e.g.,"wasm_mvp;wasm_eh;wasm_threads"). Splits on;and validates each token. An empty string is valid (no exclusions). -
validate::validate_excluded_platforms— re-exported at thevalidatemodule level (previously only accessible asvalidate::platform::validate_excluded_platforms). -
validate::semver::classify_extension_version— returnsExtensionStability(Unstable/PreRelease/Stable) classifying the tier a version falls into. -
validate::semver::ExtensionStability— enum for DuckDB extension version stability tiers (Unstable,PreRelease,Stable) withDisplayimplementation. -
scalarmodule —ScalarFunctionBuilderfor registering scalar functions with the DuckDB C Extension API. Includestry_newwith name validation,param,returns,functionsetters, andregister. Full unit tests included. -
entry_point!macro — generates the required#[no_mangle] extern "C"entry point with zero boilerplate from an identifier and registration closure. -
VectorWriter::write_varchar— writes VARCHAR string values to output vectors usingduckdb_vector_assign_string_element_len(handles both inline and pointer formats). -
VectorWriter::write_bool— writes BOOLEAN values as a single byte. -
VectorWriter::write_u16— writes USMALLINT values. -
VectorWriter::write_i16— writes SMALLINT values. -
VectorReader::read_interval— reads INTERVAL values from input vectors via the correct 16-byte layout helper. -
CI: Windows testing — the CI matrix now includes
windows-latestin thetestjob, covering all three major platforms (Linux, macOS, Windows). -
CI:
example-checkjob — CI now checks, lints, and testsexamples/hello-extas part of every PR, ensuring the example extension always compiles and its tests pass. -
validate::validate_release_profile— checks Cargo release profile settings for loadable-extension correctness. Validatespanic,lto,opt-level, andcodegen-units.
Fixed
- MSRV documentation now consistently states 1.84.1 across
README.md,CONTRIBUTING.md, andCargo.toml(previouslyREADME.mdstated 1.80).
0.1.0 — 2025-05-01
Added
- Initial release
entry_pointmodule:init_extensionhelper for correct extension initializationaggregatemodule:AggregateFunctionBuilder,AggregateFunctionSetBuilderaggregate::statemodule:AggregateStatetrait,FfiState<T>wrapperaggregate::callbacksmodule: type aliases for all 6 aggregate callback signaturesvectormodule:VectorReader,VectorWriter,ValidityBitmap,DuckStringViewtypesmodule:TypeIdenum (33 variants),LogicalTypeRAII wrapperintervalmodule:DuckInterval,interval_to_micros,read_interval_aterrormodule:ExtensionError,ExtResult<T>testingmodule:AggregateTestHarness<S>for pure-Rust aggregate testingscaffoldmodule:generate_scaffoldfor generating complete extension projectssql_macromodule:SqlMacrofor registering SQL macros without FFI callbacks- Complete
hello-extexample extension - Documentation of all 15 DuckDB Rust FFI pitfalls (
LESSONS.md) - CI pipeline: check, test, clippy, fmt, doc, msrv, bench-compile
SECURITY.mdvulnerability disclosure policy