@rocicorp/zero 1.10.0-canary.22 → 1.10.0-canary.24
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/out/analyze-query/src/analyze-cli.js +2 -2
- package/out/analyze-query/src/analyze-cli.js.map +1 -1
- package/out/analyze-query/src/bin-analyze.js +9 -8
- package/out/analyze-query/src/bin-analyze.js.map +1 -1
- package/out/replicache/src/btree/node.d.ts.map +1 -1
- package/out/replicache/src/btree/node.js +3 -6
- package/out/replicache/src/btree/node.js.map +1 -1
- package/out/replicache/src/dag/gc.d.ts.map +1 -1
- package/out/replicache/src/dag/gc.js +6 -10
- package/out/replicache/src/dag/gc.js.map +1 -1
- package/out/replicache/src/kv/sqlite-store.d.ts.map +1 -1
- package/out/replicache/src/kv/sqlite-store.js +24 -2
- package/out/replicache/src/kv/sqlite-store.js.map +1 -1
- package/out/replicache/src/persist/persist.js +1 -1
- package/out/shared/src/arrays.d.ts +5 -0
- package/out/shared/src/arrays.d.ts.map +1 -1
- package/out/shared/src/arrays.js +8 -10
- package/out/shared/src/arrays.js.map +1 -1
- package/out/shared/src/map.d.ts +19 -2
- package/out/shared/src/map.d.ts.map +1 -1
- package/out/shared/src/map.js +18 -4
- package/out/shared/src/map.js.map +1 -1
- package/out/z2s/src/compiler.js +1 -1
- package/out/z2s/src/sql.d.ts.map +1 -1
- package/out/z2s/src/sql.js +2 -2
- package/out/z2s/src/sql.js.map +1 -1
- package/out/zero/package.js +1 -1
- package/out/zero/package.js.map +1 -1
- package/out/zero-cache/src/auth/write-authorizer.d.ts.map +1 -1
- package/out/zero-cache/src/auth/write-authorizer.js +1 -0
- package/out/zero-cache/src/auth/write-authorizer.js.map +1 -1
- package/out/zero-cache/src/config/zero-config.d.ts +23 -0
- package/out/zero-cache/src/config/zero-config.d.ts.map +1 -1
- package/out/zero-cache/src/config/zero-config.js +63 -1
- package/out/zero-cache/src/config/zero-config.js.map +1 -1
- package/out/zero-cache/src/db/lite-tables.d.ts.map +1 -1
- package/out/zero-cache/src/db/lite-tables.js +3 -4
- package/out/zero-cache/src/db/lite-tables.js.map +1 -1
- package/out/zero-cache/src/observability/metrics.d.ts.map +1 -1
- package/out/zero-cache/src/observability/metrics.js +2 -7
- package/out/zero-cache/src/observability/metrics.js.map +1 -1
- package/out/zero-cache/src/server/change-streamer.d.ts.map +1 -1
- package/out/zero-cache/src/server/change-streamer.js +11 -3
- package/out/zero-cache/src/server/change-streamer.js.map +1 -1
- package/out/zero-cache/src/server/inspector-delegate.d.ts +18 -2
- package/out/zero-cache/src/server/inspector-delegate.d.ts.map +1 -1
- package/out/zero-cache/src/server/inspector-delegate.js +22 -15
- package/out/zero-cache/src/server/inspector-delegate.js.map +1 -1
- package/out/zero-cache/src/server/main.d.ts.map +1 -1
- package/out/zero-cache/src/server/main.js +8 -1
- package/out/zero-cache/src/server/main.js.map +1 -1
- package/out/zero-cache/src/server/mutator.js +2 -0
- package/out/zero-cache/src/server/mutator.js.map +1 -1
- package/out/zero-cache/src/server/reaper.d.ts.map +1 -1
- package/out/zero-cache/src/server/reaper.js +2 -0
- package/out/zero-cache/src/server/reaper.js.map +1 -1
- package/out/zero-cache/src/server/replicator.d.ts.map +1 -1
- package/out/zero-cache/src/server/replicator.js +2 -0
- package/out/zero-cache/src/server/replicator.js.map +1 -1
- package/out/zero-cache/src/server/runner/zero-dispatcher.d.ts.map +1 -1
- package/out/zero-cache/src/server/runner/zero-dispatcher.js +3 -0
- package/out/zero-cache/src/server/runner/zero-dispatcher.js.map +1 -1
- package/out/zero-cache/src/server/syncer.d.ts.map +1 -1
- package/out/zero-cache/src/server/syncer.js +5 -1
- package/out/zero-cache/src/server/syncer.js.map +1 -1
- package/out/zero-cache/src/services/analyze.d.ts.map +1 -1
- package/out/zero-cache/src/services/analyze.js +11 -9
- package/out/zero-cache/src/services/analyze.js.map +1 -1
- package/out/zero-cache/src/services/change-source/common/backfill-manager.d.ts.map +1 -1
- package/out/zero-cache/src/services/change-source/common/backfill-manager.js +14 -1
- package/out/zero-cache/src/services/change-source/common/backfill-manager.js.map +1 -1
- package/out/zero-cache/src/services/change-source/common/change-stream-multiplexer.d.ts.map +1 -1
- package/out/zero-cache/src/services/change-source/common/change-stream-multiplexer.js +15 -3
- package/out/zero-cache/src/services/change-source/common/change-stream-multiplexer.js.map +1 -1
- package/out/zero-cache/src/services/change-source/custom/change-source.js +2 -2
- package/out/zero-cache/src/services/change-source/custom/change-source.js.map +1 -1
- package/out/zero-cache/src/services/change-source/pg/initial-sync.js +1 -1
- package/out/zero-cache/src/services/change-streamer/change-streamer-http.d.ts +3 -0
- package/out/zero-cache/src/services/change-streamer/change-streamer-http.d.ts.map +1 -1
- package/out/zero-cache/src/services/change-streamer/change-streamer-http.js +6 -4
- package/out/zero-cache/src/services/change-streamer/change-streamer-http.js.map +1 -1
- package/out/zero-cache/src/services/mutagen/mutagen.d.ts +5 -0
- package/out/zero-cache/src/services/mutagen/mutagen.d.ts.map +1 -1
- package/out/zero-cache/src/services/mutagen/mutagen.js +7 -1
- package/out/zero-cache/src/services/mutagen/mutagen.js.map +1 -1
- package/out/zero-cache/src/services/mutagen/pusher.d.ts +32 -32
- package/out/zero-cache/src/services/mutagen/pusher.d.ts.map +1 -1
- package/out/zero-cache/src/services/mutagen/pusher.js +5 -6
- package/out/zero-cache/src/services/mutagen/pusher.js.map +1 -1
- package/out/zero-cache/src/services/profz.d.ts +7 -0
- package/out/zero-cache/src/services/profz.d.ts.map +1 -0
- package/out/zero-cache/src/services/profz.js +103 -0
- package/out/zero-cache/src/services/profz.js.map +1 -0
- package/out/zero-cache/src/services/run-ast.d.ts +12 -0
- package/out/zero-cache/src/services/run-ast.d.ts.map +1 -1
- package/out/zero-cache/src/services/run-ast.js +26 -14
- package/out/zero-cache/src/services/run-ast.js.map +1 -1
- package/out/zero-cache/src/services/runner.d.ts.map +1 -1
- package/out/zero-cache/src/services/runner.js +1 -1
- package/out/zero-cache/src/services/runner.js.map +1 -1
- package/out/zero-cache/src/services/view-syncer/cvr.d.ts +45 -0
- package/out/zero-cache/src/services/view-syncer/cvr.d.ts.map +1 -1
- package/out/zero-cache/src/services/view-syncer/cvr.js +133 -1
- package/out/zero-cache/src/services/view-syncer/cvr.js.map +1 -1
- package/out/zero-cache/src/services/view-syncer/drain-coordinator.d.ts +14 -1
- package/out/zero-cache/src/services/view-syncer/drain-coordinator.d.ts.map +1 -1
- package/out/zero-cache/src/services/view-syncer/drain-coordinator.js +30 -4
- package/out/zero-cache/src/services/view-syncer/drain-coordinator.js.map +1 -1
- package/out/zero-cache/src/services/view-syncer/hydration-budget.d.ts +33 -0
- package/out/zero-cache/src/services/view-syncer/hydration-budget.d.ts.map +1 -0
- package/out/zero-cache/src/services/view-syncer/hydration-budget.js +62 -0
- package/out/zero-cache/src/services/view-syncer/hydration-budget.js.map +1 -0
- package/out/zero-cache/src/services/view-syncer/hydration-circuit-breaker.d.ts +51 -0
- package/out/zero-cache/src/services/view-syncer/hydration-circuit-breaker.d.ts.map +1 -0
- package/out/zero-cache/src/services/view-syncer/hydration-circuit-breaker.js +78 -0
- package/out/zero-cache/src/services/view-syncer/hydration-circuit-breaker.js.map +1 -0
- package/out/zero-cache/src/services/view-syncer/inspect-handler.d.ts +1 -1
- package/out/zero-cache/src/services/view-syncer/inspect-handler.d.ts.map +1 -1
- package/out/zero-cache/src/services/view-syncer/inspect-handler.js +2 -2
- package/out/zero-cache/src/services/view-syncer/inspect-handler.js.map +1 -1
- package/out/zero-cache/src/services/view-syncer/pipeline-driver.d.ts +2 -1
- package/out/zero-cache/src/services/view-syncer/pipeline-driver.d.ts.map +1 -1
- package/out/zero-cache/src/services/view-syncer/pipeline-driver.js +42 -17
- package/out/zero-cache/src/services/view-syncer/pipeline-driver.js.map +1 -1
- package/out/zero-cache/src/services/view-syncer/query-covering.d.ts.map +1 -1
- package/out/zero-cache/src/services/view-syncer/query-covering.js +2 -6
- package/out/zero-cache/src/services/view-syncer/query-covering.js.map +1 -1
- package/out/zero-cache/src/services/view-syncer/snapshot-row-cache.d.ts +95 -0
- package/out/zero-cache/src/services/view-syncer/snapshot-row-cache.d.ts.map +1 -0
- package/out/zero-cache/src/services/view-syncer/snapshot-row-cache.js +155 -0
- package/out/zero-cache/src/services/view-syncer/snapshot-row-cache.js.map +1 -0
- package/out/zero-cache/src/services/view-syncer/snapshotter.d.ts +42 -4
- package/out/zero-cache/src/services/view-syncer/snapshotter.d.ts.map +1 -1
- package/out/zero-cache/src/services/view-syncer/snapshotter.js +117 -28
- package/out/zero-cache/src/services/view-syncer/snapshotter.js.map +1 -1
- package/out/zero-cache/src/services/view-syncer/view-syncer.d.ts +11 -1
- package/out/zero-cache/src/services/view-syncer/view-syncer.d.ts.map +1 -1
- package/out/zero-cache/src/services/view-syncer/view-syncer.js +466 -95
- package/out/zero-cache/src/services/view-syncer/view-syncer.js.map +1 -1
- package/out/zero-cache/src/types/processes.d.ts +32 -0
- package/out/zero-cache/src/types/processes.d.ts.map +1 -1
- package/out/zero-cache/src/types/processes.js +43 -4
- package/out/zero-cache/src/types/processes.js.map +1 -1
- package/out/zero-cache/src/types/profiler.d.ts +12 -0
- package/out/zero-cache/src/types/profiler.d.ts.map +1 -1
- package/out/zero-cache/src/types/profiler.js +46 -1
- package/out/zero-cache/src/types/profiler.js.map +1 -1
- package/out/zero-cache/src/types/row-key.d.ts.map +1 -1
- package/out/zero-cache/src/types/row-key.js +5 -5
- package/out/zero-cache/src/types/row-key.js.map +1 -1
- package/out/zero-cache/src/workers/connection.js +3 -3
- package/out/zero-cache/src/workers/connection.js.map +1 -1
- package/out/zero-cache/src/workers/syncer-ws-message-handler.d.ts.map +1 -1
- package/out/zero-cache/src/workers/syncer-ws-message-handler.js +21 -16
- package/out/zero-cache/src/workers/syncer-ws-message-handler.js.map +1 -1
- package/out/zero-cache/src/workers/syncer.d.ts.map +1 -1
- package/out/zero-cache/src/workers/syncer.js +10 -1
- package/out/zero-cache/src/workers/syncer.js.map +1 -1
- package/out/zero-client/src/client/context.d.ts +16 -3
- package/out/zero-client/src/client/context.d.ts.map +1 -1
- package/out/zero-client/src/client/context.js +85 -14
- package/out/zero-client/src/client/context.js.map +1 -1
- package/out/zero-client/src/client/ivm-branch.d.ts.map +1 -1
- package/out/zero-client/src/client/ivm-branch.js +20 -3
- package/out/zero-client/src/client/ivm-branch.js.map +1 -1
- package/out/zero-client/src/client/query-manager.d.ts.map +1 -1
- package/out/zero-client/src/client/query-manager.js +2 -5
- package/out/zero-client/src/client/query-manager.js.map +1 -1
- package/out/zero-client/src/client/version.js +1 -1
- package/out/zero-client/src/client/zero-rep.d.ts.map +1 -1
- package/out/zero-client/src/client/zero-rep.js +1 -1
- package/out/zero-client/src/client/zero-rep.js.map +1 -1
- package/out/zero-client/src/client/zero.d.ts.map +1 -1
- package/out/zero-client/src/client/zero.js +2 -2
- package/out/zero-client/src/client/zero.js.map +1 -1
- package/out/zero-protocol/src/analyze-query-result.d.ts +5 -5
- package/out/zero-protocol/src/analyze-query-result.d.ts.map +1 -1
- package/out/zero-protocol/src/analyze-query-result.js +1 -1
- package/out/zero-protocol/src/analyze-query-result.js.map +1 -1
- package/out/zero-protocol/src/ast.d.ts.map +1 -1
- package/out/zero-protocol/src/ast.js +13 -14
- package/out/zero-protocol/src/ast.js.map +1 -1
- package/out/zero-protocol/src/down.d.ts +2 -2
- package/out/zero-protocol/src/error.d.ts +1 -1
- package/out/zero-protocol/src/inspect-down.d.ts +6 -6
- package/out/zero-protocol/src/protocol-version.d.ts.map +1 -1
- package/out/zero-protocol/src/protocol-version.js.map +1 -1
- package/out/zero-protocol/src/query-hash.d.ts.map +1 -1
- package/out/zero-protocol/src/query-hash.js +2 -5
- package/out/zero-protocol/src/query-hash.js.map +1 -1
- package/out/zero-solid/src/solid-view.d.ts +7 -0
- package/out/zero-solid/src/solid-view.d.ts.map +1 -1
- package/out/zero-solid/src/solid-view.js +13 -2
- package/out/zero-solid/src/solid-view.js.map +1 -1
- package/out/zql/src/builder/builder.d.ts +19 -0
- package/out/zql/src/builder/builder.d.ts.map +1 -1
- package/out/zql/src/builder/builder.js +28 -11
- package/out/zql/src/builder/builder.js.map +1 -1
- package/out/zql/src/builder/correlated-predicate-pushdown.d.ts +43 -0
- package/out/zql/src/builder/correlated-predicate-pushdown.d.ts.map +1 -0
- package/out/zql/src/builder/correlated-predicate-pushdown.js +161 -0
- package/out/zql/src/builder/correlated-predicate-pushdown.js.map +1 -0
- package/out/zql/src/builder/debug-delegate.d.ts +6 -1
- package/out/zql/src/builder/debug-delegate.d.ts.map +1 -1
- package/out/zql/src/builder/debug-delegate.js +14 -2
- package/out/zql/src/builder/debug-delegate.js.map +1 -1
- package/out/zql/src/ivm/array-view.d.ts +19 -0
- package/out/zql/src/ivm/array-view.d.ts.map +1 -1
- package/out/zql/src/ivm/array-view.js +39 -2
- package/out/zql/src/ivm/array-view.js.map +1 -1
- package/out/zql/src/ivm/connection-index.d.ts +68 -0
- package/out/zql/src/ivm/connection-index.d.ts.map +1 -0
- package/out/zql/src/ivm/connection-index.js +149 -0
- package/out/zql/src/ivm/connection-index.js.map +1 -0
- package/out/zql/src/ivm/exists.js +1 -1
- package/out/zql/src/ivm/filter-operators.d.ts +3 -2
- package/out/zql/src/ivm/filter-operators.d.ts.map +1 -1
- package/out/zql/src/ivm/filter-operators.js +19 -4
- package/out/zql/src/ivm/filter-operators.js.map +1 -1
- package/out/zql/src/ivm/memory-source.d.ts +13 -1
- package/out/zql/src/ivm/memory-source.d.ts.map +1 -1
- package/out/zql/src/ivm/memory-source.js +43 -4
- package/out/zql/src/ivm/memory-source.js.map +1 -1
- package/out/zql/src/ivm/operator.d.ts +40 -0
- package/out/zql/src/ivm/operator.d.ts.map +1 -1
- package/out/zql/src/ivm/operator.js.map +1 -1
- package/out/zql/src/ivm/view.d.ts +15 -0
- package/out/zql/src/ivm/view.d.ts.map +1 -1
- package/out/zql/src/planner/planner-builder.d.ts +12 -3
- package/out/zql/src/planner/planner-builder.d.ts.map +1 -1
- package/out/zql/src/planner/planner-builder.js +40 -20
- package/out/zql/src/planner/planner-builder.js.map +1 -1
- package/out/zql/src/planner/planner-connection.d.ts +28 -2
- package/out/zql/src/planner/planner-connection.d.ts.map +1 -1
- package/out/zql/src/planner/planner-connection.js +108 -8
- package/out/zql/src/planner/planner-connection.js.map +1 -1
- package/out/zql/src/planner/planner-debug.d.ts +1 -1
- package/out/zql/src/planner/planner-debug.d.ts.map +1 -1
- package/out/zql/src/planner/planner-debug.js +3 -8
- package/out/zql/src/planner/planner-debug.js.map +1 -1
- package/out/zql/src/planner/planner-fan-out.d.ts +1 -0
- package/out/zql/src/planner/planner-fan-out.d.ts.map +1 -1
- package/out/zql/src/planner/planner-fan-out.js +3 -0
- package/out/zql/src/planner/planner-fan-out.js.map +1 -1
- package/out/zql/src/planner/planner-filter.d.ts +59 -0
- package/out/zql/src/planner/planner-filter.d.ts.map +1 -0
- package/out/zql/src/planner/planner-filter.js +116 -0
- package/out/zql/src/planner/planner-filter.js.map +1 -0
- package/out/zql/src/planner/planner-graph.d.ts +2 -0
- package/out/zql/src/planner/planner-graph.d.ts.map +1 -1
- package/out/zql/src/planner/planner-graph.js +2 -0
- package/out/zql/src/planner/planner-graph.js.map +1 -1
- package/out/zql/src/planner/planner-join.d.ts +2 -0
- package/out/zql/src/planner/planner-join.d.ts.map +1 -1
- package/out/zql/src/planner/planner-join.js +7 -0
- package/out/zql/src/planner/planner-join.js.map +1 -1
- package/out/zql/src/planner/planner-node.d.ts +2 -1
- package/out/zql/src/planner/planner-node.d.ts.map +1 -1
- package/out/zql/src/planner/planner-node.js.map +1 -1
- package/out/zql/src/planner/planner-source.d.ts +2 -2
- package/out/zql/src/planner/planner-source.d.ts.map +1 -1
- package/out/zql/src/planner/planner-source.js +2 -2
- package/out/zql/src/planner/planner-source.js.map +1 -1
- package/out/zql/src/query/query-delegate-base.d.ts +2 -2
- package/out/zql/src/query/query-delegate-base.d.ts.map +1 -1
- package/out/zql/src/query/query-delegate-base.js +16 -10
- package/out/zql/src/query/query-delegate-base.js.map +1 -1
- package/out/zql/src/query/query-delegate.d.ts +22 -5
- package/out/zql/src/query/query-delegate.d.ts.map +1 -1
- package/out/zql/src/query/query-impl.d.ts.map +1 -1
- package/out/zql/src/query/query-impl.js +6 -23
- package/out/zql/src/query/query-impl.js.map +1 -1
- package/out/zql/src/query/query-transitions.d.ts.map +1 -1
- package/out/zql/src/query/query-transitions.js +2 -5
- package/out/zql/src/query/query-transitions.js.map +1 -1
- package/out/zql/src/query/query.d.ts +4 -1
- package/out/zql/src/query/query.d.ts.map +1 -1
- package/out/zql/src/query/runnable-query-impl.d.ts.map +1 -1
- package/out/zql/src/query/runnable-query-impl.js +2 -10
- package/out/zql/src/query/runnable-query-impl.js.map +1 -1
- package/out/zqlite/src/db.d.ts +9 -1
- package/out/zqlite/src/db.d.ts.map +1 -1
- package/out/zqlite/src/db.js +8 -2
- package/out/zqlite/src/db.js.map +1 -1
- package/out/zqlite/src/query-builder.d.ts +1 -1
- package/out/zqlite/src/query-builder.d.ts.map +1 -1
- package/out/zqlite/src/query-builder.js +2 -1
- package/out/zqlite/src/query-builder.js.map +1 -1
- package/out/zqlite/src/query-delegate.d.ts.map +1 -1
- package/out/zqlite/src/query-delegate.js +5 -6
- package/out/zqlite/src/query-delegate.js.map +1 -1
- package/out/zqlite/src/sqlite-cost-model.d.ts.map +1 -1
- package/out/zqlite/src/sqlite-cost-model.js +2 -30
- package/out/zqlite/src/sqlite-cost-model.js.map +1 -1
- package/out/zqlite/src/sqlite-stat-fanout.d.ts.map +1 -1
- package/out/zqlite/src/sqlite-stat-fanout.js +3 -5
- package/out/zqlite/src/sqlite-stat-fanout.js.map +1 -1
- package/out/zqlite/src/table-source.d.ts +15 -2
- package/out/zqlite/src/table-source.d.ts.map +1 -1
- package/out/zqlite/src/table-source.js +28 -12
- package/out/zqlite/src/table-source.js.map +1 -1
- package/package.json +1 -1
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import { assert, unreachable } from "../../shared/src/asserts.js";
|
|
2
|
+
import { getOrInsertComputed } from "../../shared/src/map.js";
|
|
2
3
|
import { must } from "../../shared/src/must.js";
|
|
3
4
|
import { assertOrderingIncludesPK } from "../../zql/src/query/complete-ordering.js";
|
|
4
5
|
import { makeComparator } from "../../zql/src/ivm/data.js";
|
|
5
6
|
import { createPredicate, transformFilters } from "../../zql/src/builder/filter.js";
|
|
6
7
|
import { genPushAndWriteWithSplitEdit, generateWithOverlay, generateWithOverlayUnordered, generateWithStart } from "../../zql/src/ivm/memory-source.js";
|
|
7
8
|
import { timeSampled } from "../../otel/src/maybe-time.js";
|
|
9
|
+
import { ConnectionIndex } from "../../zql/src/ivm/connection-index.js";
|
|
8
10
|
import { compile, format, sql } from "./internal/sql.js";
|
|
9
11
|
import { StatementCache } from "./internal/statement-cache.js";
|
|
10
12
|
import { buildSelectQuery, toSQLiteType } from "./query-builder.js";
|
|
@@ -28,6 +30,7 @@ var eventCount = 0;
|
|
|
28
30
|
var TableSource = class {
|
|
29
31
|
#dbCache = /* @__PURE__ */ new WeakMap();
|
|
30
32
|
#connections = [];
|
|
33
|
+
#connectionIndex = new ConnectionIndex();
|
|
31
34
|
#table;
|
|
32
35
|
#columns;
|
|
33
36
|
#uniqueIndexes;
|
|
@@ -35,6 +38,7 @@ var TableSource = class {
|
|
|
35
38
|
#logConfig;
|
|
36
39
|
#lc;
|
|
37
40
|
#shouldYield;
|
|
41
|
+
#skipUnobservableChanges;
|
|
38
42
|
#stmts;
|
|
39
43
|
#overlay;
|
|
40
44
|
#pushEpoch = 0;
|
|
@@ -44,7 +48,7 @@ var TableSource = class {
|
|
|
44
48
|
* to yield control back to the caller at the end of the pipeline. Can
|
|
45
49
|
* also throw an error to abort the pipeline processing.
|
|
46
50
|
*/
|
|
47
|
-
constructor(logContext, logConfig, db, tableName, columns, primaryKey, shouldYield = () => false) {
|
|
51
|
+
constructor(logContext, logConfig, db, tableName, columns, primaryKey, shouldYield = () => false, options = {}) {
|
|
48
52
|
this.#lc = logContext;
|
|
49
53
|
this.#logConfig = logConfig;
|
|
50
54
|
this.#table = tableName;
|
|
@@ -53,6 +57,7 @@ var TableSource = class {
|
|
|
53
57
|
this.#primaryKey = primaryKey;
|
|
54
58
|
this.#stmts = this.#getStatementsFor(db);
|
|
55
59
|
this.#shouldYield = shouldYield;
|
|
60
|
+
this.#skipUnobservableChanges = options.skipUnobservableChanges ?? false;
|
|
56
61
|
const primaryKeyStr = JSON.stringify(primaryKey.toSorted());
|
|
57
62
|
assert(this.#uniqueIndexes.has(primaryKeyStr), `primary key ${primaryKeyStr} does not have a UNIQUE index`);
|
|
58
63
|
}
|
|
@@ -99,6 +104,9 @@ var TableSource = class {
|
|
|
99
104
|
compareRows: connection.compareRows
|
|
100
105
|
};
|
|
101
106
|
}
|
|
107
|
+
hasConnections() {
|
|
108
|
+
return this.#connections.length > 0;
|
|
109
|
+
}
|
|
102
110
|
connect(sort, filters, splitEditKeys, debug) {
|
|
103
111
|
const transformedFilters = transformFilters(filters);
|
|
104
112
|
const unordered = sort === void 0;
|
|
@@ -113,6 +121,7 @@ var TableSource = class {
|
|
|
113
121
|
const idx = this.#connections.indexOf(connection);
|
|
114
122
|
assert(idx !== -1, "Connection not found");
|
|
115
123
|
this.#connections.splice(idx, 1);
|
|
124
|
+
this.#connectionIndex.remove(connection);
|
|
116
125
|
},
|
|
117
126
|
fullyAppliedFilters: !transformedFilters.conditionsRemoved
|
|
118
127
|
};
|
|
@@ -132,6 +141,7 @@ var TableSource = class {
|
|
|
132
141
|
const schema = this.#getSchema(connection, unordered);
|
|
133
142
|
if (!unordered) assertOrderingIncludesPK(sort, this.#primaryKey);
|
|
134
143
|
this.#connections.push(connection);
|
|
144
|
+
this.#connectionIndex.add(connection, transformedFilters.filters);
|
|
135
145
|
return input;
|
|
136
146
|
}
|
|
137
147
|
toSQLiteRow(row) {
|
|
@@ -143,12 +153,13 @@ var TableSource = class {
|
|
|
143
153
|
const cachedStatement = this.#stmts.cache.get(sqlAndBindings.text);
|
|
144
154
|
cachedStatement.statement.safeIntegers(true);
|
|
145
155
|
const rowIterator = cachedStatement.statement.iterate(...sqlAndBindings.values);
|
|
156
|
+
const overlayPredicate = mergeOverlayPredicate(connection.filters?.predicate, req.filter);
|
|
146
157
|
try {
|
|
147
158
|
debug?.initQuery(this.#table, sqlAndBindings.text);
|
|
148
159
|
if (sort) {
|
|
149
160
|
const comparator = makeComparator(sort, req.reverse);
|
|
150
|
-
yield* generateWithStart(generateWithYields(generateWithOverlay(req.start?.row, this.#mapFromSQLiteTypes(this.#columns, rowIterator, sqlAndBindings.text, debug), req.constraint, this.#overlay, connection.lastPushedEpoch, comparator, comparator,
|
|
151
|
-
} else yield* generateWithYields(generateWithOverlayUnordered(this.#mapFromSQLiteTypes(this.#columns, rowIterator, sqlAndBindings.text, debug), req.constraint, this.#overlay, connection.lastPushedEpoch, this.#primaryKey,
|
|
161
|
+
yield* generateWithStart(generateWithYields(generateWithOverlay(req.start?.row, this.#mapFromSQLiteTypes(this.#columns, rowIterator, sqlAndBindings.text, debug), req.constraint, this.#overlay, connection.lastPushedEpoch, comparator, comparator, overlayPredicate, req.multiConstraints), this.#shouldYield), req.start, comparator);
|
|
162
|
+
} else yield* generateWithYields(generateWithOverlayUnordered(this.#mapFromSQLiteTypes(this.#columns, rowIterator, sqlAndBindings.text, debug), req.constraint, this.#overlay, connection.lastPushedEpoch, this.#primaryKey, overlayPredicate, req.multiConstraints), this.#shouldYield);
|
|
152
163
|
} finally {
|
|
153
164
|
rowIterator.return?.();
|
|
154
165
|
if (debug) {
|
|
@@ -181,11 +192,15 @@ var TableSource = class {
|
|
|
181
192
|
*push(change) {
|
|
182
193
|
for (const result of this.genPush(change)) if (result === "yield") yield result;
|
|
183
194
|
}
|
|
184
|
-
genPush(change) {
|
|
195
|
+
*genPush(change) {
|
|
196
|
+
if (this.#skipUnobservableChanges && !this.#connectionIndex.mayAcceptChange(change)) {
|
|
197
|
+
if (change[0] === 1) this.#writeChange(change);
|
|
198
|
+
return;
|
|
199
|
+
}
|
|
185
200
|
const exists = (row) => this.#stmts.checkExists.get(...toSQLiteTypes(this.#primaryKey, row, this.#columns))?.exists === 1;
|
|
186
201
|
const setOverlay = (o) => this.#overlay = o;
|
|
187
202
|
const writeChange = (c) => this.#writeChange(c);
|
|
188
|
-
|
|
203
|
+
yield* genPushAndWriteWithSplitEdit(this.#connections, change, exists, setOverlay, writeChange, () => ++this.#pushEpoch);
|
|
189
204
|
}
|
|
190
205
|
#writeChange(change) {
|
|
191
206
|
switch (change[0]) {
|
|
@@ -214,12 +229,7 @@ var TableSource = class {
|
|
|
214
229
|
#getRowStmtCache = /* @__PURE__ */ new Map();
|
|
215
230
|
#getRowStmt(keyCols) {
|
|
216
231
|
const keyString = JSON.stringify(keyCols);
|
|
217
|
-
|
|
218
|
-
if (!stmt) {
|
|
219
|
-
stmt = compile(sql`SELECT ${this.#allColumns} FROM ${sql.ident(this.#table)} WHERE ${sql.join(keyCols.map((k) => sql`${sql.ident(k)}=?`), sql` AND`)}`);
|
|
220
|
-
this.#getRowStmtCache.set(keyString, stmt);
|
|
221
|
-
}
|
|
222
|
-
return stmt;
|
|
232
|
+
return getOrInsertComputed(this.#getRowStmtCache, keyString, () => compile(sql`SELECT ${this.#allColumns} FROM ${sql.ident(this.#table)} WHERE ${sql.join(keyCols.map((k) => sql`${sql.ident(k)}=?`), sql` AND`)}`));
|
|
223
233
|
}
|
|
224
234
|
/**
|
|
225
235
|
* Retrieves a row from the backing DB by a unique key, or `undefined` if such a
|
|
@@ -236,9 +246,15 @@ var TableSource = class {
|
|
|
236
246
|
return row;
|
|
237
247
|
}
|
|
238
248
|
#requestToSQL(request, filters, order) {
|
|
239
|
-
return buildSelectQuery(this.#table, this.#columns, request.constraint, filters, order, request.reverse, request.start, request.multiConstraints);
|
|
249
|
+
return buildSelectQuery(this.#table, this.#columns, request.constraint, filters, order, request.reverse, request.start, request.multiConstraints, request.filter);
|
|
240
250
|
}
|
|
241
251
|
};
|
|
252
|
+
function mergeOverlayPredicate(connPredicate, reqFilter) {
|
|
253
|
+
if (!reqFilter) return connPredicate;
|
|
254
|
+
const reqPredicate = createPredicate(reqFilter);
|
|
255
|
+
if (!connPredicate) return reqPredicate;
|
|
256
|
+
return (row) => connPredicate(row) && reqPredicate(row);
|
|
257
|
+
}
|
|
242
258
|
function getUniqueIndexes(db, tableName) {
|
|
243
259
|
const sqlAndBindings = format(sql`
|
|
244
260
|
SELECT idx.name, json_group_array(col.name) as columnsJSON
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"table-source.js","names":["#dbCache","#connections","#table","#columns","#uniqueIndexes","#primaryKey","#logConfig","#lc","#shouldYield","#stmts","#getStatementsFor","#allColumns","#fetch","#getSchema","#requestToSQL","#mapFromSQLiteTypes","#overlay","#writeChange","#pushEpoch","#getRowStmtCache","#getRowStmt"],"sources":["../../../../zqlite/src/table-source.ts"],"sourcesContent":["import type {SQLQuery} from '@databases/sql';\nimport type {LogContext} from '@rocicorp/logger';\nimport SQLite3Database from '@rocicorp/zero-sqlite3';\nimport type {LogConfig} from '../../otel/src/log-options.ts';\nimport {timeSampled} from '../../otel/src/maybe-time.ts';\nimport {assert, unreachable} from '../../shared/src/asserts.ts';\nimport {must} from '../../shared/src/must.ts';\nimport type {Writable} from '../../shared/src/writable.ts';\nimport type {Condition, Ordering} from '../../zero-protocol/src/ast.ts';\nimport type {Row, Value} from '../../zero-protocol/src/data.ts';\nimport type {PrimaryKey} from '../../zero-protocol/src/primary-key.ts';\nimport type {\n SchemaValue,\n ValueType,\n} from '../../zero-schema/src/table-schema.ts';\nimport type {DebugDelegate} from '../../zql/src/builder/debug-delegate.ts';\nimport {\n createPredicate,\n transformFilters,\n} from '../../zql/src/builder/filter.ts';\nimport {ChangeType} from '../../zql/src/ivm/change-type.ts';\nimport {makeComparator, type Node} from '../../zql/src/ivm/data.ts';\nimport {\n generateWithOverlay,\n generateWithOverlayUnordered,\n generateWithStart,\n genPushAndWriteWithSplitEdit,\n type Connection,\n type Overlay,\n} from '../../zql/src/ivm/memory-source.ts';\nimport {type FetchRequest} from '../../zql/src/ivm/operator.ts';\nimport type {SourceSchema} from '../../zql/src/ivm/schema.ts';\nimport {SourceChangeIndex} from '../../zql/src/ivm/source-change-index.ts';\nimport {\n type Source,\n type SourceChange,\n type SourceInput,\n} from '../../zql/src/ivm/source.ts';\nimport type {Stream} from '../../zql/src/ivm/stream.ts';\nimport {assertOrderingIncludesPK} from '../../zql/src/query/complete-ordering.ts';\nimport type {Database, Statement} from './db.ts';\nimport {compile, format, sql} from './internal/sql.ts';\nimport {StatementCache} from './internal/statement-cache.ts';\nimport {\n buildSelectQuery,\n toSQLiteType,\n type NoSubqueryCondition,\n} from './query-builder.ts';\n\ntype Statements = {\n readonly cache: StatementCache;\n readonly insert: Statement;\n readonly delete: Statement;\n readonly update: Statement | undefined;\n readonly checkExists: Statement;\n readonly getExisting: Statement;\n};\n\nlet eventCount = 0;\n\n/**\n * A source that is backed by a SQLite table.\n *\n * Values are written to the backing table _after_ being vended by the source.\n *\n * This ordering of events is to ensure self joins function properly. That is,\n * we can't reveal a value to an output before it has been pushed to that output.\n *\n * The code is fairly straightforward except for:\n * 1. Dealing with a `fetch` that has a basis of `before`.\n * 2. Dealing with compound orders that have differing directions (a ASC, b DESC, c ASC)\n *\n * See comments in relevant functions for more details.\n */\nexport class TableSource implements Source {\n readonly #dbCache = new WeakMap<Database, Statements>();\n readonly #connections: Connection[] = [];\n readonly #table: string;\n readonly #columns: Record<string, SchemaValue>;\n // Maps sorted columns JSON string (e.g. '[\"a\",\"b\"]) to Set of columns.\n readonly #uniqueIndexes: Map<string, Set<string>>;\n readonly #primaryKey: PrimaryKey;\n readonly #logConfig: LogConfig;\n readonly #lc: LogContext;\n readonly #shouldYield: () => boolean;\n #stmts: Statements;\n #overlay?: Overlay | undefined;\n #pushEpoch = 0;\n\n /**\n * @param shouldYield a function called after each row is read from the database,\n * which should return true if the source should yield the special 'yield' value\n * to yield control back to the caller at the end of the pipeline. Can\n * also throw an error to abort the pipeline processing.\n */\n constructor(\n logContext: LogContext,\n logConfig: LogConfig,\n db: Database,\n tableName: string,\n columns: Record<string, SchemaValue>,\n primaryKey: PrimaryKey,\n shouldYield = () => false,\n ) {\n this.#lc = logContext;\n this.#logConfig = logConfig;\n this.#table = tableName;\n this.#columns = columns;\n this.#uniqueIndexes = getUniqueIndexes(db, tableName);\n this.#primaryKey = primaryKey;\n this.#stmts = this.#getStatementsFor(db);\n this.#shouldYield = shouldYield;\n\n const primaryKeyStr = JSON.stringify(primaryKey.toSorted());\n assert(\n this.#uniqueIndexes.has(primaryKeyStr),\n `primary key ${primaryKeyStr} does not have a UNIQUE index`,\n );\n }\n\n get tableSchema() {\n return {\n name: this.#table,\n columns: this.#columns,\n primaryKey: this.#primaryKey,\n };\n }\n\n /**\n * Sets the db (snapshot) to use, to facilitate the Snapshotter leapfrog\n * algorithm for concurrent traversal of historic timelines.\n */\n setDB(db: Database) {\n this.#stmts = this.#getStatementsFor(db);\n }\n\n #getStatementsFor(db: Database) {\n const cached = this.#dbCache.get(db);\n if (cached) {\n return cached;\n }\n\n const stmts = {\n cache: new StatementCache(db),\n insert: db.prepare(\n compile(\n sql`INSERT INTO ${sql.ident(this.#table)} (${sql.join(\n Object.keys(this.#columns).map(c => sql.ident(c)),\n ', ',\n )}) VALUES (${sql.__dangerous__rawValue(\n Array.from({length: Object.keys(this.#columns).length})\n .fill('?')\n .join(','),\n )})`,\n ),\n ),\n delete: db.prepare(\n compile(\n sql`DELETE FROM ${sql.ident(this.#table)} WHERE ${sql.join(\n this.#primaryKey.map(k => sql`${sql.ident(k)}=?`),\n ' AND ',\n )}`,\n ),\n ),\n // If all the columns are part of the primary key, we cannot use UPDATE.\n update:\n Object.keys(this.#columns).length > this.#primaryKey.length\n ? db.prepare(\n compile(\n sql`UPDATE ${sql.ident(this.#table)} SET ${sql.join(\n nonPrimaryKeys(this.#columns, this.#primaryKey).map(\n c => sql`${sql.ident(c)}=?`,\n ),\n ',',\n )} WHERE ${sql.join(\n this.#primaryKey.map(k => sql`${sql.ident(k)}=?`),\n ' AND ',\n )}`,\n ),\n )\n : undefined,\n checkExists: db.prepare(\n compile(\n sql`SELECT 1 AS \"exists\" FROM ${sql.ident(\n this.#table,\n )} WHERE ${sql.join(\n this.#primaryKey.map(k => sql`${sql.ident(k)}=?`),\n ' AND ',\n )} LIMIT 1`,\n ),\n ),\n getExisting: db.prepare(\n compile(\n sql`SELECT * FROM ${sql.ident(this.#table)} WHERE ${sql.join(\n this.#primaryKey.map(k => sql`${sql.ident(k)}=?`),\n ' AND ',\n )}`,\n ),\n ),\n };\n this.#dbCache.set(db, stmts);\n return stmts;\n }\n\n get #allColumns() {\n return sql.join(\n Object.keys(this.#columns).map(c => sql.ident(c)),\n sql`,`,\n );\n }\n\n #getSchema(connection: Connection, unordered: boolean): SourceSchema {\n return {\n tableName: this.#table,\n columns: this.#columns,\n primaryKey: this.#primaryKey,\n sort: unordered ? undefined : connection.sort,\n relationships: {},\n isHidden: false,\n system: 'client',\n compareRows: connection.compareRows,\n };\n }\n\n connect(\n sort: Ordering | undefined,\n filters?: Condition,\n splitEditKeys?: Set<string>,\n debug?: DebugDelegate,\n ) {\n const transformedFilters = transformFilters(filters);\n const unordered = sort === undefined;\n // PK comparator is used for source-level overlay matching (remove by PK\n // equality) even when no ordering is requested.\n const primaryKeySort: Ordering = this.#primaryKey.map(k => [k, 'asc']);\n\n const input: SourceInput = {\n getSchema: () => schema,\n fetch: req => this.#fetch(req, connection),\n setOutput: output => {\n connection.output = output;\n },\n destroy: () => {\n const idx = this.#connections.indexOf(connection);\n assert(idx !== -1, 'Connection not found');\n this.#connections.splice(idx, 1);\n },\n fullyAppliedFilters: !transformedFilters.conditionsRemoved,\n };\n\n const connection: Connection = {\n input,\n debug,\n output: undefined,\n sort,\n splitEditKeys,\n filters: transformedFilters.filters\n ? {\n condition: transformedFilters.filters,\n predicate: createPredicate(transformedFilters.filters),\n }\n : undefined,\n compareRows: sort ? makeComparator(sort) : makeComparator(primaryKeySort),\n lastPushedEpoch: 0,\n };\n const schema = this.#getSchema(connection, unordered);\n if (!unordered) {\n assertOrderingIncludesPK(sort, this.#primaryKey);\n }\n\n this.#connections.push(connection);\n return input;\n }\n\n toSQLiteRow(row: Row): Row {\n return Object.fromEntries(\n Object.entries(row).map(([key, value]) => [\n key,\n toSQLiteType(value, this.#columns[key].type),\n ]),\n ) as Row;\n }\n\n *#fetch(req: FetchRequest, connection: Connection): Stream<Node | 'yield'> {\n const {sort, debug} = connection;\n\n const query = this.#requestToSQL(req, connection.filters?.condition, sort);\n const sqlAndBindings = format(query);\n\n const cachedStatement = this.#stmts.cache.get(sqlAndBindings.text);\n cachedStatement.statement.safeIntegers(true);\n const rowIterator = cachedStatement.statement.iterate<Row>(\n ...sqlAndBindings.values,\n );\n try {\n debug?.initQuery(this.#table, sqlAndBindings.text);\n\n if (sort) {\n const comparator = makeComparator(sort, req.reverse);\n yield* generateWithStart(\n generateWithYields(\n generateWithOverlay(\n req.start?.row,\n this.#mapFromSQLiteTypes(\n this.#columns,\n rowIterator,\n sqlAndBindings.text,\n debug,\n ),\n req.constraint,\n this.#overlay,\n connection.lastPushedEpoch,\n comparator,\n // SQL does the ordering and constraining, so the row stream is\n // already in the connection's sort order: the splice comparator\n // and the `startAt` comparator coincide here.\n comparator,\n connection.filters?.predicate,\n req.multiConstraints,\n ),\n this.#shouldYield,\n ),\n req.start,\n comparator,\n );\n } else {\n yield* generateWithYields(\n generateWithOverlayUnordered(\n this.#mapFromSQLiteTypes(\n this.#columns,\n rowIterator,\n sqlAndBindings.text,\n debug,\n ),\n req.constraint,\n this.#overlay,\n connection.lastPushedEpoch,\n this.#primaryKey,\n connection.filters?.predicate,\n req.multiConstraints,\n ),\n this.#shouldYield,\n );\n }\n } finally {\n // Ensure the SQLite iterate() is closed.\n rowIterator.return?.();\n if (debug) {\n let totalNvisit = 0;\n const planLines: string[] = [];\n for (let i = 0; ; i++) {\n const nvisit = cachedStatement.statement.scanStatus(\n i,\n SQLite3Database.SQLITE_SCANSTAT_NVISIT,\n 1,\n );\n if (nvisit === undefined) {\n break;\n }\n totalNvisit += Number(nvisit);\n const explain = cachedStatement.statement.scanStatus(\n i,\n SQLite3Database.SQLITE_SCANSTAT_EXPLAIN,\n 1,\n );\n if (typeof explain === 'string' && explain.length > 0) {\n planLines.push(explain);\n }\n }\n if (totalNvisit !== 0) {\n debug.recordNVisit(this.#table, sqlAndBindings.text, totalNvisit);\n }\n if (planLines.length > 0) {\n debug.recordExplain(this.#table, sqlAndBindings.text, planLines);\n }\n cachedStatement.statement.scanStatusReset();\n }\n this.#stmts.cache.return(cachedStatement);\n }\n }\n\n *#mapFromSQLiteTypes(\n valueTypes: Record<string, SchemaValue>,\n rowIterator: IterableIterator<Row>,\n query: string,\n debug: DebugDelegate | undefined,\n ): IterableIterator<Row> {\n let result;\n do {\n result = timeSampled(\n this.#lc,\n ++eventCount,\n this.#logConfig.ivmSampling,\n () => rowIterator.next(),\n this.#logConfig.slowRowThreshold,\n () =>\n `table-source.next took too long for ${query}. Are you missing an index?`,\n );\n if (result.done) {\n break;\n }\n const row = fromSQLiteTypes(valueTypes, result.value, this.#table);\n debug?.rowVended(this.#table, query, row);\n yield row;\n } while (!result.done);\n }\n\n *push(change: SourceChange): Stream<'yield'> {\n for (const result of this.genPush(change)) {\n if (result === 'yield') {\n yield result;\n }\n }\n }\n\n genPush(change: SourceChange) {\n const exists = (row: Row) =>\n this.#stmts.checkExists.get<{exists: number} | undefined>(\n ...toSQLiteTypes(this.#primaryKey, row, this.#columns),\n )?.exists === 1;\n const setOverlay = (o: Overlay | undefined) => (this.#overlay = o);\n const writeChange = (c: SourceChange) => this.#writeChange(c);\n\n return genPushAndWriteWithSplitEdit(\n this.#connections,\n change,\n exists,\n setOverlay,\n writeChange,\n () => ++this.#pushEpoch,\n );\n }\n\n #writeChange(change: SourceChange) {\n switch (change[SourceChangeIndex.TYPE]) {\n case ChangeType.ADD:\n this.#stmts.insert.run(\n ...toSQLiteTypes(\n // TODO(arv): Compute this once!\n Object.keys(this.#columns),\n change[SourceChangeIndex.ROW],\n this.#columns,\n ),\n );\n break;\n case ChangeType.REMOVE:\n this.#stmts.delete.run(\n ...toSQLiteTypes(\n this.#primaryKey,\n change[SourceChangeIndex.ROW],\n this.#columns,\n ),\n );\n break;\n case ChangeType.EDIT: {\n // If the PK is the same, use UPDATE.\n if (\n canUseUpdate(\n change[SourceChangeIndex.OLD_ROW],\n change[SourceChangeIndex.ROW],\n this.#columns,\n this.#primaryKey,\n )\n ) {\n const mergedRow = {\n ...change[SourceChangeIndex.OLD_ROW],\n ...change[SourceChangeIndex.ROW],\n };\n const params = [\n ...nonPrimaryValues(this.#columns, this.#primaryKey, mergedRow),\n ...toSQLiteTypes(this.#primaryKey, mergedRow, this.#columns),\n ];\n must(this.#stmts.update).run(params);\n } else {\n this.#stmts.delete.run(\n ...toSQLiteTypes(\n this.#primaryKey,\n change[SourceChangeIndex.OLD_ROW],\n this.#columns,\n ),\n );\n this.#stmts.insert.run(\n ...toSQLiteTypes(\n Object.keys(this.#columns),\n change[SourceChangeIndex.ROW],\n this.#columns,\n ),\n );\n }\n\n break;\n }\n default:\n unreachable(change);\n }\n }\n\n #getRowStmtCache = new Map<string, string>();\n\n #getRowStmt(keyCols: string[]): string {\n const keyString = JSON.stringify(keyCols);\n let stmt = this.#getRowStmtCache.get(keyString);\n if (!stmt) {\n stmt = compile(\n sql`SELECT ${this.#allColumns} FROM ${sql.ident(\n this.#table,\n )} WHERE ${sql.join(\n keyCols.map(k => sql`${sql.ident(k)}=?`),\n sql` AND`,\n )}`,\n );\n this.#getRowStmtCache.set(keyString, stmt);\n }\n return stmt;\n }\n\n /**\n * Retrieves a row from the backing DB by a unique key, or `undefined` if such a\n * row does not exist. This is not used in the IVM pipeline but is useful\n * for retrieving data that is consistent with the state (and type\n * semantics) of the pipeline. Note that this key may not necessarily correspond\n * to the `primaryKey` with which this TableSource.\n */\n getRow(rowKey: Row): Row | undefined {\n const keyCols = Object.keys(rowKey);\n\n const stmt = this.#getRowStmt(keyCols);\n const row = this.#stmts.cache.use(stmt, cached =>\n cached.statement\n .safeIntegers(true)\n .get<Row>(...toSQLiteTypes(keyCols, rowKey, this.#columns)),\n );\n if (row) {\n return fromSQLiteTypes(this.#columns, row, this.#table);\n }\n return row;\n }\n\n #requestToSQL(\n request: FetchRequest,\n filters: NoSubqueryCondition | undefined,\n order: Ordering | undefined,\n ): SQLQuery {\n return buildSelectQuery(\n this.#table,\n this.#columns,\n request.constraint,\n filters,\n order,\n request.reverse,\n request.start,\n request.multiConstraints,\n );\n }\n}\n\nfunction getUniqueIndexes(\n db: Database,\n tableName: string,\n): Map<string, Set<string>> {\n const sqlAndBindings = format(\n sql`\n SELECT idx.name, json_group_array(col.name) as columnsJSON\n FROM sqlite_master as idx\n JOIN pragma_index_list(idx.tbl_name) AS info ON info.name = idx.name\n JOIN pragma_index_info(idx.name) as col\n WHERE idx.tbl_name = ${tableName} AND\n idx.type = 'index' AND \n info.\"unique\" != 0 AND\n info.partial = 0\n GROUP BY idx.name\n ORDER BY idx.name`,\n );\n const stmt = db.prepare(sqlAndBindings.text);\n const indexes = stmt.all<{columnsJSON: string}>(...sqlAndBindings.values);\n return new Map(\n indexes.map(({columnsJSON}) => {\n const columns = JSON.parse(columnsJSON);\n const set = new Set<string>(columns);\n return [JSON.stringify(columns.sort()), set];\n }),\n );\n}\n\nexport function toSQLiteTypes(\n columns: readonly string[],\n row: Row,\n columnTypes: Record<string, SchemaValue>,\n): readonly unknown[] {\n return columns.map(col => toSQLiteType(row[col], columnTypes[col].type));\n}\n\nexport function toSQLiteTypeName(type: ValueType) {\n switch (type) {\n case 'boolean':\n return 'INTEGER';\n case 'number':\n return 'REAL';\n case 'string':\n return 'TEXT';\n case 'null':\n return 'NULL';\n case 'json':\n return 'TEXT';\n }\n}\n\nexport function fromSQLiteTypes(\n valueTypes: Record<string, SchemaValue>,\n row: Row,\n tableName: string,\n): Row {\n const newRow: Writable<Row> = {};\n for (const key of Object.keys(row)) {\n const valueType = valueTypes[key];\n if (valueType === undefined) {\n const columnList = Object.keys(valueTypes).sort().join(', ');\n throw new Error(\n `Invalid column \"${key}\" for table \"${tableName}\". Synced columns include ${columnList}`,\n );\n }\n newRow[key] = fromSQLiteType(valueType.type, row[key], key, tableName);\n }\n return newRow;\n}\n\nfunction fromSQLiteType(\n valueType: ValueType,\n v: Value,\n column: string,\n tableName: string,\n): Value {\n if (v === null) {\n return null;\n }\n switch (valueType) {\n case 'boolean':\n return !!v;\n case 'number':\n case 'string':\n case 'null':\n if (typeof v === 'bigint') {\n const bi = v as bigint;\n if (bi > Number.MAX_SAFE_INTEGER || bi < Number.MIN_SAFE_INTEGER) {\n throw new UnsupportedValueError(\n `value ${bi} (in ${tableName}.${column}) is outside of supported bounds`,\n );\n }\n return Number(bi);\n }\n return v;\n case 'json':\n try {\n return JSON.parse(v as string);\n } catch (error) {\n const errorMessage =\n error instanceof Error ? error.message : String(error);\n throw new UnsupportedValueError(\n `Failed to parse JSON for ${tableName}.${column}: ${errorMessage}`,\n {cause: error},\n );\n }\n }\n}\n\nexport class UnsupportedValueError extends Error {}\n\nfunction canUseUpdate(\n oldRow: Row,\n row: Row,\n columns: Record<string, SchemaValue>,\n primaryKey: PrimaryKey,\n): boolean {\n for (const pk of primaryKey) {\n if (oldRow[pk] !== row[pk]) {\n return false;\n }\n }\n return Object.keys(columns).length > primaryKey.length;\n}\n\nfunction nonPrimaryValues(\n columns: Record<string, SchemaValue>,\n primaryKey: PrimaryKey,\n row: Row,\n): Iterable<unknown> {\n return nonPrimaryKeys(columns, primaryKey).map(c =>\n toSQLiteType(row[c], columns[c].type),\n );\n}\n\nfunction nonPrimaryKeys(\n columns: Record<string, SchemaValue>,\n primaryKey: PrimaryKey,\n) {\n return Object.keys(columns).filter(c => !primaryKey.includes(c));\n}\n\nfunction* generateWithYields(stream: Stream<Node>, shouldYield: () => boolean) {\n for (const n of stream) {\n if (shouldYield()) {\n yield 'yield';\n }\n yield n;\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"table-source.js","names":["#dbCache","#connections","#connectionIndex","#table","#columns","#uniqueIndexes","#primaryKey","#logConfig","#lc","#shouldYield","#skipUnobservableChanges","#stmts","#getStatementsFor","#allColumns","#fetch","#getSchema","#requestToSQL","#mapFromSQLiteTypes","#overlay","#writeChange","#pushEpoch","#getRowStmtCache","#getRowStmt"],"sources":["../../../../zqlite/src/table-source.ts"],"sourcesContent":["import type {SQLQuery} from '@databases/sql';\nimport type {LogContext} from '@rocicorp/logger';\nimport SQLite3Database from '@rocicorp/zero-sqlite3';\nimport type {LogConfig} from '../../otel/src/log-options.ts';\nimport {timeSampled} from '../../otel/src/maybe-time.ts';\nimport {assert, unreachable} from '../../shared/src/asserts.ts';\nimport {getOrInsertComputed} from '../../shared/src/map.ts';\nimport {must} from '../../shared/src/must.ts';\nimport type {Writable} from '../../shared/src/writable.ts';\nimport type {Condition, Ordering} from '../../zero-protocol/src/ast.ts';\nimport type {Row, Value} from '../../zero-protocol/src/data.ts';\nimport type {PrimaryKey} from '../../zero-protocol/src/primary-key.ts';\nimport type {\n SchemaValue,\n ValueType,\n} from '../../zero-schema/src/table-schema.ts';\nimport type {DebugDelegate} from '../../zql/src/builder/debug-delegate.ts';\nimport {\n createPredicate,\n transformFilters,\n type NoSubqueryCondition as StrictNoSubqueryCondition,\n} from '../../zql/src/builder/filter.ts';\nimport {ChangeType} from '../../zql/src/ivm/change-type.ts';\nimport {ConnectionIndex} from '../../zql/src/ivm/connection-index.ts';\nimport {makeComparator, type Node} from '../../zql/src/ivm/data.ts';\nimport {\n generateWithOverlay,\n generateWithOverlayUnordered,\n generateWithStart,\n genPushAndWriteWithSplitEdit,\n type Connection,\n type Overlay,\n} from '../../zql/src/ivm/memory-source.ts';\nimport {type FetchRequest} from '../../zql/src/ivm/operator.ts';\nimport type {SourceSchema} from '../../zql/src/ivm/schema.ts';\nimport {SourceChangeIndex} from '../../zql/src/ivm/source-change-index.ts';\nimport {\n type Source,\n type SourceChange,\n type SourceInput,\n} from '../../zql/src/ivm/source.ts';\nimport type {Stream} from '../../zql/src/ivm/stream.ts';\nimport {assertOrderingIncludesPK} from '../../zql/src/query/complete-ordering.ts';\nimport type {Database, Statement} from './db.ts';\nimport {compile, format, sql} from './internal/sql.ts';\nimport {StatementCache} from './internal/statement-cache.ts';\nimport {\n buildSelectQuery,\n toSQLiteType,\n type NoSubqueryCondition,\n} from './query-builder.ts';\n\ntype Statements = {\n readonly cache: StatementCache;\n readonly insert: Statement;\n readonly delete: Statement;\n readonly update: Statement | undefined;\n readonly checkExists: Statement;\n readonly getExisting: Statement;\n};\n\nlet eventCount = 0;\n\nexport type TableSourceOptions = {\n /**\n * When set, a pushed change that the filters of every connection reject\n * is neither pushed nor applied to the backing table, on the grounds that\n * no connection can observe it. This departs from the `Source.push`\n * contract (a push commits the change to the source), so it is only\n * appropriate when the caller does not read the table through any other\n * path and replaces the table's contents afterwards, as the view-syncer's\n * pipeline driver does when it advances to the next snapshot.\n */\n skipUnobservableChanges?: boolean | undefined;\n};\n\n/**\n * A source that is backed by a SQLite table.\n *\n * Values are written to the backing table _after_ being vended by the source.\n *\n * This ordering of events is to ensure self joins function properly. That is,\n * we can't reveal a value to an output before it has been pushed to that output.\n *\n * The code is fairly straightforward except for:\n * 1. Dealing with a `fetch` that has a basis of `before`.\n * 2. Dealing with compound orders that have differing directions (a ASC, b DESC, c ASC)\n *\n * See comments in relevant functions for more details.\n */\nexport class TableSource implements Source {\n readonly #dbCache = new WeakMap<Database, Statements>();\n readonly #connections: Connection[] = [];\n // Indexes #connections by the static equality constraints in their filters\n // so that a push can cheaply skip rows that no connection could accept.\n readonly #connectionIndex = new ConnectionIndex<Connection>();\n readonly #table: string;\n readonly #columns: Record<string, SchemaValue>;\n // Maps sorted columns JSON string (e.g. '[\"a\",\"b\"]) to Set of columns.\n readonly #uniqueIndexes: Map<string, Set<string>>;\n readonly #primaryKey: PrimaryKey;\n readonly #logConfig: LogConfig;\n readonly #lc: LogContext;\n readonly #shouldYield: () => boolean;\n readonly #skipUnobservableChanges: boolean;\n #stmts: Statements;\n #overlay?: Overlay | undefined;\n #pushEpoch = 0;\n\n /**\n * @param shouldYield a function called after each row is read from the database,\n * which should return true if the source should yield the special 'yield' value\n * to yield control back to the caller at the end of the pipeline. Can\n * also throw an error to abort the pipeline processing.\n */\n constructor(\n logContext: LogContext,\n logConfig: LogConfig,\n db: Database,\n tableName: string,\n columns: Record<string, SchemaValue>,\n primaryKey: PrimaryKey,\n shouldYield = () => false,\n options: TableSourceOptions = {},\n ) {\n this.#lc = logContext;\n this.#logConfig = logConfig;\n this.#table = tableName;\n this.#columns = columns;\n this.#uniqueIndexes = getUniqueIndexes(db, tableName);\n this.#primaryKey = primaryKey;\n this.#stmts = this.#getStatementsFor(db);\n this.#shouldYield = shouldYield;\n this.#skipUnobservableChanges = options.skipUnobservableChanges ?? false;\n\n const primaryKeyStr = JSON.stringify(primaryKey.toSorted());\n assert(\n this.#uniqueIndexes.has(primaryKeyStr),\n `primary key ${primaryKeyStr} does not have a UNIQUE index`,\n );\n }\n\n get tableSchema() {\n return {\n name: this.#table,\n columns: this.#columns,\n primaryKey: this.#primaryKey,\n };\n }\n\n /**\n * Sets the db (snapshot) to use, to facilitate the Snapshotter leapfrog\n * algorithm for concurrent traversal of historic timelines.\n */\n setDB(db: Database) {\n this.#stmts = this.#getStatementsFor(db);\n }\n\n #getStatementsFor(db: Database) {\n const cached = this.#dbCache.get(db);\n if (cached) {\n return cached;\n }\n\n const stmts = {\n cache: new StatementCache(db),\n insert: db.prepare(\n compile(\n sql`INSERT INTO ${sql.ident(this.#table)} (${sql.join(\n Object.keys(this.#columns).map(c => sql.ident(c)),\n ', ',\n )}) VALUES (${sql.__dangerous__rawValue(\n Array.from({length: Object.keys(this.#columns).length})\n .fill('?')\n .join(','),\n )})`,\n ),\n ),\n delete: db.prepare(\n compile(\n sql`DELETE FROM ${sql.ident(this.#table)} WHERE ${sql.join(\n this.#primaryKey.map(k => sql`${sql.ident(k)}=?`),\n ' AND ',\n )}`,\n ),\n ),\n // If all the columns are part of the primary key, we cannot use UPDATE.\n update:\n Object.keys(this.#columns).length > this.#primaryKey.length\n ? db.prepare(\n compile(\n sql`UPDATE ${sql.ident(this.#table)} SET ${sql.join(\n nonPrimaryKeys(this.#columns, this.#primaryKey).map(\n c => sql`${sql.ident(c)}=?`,\n ),\n ',',\n )} WHERE ${sql.join(\n this.#primaryKey.map(k => sql`${sql.ident(k)}=?`),\n ' AND ',\n )}`,\n ),\n )\n : undefined,\n checkExists: db.prepare(\n compile(\n sql`SELECT 1 AS \"exists\" FROM ${sql.ident(\n this.#table,\n )} WHERE ${sql.join(\n this.#primaryKey.map(k => sql`${sql.ident(k)}=?`),\n ' AND ',\n )} LIMIT 1`,\n ),\n ),\n getExisting: db.prepare(\n compile(\n sql`SELECT * FROM ${sql.ident(this.#table)} WHERE ${sql.join(\n this.#primaryKey.map(k => sql`${sql.ident(k)}=?`),\n ' AND ',\n )}`,\n ),\n ),\n };\n this.#dbCache.set(db, stmts);\n return stmts;\n }\n\n get #allColumns() {\n return sql.join(\n Object.keys(this.#columns).map(c => sql.ident(c)),\n sql`,`,\n );\n }\n\n #getSchema(connection: Connection, unordered: boolean): SourceSchema {\n return {\n tableName: this.#table,\n columns: this.#columns,\n primaryKey: this.#primaryKey,\n sort: unordered ? undefined : connection.sort,\n relationships: {},\n isHidden: false,\n system: 'client',\n compareRows: connection.compareRows,\n };\n }\n\n hasConnections(): boolean {\n return this.#connections.length > 0;\n }\n\n connect(\n sort: Ordering | undefined,\n filters?: Condition,\n splitEditKeys?: Set<string>,\n debug?: DebugDelegate,\n ) {\n const transformedFilters = transformFilters(filters);\n const unordered = sort === undefined;\n // PK comparator is used for source-level overlay matching (remove by PK\n // equality) even when no ordering is requested.\n const primaryKeySort: Ordering = this.#primaryKey.map(k => [k, 'asc']);\n\n const input: SourceInput = {\n getSchema: () => schema,\n fetch: req => this.#fetch(req, connection),\n setOutput: output => {\n connection.output = output;\n },\n destroy: () => {\n const idx = this.#connections.indexOf(connection);\n assert(idx !== -1, 'Connection not found');\n this.#connections.splice(idx, 1);\n this.#connectionIndex.remove(connection);\n },\n fullyAppliedFilters: !transformedFilters.conditionsRemoved,\n };\n\n const connection: Connection = {\n input,\n debug,\n output: undefined,\n sort,\n splitEditKeys,\n filters: transformedFilters.filters\n ? {\n condition: transformedFilters.filters,\n predicate: createPredicate(transformedFilters.filters),\n }\n : undefined,\n compareRows: sort ? makeComparator(sort) : makeComparator(primaryKeySort),\n lastPushedEpoch: 0,\n };\n const schema = this.#getSchema(connection, unordered);\n if (!unordered) {\n assertOrderingIncludesPK(sort, this.#primaryKey);\n }\n\n this.#connections.push(connection);\n this.#connectionIndex.add(connection, transformedFilters.filters);\n return input;\n }\n\n toSQLiteRow(row: Row): Row {\n return Object.fromEntries(\n Object.entries(row).map(([key, value]) => [\n key,\n toSQLiteType(value, this.#columns[key].type),\n ]),\n ) as Row;\n }\n\n *#fetch(req: FetchRequest, connection: Connection): Stream<Node | 'yield'> {\n const {sort, debug} = connection;\n\n const query = this.#requestToSQL(req, connection.filters?.condition, sort);\n const sqlAndBindings = format(query);\n\n const cachedStatement = this.#stmts.cache.get(sqlAndBindings.text);\n cachedStatement.statement.safeIntegers(true);\n const rowIterator = cachedStatement.statement.iterate<Row>(\n ...sqlAndBindings.values,\n );\n const overlayPredicate = mergeOverlayPredicate(\n connection.filters?.predicate,\n req.filter,\n );\n try {\n debug?.initQuery(this.#table, sqlAndBindings.text);\n\n if (sort) {\n const comparator = makeComparator(sort, req.reverse);\n yield* generateWithStart(\n generateWithYields(\n generateWithOverlay(\n req.start?.row,\n this.#mapFromSQLiteTypes(\n this.#columns,\n rowIterator,\n sqlAndBindings.text,\n debug,\n ),\n req.constraint,\n this.#overlay,\n connection.lastPushedEpoch,\n comparator,\n // SQL does the ordering and constraining, so the row stream is\n // already in the connection's sort order: the splice comparator\n // and the `startAt` comparator coincide here.\n comparator,\n overlayPredicate,\n req.multiConstraints,\n ),\n this.#shouldYield,\n ),\n req.start,\n comparator,\n );\n } else {\n yield* generateWithYields(\n generateWithOverlayUnordered(\n this.#mapFromSQLiteTypes(\n this.#columns,\n rowIterator,\n sqlAndBindings.text,\n debug,\n ),\n req.constraint,\n this.#overlay,\n connection.lastPushedEpoch,\n this.#primaryKey,\n overlayPredicate,\n req.multiConstraints,\n ),\n this.#shouldYield,\n );\n }\n } finally {\n // Ensure the SQLite iterate() is closed.\n rowIterator.return?.();\n if (debug) {\n let totalNvisit = 0;\n const planLines: string[] = [];\n for (let i = 0; ; i++) {\n const nvisit = cachedStatement.statement.scanStatus(\n i,\n SQLite3Database.SQLITE_SCANSTAT_NVISIT,\n 1,\n );\n if (nvisit === undefined) {\n break;\n }\n totalNvisit += Number(nvisit);\n const explain = cachedStatement.statement.scanStatus(\n i,\n SQLite3Database.SQLITE_SCANSTAT_EXPLAIN,\n 1,\n );\n if (typeof explain === 'string' && explain.length > 0) {\n planLines.push(explain);\n }\n }\n if (totalNvisit !== 0) {\n debug.recordNVisit(this.#table, sqlAndBindings.text, totalNvisit);\n }\n if (planLines.length > 0) {\n debug.recordExplain(this.#table, sqlAndBindings.text, planLines);\n }\n cachedStatement.statement.scanStatusReset();\n }\n this.#stmts.cache.return(cachedStatement);\n }\n }\n\n *#mapFromSQLiteTypes(\n valueTypes: Record<string, SchemaValue>,\n rowIterator: IterableIterator<Row>,\n query: string,\n debug: DebugDelegate | undefined,\n ): IterableIterator<Row> {\n let result;\n do {\n result = timeSampled(\n this.#lc,\n ++eventCount,\n this.#logConfig.ivmSampling,\n () => rowIterator.next(),\n this.#logConfig.slowRowThreshold,\n () =>\n `table-source.next took too long for ${query}. Are you missing an index?`,\n );\n if (result.done) {\n break;\n }\n const row = fromSQLiteTypes(valueTypes, result.value, this.#table);\n debug?.rowVended(this.#table, query, row);\n yield row;\n } while (!result.done);\n }\n\n *push(change: SourceChange): Stream<'yield'> {\n for (const result of this.genPush(change)) {\n if (result === 'yield') {\n yield result;\n }\n }\n }\n\n *genPush(change: SourceChange): Stream<'yield' | undefined> {\n if (\n this.#skipUnobservableChanges &&\n !this.#connectionIndex.mayAcceptChange(change)\n ) {\n // No connection can observe this row, so only a REMOVE needs to be\n // applied to the snapshot.\n if (change[SourceChangeIndex.TYPE] === ChangeType.REMOVE) {\n this.#writeChange(change);\n }\n return;\n }\n\n const exists = (row: Row) =>\n this.#stmts.checkExists.get<{exists: number} | undefined>(\n ...toSQLiteTypes(this.#primaryKey, row, this.#columns),\n )?.exists === 1;\n const setOverlay = (o: Overlay | undefined) => (this.#overlay = o);\n const writeChange = (c: SourceChange) => this.#writeChange(c);\n\n yield* genPushAndWriteWithSplitEdit(\n this.#connections,\n change,\n exists,\n setOverlay,\n writeChange,\n () => ++this.#pushEpoch,\n );\n }\n\n #writeChange(change: SourceChange) {\n switch (change[SourceChangeIndex.TYPE]) {\n case ChangeType.ADD:\n this.#stmts.insert.run(\n ...toSQLiteTypes(\n // TODO(arv): Compute this once!\n Object.keys(this.#columns),\n change[SourceChangeIndex.ROW],\n this.#columns,\n ),\n );\n break;\n case ChangeType.REMOVE:\n this.#stmts.delete.run(\n ...toSQLiteTypes(\n this.#primaryKey,\n change[SourceChangeIndex.ROW],\n this.#columns,\n ),\n );\n break;\n case ChangeType.EDIT: {\n // If the PK is the same, use UPDATE.\n if (\n canUseUpdate(\n change[SourceChangeIndex.OLD_ROW],\n change[SourceChangeIndex.ROW],\n this.#columns,\n this.#primaryKey,\n )\n ) {\n const mergedRow = {\n ...change[SourceChangeIndex.OLD_ROW],\n ...change[SourceChangeIndex.ROW],\n };\n const params = [\n ...nonPrimaryValues(this.#columns, this.#primaryKey, mergedRow),\n ...toSQLiteTypes(this.#primaryKey, mergedRow, this.#columns),\n ];\n must(this.#stmts.update).run(params);\n } else {\n this.#stmts.delete.run(\n ...toSQLiteTypes(\n this.#primaryKey,\n change[SourceChangeIndex.OLD_ROW],\n this.#columns,\n ),\n );\n this.#stmts.insert.run(\n ...toSQLiteTypes(\n Object.keys(this.#columns),\n change[SourceChangeIndex.ROW],\n this.#columns,\n ),\n );\n }\n\n break;\n }\n default:\n unreachable(change);\n }\n }\n\n #getRowStmtCache = new Map<string, string>();\n\n #getRowStmt(keyCols: string[]): string {\n const keyString = JSON.stringify(keyCols);\n return getOrInsertComputed(this.#getRowStmtCache, keyString, () =>\n compile(\n sql`SELECT ${this.#allColumns} FROM ${sql.ident(\n this.#table,\n )} WHERE ${sql.join(\n keyCols.map(k => sql`${sql.ident(k)}=?`),\n sql` AND`,\n )}`,\n ),\n );\n }\n\n /**\n * Retrieves a row from the backing DB by a unique key, or `undefined` if such a\n * row does not exist. This is not used in the IVM pipeline but is useful\n * for retrieving data that is consistent with the state (and type\n * semantics) of the pipeline. Note that this key may not necessarily correspond\n * to the `primaryKey` with which this TableSource.\n */\n getRow(rowKey: Row): Row | undefined {\n const keyCols = Object.keys(rowKey);\n\n const stmt = this.#getRowStmt(keyCols);\n const row = this.#stmts.cache.use(stmt, cached =>\n cached.statement\n .safeIntegers(true)\n .get<Row>(...toSQLiteTypes(keyCols, rowKey, this.#columns)),\n );\n if (row) {\n return fromSQLiteTypes(this.#columns, row, this.#table);\n }\n return row;\n }\n\n #requestToSQL(\n request: FetchRequest,\n filters: NoSubqueryCondition | undefined,\n order: Ordering | undefined,\n ): SQLQuery {\n return buildSelectQuery(\n this.#table,\n this.#columns,\n request.constraint,\n filters,\n order,\n request.reverse,\n request.start,\n request.multiConstraints,\n request.filter,\n );\n }\n}\n\nfunction mergeOverlayPredicate(\n connPredicate: ((row: Row) => boolean) | undefined,\n reqFilter: StrictNoSubqueryCondition | undefined,\n): ((row: Row) => boolean) | undefined {\n if (!reqFilter) {\n return connPredicate;\n }\n const reqPredicate = createPredicate(reqFilter);\n if (!connPredicate) {\n return reqPredicate;\n }\n return row => connPredicate(row) && reqPredicate(row);\n}\n\nfunction getUniqueIndexes(\n db: Database,\n tableName: string,\n): Map<string, Set<string>> {\n const sqlAndBindings = format(\n sql`\n SELECT idx.name, json_group_array(col.name) as columnsJSON\n FROM sqlite_master as idx\n JOIN pragma_index_list(idx.tbl_name) AS info ON info.name = idx.name\n JOIN pragma_index_info(idx.name) as col\n WHERE idx.tbl_name = ${tableName} AND\n idx.type = 'index' AND \n info.\"unique\" != 0 AND\n info.partial = 0\n GROUP BY idx.name\n ORDER BY idx.name`,\n );\n const stmt = db.prepare(sqlAndBindings.text);\n const indexes = stmt.all<{columnsJSON: string}>(...sqlAndBindings.values);\n return new Map(\n indexes.map(({columnsJSON}) => {\n const columns = JSON.parse(columnsJSON);\n const set = new Set<string>(columns);\n return [JSON.stringify(columns.sort()), set];\n }),\n );\n}\n\nexport function toSQLiteTypes(\n columns: readonly string[],\n row: Row,\n columnTypes: Record<string, SchemaValue>,\n): readonly unknown[] {\n return columns.map(col => toSQLiteType(row[col], columnTypes[col].type));\n}\n\nexport function toSQLiteTypeName(type: ValueType) {\n switch (type) {\n case 'boolean':\n return 'INTEGER';\n case 'number':\n return 'REAL';\n case 'string':\n return 'TEXT';\n case 'null':\n return 'NULL';\n case 'json':\n return 'TEXT';\n }\n}\n\nexport function fromSQLiteTypes(\n valueTypes: Record<string, SchemaValue>,\n row: Row,\n tableName: string,\n): Row {\n const newRow: Writable<Row> = {};\n for (const key of Object.keys(row)) {\n const valueType = valueTypes[key];\n if (valueType === undefined) {\n const columnList = Object.keys(valueTypes).sort().join(', ');\n throw new Error(\n `Invalid column \"${key}\" for table \"${tableName}\". Synced columns include ${columnList}`,\n );\n }\n newRow[key] = fromSQLiteType(valueType.type, row[key], key, tableName);\n }\n return newRow;\n}\n\nfunction fromSQLiteType(\n valueType: ValueType,\n v: Value,\n column: string,\n tableName: string,\n): Value {\n if (v === null) {\n return null;\n }\n switch (valueType) {\n case 'boolean':\n return !!v;\n case 'number':\n case 'string':\n case 'null':\n if (typeof v === 'bigint') {\n const bi = v as bigint;\n if (bi > Number.MAX_SAFE_INTEGER || bi < Number.MIN_SAFE_INTEGER) {\n throw new UnsupportedValueError(\n `value ${bi} (in ${tableName}.${column}) is outside of supported bounds`,\n );\n }\n return Number(bi);\n }\n return v;\n case 'json':\n try {\n return JSON.parse(v as string);\n } catch (error) {\n const errorMessage =\n error instanceof Error ? error.message : String(error);\n throw new UnsupportedValueError(\n `Failed to parse JSON for ${tableName}.${column}: ${errorMessage}`,\n {cause: error},\n );\n }\n }\n}\n\nexport class UnsupportedValueError extends Error {}\n\nfunction canUseUpdate(\n oldRow: Row,\n row: Row,\n columns: Record<string, SchemaValue>,\n primaryKey: PrimaryKey,\n): boolean {\n for (const pk of primaryKey) {\n if (oldRow[pk] !== row[pk]) {\n return false;\n }\n }\n return Object.keys(columns).length > primaryKey.length;\n}\n\nfunction nonPrimaryValues(\n columns: Record<string, SchemaValue>,\n primaryKey: PrimaryKey,\n row: Row,\n): Iterable<unknown> {\n return nonPrimaryKeys(columns, primaryKey).map(c =>\n toSQLiteType(row[c], columns[c].type),\n );\n}\n\nfunction nonPrimaryKeys(\n columns: Record<string, SchemaValue>,\n primaryKey: PrimaryKey,\n) {\n return Object.keys(columns).filter(c => !primaryKey.includes(c));\n}\n\nfunction* generateWithYields(stream: Stream<Node>, shouldYield: () => boolean) {\n for (const n of stream) {\n if (shouldYield()) {\n yield 'yield';\n }\n yield n;\n }\n}\n"],"mappings":"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"}
|