Skip to content

feat(db)!: make grouping, includes, and pooling opt-in - #2232

Open
KyleAMathews wants to merge 29 commits into
mainfrom
opt-in-operators
Open

KyleAMathews wants to merge 29 commits into
mainfrom
opt-in-operators

Conversation

@KyleAMathews

@KyleAMathews KyleAMathews commented Oct 22, 2026 •

Copy link
Copy Markdown
Collaborator

🎯 Changes

Every app bundled the code for grouping, includes, and live-query pooling, even when it used none of them. The query builder and the compiler imported that code statically. This change makes these three features opt-in. A feature's code arrives with the value that names it, so an app bundles only the features it imports. Joins stay in core and keep their API: .join(source, on, type) and the .leftJoin(), .innerJoin(), .rightJoin(), and .fullJoin() methods do not change.

Feature The value that carries the code Migration
Grouping count, sum, avg, min, max, groupKeys Queries with an aggregate do not change. A groupBy with no aggregate takes groupKeys(...)
Includes include, toArray, materialize issues: q.from(...) becomes issues: include(q.from(...))
Pooling pooledLiveQueries Pass pool: pooledLiveQueries in the hook's query config

How it works:

  • Aggregates and groupKeys() carry the grouping compiler. orderBy rewrites aggregates only when it finds one.
  • Include functions carry the materializer and the Collection-facade adapter (includes-runtime.ts). They live in include-functions.ts, apart from the expression functions that core modules import.
  • pooledLiveQueries carries the pooled view and its identity shortcut. Hooks take it as pool in their query config (LiveQueryHookConfig). Angular's { params, query } form takes it too. React Suspense and DbClient queries pass pool: false and never pool. A DbClient query drops pool from its identity, so a server preload and a client hook hash alike.
  • A query that uses an operator always holds the value that carries it. Compilation stays synchronous, and a missing operator throws a coded error:
    • GroupingOperatorRequiredError (246) for a groupBy with no aggregate and no groupKeys()
    • IncludeOperatorRequiredError (247) for a subquery in select() without an include function. A bare subquery in select, also in a nested object or a caseWhen branch, is also a type error.
    • Errors 248 and 249 for include() of something that is not a query builder.

How a query with a custom key reaches public-key reduction:

  • A query with includes uses the include materializer, which reduces its root rows by public key.
  • A joined query with a custom key and no includes uses reducePublicKeys from public-key-reduction.ts. It does not bundle the include materializer or create a facade adapter. On main, this query went through the include materializer.
  • Other queries keep their compiled pipeline.
  • The existing test for duplicate public keys under a custom key and a join covers this path. A mutant that sends the query to the plain pipeline fails it.

An earlier version of this PR also made joins opt-in, with .join(leftJoin(source, on)). That saved about 3.6 kB in apps that never join. The maintainer reverted that part: joins are common, and models already know the existing API.

The architecture document records the include contract and how values carry operator code.

Size

pnpm size:compare against origin/main (gzip bytes):

Scenario main this PR Change
app (query collection, filtered live query, React useLiveQuery) 102,023 94,419 −7,604 (−7.5%)
app-join 102,087 94,481 −7,606 (−7.5%)
app-group-by 101,953 98,198 −3,755 (−3.7%)
app-includes 102,095 97,225 −4,870 (−4.8%)
db package bundle, every export kept 102,130 102,919 +789 (+0.8%)

The package-bundle figure is the cost of the indirection when an app uses every feature.

Evidence

This change moves behavior in areas that oracles own: query compilation, includes, pooling, and the adapter bindings. Each law below lists its evidence.

1. Pooling is opt-in per query

  • Law: a query shares a pooled source subscription only when its hook config passes pool: pooledLiveQueries. Every other query has its own subscription. A pooled query with a parameter follows the parameter. Authority: the maintainer's design decision for this release (pooling off by default, opt-in by import).
  • Reach: the two conformance scenarios are fixed histories, not generated ones. Each runs in all five framework drivers, and each driver runs the function, config, and parameterized forms. ORC-015 does not apply, because no generated property changed.
  • RED: the old suite cannot run on main, because main has no pool option. These mutants take the place of the old behavior:
    • pooling every query by default: pool-opt-in fails in React and Angular.
    • a pooled identity that ignores literal values: pooled-param-change fails in React, and the older eq-filter-peers scenario does not catch it.
    • an Angular params form that drops pool: pooled-param-change fails.
  • GREEN: npx vitest run tests/conformance passes in each adapter (React 85, Vue 87, Solid 44, Svelte 84, Angular 46).
  • Mutant: the three mutants above.
  • Limits: the scenarios use one source and eq filters on one field. The pooled live-query oracle owns the membership and order laws.

2. An app bundles an operator's code only when it imports the operator

  • Law: an app's production bundle contains an operator family's modules exactly when the app imports one of that family's values. The join compiler and public-key reduction are in every app. Authority: the maintainer's design decisions.
  • Reach: opt-in-operator-bundle.test.ts runs each of the 10 operator values alone and all 8 combinations of the three families, with rotating values (18 bundles). These are fixed cases, not generated histories, so ORC-015 does not apply.
  • RED: an earlier version of this test checked group-by.ts with a size limit under 1,000 bytes. The first mutant below passed it.
  • GREEN: 18 of 18 pass.
  • Mutant: a static use of a group-by.ts helper from the live-query Collection builder fails 8 of 18 cases. A static import of BucketFacadeAdapter into the builder fails the absence checks.
  • Limits: the test bundles @tanstack/db with other packages external, so it does not cover db-ivm operators or framework adapters. pnpm size:compare measures bytes.

3. A groupKeys() callback compiles in both TypeScript modes

  • Law: groupKeys() gets the query's context from .groupBy(). Inline, its callback is typed in strict mode and untyped without noImplicitAny, as other unannotated callbacks are. Group keys that pass their context as a type argument, groupKeys<ContextFromSource<…>>(…), are typed in both modes. Authority: the maintainer's decisions in this PR's review.
  • Reach: group-keys-typescript-modes.test.ts compiles a wrong field in three forms: inline, reusable with context, and reusable without context. It compiles each form in both modes and checks the stated result. A fixture with valid code must compile in both modes. These are fixed cases, not generated histories.
  • RED: without the groupKeys() fallback, the valid fixture fails without noImplicitAny ("'user' is possibly 'undefined'").
  • GREEN: 5 of 5 pass.
  • Mutant: an OperatorCallback that is always untyped fails the cases that must report the wrong field.
  • Limits: group keys built without an explicit context are untyped in both modes. TypeScript cannot infer a context there. The guide and the db-core skill show the explicit form.

