Repository navigation
docs: sync results-cache invalidation, Arrow on_conflict, SQLite null keys, query nesting limit, and v2.4 per-dataset cdc_prefetch_buffer - #2454
Merged
Conversation
added 2 commits
October 28, 2026 14:53
… keys, query nesting limit, and v2.4 per-dataset cdc_prefetch_buffer Documents spiceai/spiceai#15698, #15623, #15494, #15722, and #15439.
….4.x view and catalog note
Contributor
✅ Pull with Spice PassedPassing checks:
|
Contributor
🔍 Pull with Spice FailedPassing checks:
Failed checks:
Please address these issues and update your pull request. |
Contributor
There was a problem hiding this comment.
🟢 Approved
No active review issues are reported for this documentation-only update.
No open issues 🎉
What changed in this PR
This documentation-only PR aligns the Spice reference pages with vNext runtime behavior and clarifies differences in v2.4.x.
Changes:
- Documents results-cache invalidation after definition changes and the deprecated
xxh32setting’s use of XXH64. - Corrects Arrow index and conflict-resolution support, documents null primary-key rejection, and clarifies the v2.4.0 CDC buffer limitation.
- Adds the 64-level query nesting limit and links it from related SQL reference pages.
| File | Description |
|---|---|
website/versioned_docs/version-2.4.x/reference/spicepod/views.md |
Corrects Arrow index, primary-key, and conflict-resolution support for views. |
website/versioned_docs/version-2.4.x/reference/spicepod/datasets.md |
Corrects Arrow index, primary-key, and conflict-resolution support for datasets. |
website/versioned_docs/version-2.4.x/features/cdc/index.md |
Documents the ineffective per-dataset buffer setting and instance-wide workaround. |
website/docs/reference/sql/subqueries.md |
Documents query nesting limits, boundaries, and errors. |
website/docs/reference/sql/select.md |
Links CTE nesting behavior to the query depth limit. |
website/docs/reference/sql/operators.md |
Distinguishes query nesting limits from expression depth limits. |
website/docs/reference/spicepod/views.md |
Documents vNext Arrow indexing and conflict-resolution constraints for views. |
website/docs/reference/spicepod/datasets.md |
Documents vNext Arrow indexing and conflict-resolution constraints for datasets. |
website/docs/features/data-acceleration/constraints.md |
Explains DuckDB and SQLite null primary-key rejection and SQLite NaN handling. |
website/docs/features/caching/index.md |
Explains definition-change invalidation, earlier-version behavior, and XXH64 key hashing. |
Review effort: Balanced
Contributor
|
🚀 deployed to https://f96b3a25.spiceai-org-website.pages.dev |
lukekim
approved these changes
Oct 28, 2026
This branch was successfully deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Results cache: view, catalog, and function changes clear cached results;
xxh32keys use XXH64 (spiceai/spiceai#15698, vNext). The caching page said SQL results are invalidated "only by client writes, dataset reload, and dataset unload", which is no longer true on trunk. A new "Cached Results and Definition Changes" section lists the changes that now clear every cached SQL result with the plan cache (view update or removal, catalog replacement on hot reload, function set change), states that a query started before the clear does not store its result, and notes the v2.4.x behavior. Thexxh32bullet, marked deprecated by a22646a, now also saysxxh32builds keys with XXH64.reference/spicepod/runtime.mdcarries the same bullet but is left alone because open PR #2450 edits that file.The v2.4.x note ends with the stale-while-revalidate bound: a stale result stays servable until
item_ttl + stale_while_revalidate_ttlwhen SWR is set, per v2.4.0crates/cache/src/lib.rs:865let max_servable_age = ttl.saturating_add(stale_while_revalidate_ttl.unwrap_or_default());.Arrow acceleration
on_conflict,primary_key, andindexes(spiceai/spiceai#15623, vNext + 2.4.x).datasets.mdandviews.mdsaidon_conflict,primary_key, andindexesare "Not supported for in-memory Arrow acceleration engine". Arrow builds a primary key and indexes as a hash index (v2.4.0 and trunk), so theprimary_keyandindexessentences now say that and link the Hash Index page. Theon_conflictsentence is per version. vNext: the target must be the primary key, every strategy works, and theupsert_dedupoptions refuse a table with a__row_numor__max_row_numcolumn. 2.4.x: onlyupserttakes effect,dropis ignored with a warning, and the two dedup strategies act as plainupsert, so a write that repeats a key fails withPrimary key values must be unique.SQLite and DuckDB reject null primary keys (spiceai/spiceai#15494, vNext). The "Primary key columns must be non-null" section described only Cayenne. It now says DuckDB and SQLite reject a write with a null in a primary key column before it reaches the engine, that SQLite treats a
NaNkey as null, and that SQLite stored null-key rows in v2.4.x.Query nesting depth limit (spiceai/spiceai#15722, vNext). Extends #2441, which documented the 512-level expression limit. A new "Nesting depth limit" section on the Subqueries page documents the fixed 64-level query nesting limit (subqueries, derived tables, and CTEs that read one another), the 63/64 CTE-chain boundary,
EXPLAINcoverage, the HTTP 400 /InvalidArgumentresult, and the exact error text. TheWITHclause on the SELECT page and the expression-limit paragraph inoperators.mdlink to it.Per-dataset
cdc_prefetch_bufferhas no effect in v2.4.0 (spiceai/spiceai#15439, 2.4.x only). The 2.4.x CDC page offeredcdc_prefetch_bufferas a per-dataset override, with an example comment "buffers more aggressively". In v2.4.0 both change-queue constructions read the process-wide value, so the per-dataset value does nothing. The 2.4.x example drops that line, and a note gives the effective source of the value, the gauge that reports it, and the workaround. vNext already describes the fixed behavior and is unchanged.Source PRs
81e84176, not in v2.4.0)2fe516b4, not in v2.4.0)cb6b80d2, not in v2.4.0)e7f5cb7f, not in v2.4.0)cf5f1d97, not in v2.4.0)Propagation was checked with
gh api repos/spiceai/spiceai/compare/v2.4.0...<merge-sha> --jq .status. Each returneddiverged, so none of the merge commits is in v2.4.0 (released 2026-10-27).Items
Reproduction
1. Results cache invalidation (#15698), Unverified, code inspection only
Doc said (vNext
features/caching/index.md): "SQL results are invalidated only by client writes, dataset reload, and dataset unload; an accelerated refresh leaves them to expire by age."Code says (spiceai trunk
eb5d4cb8):crates/runtime/src/init/view.rs:916remove_viewcallsself.df.clear_cached_plans_and_results().await;.update_view(:921) andreplace_view(:768) both callremove_view.crates/runtime/src/init/catalog.rs:282:if replaced_a_catalog { self.df.clear_cached_plans_and_results().await; }crates/runtime/src/datafusion/udf.rs:450:runtime.df.clear_cached_plans_and_results().await;crates/cache/src/lib.rs:1143invalidate_allcallsself.table_changes.record_change_everywhere(...)beforeself.cache.invalidate_all().crates/cache/src/lib.rs:442:HashingAlgorithm::XXH32 | HashingAlgorithm::XXH64 => Ok(HashBuilder::XxHash64(...))view.rs:798andcatalog.rs:282call onlyclear_cached_plans().Behavior claim: after a view is updated, a repeated query returns the new definition's result, and after the view is removed the query fails. This comes from the PR's integration test
results_cache_follows_a_redefined_or_removed_viewand itsspicedrun. I did not run either.2. Arrow
on_conflict/primary_key/indexes(#15623), Unverified, code inspection onlyDoc said (vNext and 2.4.x
reference/spicepod/datasets.md,views.md): "Not supported for in-memory Arrow acceleration engine." This appeared underindexes,primary_key, andon_conflict.Code says:
crates/data_components/src/arrow/write.rs:161-170:with_on_conflictacceptsOnConflict::Upsert(_) | OnConflict::DoNothing(_).:182addswith_upsert_options.:251-269:verify_on_conflict_matches_primary_keyreturns "Primary key columns must match the on_conflict definition".:740-750returnsDataFusionError::Plan("on_conflict upsert options cannot be used on a table with a column named ...")forDEDUP_WORKING_COLUMNS = ["__row_num", "__max_row_num"], and that check runs only after duplicates are found.crates/data_components/src/arrow.rs:233,269:.with_upsert_options(upsert_options_from(&cmd.options)?).arrow/write.rs:153-160:if !matches!(on_conflict, OnConflict::Upsert(_)) { warn!("In-memory tables only support Upsert on_conflict ... Setting will be ignored.") }. v2.4.0arrow.rsnever readsupsert_remove_duplicates/upsert_last_write_wins.write.rs:715-755returns"Primary key values must be unique".arrow.rs:147-207: the primary key andindexesbuild anIndexedMemTable(hash index) when the runtime setshash_index, which it does "when a primary_key or secondary indexes are specified".Behavior claim: the PR's before/after
spicedruns show Arrow matching DuckDB on all six cases after the fix. I did not run them.3. SQLite/DuckDB null primary keys (#15494), Unverified, code inspection only
Doc said (vNext
features/data-acceleration/constraints.md): only Cayenne was described as rejecting null primary keys.Code says (trunk):
crates/data-accelerator-api/src/pk_write_guard.rs: the module doc says it "Rejects a NULL primary key, and a key a single batch repeats, before the write reachesDuckDBorSQLite", and "SQLitestores a bound NaN as NULL, so underNanKey::Nulla NaN key is refused the same way."null_primary_key_message(:186) producesPrimary key column '<c>' has null values. ....crates/accelerators/accelerator-sqlite/src/lib.rs:647-652wraps the writer withkeep_first::NanKey::Null.accelerator-duckdb/src/lib.rs:1743-1748wraps it withNanKey::Value.accelerator-sqlite/src/lib.rshas 0 occurrences ofpk_write_guard.Behavior claim: SQLite rejects a null key. The PR's live script shows
[{"count":1}]on trunk before the fix and rejection after. I did not run it.4. Query nesting depth limit (#15722), Unverified, code inspection only
This is an addition. No existing sentence covered it.
Code says (trunk
crates/runtime-query-engine/src/sql_depth_guard.rs)::103pub const MAX_QUERY_NESTING_DEPTH: usize = 64;:236if depth > MAX_QUERY_NESTING_DEPTH { return self.reject(too_deep_query_error()); }:375-380gives the message text quoted on the page.cte_chain_is_bounded_at_the_query_cap:cte_chain(63)passes andcte_chain(64)is rejected, including underEXPLAIN.The HTTP 400 /
InvalidArgumentmapping is the sameDataFusionError::Planpath as the 512-level expression limit that #2441 documented. The PR'sspicedrun reports HTTP 400 for a 64-step chain. I did not run it.5. v2.4.0 per-dataset
cdc_prefetch_buffer(#15439), Unverified, code inspection onlyDoc said (2.4.x
features/cdc/index.md):cdc_prefetch_buffercan be overridden per dataset, with the examplecdc_prefetch_buffer: 1024 # ...and buffers more aggressively.Code says (v2.4.0):
crates/runtime-table/src/accelerated/mod.rs:1121:let capacity = refresh_task::changes::cdc_config().prefetch_buffer;refresh_task.rs:739:changes::cdc_config().prefetch_buffer,. Both are process-wide..prefetch_bufferexists inchanges.rs, apart from the overlay and tests.crates/runtime-metrics/src/acceleration.rs:406: gaugedataset_acceleration_cdc_prefetch_buffer_capacity.dataset_cdc_config(self.cdc_param_overrides.as_deref()).Behavior claim: in v2.4.0 the per-dataset value does not change the queue capacity. The PR's tests on its parent commit fail with
left: Some(128.0), right: Some(1024.0). I did not run them on v2.4.0.Verification
Style grep on added lines (the brief's pattern): no matches (exit 1).
Code refs: spiceai trunk
eb5d4cb8fbd19b7e665b64e326031f8d536de5edand tagv2.4.0, read withgh api repos/spiceai/spiceai/contents/<path>?ref=<ref>.Checks:
cd website && npm run buildat8f735a15:[SUCCESS] Generated static files in "build"., exit 0, no broken links or anchorsspicedreproduction: not run. Every item is labeled Unverified, code inspection only.Review gate
codex— jobreview-mvsnwhmw-5nv05h— verdict approve, no findings on8f735a15. The first pass (jobreview-mvsnnstc-4v57k3, onec47f6f4) raised 1 medium finding, that the v2.4.x note bounded stale results byitem_ttlalone; fixed in8f735a15with thestale_while_revalidate_ttlbound./security-review: skipped — the skill was not invoked for this content-only diff; a manual scan of the added lines for credentials, tokens, internal hosts, private repository references, and local paths found none./simplify: not run — documentation-only diff, no code.Follow-ups (not in this PR)
website/docs/reference/spicepod/runtime.mdhas the samexxh32bullet. Add the XXH64 sentence after docs(sql): define datasets and catalogs with SQL DDL #2450 merges.Not supported for in-memory Arrowsentences forprimary_keyandindexesremain inversion-2.3.xthroughversion-1.5.x(22 files). Arrow has supported both since the v1.11 hash index. Each snapshot needs per-version verification before it is corrected.