Skip to content

feat(electric-db-collection): DNF/active_conditions support#1270

Open
kevin-dp wants to merge 7 commits intomainfrom
feat/dnf-active-conditions
Open

feat(electric-db-collection): DNF/active_conditions support#1270
kevin-dp wants to merge 7 commits intomainfrom
feat/dnf-active-conditions

Conversation

@kevin-dp
Copy link
Contributor

Summary

  • Adds support for the new Electric server wire protocol (electric-sql/electric#3791) which enables arbitrary boolean WHERE clauses with OR/NOT and multiple subqueries
  • Changes tag delimiter from | to / and replaces _ wildcards with empty segments (NON_PARTICIPATING positions)
  • Adds active_conditions header support: shapes with subquery dependencies use DNF evaluation (row visible if ANY disjunct has ALL its positions satisfied), simple shapes retain existing empty-tag-set deletion behavior
  • Derives disjunct_positions once per shape (global) rather than per-row, since the DNF structure is fixed by the WHERE clause

Test plan

  • Updated all existing tag tests to use new / delimiter and empty-segment syntax
  • Added 7 new test cases covering DNF scenarios: partial deactivation, full deactivation, multi-disjunct visibility, active_conditions overwrite on re-send, simple shapes without active_conditions, and mixed rows
  • Full test suite passes (419 tests, 0 failures, no type errors)

🤖 Generated with Claude Code

@changeset-bot
Copy link

changeset-bot bot commented Feb 19, 2026

🦋 Changeset detected

Latest commit: d637d0f

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

This PR includes changesets to release 3 packages
Name Type
@tanstack/electric-db-collection Minor
@tanstack/db-example-react-todo Patch
@tanstack/db-example-solid-todo 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

@pkg-pr-new
Copy link

pkg-pr-new bot commented Feb 19, 2026

More templates

@tanstack/angular-db

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

@tanstack/db

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

@tanstack/db-browser-wa-sqlite-persisted-collection

npm i https://pkg.pr.new/TanStack/db/@tanstack/db-browser-wa-sqlite-persisted-collection@1270

@tanstack/db-capacitor-sqlite-persisted-collection

npm i https://pkg.pr.new/TanStack/db/@tanstack/db-capacitor-sqlite-persisted-collection@1270

@tanstack/db-cloudflare-do-sqlite-persisted-collection

npm i https://pkg.pr.new/TanStack/db/@tanstack/db-cloudflare-do-sqlite-persisted-collection@1270

@tanstack/db-electron-sqlite-persisted-collection

npm i https://pkg.pr.new/TanStack/db/@tanstack/db-electron-sqlite-persisted-collection@1270

@tanstack/db-expo-sqlite-persisted-collection

npm i https://pkg.pr.new/TanStack/db/@tanstack/db-expo-sqlite-persisted-collection@1270

@tanstack/db-ivm

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

@tanstack/db-node-sqlite-persisted-collection

npm i https://pkg.pr.new/TanStack/db/@tanstack/db-node-sqlite-persisted-collection@1270

@tanstack/db-react-native-sqlite-persisted-collection

npm i https://pkg.pr.new/TanStack/db/@tanstack/db-react-native-sqlite-persisted-collection@1270

@tanstack/db-sqlite-persisted-collection-core

npm i https://pkg.pr.new/TanStack/db/@tanstack/db-sqlite-persisted-collection-core@1270

@tanstack/db-tauri-sqlite-persisted-collection

npm i https://pkg.pr.new/TanStack/db/@tanstack/db-tauri-sqlite-persisted-collection@1270

@tanstack/electric-db-collection

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

@tanstack/offline-transactions

npm i https://pkg.pr.new/TanStack/db/@tanstack/offline-transactions@1270

@tanstack/powersync-db-collection

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

@tanstack/query-db-collection

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

@tanstack/react-db

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

@tanstack/rxdb-db-collection

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

@tanstack/solid-db

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

@tanstack/svelte-db

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

@tanstack/trailbase-db-collection

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

@tanstack/vue-db

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

commit: a8ae8b7

@github-actions
Copy link
Contributor

github-actions bot commented Feb 19, 2026

Size Change: +1 B (0%)

Total Size: 111 kB

Filename Size Change
./packages/db/dist/esm/index.js 2.86 kB +1 B (+0.04%)
ℹ️ View Unchanged
Filename Size
./packages/db/dist/esm/collection/change-events.js 1.39 kB
./packages/db/dist/esm/collection/changes.js 1.38 kB
./packages/db/dist/esm/collection/cleanup-queue.js 810 B
./packages/db/dist/esm/collection/events.js 434 B
./packages/db/dist/esm/collection/index.js 3.7 kB
./packages/db/dist/esm/collection/indexes.js 2.35 kB
./packages/db/dist/esm/collection/lifecycle.js 1.76 kB
./packages/db/dist/esm/collection/mutations.js 2.47 kB
./packages/db/dist/esm/collection/state.js 5.26 kB
./packages/db/dist/esm/collection/subscription.js 3.71 kB
./packages/db/dist/esm/collection/sync.js 2.88 kB
./packages/db/dist/esm/collection/transaction-metadata.js 144 B
./packages/db/dist/esm/deferred.js 207 B
./packages/db/dist/esm/errors.js 4.83 kB
./packages/db/dist/esm/event-emitter.js 748 B
./packages/db/dist/esm/indexes/auto-index.js 777 B
./packages/db/dist/esm/indexes/base-index.js 766 B
./packages/db/dist/esm/indexes/btree-index.js 2.17 kB
./packages/db/dist/esm/indexes/lazy-index.js 1.24 kB
./packages/db/dist/esm/indexes/reverse-index.js 538 B
./packages/db/dist/esm/local-only.js 890 B
./packages/db/dist/esm/local-storage.js 2.1 kB
./packages/db/dist/esm/optimistic-action.js 359 B
./packages/db/dist/esm/paced-mutations.js 496 B
./packages/db/dist/esm/proxy.js 3.75 kB
./packages/db/dist/esm/query/builder/functions.js 792 B
./packages/db/dist/esm/query/builder/index.js 5.15 kB
./packages/db/dist/esm/query/builder/ref-proxy.js 1.05 kB
./packages/db/dist/esm/query/compiler/evaluators.js 1.62 kB
./packages/db/dist/esm/query/compiler/expressions.js 430 B
./packages/db/dist/esm/query/compiler/group-by.js 2.69 kB
./packages/db/dist/esm/query/compiler/index.js 3.62 kB
./packages/db/dist/esm/query/compiler/joins.js 2.11 kB
./packages/db/dist/esm/query/compiler/order-by.js 1.5 kB
./packages/db/dist/esm/query/compiler/select.js 1.11 kB
./packages/db/dist/esm/query/effect.js 4.78 kB
./packages/db/dist/esm/query/expression-helpers.js 1.43 kB
./packages/db/dist/esm/query/ir.js 784 B
./packages/db/dist/esm/query/live-query-collection.js 360 B
./packages/db/dist/esm/query/live/collection-config-builder.js 7.63 kB
./packages/db/dist/esm/query/live/collection-registry.js 264 B
./packages/db/dist/esm/query/live/collection-subscriber.js 1.94 kB
./packages/db/dist/esm/query/live/internal.js 145 B
./packages/db/dist/esm/query/live/utils.js 1.57 kB
./packages/db/dist/esm/query/optimizer.js 2.62 kB
./packages/db/dist/esm/query/predicate-utils.js 2.97 kB
./packages/db/dist/esm/query/query-once.js 359 B
./packages/db/dist/esm/query/subset-dedupe.js 960 B
./packages/db/dist/esm/scheduler.js 1.3 kB
./packages/db/dist/esm/SortedMap.js 1.3 kB
./packages/db/dist/esm/strategies/debounceStrategy.js 247 B
./packages/db/dist/esm/strategies/queueStrategy.js 428 B
./packages/db/dist/esm/strategies/throttleStrategy.js 246 B
./packages/db/dist/esm/transactions.js 2.9 kB
./packages/db/dist/esm/utils.js 927 B
./packages/db/dist/esm/utils/browser-polyfills.js 304 B
./packages/db/dist/esm/utils/btree.js 5.61 kB
./packages/db/dist/esm/utils/comparison.js 1.05 kB
./packages/db/dist/esm/utils/cursor.js 457 B
./packages/db/dist/esm/utils/index-optimization.js 1.54 kB
./packages/db/dist/esm/utils/type-guards.js 157 B
./packages/db/dist/esm/virtual-props.js 360 B

compressed-size-action::db-package-size

@github-actions
Copy link
Contributor

github-actions bot commented Feb 19, 2026

Size Change: 0 B

Total Size: 4.23 kB

ℹ️ View Unchanged
Filename Size
./packages/react-db/dist/esm/index.js 249 B
./packages/react-db/dist/esm/useLiveInfiniteQuery.js 1.32 kB
./packages/react-db/dist/esm/useLiveQuery.js 1.34 kB
./packages/react-db/dist/esm/useLiveQueryEffect.js 355 B
./packages/react-db/dist/esm/useLiveSuspenseQuery.js 559 B
./packages/react-db/dist/esm/usePacedMutations.js 401 B

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

robacourt added a commit to electric-sql/electric that referenced this pull request Mar 2, 2026
Adds 4 new test cases covering DNF scenarios: multi-disjunct partial/full
deactivation, active_conditions overwrite on re-send, simple shapes without
active_conditions, and mixed rows with/without active_conditions.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@kevin-dp
Copy link
Contributor Author

Important

Preview package dependency: This PR currently uses a preview build of @electric-sql/client from electric-sql/electric#4043:

"@electric-sql/client": "https://pkg.pr.new/@electric-sql/client@4043"

Before merging this PR, replace the preview URL with the published version (e.g. "^1.6.0" or whatever version includes the move-in event support).

kevin-dp and others added 6 commits March 23, 2026 15:59
…rbitrary boolean WHERE clauses

Support the new Electric server wire protocol (PR electric-sql/electric#3791):
- Change tag delimiter from `|` to `/`, replace `_` wildcards with empty
  segments (NON_PARTICIPATING positions)
- Add `active_conditions` header support for DNF visibility evaluation
- Shapes with subquery dependencies use DNF: a row is visible if ANY
  disjunct has ALL its positions satisfied in active_conditions
- Simple shapes (no subquery dependencies) retain existing behavior:
  row deleted when tag set becomes empty
- Derive disjunct_positions once per shape (not per-row like the Elixir
  client) since the DNF structure is fixed by the WHERE clause

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…attern to MovePattern

- Rename MoveOutPattern to MovePattern in tag-index.ts and electric.ts
- Add isMoveInMessage() type guard
- Add processMoveInEvent(): re-activates conditions for matching rows
  (silent operation, no messages emitted to collection)
- Refactor move-out in DNF mode to preserve tag index entries for
  visible rows, so move-in can find them to re-activate positions
- Handle move-in in message loop and progressive mode atomic swap

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add tests ported from the Elixir client's tag_tracker_test.exs:
- Move-in activates correct positions
- Move-out → move-in → move-out full lifecycle cycle
- Deleted rows not resurrected by move-in (tag index cleaned up)
- Orphaned tag index entries don't cause phantom deletes
- Deleted row cleans up ALL tag index entries
- Multiple patterns deactivating same row in one call
- Unit tests for parseTag, rowVisible, and deriveDisjunctPositions

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Switch to the preview package from electric-sql/electric#4043 so that
move-in event types are available without unsafe casts in tests.

NOTE: replace the preview URL with the released version before merging.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@kevin-dp kevin-dp force-pushed the feat/dnf-active-conditions branch from 0d94d47 to 532e779 Compare March 23, 2026 15:01
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