4. Examples in the docs and skills typecheck

  • Law: each TypeScript example in docs/ and in the shipped skills parses and typechecks against the workspace source, unless its fence says nocheck.
  • Reach: 734 examples in 247 files. A baseline lists the 277 that failed when the check started. 61 of them do not parse. The baseline keys each example by its syntax tokens. The key ignores spacing, comments, commas, and semicolons. It also ignores the parentheses around JSX and around a single arrow parameter. After a reflow of seven docs to 50 columns, every entry still matches. A fence closes with as many backticks as it opened with, so a ````ts example that holds a ``` block is read whole.
  • RED: I wrote a scratch example for each defect, and the check fails each one. The defects are a bare subquery and a misspelled lefJoin. Others are code that does not parse, a missing default export, and a moved parenthesis. A scratch example with the app names collection and counter passes, as it must.
  • GREEN: pnpm test:doc-snippets: 0 new failures. Its self-test runs first, on every check.
  • Mutant: the self-test (scripts/doc-snippet-syntax.mjs) fails when the typo check ignores case. It also fails when the fingerprint keeps the parentheses around JSX. The CI lint job once failed because a subpath import resolved to an unbuilt dist/. With every dist/ hidden locally, the old script fails the same way.
  • Limits: names that an example uses without declaring them are typed any. The check reports errors in the TanStack API, not in the example's own code. The typo check compares only with names that the example imports from a TanStack package.

Other tests:

  • Codemods migrated the tests to include() and groupKeys(). The assertions did not change. When joins went back to core, a reverse codemod restored main's exact join call at each site, and 25 test files are identical to main again.
  • New tests cover the coded errors for the two removed shapes, groupKeys() grouping, include() Collections, pooling off by default, and pool: false.
  • Type tests reject a bare subquery in select, also in a nested object.

Remaining limits:

  • No oracle compares a query's old and new spellings on one input. The query and includes oracles pass with migrated queries.
  • A hook without pool computes the full IR hash of its query on each render. Measured on a two-condition where query: building the query takes 1.1 µs, and building plus hashing takes 3.6 µs. The pooled identity adds almost nothing. For 1,000 mounted hooks, the hash adds about 2.5 ms for each render. Keeping a fast identity in core would bundle part of pooling in every app.
  • Open counterexample, recorded in the coverage map: load-subset-replay-refinement-oracle fails with seed 1593300187, path 121:1:2:3:2:2. The history is a held load, truncateMarkers, and a failed settle. main at 65d9ada50 fails with the same counterexample. A full suite run on the branch found it again with seed -1005431615. The random campaign can fail CI intermittently until someone fixes the defect.
  • One run of the includes-oracle random campaign failed on this branch without a recorded seed. Five dedicated runs and two full-suite runs passed later. The coverage map records it as open, with the witness it needs. This PR does not call it pre-existing.
  • In buildNestedSelect, include() checks the field name before the query. toArray() checks the query first. Both throw a coded error. Changing the order costs 8 bytes in every app, so this PR keeps it. The eight wrapper blocks remain, because the error-site oracle freezes one message and code for each site.
  • Pre-existing type errors in query-db-collection and db-collection-e2e, and the link checker's 33 broken links, also occur on main. The React Native example cannot typecheck in a workspace without built packages.

✅ Checklist

  • I ran these suites:
    • @tanstack/db: 13,825 tests. One test timed out while other sessions loaded the machine, and it passes alone.
    • @tanstack/react-db: 421
    • @tanstack/vue-db: 134
    • @tanstack/solid-db: 101
    • @tanstack/svelte-db: 135
    • @tanstack/angular-db: 76
    • @tanstack/query-db-collection: 1,460
    • @tanstack/db-sqlite-persistence-core: some sqlite3 CLI tests time out while the machine is loaded. Each one passes alone. This package differs from main in two test files only.
  • tsc reports no new errors.
  • eslint reports no errors.
  • The mangle cache is current.
  • I regenerated the error docs and the API reference at this head. The release workflow also regenerates the reference after each publish.

🚀 Release Impact

  • This change affects published code, and I have generated a changeset.
  • This change is docs/CI/dev-only (no release).

This is a breaking change for the first 1.0 release candidate. The changeset lists the migration for each feature.

This pull request and its description were written by Isaac.

Test and others added 8 commits October 22, 2026 15:04
Joins take an operator value: .join(leftJoin(source, on)). The operator
carries the join compiler and the optimizer's join pushdown onto the IR
join clause, so apps without joins do not bundle them.

Co-authored-by: Isaac <no-reply@databricks.com>
…ll shape

Co-authored-by: Isaac <no-reply@databricks.com>
Aggregate values (count, sum, avg, min, max) carry the grouping compiler.
A groupBy with no aggregate takes groupKeys(...); without it, compilation
throws GroupingOperatorRequiredError. orderBy rewrites aggregates only when
it finds one.

Co-authored-by: Isaac <no-reply@databricks.com>
include(), toArray(), and materialize() carry the materializer and the
Collection-facade adapter. A bare subquery in select() throws
IncludeOperatorRequiredError; include(subquery) gives the Collection-valued
include. Join operators carry the materializer for custom-key reduction.

Co-authored-by: Isaac <no-reply@databricks.com>
Hooks pool a query only when its config passes pool: pooledLiveQueries.
The value carries the pooled view and its identity shortcut, so apps that
do not pool do not bundle them. React Suspense and DbClient queries pass
pool: false and never pool.

Co-authored-by: Isaac <no-reply@databricks.com>
Join calls use operator values, bare includes use include(), and the
conformance pooling scenario passes pooledLiveQueries through each driver's
config form. A pooled config with a query function builds it once.

Co-authored-by: Isaac <no-reply@databricks.com>
The live-queries guide, JSDoc examples, and generated reference use join
operators, include(), groupKeys(), and pooledLiveQueries. The join size
scenario uses leftJoin; size:compare reports n/a for a scenario that cannot
build against an older base.

Co-authored-by: Isaac <no-reply@databricks.com>
Co-authored-by: Isaac <no-reply@databricks.com>
@changeset-bot

changeset-bot Bot commented Oct 22, 2026 •

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: e642360

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 29 packages
Name Type
@tanstack/db Minor
@tanstack/react-db Patch
@tanstack/svelte-db Patch
@tanstack/vue-db Patch
@tanstack/solid-db Patch
@tanstack/angular-db Patch
@tanstack/capacitor-db-sqlite-persistence-e2e-app Patch
@tanstack/db-sqlite-persistence-core Patch
@tanstack/electric-db-collection Patch
@tanstack/expo-db-sqlite-persistence-e2e-app Patch
@tanstack/offline-transactions Patch
@tanstack/powersync-db-collection Patch
@tanstack/query-db-collection Patch
@tanstack/rxdb-db-collection Patch
@tanstack/tauri-db-sqlite-persistence-e2e-app Patch
@tanstack/trailbase-db-collection Patch
todos Patch
offline-transactions-react-native Patch
shopping-list-react-native Patch
@tanstack/db-example-react-next-ssr-e2e Patch
@tanstack/db-example-paced-mutations-demo Patch
@tanstack/browser-db-sqlite-persistence Patch
@tanstack/capacitor-db-sqlite-persistence Patch
@tanstack/cloudflare-durable-objects-db-sqlite-persistence Patch
@tanstack/electron-db-sqlite-persistence Patch
@tanstack/expo-db-sqlite-persistence Patch
@tanstack/node-db-sqlite-persistence Patch
@tanstack/react-native-db-sqlite-persistence Patch
@tanstack/tauri-db-sqlite-persistence Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@coderabbitai

coderabbitai Bot commented Oct 22, 2026 •

Copy link
Copy Markdown
Contributor

Important

Review skipped

Too many files!

This PR contains 350 files, which is 50 over the limit of 300.

To get a review, reduce the PR to 300 files or fewer by splitting it into smaller PRs or changing its base branch.

Usage-priced reviews support at most 300 files.

⚙️ Run configuration
  • Source mode: Auto
  • Repository: Unavailable
  • Branch: Unavailable
  • File: No configuration file from this repository applied
  • Commit: Unavailable
  • Layers: defaults
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 72e9979c-5643-4edc-8c7b-1f066480f6f0
📥 Commits

Reviewing files that changed from the base of the PR and between 427a7c3 and e642360.

📒 Files selected for processing: 350
  • .changeset/opt-in-operators.md
  • .github/workflows/pr.yml
  • docs/contributing/oracle-coverage.md
  • docs/errors.md
  • docs/framework/angular/reference/functions/injectLiveQuery.md
  • docs/framework/angular/reference/interfaces/InjectLiveQueryResult.md
  • docs/framework/angular/reference/interfaces/InjectLiveQueryResultWithCollection.md
  • docs/framework/angular/reference/interfaces/InjectLiveQueryResultWithSingleResultCollection.md
  • docs/framework/angular/reference/type-aliases/InjectConditionalLiveQueryResult.md
  • docs/framework/react/reference/functions/useLiveQuery.md
  • docs/framework/react/reference/type-aliases/ConditionalUseLiveQueryConfig.md
  • docs/framework/react/reference/type-aliases/LiveQueryKey.md
  • docs/framework/react/reference/type-aliases/UseLiveQueryConfig.md
  • docs/framework/react/reference/type-aliases/UseLiveQueryStatus.md
  • docs/framework/solid/reference/functions/useLiveQuery.md
  • docs/framework/svelte/reference/functions/useLiveQuery.md
  • docs/framework/svelte/reference/type-aliases/UseLiveQueryConfig.md
  • docs/framework/vue/reference/functions/useLiveQuery.md
  • docs/guides/live-queries.md
  • docs/reference/@tanstack/namespaces/IR/classes/Aggregate.md
  • docs/reference/@tanstack/namespaces/IR/classes/CollectionRef.md
  • docs/reference/@tanstack/namespaces/IR/classes/ConditionalSelect.md
  • docs/reference/@tanstack/namespaces/IR/classes/DescriptorRef.md
  • docs/reference/@tanstack/namespaces/IR/classes/Func.md
  • docs/reference/@tanstack/namespaces/IR/classes/IncludesSubquery.md
  • docs/reference/@tanstack/namespaces/IR/classes/PropRef.md
  • docs/reference/@tanstack/namespaces/IR/classes/QueryRef.md
  • docs/reference/@tanstack/namespaces/IR/classes/UnionAll.md
  • docs/reference/@tanstack/namespaces/IR/classes/UnionFrom.md
  • docs/reference/@tanstack/namespaces/IR/classes/Value.md
  • docs/reference/@tanstack/namespaces/IR/functions/collectCollectionSources.md
  • docs/reference/@tanstack/namespaces/IR/functions/collectPropRefs.md
  • docs/reference/@tanstack/namespaces/IR/functions/collectSourceRefs.md
  • docs/reference/@tanstack/namespaces/IR/functions/createResidualWhere.md
  • docs/reference/@tanstack/namespaces/IR/functions/followRef.md
  • docs/reference/@tanstack/namespaces/IR/functions/getFromSources.md
  • docs/reference/@tanstack/namespaces/IR/functions/getHavingExpression.md
  • docs/reference/@tanstack/namespaces/IR/functions/getPropRefPropertyPath.md
  • docs/reference/@tanstack/namespaces/IR/functions/getPropRefSourceAlias.md
  • docs/reference/@tanstack/namespaces/IR/functions/getWhereExpression.md
  • docs/reference/@tanstack/namespaces/IR/functions/isBasicOrAggregateExpression.md
  • docs/reference/@tanstack/namespaces/IR/functions/isExpressionLike.md
  • docs/reference/@tanstack/namespaces/IR/functions/isResidualWhere.md
  • docs/reference/@tanstack/namespaces/IR/functions/requireCollectionSource.md
  • docs/reference/@tanstack/namespaces/IR/interfaces/JoinClause.md
  • docs/reference/@tanstack/namespaces/IR/interfaces/QueryIR.md
  • docs/reference/@tanstack/namespaces/IR/type-aliases/BasicExpression.md
  • docs/reference/@tanstack/namespaces/IR/type-aliases/CollectionSourceRef.md
  • docs/reference/@tanstack/namespaces/IR/type-aliases/ConditionalSelectBranch.md
  • docs/reference/@tanstack/namespaces/IR/type-aliases/From.md
  • docs/reference/@tanstack/namespaces/IR/type-aliases/GroupBy.md
  • docs/reference/@tanstack/namespaces/IR/type-aliases/Having.md
  • docs/reference/@tanstack/namespaces/IR/type-aliases/IncludesMaterialization.md
  • docs/reference/@tanstack/namespaces/IR/type-aliases/Join.md
  • docs/reference/@tanstack/namespaces/IR/type-aliases/Limit.md
  • docs/reference/@tanstack/namespaces/IR/type-aliases/Offset.md
  • docs/reference/@tanstack/namespaces/IR/type-aliases/OrderBy.md
  • docs/reference/@tanstack/namespaces/IR/type-aliases/OrderByClause.md
  • docs/reference/@tanstack/namespaces/IR/type-aliases/OrderByDirection.md
  • docs/reference/@tanstack/namespaces/IR/type-aliases/Select.md
  • docs/reference/@tanstack/namespaces/IR/type-aliases/SelectValueExpression.md
  • docs/reference/@tanstack/namespaces/IR/type-aliases/Where.md
  • docs/reference/@tanstack/namespaces/IR/variables/INCLUDES_SCALAR_FIELD.md
  • docs/reference/classes/AggregateFunctionNotInSelectError.md
  • docs/reference/classes/BaseQueryBuilder.md
  • docs/reference/classes/CannotCombineEmptyExpressionListError.md
  • docs/reference/classes/CollectionInputNotFoundError.md
  • docs/reference/classes/CollectionPreloadAbortedError.md
  • docs/reference/classes/DistinctRequiresSelectError.md
  • docs/reference/classes/DuplicateAliasInSubqueryError.md
  • docs/reference/classes/EmptyReferencePathError.md
  • docs/reference/classes/FnSelectWithGroupByError.md
  • docs/reference/classes/GroupByError.md
  • docs/reference/classes/GroupingOperatorRequiredError.md
  • docs/reference/classes/HavingRequiresGroupByError.md
  • docs/reference/classes/IncludeOperatorRequiredError.md
  • docs/reference/classes/InvalidJoinCondition.md
  • docs/reference/classes/InvalidJoinConditionLeftSourceError.md
  • docs/reference/classes/InvalidJoinConditionRightSourceError.md
  • docs/reference/classes/InvalidJoinConditionSameSourceError.md
  • docs/reference/classes/InvalidJoinConditionSourceMismatchError.md
  • docs/reference/classes/InvalidSourceTypeError.md
  • docs/reference/classes/InvalidStorageDataFormatError.md
  • docs/reference/classes/InvalidStorageObjectFormatError.md
  • docs/reference/classes/InvalidWhereExpressionError.md
  • docs/reference/classes/JoinCollectionNotFoundError.md
  • docs/reference/classes/JoinConditionMustBeEqualityError.md
  • docs/reference/classes/JoinError.md
  • docs/reference/classes/LimitOffsetRequireOrderByError.md
  • docs/reference/classes/LoadSubsetOperationAbortedError.md
  • docs/reference/classes/LocalStorageCollectionError.md
  • docs/reference/classes/MissingAliasInputsError.md
  • docs/reference/classes/NonAggregateExpressionNotInGroupByError.md
  • docs/reference/classes/QueryBuilderError.md
  • docs/reference/classes/QueryCompilationError.md
  • docs/reference/classes/QueryMustHaveFromClauseError.md
  • docs/reference/classes/QueryOptimizerError.md
  • docs/reference/classes/SerializationError.md
  • docs/reference/classes/SetWindowFindOneLimitError.md
  • docs/reference/classes/SetWindowReentrancyError.md
  • docs/reference/classes/SetWindowRequiresOrderByError.md
  • docs/reference/classes/StorageError.md
  • docs/reference/classes/StorageKeyRequiredError.md
  • docs/reference/classes/SyncCleanupError.md
  • docs/reference/classes/SyncTransactionAbortedError.md
  • docs/reference/classes/UnhashableQueryIRError.md
  • docs/reference/classes/UnknownExpressionTypeError.md
  • docs/reference/classes/UnknownFunctionError.md
  • docs/reference/classes/UnknownHavingExpressionTypeError.md
  • docs/reference/classes/UnsafeAliasPathError.md
  • docs/reference/classes/UnsupportedAggregateFunctionError.md
  • docs/reference/classes/UnsupportedFnSelectResultError.md
  • docs/reference/classes/UnsupportedFromTypeError.md
  • docs/reference/classes/UnsupportedJoinSourceTypeError.md
  • docs/reference/classes/UnsupportedJoinTypeError.md
  • docs/reference/classes/UnsupportedRootScalarSelectError.md
  • docs/reference/functions/add.md
  • docs/reference/functions/and.md
  • docs/reference/functions/avg.md
  • docs/reference/functions/caseWhen.md
  • docs/reference/functions/coalesce.md
  • docs/reference/functions/compileExpression.md
  • docs/reference/functions/compileQuery.md
  • docs/reference/functions/concat.md
  • docs/reference/functions/count.md
  • docs/reference/functions/createLiveQueryObserver.md
  • docs/reference/functions/divide.md
  • docs/reference/functions/eq.md
  • docs/reference/functions/getLiveQueryHash.md
  • docs/reference/functions/getPersistedReadinessSource.md
  • docs/reference/functions/getPreparedLiveQueryIdentity.md
  • docs/reference/functions/getPreparedLiveQuerySources.md
  • docs/reference/functions/groupKeys.md
  • docs/reference/functions/gt.md
  • docs/reference/functions/gte.md
  • docs/reference/functions/ilike.md
  • docs/reference/functions/inArray.md
  • docs/reference/functions/include.md
  • docs/reference/functions/isNull.md
  • docs/reference/functions/isUndefined.md
  • docs/reference/functions/length.md
  • docs/reference/functions/like.md
  • docs/reference/functions/lower.md
  • docs/reference/functions/lt.md
  • docs/reference/functions/lte.md
  • docs/reference/functions/materialize.md
  • docs/reference/functions/max.md
  • docs/reference/functions/min.md
  • docs/reference/functions/multiply.md
  • docs/reference/functions/not.md
  • docs/reference/functions/or.md
  • docs/reference/functions/prepareLiveQueryValue.md
  • docs/reference/functions/resolveLiveQueryValue.md
  • docs/reference/functions/resumeDeferredLiveQueryCollections.md
  • docs/reference/functions/subtract.md
  • docs/reference/functions/sum.md
  • docs/reference/functions/toArray.md
  • docs/reference/functions/upper.md
  • docs/reference/functions/waitForPersistedInitialRender.md
  • docs/reference/index.md
  • docs/reference/interfaces/Context.md
  • docs/reference/interfaces/CreateLiveQueryObserverOptions.md
  • docs/reference/interfaces/GroupKeys.md
  • docs/reference/interfaces/LiveQueryCollectionConfig.md
  • docs/reference/interfaces/PersistedInitialRenderInput.md
  • docs/reference/interfaces/PersistedReadinessSource.md
  • docs/reference/type-aliases/ApplyJoinOptionalityToMergedSchema.md
  • docs/reference/type-aliases/ContextFromSource.md
  • docs/reference/type-aliases/ContextFromUnionBranches.md
  • docs/reference/type-aliases/ContextFromUnionSource.md
  • docs/reference/type-aliases/ContextSchema.md
  • docs/reference/type-aliases/DeferredLiveQueryCollections.md
  • docs/reference/type-aliases/ExtractContext.md
  • docs/reference/type-aliases/FunctionalHavingRow.md
  • docs/reference/type-aliases/GetResult.md
  • docs/reference/type-aliases/GroupByCallback.md
  • docs/reference/type-aliases/InferCollectionType.md
  • docs/reference/type-aliases/InferResultType.md
  • docs/reference/type-aliases/InitialQueryBuilder.md
  • docs/reference/type-aliases/JoinOnCallback.md
  • docs/reference/type-aliases/LiveQueryCollectionUtils.md
  • docs/reference/type-aliases/LiveQueryHookConfig.md
  • docs/reference/type-aliases/LiveQueryKey.md
  • docs/reference/type-aliases/LiveQueryOptions.md
  • docs/reference/type-aliases/MergeContextForJoinCallback.md
  • docs/reference/type-aliases/MergeContextWithJoinType.md
  • docs/reference/type-aliases/OperatorCallback.md
  • docs/reference/type-aliases/OperatorName.md
  • docs/reference/type-aliases/OrderByCallback.md
  • docs/reference/type-aliases/PersistedReadinessSnapshot.md
  • docs/reference/type-aliases/PooledLiveQueries.md
  • docs/reference/type-aliases/Prettify.md
  • docs/reference/type-aliases/QueryBuilder.md
  • docs/reference/type-aliases/QueryResult.md
  • docs/reference/type-aliases/Ref.md
  • docs/reference/type-aliases/RefsForContext.md
  • docs/reference/type-aliases/ResultTypeFromSelect.md
  • docs/reference/type-aliases/SchemaFromSource.md
  • docs/reference/type-aliases/SelectObject.md
  • docs/reference/type-aliases/SingleSource.md
  • docs/reference/type-aliases/Source.md
  • docs/reference/type-aliases/SourceClauseContext.md
  • docs/reference/type-aliases/WhereCallback.md
  • docs/reference/type-aliases/WithResult.md
  • docs/reference/variables/PERSISTED_READINESS.md
  • docs/reference/variables/Query.md
  • docs/reference/variables/operators.md
  • docs/reference/variables/pooledLiveQueries.md
  • examples/react-native/shopping-list/src/components/ListsScreen.tsx
  • examples/react/projects/README.md
  • package.json
  • packages/angular-db/skills/angular-db/SKILL.md
  • packages/angular-db/src/index.ts
  • packages/angular-db/tests/conformance.test.ts
  • packages/angular-db/tests/inject-live-query.test.ts
  • packages/db-collection-e2e/README.md
  • packages/db-collection-e2e/src/suites/joins-oracle.suite.ts
  • packages/db-sqlite-persistence-core/tests/persisted-readiness-oracle.test.ts
  • packages/db/mangle-cache.json
  • packages/db/skills/db-core/live-queries/SKILL.md
  • packages/db/src/errors.ts
  • packages/db/src/live-query-options.ts
  • packages/db/src/query/builder/clone-query.ts
  • packages/db/src/query/builder/functions.ts
  • packages/db/src/query/builder/group-keys.ts
  • packages/db/src/query/builder/include-functions.ts
  • packages/db/src/query/builder/index.ts
  • packages/db/src/query/builder/types.ts
  • packages/db/src/query/compiler/find-aggregate.ts
  • packages/db/src/query/compiler/group-by.ts
  • packages/db/src/query/compiler/grouping.ts
  • packages/db/src/query/compiler/index.ts
  • packages/db/src/query/compiler/order-by.ts
  • packages/db/src/query/index.ts
  • packages/db/src/query/ir.ts
  • packages/db/src/query/live/ARCHITECTURE.md
  • packages/db/src/query/live/collection-config-builder.ts
  • packages/db/src/query/live/includes-runtime.ts
  • packages/db/src/query/live/materialized-pipeline.ts
  • packages/db/src/query/live/public-key-reduction.ts
  • packages/db/src/query/live/types.ts
  • packages/db/src/query/optimizer.ts
  • packages/db/src/query/pooled-live-query.ts
  • packages/db/tests/collection-auto-index.test.ts
  • packages/db/tests/collection-query-publication-boundaries.test.ts
  • packages/db/tests/collection-subscriber-duplicate-inserts.test.ts
  • packages/db/tests/conformance/contract.ts
  • packages/db/tests/conformance/suite.ts
  • packages/db/tests/db-client-preload-identity-oracle.test.ts
  • packages/db/tests/effect.test.ts
  • packages/db/tests/error-sample-arguments.ts
  • packages/db/tests/fixtures/error-codes.json
  • packages/db/tests/fixtures/error-messages.json
  • packages/db/tests/fixtures/error-site-messages.json
  • packages/db/tests/fixtures/loose-typescript-group-keys.ts
  • packages/db/tests/group-keys-typescript-modes.test.ts
  • packages/db/tests/initial-readiness-exposure.test.ts
  • packages/db/tests/live-query-options.test.ts
  • packages/db/tests/live-query-order-only-move.test.ts
  • packages/db/tests/opt-in-operator-bundle.test.ts
  • packages/db/tests/query/aggregate-select-oracle.property.test.ts
  • packages/db/tests/query/aggregate-value-contracts.test-d.ts
  • packages/db/tests/query/async-hold-outcomes.test.ts
  • packages/db/tests/query/bucket-facade-adapter.test.ts
  • packages/db/tests/query/builder/functions.test.ts
  • packages/db/tests/query/builder/ref-proxy.test.ts
  • packages/db/tests/query/case-when.test-d.ts
  • packages/db/tests/query/case-when.test.ts
  • packages/db/tests/query/clone-query.test.ts
  • packages/db/tests/query/cold-join-reconciliation-oracle.test.ts
  • packages/db/tests/query/collection-ref-compatibility.test.ts
  • packages/db/tests/query/compiler/group-by-pipeline.test.ts
  • packages/db/tests/query/compiler/group-by.test.ts
  • packages/db/tests/query/compiler/select.test.ts
  • packages/db/tests/query/functional-variants.test-d.ts
  • packages/db/tests/query/functional-variants.test.ts
  • packages/db/tests/query/group-by-work.test.ts
  • packages/db/tests/query/group-by.test.ts
  • packages/db/tests/query/identity-output-shape-oracle.test.ts
  • packages/db/tests/query/includes-collection-oracle.property.test.ts
  • packages/db/tests/query/includes-context-transport-oracle.test.ts
  • packages/db/tests/query/includes-cross-formulation-oracle.property.test.ts
  • packages/db/tests/query/includes-functional-input-boundary.test.ts
  • packages/db/tests/query/includes-functional-projection-oracle.test.ts
  • packages/db/tests/query/includes-lazy-loading.test.ts
  • packages/db/tests/query/includes-publication-oracle.test.ts
  • packages/db/tests/query/includes-query-shape-oracle.test.ts
  • packages/db/tests/query/includes-scope-identity-oracle.ts
  • packages/db/tests/query/includes-space-oracle-fixture.ts
  • packages/db/tests/query/includes-temporal-oracle.test.ts
  • packages/db/tests/query/includes-work-counter-oracle.test.ts
  • packages/db/tests/query/includes.test-d.ts
  • packages/db/tests/query/includes.test.ts
  • packages/db/tests/query/ir-stable-identity-oracle.test.ts
  • packages/db/tests/query/join-result-key-oracle.property.test.ts
  • packages/db/tests/query/join.test-d.ts
  • packages/db/tests/query/live-query-collection.test.ts
  • packages/db/tests/query/load-subset-join-dedupe.test.ts
  • packages/db/tests/query/load-subset-replay-refinement-oracle.test.ts
  • packages/db/tests/query/load-subset-source-readiness-refinement-oracle.test.ts
  • packages/db/tests/query/load-subset-subquery.test.ts
  • packages/db/tests/query/optimizer-semantics-oracle.test.ts
  • packages/db/tests/query/optimizer.test.ts
  • packages/db/tests/query/optional-fields-runtime.test.ts
  • packages/db/tests/query/order-by.test.ts
  • packages/db/tests/query/ordered-lifecycle-oracle.property.test.ts
  • packages/db/tests/query/ordered-work-oracle.property.test.ts
  • packages/db/tests/query/pagination-oracle.property.test.ts
  • packages/db/tests/query/pooled-live-query-gc-oracle.test.ts
  • packages/db/tests/query/pooled-query-identity.test.ts
  • packages/db/tests/query/public-container-copy.test.ts
  • packages/db/tests/query/query-api-type-algebra.test.ts
  • packages/db/tests/query/query-once.test.ts
  • packages/db/tests/query/replay-failure-boundary.test.ts
  • packages/db/tests/query/scheduler.test.ts
  • packages/db/tests/query/select-spread.test.ts
  • packages/db/tests/query/subquery-user-value-oracle.test.ts
  • packages/db/tests/query/subset-error-matrix.test.ts
  • packages/db/tests/query/union-all.test-d.ts
  • packages/db/tests/query/union-all.test.ts
  • packages/db/tests/query/virtual-row-fields-oracle.test-d.ts
  • packages/db/tests/query/virtual-row-fields-oracle.test.ts
  • packages/query-db-collection/tests/includes-work-counter-oracle.test.ts
  • packages/query-db-collection/tests/load-subset-lifecycle-oracle.test.ts
  • packages/query-db-collection/tests/query.test.ts
  • packages/query-db-collection/tests/refetch-ordered-prefix-oracle.test.ts
  • packages/react-db/skills/react-db/SKILL.md
  • packages/react-db/src/useLiveQuery.ts
  • packages/react-db/tests/conformance.test.tsx
  • packages/react-db/tests/descriptor-query-binding-oracle.test.tsx
  • packages/react-db/tests/source-id-reuse-oracle.test.tsx
  • packages/react-db/tests/useLiveQuery.test.tsx
  • packages/solid-db/skills/solid-db/SKILL.md
  • packages/solid-db/src/useLiveQuery.ts
  • packages/solid-db/tests/conformance.test.tsx
  • packages/solid-db/tests/useLiveQuery.test.tsx
  • packages/svelte-db/skills/svelte-db/SKILL.md
  • packages/svelte-db/src/useLiveQuery.svelte.ts
  • packages/svelte-db/tests/conformance.svelte.test.ts
  • packages/svelte-db/tests/useLiveQuery.svelte.test.ts
  • packages/vue-db/skills/vue-db/SKILL.md
  • packages/vue-db/src/useLiveQuery.ts
  • packages/vue-db/tests/conformance.test.ts
  • packages/vue-db/tests/useLiveQuery.test.ts
  • scripts/bench/incremental-update.ts
  • scripts/check-doc-snippets.mjs
  • scripts/doc-snippet-syntax.mjs
  • scripts/doc-snippets-baseline.json
  • scripts/size-compare.mjs
  • scripts/test-minified-db.mjs

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions

github-actions Bot commented Oct 22, 2026 •

Copy link
Copy Markdown
Contributor

Size Change: +2.46 kB (+1.12%)

Total Size: 223 kB

📦 View Changed
Filename Size Change
packages/db/dist/esm/errors.js 6.71 kB +170 B (+2.6%)
packages/db/dist/esm/index.js 4.65 kB +101 B (+2.22%)
packages/db/dist/esm/live-query-options.js 1.55 kB +143 B (+10.16%) ⚠️
packages/db/dist/esm/query/builder/clone-query.js 854 B +5 B (+0.59%)
packages/db/dist/esm/query/builder/functions.js 1.61 kB +50 B (+3.21%)
packages/db/dist/esm/query/builder/group-keys.js 157 B +157 B (new file) 🆕
packages/db/dist/esm/query/builder/include-functions.js 229 B +229 B (new file) 🆕
packages/db/dist/esm/query/builder/index.js 7.72 kB +244 B (+3.26%)
packages/db/dist/esm/query/compiler/find-aggregate.js 328 B +328 B (new file) 🆕
packages/db/dist/esm/query/compiler/group-by.js 4.37 kB -109 B (-2.43%)
packages/db/dist/esm/query/compiler/grouping.js 161 B +161 B (new file) 🆕
packages/db/dist/esm/query/compiler/index.js 10.4 kB +99 B (+0.96%)
packages/db/dist/esm/query/compiler/order-by.js 2.82 kB +22 B (+0.79%)
packages/db/dist/esm/query/equality-value-identity.js 736 B +1 B (+0.14%)
packages/db/dist/esm/query/ir.js 2.22 kB +23 B (+1.05%)
packages/db/dist/esm/query/live/collection-config-builder.js 6.95 kB +47 B (+0.68%)
packages/db/dist/esm/query/live/includes-runtime.js 212 B +212 B (new file) 🆕
packages/db/dist/esm/query/live/materialized-pipeline.js 1.94 kB -450 B (-18.81%) 👏
packages/db/dist/esm/query/live/public-key-reduction.js 970 B +970 B (new file) 🆕
packages/db/dist/esm/query/optimizer.js 2.95 kB -3 B (-0.1%)
packages/db/dist/esm/query/pooled-live-query.js 4.16 kB +28 B (+0.68%)
packages/react-db/dist/esm/useLiveQuery.js 3.42 kB +35 B (+1.04%)
ℹ️ View Unchanged
Filename Size
packages/db/dist/esm/client.js 4.22 kB
packages/db/dist/esm/collection-options-brand.js 219 B
packages/db/dist/esm/collection-options.js 258 B
packages/db/dist/esm/collection/change-events.js 1.76 kB
packages/db/dist/esm/collection/changes.js 2.96 kB
packages/db/dist/esm/collection/cleanup-queue.js 901 B
packages/db/dist/esm/collection/config-errors.js 547 B
packages/db/dist/esm/collection/events.js 481 B
packages/db/dist/esm/collection/index.js 5.27 kB
packages/db/dist/esm/collection/indexes.js 2.3 kB
packages/db/dist/esm/collection/lifecycle.js 2.94 kB
packages/db/dist/esm/collection/mutations.js 2.99 kB
packages/db/dist/esm/collection/state.js 7.36 kB
packages/db/dist/esm/collection/subscription.js 8.89 kB
packages/db/dist/esm/collection/sync.js 5.4 kB
packages/db/dist/esm/collection/validate-config.js 1.17 kB
packages/db/dist/esm/deferred.js 207 B
packages/db/dist/esm/error-message.js 642 B
packages/db/dist/esm/event-emitter.js 1.06 kB
packages/db/dist/esm/indexed-db-wrapper.js 1.91 kB
packages/db/dist/esm/indexed-db.js 3.79 kB
packages/db/dist/esm/indexes/auto-index.js 924 B
packages/db/dist/esm/indexes/base-index.js 1.92 kB
packages/db/dist/esm/indexes/basic-index.js 1.93 kB
packages/db/dist/esm/indexes/btree-index.js 1.62 kB
packages/db/dist/esm/indexes/index-registry.js 916 B
packages/db/dist/esm/indexes/reverse-index.js 1.01 kB
packages/db/dist/esm/live-query-adapter.js 338 B
packages/db/dist/esm/live-query-observer.js 4.52 kB
packages/db/dist/esm/live-query-window-controller.js 4.27 kB
packages/db/dist/esm/local-only.js 1.08 kB
packages/db/dist/esm/local-storage.js 4.58 kB
packages/db/dist/esm/optimistic-action.js 359 B
packages/db/dist/esm/paced-mutations.js 1.11 kB
packages/db/dist/esm/persisted-readiness.js 841 B
packages/db/dist/esm/proxy.js 3.51 kB
packages/db/dist/esm/query/builder/query-ir.js 312 B
packages/db/dist/esm/query/builder/ref-proxy-identity.js 292 B
packages/db/dist/esm/query/builder/ref-proxy.js 1.67 kB
packages/db/dist/esm/query/builder/wrapper-identity.js 221 B
packages/db/dist/esm/query/compiler/evaluators.js 2.51 kB
packages/db/dist/esm/query/compiler/expressions.js 603 B
packages/db/dist/esm/query/compiler/joins.js 3.42 kB
packages/db/dist/esm/query/compiler/lazy-targets.js 1.11 kB
packages/db/dist/esm/query/compiler/parent-routes.js 319 B
packages/db/dist/esm/query/compiler/query-equivalence.js 568 B
packages/db/dist/esm/query/compiler/route-metadata.js 1.24 kB
packages/db/dist/esm/query/compiler/select.js 1.5 kB
packages/db/dist/esm/query/effect.js 5.36 kB
packages/db/dist/esm/query/equality-conjunct.js 486 B
packages/db/dist/esm/query/expression-helpers.js 1.61 kB
packages/db/dist/esm/query/ir-stable-identity.js 4.2 kB
packages/db/dist/esm/query/join-conditions.js 257 B
packages/db/dist/esm/query/live-query-collection.js 391 B
packages/db/dist/esm/query/live/bucket-facade-adapter.js 3.17 kB
packages/db/dist/esm/query/live/collection-registry.js 264 B
packages/db/dist/esm/query/live/collection-subscriber.js 2.3 kB
packages/db/dist/esm/query/live/graph-scheduler.js 305 B
packages/db/dist/esm/query/live/internal.js 145 B
packages/db/dist/esm/query/live/ordered-source-loader.js 6.46 kB
packages/db/dist/esm/query/live/subset-demand-controller.js 1.76 kB
packages/db/dist/esm/query/live/utils.js 1.35 kB
packages/db/dist/esm/query/query-once.js 359 B
packages/db/dist/esm/query/runtime-reference-identity.js 630 B
packages/db/dist/esm/query/subset-dedupe.js 493 B
packages/db/dist/esm/scheduler.js 1.23 kB
packages/db/dist/esm/SortedMap.js 1.6 kB
packages/db/dist/esm/strategies/commit-completion.js 156 B
packages/db/dist/esm/strategies/debounceStrategy.js 658 B
packages/db/dist/esm/strategies/queueStrategy.js 523 B
packages/db/dist/esm/strategies/serial-pacer.js 486 B
packages/db/dist/esm/strategies/throttleStrategy.js 738 B
packages/db/dist/esm/sync-persistence.js 626 B
packages/db/dist/esm/sync-receipt.js 211 B
packages/db/dist/esm/transaction-commit-work.js 351 B
packages/db/dist/esm/transactions.js 4.61 kB
packages/db/dist/esm/utils.js 1.67 kB
packages/db/dist/esm/utils/array-utils.js 270 B
packages/db/dist/esm/utils/browser-polyfills.js 304 B
packages/db/dist/esm/utils/btree.js 3.02 kB
packages/db/dist/esm/utils/callbacks.js 219 B
packages/db/dist/esm/utils/comparison.js 1.94 kB
packages/db/dist/esm/utils/cursor.js 753 B
packages/db/dist/esm/utils/error.js 262 B
packages/db/dist/esm/utils/get-or-create.js 155 B
packages/db/dist/esm/utils/index-optimization.js 2.58 kB
packages/db/dist/esm/utils/source-record.js 140 B
packages/db/dist/esm/utils/type-guards.js 230 B
packages/db/dist/esm/utils/uuid.js 530 B
packages/db/dist/esm/virtual-props.js 413 B
packages/react-db/dist/esm/DbProvider.js 317 B
packages/react-db/dist/esm/development.js 190 B
packages/react-db/dist/esm/HydrationBoundary.js 263 B
packages/react-db/dist/esm/index.js 330 B
packages/react-db/dist/esm/live-query-internals.js 282 B
packages/react-db/dist/esm/source-id-bindings.js 746 B
packages/react-db/dist/esm/useLiveInfiniteQuery.js 2.15 kB
packages/react-db/dist/esm/useLiveQueryEffect.js 504 B
packages/react-db/dist/esm/useLiveSuspenseQuery.js 1.33 kB
packages/react-db/dist/esm/usePacedMutations.js 429 B

compressed-size-action::db-and-react-package-size

@pkg-pr-new

pkg-pr-new Bot commented Oct 22, 2026 •

Copy link
Copy Markdown
More templates

@tanstack/angular-db

npm i https://pkg.pr.new/@tanstack/angular-db@2232

@tanstack/browser-db-sqlite-persistence

npm i https://pkg.pr.new/@tanstack/browser-db-sqlite-persistence@2232

@tanstack/capacitor-db-sqlite-persistence

npm i https://pkg.pr.new/@tanstack/capacitor-db-sqlite-persistence@2232

@tanstack/cloudflare-durable-objects-db-sqlite-persistence

npm i https://pkg.pr.new/@tanstack/cloudflare-durable-objects-db-sqlite-persistence@2232

@tanstack/db

npm i https://pkg.pr.new/@tanstack/db@2232

@tanstack/db-ivm

npm i https://pkg.pr.new/@tanstack/db-ivm@2232

@tanstack/db-sqlite-persistence-core

npm i https://pkg.pr.new/@tanstack/db-sqlite-persistence-core@2232

@tanstack/electric-db-collection

npm i https://pkg.pr.new/@tanstack/electric-db-collection@2232

@tanstack/electron-db-sqlite-persistence

npm i https://pkg.pr.new/@tanstack/electron-db-sqlite-persistence@2232

@tanstack/expo-db-sqlite-persistence

npm i https://pkg.pr.new/@tanstack/expo-db-sqlite-persistence@2232

@tanstack/node-db-sqlite-persistence

npm i https://pkg.pr.new/@tanstack/node-db-sqlite-persistence@2232

@tanstack/offline-transactions

npm i https://pkg.pr.new/@tanstack/offline-transactions@2232

@tanstack/powersync-db-collection

npm i https://pkg.pr.new/@tanstack/powersync-db-collection@2232

@tanstack/query-db-collection

npm i https://pkg.pr.new/@tanstack/query-db-collection@2232

@tanstack/react-db

npm i https://pkg.pr.new/@tanstack/react-db@2232

@tanstack/react-native-db-sqlite-persistence

npm i https://pkg.pr.new/@tanstack/react-native-db-sqlite-persistence@2232

@tanstack/react-router-with-db

npm i https://pkg.pr.new/@tanstack/react-router-with-db@2232

@tanstack/rxdb-db-collection

npm i https://pkg.pr.new/@tanstack/rxdb-db-collection@2232

@tanstack/solid-db

npm i https://pkg.pr.new/@tanstack/solid-db@2232

@tanstack/svelte-db

npm i https://pkg.pr.new/@tanstack/svelte-db@2232

@tanstack/tauri-db-sqlite-persistence

npm i https://pkg.pr.new/@tanstack/tauri-db-sqlite-persistence@2232

@tanstack/trailbase-db-collection

npm i https://pkg.pr.new/@tanstack/trailbase-db-collection@2232

@tanstack/vue-db

npm i https://pkg.pr.new/@tanstack/vue-db@2232

commit: e642360

Test and others added 4 commits October 22, 2026 21:23
… pool

A DbClient query never pools, so prepareLiveQueryValue drops pool and a
server preload hashes like a pooling hook. pool moves from
LiveQueryCollectionConfig to LiveQueryHookConfig, which the framework hooks
accept. Angular's { params, query } form takes pool. Join operators have a
named function type so their declarations stay portable. The benchmark runs
against either join API, and the minified API check lists the new errors.

Co-authored-by: Isaac <no-reply@databricks.com>
…rializer

A join clause carries one runtime object (compiler, pushdown, validation,
and public-key reduction), and the optimizer copies it by spreading the
clause. Public-key reduction moves to its own module, so a joined query with a
custom key no longer bundles the include materializer. The bundle test now
tracks the materializer and the shared reduction module.

Co-authored-by: Isaac <no-reply@databricks.com>
… input

caseWhen branches take include() for a subquery; the select-object branch no
longer accepts a query builder. include() of a non-builder throws a coded
error. The compiler finds aggregates with one walker, and the fn.select error
names include(). size:compare skips only a base that lacks a scenario's new
export.

Co-authored-by: Isaac <no-reply@databricks.com>
The shipped agent skills use join operators, include(), groupKeys(), and
pooledLiveQueries. join() and groupBy() JSDoc describe the new parameters.
The changeset covers Angular's params pool and hand-built IR. Oracle files
keep their opening contract prose above their imports.

Co-authored-by: Isaac <no-reply@databricks.com>
@github-actions

github-actions Bot commented Oct 23, 2026 •

Copy link
Copy Markdown
Contributor

Incremental update benchmark

Comparing 50425bffd (this PR) against 427a7c31e (base). Write times are per-write medians over 100 iterations (20 warmup writes). Cold hydrate is one timed first load of each query.

Overall median write time vs base: 1.02× · cold hydrate time: 1.00× (geometric mean of per-case ratios; lower is faster).

Writes: 3 regression(s), 2 improvement(s) (threshold: ±20% and >0.05ms).

Cold hydrate: 3 regression(s), 0 improvement(s) (threshold: ±50% and >5ms).

Per-case flags are noisy on shared runners. Read the geometric means first.

Writes

Query Δ median write time (geomean) Best case Worst case Flags
list: newest 50 open -0.6% -26.6% +16.5% —
list + author +5.7% -9.2% +31.8% 1 🔴
list + comment count +1.4% -39.0% +62.7% 1 🔴 1 🟢
list + 3 recent comments +0.7% -39.3% +12.2% 1 🟢
issue detail + comments +6.1% -13.4% +57.9% 1 🔴

Cold hydrate

Query Δ cold hydrate time (geomean) Best case Worst case Flags
list: newest 50 open -1.8% -39.7% +76.4% 1 🔴
list + author +1.4% -32.6% +58.2% 1 🔴
list + comment count -1.5% -64.1% +193.2% 1 🔴
list + 3 recent comments +5.7% -16.0% +48.9% —
issue detail + comments +1.0% -39.0% +43.6% —

Each row aggregates the 14.4 scale/index/write-mode configurations of that query; per-configuration tables below.

100 rows/collection | source indexes: none | synced writes — geomean 0.98×, cold 1.05×
Query Base median PR median Δ median Base p95 PR p95 Δ p95 Base cold PR cold Δ cold
list: newest 50 open 0.221ms 0.216ms -2.0% 0.344ms 0.355ms +3.2% 14.887ms 13.575ms -8.8%
list: newest 50 open 0.460ms 0.515ms +12.0% 0.717ms 0.799ms +11.4% 3.699ms 5.324ms +43.9%
list + author 0.228ms 0.207ms -9.2% 0.386ms 0.339ms -12.2% 9.030ms 10.690ms +18.4%
list + comment count 0.418ms 0.338ms -19.1% 0.721ms 0.540ms -25.1% 14.395ms 12.951ms -10.0%
list + 3 recent comments 0.231ms 0.235ms +1.5% 0.360ms 0.402ms +11.8% 10.319ms 11.434ms +10.8%
issue detail + comments 0.161ms 0.172ms +7.3% 0.231ms 0.282ms +22.2% 2.117ms 1.860ms -12.1%
100 rows/collection | source indexes: none | optimistic writes — geomean 1.06×, cold 1.03×, 1 change(s)
Query Base median PR median Δ median Base p95 PR p95 Δ p95 Base cold PR cold Δ cold
list: newest 50 open 0.144ms 0.140ms -2.5% 0.228ms 0.195ms -14.7% 2.781ms 2.617ms -5.9%
list: newest 50 open 0.096ms 0.095ms -0.9% 0.170ms 0.165ms -2.9% 2.152ms 2.133ms -0.9%
list + author 0.158ms 0.208ms +31.8% 0.281ms 0.293ms +4.4% 🔴 3.349ms 4.648ms +38.8%
list + comment count 0.236ms 0.233ms -1.2% 0.386ms 0.384ms -0.4% 5.217ms 4.466ms -14.4%
list + 3 recent comments 0.135ms 0.141ms +4.7% 0.253ms 0.261ms +3.4% 6.595ms 6.953ms +5.4%
issue detail + comments 0.159ms 0.166ms +4.7% 0.216ms 0.249ms +15.3% 1.030ms 1.068ms +3.7%
100 rows/collection | source indexes: manual | synced writes — geomean 0.93×, cold 0.93×
Query Base median PR median Δ median Base p95 PR p95 Δ p95 Base cold PR cold Δ cold
list: newest 50 open 0.151ms 0.111ms -26.6% 0.233ms 0.220ms -5.6% 3.304ms 3.423ms +3.6%
list: newest 50 open 0.480ms 0.460ms -4.2% 0.780ms 0.747ms -4.2% 1.275ms 1.272ms -0.3%
list + author 0.129ms 0.146ms +13.3% 0.176ms 0.248ms +41.2% 3.887ms 2.618ms -32.6%
list + comment count 0.244ms 0.244ms +0.2% 0.422ms 0.433ms +2.5% 3.551ms 3.272ms -7.9%
list + 3 recent comments 0.169ms 0.160ms -5.1% 0.268ms 0.275ms +2.8% 4.334ms 4.527ms +4.4%
issue detail + comments 0.134ms 0.116ms -13.4% 0.228ms 0.226ms -1.1% 0.558ms 0.554ms -0.8%
100 rows/collection | source indexes: manual | optimistic writes — geomean 0.98×, cold 0.96×
Query Base median PR median Δ median Base p95 PR p95 Δ p95 Base cold PR cold Δ cold
list: newest 50 open 0.110ms 0.106ms -3.5% 0.203ms 0.177ms -13.0% 1.523ms 1.598ms +4.9%
list: newest 50 open 0.088ms 0.085ms -2.5% 0.151ms 0.129ms -14.1% 1.083ms 0.857ms -20.9%
list + author 0.140ms 0.136ms -2.4% 0.188ms 0.215ms +14.6% 3.750ms 2.597ms -30.8%
list + comment count 0.210ms 0.200ms -4.6% 0.361ms 0.320ms -11.5% 2.758ms 2.875ms +4.2%
list + 3 recent comments 0.127ms 0.129ms +2.1% 0.201ms 0.219ms +9.3% 5.107ms 5.748ms +12.6%
issue detail + comments 0.108ms 0.108ms -0.2% 0.184ms 0.156ms -14.9% 0.398ms 0.453ms +13.9%
1,000 rows/collection | source indexes: none | synced writes — geomean 1.06×, cold 1.27×, 5 change(s)
Query Base median PR median Δ median Base p95 PR p95 Δ p95 Base cold PR cold Δ cold
list: newest 50 open 0.101ms 0.082ms -18.2% 0.184ms 0.141ms -23.3% 6.612ms 11.665ms +76.4% 🔴
list: newest 50 open 1.100ms 1.125ms +2.2% 2.015ms 2.192ms +8.8% 6.558ms 5.871ms -10.5%
list + author 0.107ms 0.117ms +9.0% 0.153ms 0.159ms +4.1% 18.226ms 28.841ms +58.2% 🔴
list + comment count 0.197ms 0.320ms +62.7% 0.331ms 0.415ms +25.3% 🔴 9.962ms 13.690ms +37.4%
list + 3 recent comments 0.279ms 0.169ms -39.3% 0.342ms 0.284ms -17.2% 🟢 11.035ms 9.539ms -13.6%
issue detail + comments 0.150ms 0.237ms +57.9% 0.299ms 0.314ms +5.2% 🔴 1.207ms 1.733ms +43.6%
1,000 rows/collection | source indexes: none | optimistic writes — geomean 1.08×, cold 0.87×
Query Base median PR median Δ median Base p95 PR p95 Δ p95 Base cold PR cold Δ cold
list: newest 50 open 0.101ms 0.117ms +16.5% 0.199ms 0.191ms -3.7% 6.494ms 7.858ms +21.0%
list: newest 50 open 0.066ms 0.066ms +1.0% 0.116ms 0.135ms +16.5% 7.241ms 4.763ms -34.2%
list + author 0.129ms 0.128ms -0.9% 0.207ms 0.178ms -14.1% 20.750ms 21.438ms +3.3%
list + comment count 0.170ms 0.192ms +13.3% 0.261ms 0.224ms -14.4% 12.267ms 8.230ms -32.9%
list + 3 recent comments 0.106ms 0.116ms +10.2% 0.135ms 0.150ms +10.8% 10.031ms 10.242ms +2.1%
issue detail + comments 0.094ms 0.105ms +11.2% 0.125ms 0.138ms +11.2% 1.504ms 1.191ms -20.8%
1,000 rows/collection | source indexes: manual | synced writes — geomean 1.11×, cold 1.24×
Query Base median PR median Δ median Base p95 PR p95 Δ p95 Base cold PR cold Δ cold
list: newest 50 open 0.076ms 0.078ms +2.3% 0.099ms 0.102ms +2.9% 1.012ms 0.954ms -5.7%
list: newest 50 open 0.305ms 0.323ms +6.0% 0.493ms 0.609ms +23.5% 0.819ms 0.819ms -0.1%
list + author 0.101ms 0.110ms +8.8% 0.181ms 0.191ms +5.6% 1.622ms 1.761ms +8.6%
list + comment count 0.198ms 0.246ms +24.1% 0.350ms 0.401ms +14.7% 2.306ms 6.761ms +193.2%
list + 3 recent comments 0.133ms 0.149ms +12.2% 0.225ms 0.272ms +20.8% 4.570ms 4.751ms +4.0%
issue detail + comments 0.095ms 0.110ms +15.5% 0.127ms 0.205ms +61.7% 0.405ms 0.481ms +18.9%
1,000 rows/collection | source indexes: manual | optimistic writes — geomean 1.02×, cold 0.87×
Query Base median PR median Δ median Base p95 PR p95 Δ p95 Base cold PR cold Δ cold
list: newest 50 open 0.088ms 0.092ms +4.1% 0.113ms 0.120ms +6.0% 0.792ms 0.747ms -5.7%
list: newest 50 open 0.073ms 0.074ms +1.9% 0.116ms 0.111ms -4.2% 1.045ms 0.990ms -5.3%
list + author 0.118ms 0.122ms +3.3% 0.210ms 0.152ms -27.6% 1.753ms 2.094ms +19.5%
list + comment count 0.184ms 0.192ms +4.6% 0.307ms 0.230ms -25.3% 7.311ms 2.628ms -64.1%
list + 3 recent comments 0.113ms 0.124ms +9.9% 0.159ms 0.155ms -2.5% 3.910ms 3.836ms -1.9%
issue detail + comments 0.127ms 0.112ms -11.3% 0.191ms 0.194ms +1.9% 0.338ms 0.402ms +18.8%
10,000 rows/collection | source indexes: none | synced writes — geomean 0.97×, cold 0.91×, 1 change(s)
Query Base median PR median Δ median Base p95 PR p95 Δ p95 Base cold PR cold Δ cold
list: newest 50 open 0.073ms 0.077ms +4.9% 0.134ms 0.103ms -23.7% 66.671ms 69.588ms +4.4%
list: newest 50 open 10.267ms 10.246ms -0.2% 11.111ms 10.933ms -1.6% 63.935ms 64.235ms +0.5%
list + author 0.112ms 0.131ms +16.3% 0.197ms 0.224ms +13.6% 189.765ms 201.408ms +6.1%
list + comment count 0.337ms 0.206ms -39.0% 0.413ms 0.342ms -17.0% 🟢 72.290ms 73.491ms +1.7%
list + 3 recent comments 0.125ms 0.131ms +4.7% 0.236ms 0.165ms -29.8% 88.032ms 73.970ms -16.0%
issue detail + comments 0.093ms 0.099ms +6.8% 0.118ms 0.127ms +7.6% 9.168ms 5.592ms -39.0%
10,000 rows/collection | source indexes: none | optimistic writes — geomean 1.08×, cold 1.11×, 1 change(s)
Query Base median PR median Δ median Base p95 PR p95 Δ p95 Base cold PR cold Δ cold
list: newest 50 open 0.091ms 0.100ms +10.3% 0.128ms 0.169ms +31.9% 57.196ms 65.646ms +14.8%
list: newest 50 open 0.060ms 0.062ms +2.7% 0.086ms 0.101ms +17.2% 62.539ms 63.119ms +0.9%
list + author 0.115ms 0.126ms +9.6% 0.196ms 0.174ms -11.3% 190.515ms 181.661ms -4.6%
list + comment count 0.195ms 0.223ms +14.3% 0.256ms 0.262ms +2.3% 69.705ms 106.397ms +52.6% 🔴
list + 3 recent comments 0.108ms 0.117ms +7.7% 0.143ms 0.148ms +3.2% 70.885ms 76.829ms +8.4%
issue detail + comments 0.101ms 0.106ms +5.0% 0.137ms 0.144ms +5.7% 4.908ms 5.134ms +4.6%
10,000 rows/collection | source indexes: manual | synced writes — geomean 0.97×, cold 0.94×
Query Base median PR median Δ median Base p95 PR p95 Δ p95 Base cold PR cold Δ cold
list: newest 50 open 0.090ms 0.076ms -15.7% 0.172ms 0.104ms -39.3% 2.180ms 1.736ms -20.4%
list: newest 50 open 0.957ms 0.953ms -0.4% 1.547ms 1.442ms -6.8% 1.621ms 1.598ms -1.4%
list + author 0.105ms 0.100ms -4.5% 0.136ms 0.136ms +0.0% 2.897ms 2.496ms -13.9%
list + comment count 0.230ms 0.216ms -5.8% 0.342ms 0.253ms -26.0% 4.162ms 3.463ms -16.8%
list + 3 recent comments 0.149ms 0.156ms +5.3% 0.243ms 0.192ms -21.0% 5.072ms 5.895ms +16.2%
issue detail + comments 0.107ms 0.112ms +4.2% 0.136ms 0.155ms +14.1% 0.563ms 0.601ms +6.9%
10,000 rows/collection | source indexes: manual | optimistic writes — geomean 1.02×, cold 0.94×
Query Base median PR median Δ median Base p95 PR p95 Δ p95 Base cold PR cold Δ cold
list: newest 50 open 0.107ms 0.121ms +13.7% 0.202ms 0.210ms +3.7% 2.703ms 1.629ms -39.7%
list: newest 50 open 0.081ms 0.078ms -3.9% 0.116ms 0.129ms +10.9% 1.565ms 1.572ms +0.4%
list + author 0.124ms 0.123ms -1.1% 0.162ms 0.154ms -4.7% 3.264ms 2.736ms -16.2%
list + comment count 0.247ms 0.243ms -1.4% 0.392ms 0.300ms -23.5% 3.812ms 3.426ms -10.1%
list + 3 recent comments 0.134ms 0.144ms +7.8% 0.216ms 0.226ms +4.3% 4.363ms 6.499ms +48.9%
issue detail + comments 0.119ms 0.119ms +0.0% 0.152ms 0.173ms +14.1% 0.550ms 0.553ms +0.5%

Runner: node v24.8.0, linux 6.17.0-1022-azure, AMD EPYC 7763 64-Core Processor. Timings on shared CI runners are noisy; treat small deltas as indicative only.

autofix-ci Bot and others added 12 commits October 23, 2026 03:47
A join operator infers the query's context from .join(). TypeScript skips
that inference when noImplicitAny is off, which left every join condition
with unknown refs and compile errors. The context now defaults to any there,
so the condition is untyped like other unannotated callbacks in that mode.
Strict mode keeps full typing.

Co-authored-by: Isaac <no-reply@databricks.com>
Co-authored-by: Isaac <no-reply@databricks.com>
Add scripts/check-doc-snippets.mjs, run in the CI lint job as
`pnpm test:doc-snippets`. It typechecks each TypeScript example in docs/
and the shipped skills against the workspace sources. Examples that
already failed are listed in a baseline by content hash, so a new or
edited example must pass.

The check found these errors:
- Joins lost their types without noImplicitAny. Strict mode keeps them;
  the test compiles a wrong field in both modes.
- A bare subquery in select type-checked, also nested, because the ref
  and nested-object shapes are open. Both select overloads now reject
  a value that holds a query builder outside include(), toArray(), or
  materialize().
- Guide and skill examples: a nested bare subquery, missing imports,
  an orderBy on $selected, and iteration over a Collection.

Co-authored-by: Isaac <no-reply@databricks.com>
The autofix bot reformatted skill examples, which changed their hashes and
made known failures look new. The baseline now hashes each example's
tokens without commas, semicolons, parentheses, and spacing, so a
reformatted example keeps its entry. An edit to its code still does not.

Co-authored-by: Isaac <no-reply@databricks.com>
The conformance suite checked pooling only in the config form with pool.
Two scenarios now run in every framework driver:

- pool-opt-in: queries without pool keep a source subscription each in
  the function, config, and parameterized forms.
- pooled-param-change: a pooled parameterized query follows its
  parameter between pool groups beside an unchanged peer, and releases
  its subscription on unmount.

mountControllable takes an optional pool, and each driver uses its
adapter's config form for it (React without deps, Angular params).
Pooling every query by default, a pooled identity that ignores literal
values, and an Angular params form that drops pool each fail them.

Co-authored-by: Isaac <no-reply@databricks.com>
CI does not build the packages before lint. A subpath import such as
`@tanstack/db-sqlite-persistence-core/broadcast-coordinator` resolved to
dist/ locally and to nothing in CI, so one skill example failed only in
CI. Each export in a package's manifest now maps to its source file.

Co-authored-by: Isaac <no-reply@databricks.com>
- groupKeys() compiles without noImplicitAny, as join operators do. Both
  use one OperatorCallback type. The TypeScript-modes test now covers
  groupKeys and a reusable join operator, which passes its context
  explicitly and stays typed in both modes.
- Document reusable join operators in the guide and the db-core skill.
- Migrate the React Native shopping-list example to include() and the
  projects README to the current join API.
- The changeset and skill say that the join methods are removed. They
  do not throw the coded error. The changeset notes the new type of
  resolveLiveQueryValue's pool option.
- The bundle test runs every operator value alone and every combination
  of operator families, and checks group-by.ts exactly.
- The doc example check reports typos of imported TanStack names and
  examples that do not parse, and keeps parentheses in its fingerprint.
- Correct ARCHITECTURE.md and includes-runtime.ts on which module owns
  public-key reduction.
- Remove dead code: containsAggregate, the pool key check in poolConfig,
  the joined-key parameter of materializeCompilation, and two needless
  exports.
- Record the open load-subset replay counterexample (seed 1593300187),
  which fails the same way on main, in the coverage map.

Co-authored-by: Isaac <no-reply@databricks.com>
- The TypeScript-modes test covers every operator and form: join and
  groupKeys, inline, reusable with context, and reusable without
  context, in both modes, with a stated result per cell. It compiles one
  program per mode, so it stays fast.
- Document the typed reusable groupKeys<Context>() form.
- Export JoinCondition and OperatorCallback, so a factory can name the
  condition type.
- The doc example check reads examples through the TypeScript syntax
  tree: JSX text no longer breaks the fingerprint, every import form is
  found, and only syntax errors count as "does not parse". The typo
  check ignores case-only and prefix differences. A self-test with
  positive and negative cases runs before each check.
- Regenerate the API reference.
- Record the untraced includes-oracle failure, and the second seed of
  the load-subset counterexample, in the coverage map.

Co-authored-by: Isaac <no-reply@databricks.com>
Test and others added 2 commits October 23, 2026 12:49
Joins are common, and models already know `.join(source, on)` and the
`.leftJoin()` family. Making them opt-in saved about 3.6 kB in apps that
never join. Grouping, includes, and pooling stay opt-in.

- Restore `.join(source, on, type)` and the `leftJoin`, `rightJoin`,
  `innerJoin`, and `fullJoin` methods. Remove the join operator values,
  `JoinCondition`, the join runtime on IR join clauses, and
  `JoinOperatorRequiredError` (245).
- Restore the static join compile path, main's optimizer, and main's
  joins.ts. Public-key reduction stays its own module, so a joined query
  with a custom key still does not bundle the include materializer.
- Tests: a reverse codemod restored main's exact join call at each site.
  25 files are identical to main again.
- Docs and skills use the existing join API again. The doc example check
  matches a fence by its backtick count, so a ````ts example that holds a
  ``` block is read whole.
- The TypeScript-modes test covers groupKeys only, and the bundle test
  treats join modules as core.

Typical app: 102,023 to 94,419 B gzip (-7.5%).

Co-authored-by: Isaac <no-reply@databricks.com>
@KyleAMathews KyleAMathews changed the title feat(db)!: make joins, grouping, includes, and pooling opt-in feat(db)!: make grouping, includes, and pooling opt-in Oct 23, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant