@rocicorp/zero 1.3.0-canary.3 → 1.3.1-canary.1
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/bin-analyze.js +7 -7
- package/out/analyze-query/src/bin-transform.js +3 -3
- package/out/ast-to-zql/src/bin.js +2 -2
- package/out/shared/src/logging.d.ts.map +1 -1
- package/out/shared/src/logging.js +1 -1
- package/out/shared/src/logging.js.map +1 -1
- package/out/shared/src/options.d.ts.map +1 -1
- package/out/shared/src/options.js +1 -1
- package/out/shared/src/options.js.map +1 -1
- package/out/zero/package.js +89 -91
- package/out/zero/package.js.map +1 -1
- package/out/zero/src/zero-cache-dev.js +1 -1
- package/out/zero/src/zero-cache-dev.js.map +1 -1
- package/out/zero/src/zero-out.js +1 -1
- package/out/zero-cache/src/auth/auth.d.ts.map +1 -1
- package/out/zero-cache/src/auth/auth.js.map +1 -1
- package/out/zero-cache/src/auth/load-permissions.js +2 -2
- package/out/zero-cache/src/auth/write-authorizer.d.ts.map +1 -1
- package/out/zero-cache/src/auth/write-authorizer.js +14 -5
- package/out/zero-cache/src/auth/write-authorizer.js.map +1 -1
- package/out/zero-cache/src/config/network.d.ts +1 -1
- package/out/zero-cache/src/config/network.d.ts.map +1 -1
- package/out/zero-cache/src/config/network.js +1 -1
- package/out/zero-cache/src/config/network.js.map +1 -1
- package/out/zero-cache/src/config/normalize.d.ts.map +1 -1
- package/out/zero-cache/src/config/normalize.js.map +1 -1
- package/out/zero-cache/src/config/zero-config.d.ts +0 -5
- package/out/zero-cache/src/config/zero-config.d.ts.map +1 -1
- package/out/zero-cache/src/config/zero-config.js +3 -16
- 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 -3
- package/out/zero-cache/src/db/lite-tables.js.map +1 -1
- package/out/zero-cache/src/db/pg-to-lite.d.ts +1 -1
- package/out/zero-cache/src/db/pg-to-lite.d.ts.map +1 -1
- package/out/zero-cache/src/db/pg-to-lite.js +13 -13
- package/out/zero-cache/src/db/pg-to-lite.js.map +1 -1
- package/out/zero-cache/src/db/transaction-pool.d.ts +40 -43
- package/out/zero-cache/src/db/transaction-pool.d.ts.map +1 -1
- package/out/zero-cache/src/db/transaction-pool.js +56 -76
- package/out/zero-cache/src/db/transaction-pool.js.map +1 -1
- package/out/zero-cache/src/observability/events.d.ts.map +1 -1
- package/out/zero-cache/src/observability/events.js +1 -1
- package/out/zero-cache/src/observability/events.js.map +1 -1
- package/out/zero-cache/src/scripts/decommission.js +1 -1
- package/out/zero-cache/src/scripts/deploy-permissions.js +2 -2
- package/out/zero-cache/src/scripts/permissions.js +1 -1
- package/out/zero-cache/src/server/anonymous-otel-start.d.ts.map +1 -1
- package/out/zero-cache/src/server/anonymous-otel-start.js +3 -3
- package/out/zero-cache/src/server/anonymous-otel-start.js.map +1 -1
- package/out/zero-cache/src/server/change-streamer.d.ts +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 -26
- package/out/zero-cache/src/server/change-streamer.js.map +1 -1
- package/out/zero-cache/src/server/logging.d.ts +3 -1
- package/out/zero-cache/src/server/logging.d.ts.map +1 -1
- package/out/zero-cache/src/server/logging.js +3 -6
- package/out/zero-cache/src/server/logging.js.map +1 -1
- package/out/zero-cache/src/server/main.d.ts.map +1 -1
- package/out/zero-cache/src/server/main.js +26 -26
- package/out/zero-cache/src/server/main.js.map +1 -1
- package/out/zero-cache/src/server/mutator.js +2 -4
- package/out/zero-cache/src/server/mutator.js.map +1 -1
- package/out/zero-cache/src/server/otel-log-sink.d.ts.map +1 -1
- package/out/zero-cache/src/server/otel-log-sink.js +2 -0
- package/out/zero-cache/src/server/otel-log-sink.js.map +1 -1
- package/out/zero-cache/src/server/otel-start.d.ts +1 -1
- package/out/zero-cache/src/server/otel-start.d.ts.map +1 -1
- package/out/zero-cache/src/server/otel-start.js +3 -7
- package/out/zero-cache/src/server/otel-start.js.map +1 -1
- package/out/zero-cache/src/server/reaper.js +6 -6
- 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 +3 -5
- package/out/zero-cache/src/server/replicator.js.map +1 -1
- package/out/zero-cache/src/server/runner/run-worker.js +2 -2
- package/out/zero-cache/src/server/runner/run-worker.js.map +1 -1
- package/out/zero-cache/src/server/syncer.d.ts.map +1 -1
- package/out/zero-cache/src/server/syncer.js +12 -13
- package/out/zero-cache/src/server/syncer.js.map +1 -1
- package/out/zero-cache/src/server/worker-dispatcher.js +1 -1
- package/out/zero-cache/src/services/change-source/common/backfill-manager.js +1 -1
- package/out/zero-cache/src/services/change-source/common/replica-schema.js +1 -1
- package/out/zero-cache/src/services/change-source/custom/change-source.js +2 -2
- package/out/zero-cache/src/services/change-source/pg/backfill-stream.js +1 -4
- package/out/zero-cache/src/services/change-source/pg/backfill-stream.js.map +1 -1
- package/out/zero-cache/src/services/change-source/pg/change-source.js +2 -2
- package/out/zero-cache/src/services/change-source/pg/initial-sync.d.ts +3 -58
- package/out/zero-cache/src/services/change-source/pg/initial-sync.d.ts.map +1 -1
- package/out/zero-cache/src/services/change-source/pg/initial-sync.js +51 -208
- package/out/zero-cache/src/services/change-source/pg/initial-sync.js.map +1 -1
- package/out/zero-cache/src/services/change-source/pg/logical-replication/stream.js +1 -1
- package/out/zero-cache/src/services/change-source/pg/schema/ddl.js +1 -1
- package/out/zero-cache/src/services/change-source/pg/schema/init.js +1 -1
- package/out/zero-cache/src/services/change-source/pg/schema/shard.js +1 -1
- package/out/zero-cache/src/services/change-streamer/backup-monitor.js +1 -1
- package/out/zero-cache/src/services/change-streamer/change-streamer-http.d.ts +1 -1
- 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 +1 -1
- package/out/zero-cache/src/services/change-streamer/change-streamer-http.js.map +1 -1
- package/out/zero-cache/src/services/change-streamer/change-streamer-service.d.ts +1 -5
- package/out/zero-cache/src/services/change-streamer/change-streamer-service.d.ts.map +1 -1
- package/out/zero-cache/src/services/change-streamer/change-streamer-service.js +7 -10
- package/out/zero-cache/src/services/change-streamer/change-streamer-service.js.map +1 -1
- package/out/zero-cache/src/services/change-streamer/replica-monitor.js +2 -2
- package/out/zero-cache/src/services/change-streamer/storer.d.ts +2 -19
- package/out/zero-cache/src/services/change-streamer/storer.d.ts.map +1 -1
- package/out/zero-cache/src/services/change-streamer/storer.js +5 -69
- package/out/zero-cache/src/services/change-streamer/storer.js.map +1 -1
- package/out/zero-cache/src/services/heapz.d.ts.map +1 -1
- package/out/zero-cache/src/services/heapz.js +1 -1
- package/out/zero-cache/src/services/heapz.js.map +1 -1
- package/out/zero-cache/src/services/life-cycle.d.ts +1 -2
- package/out/zero-cache/src/services/life-cycle.d.ts.map +1 -1
- package/out/zero-cache/src/services/life-cycle.js +7 -10
- package/out/zero-cache/src/services/life-cycle.js.map +1 -1
- package/out/zero-cache/src/services/litestream/commands.d.ts +4 -15
- package/out/zero-cache/src/services/litestream/commands.d.ts.map +1 -1
- package/out/zero-cache/src/services/litestream/commands.js +31 -31
- package/out/zero-cache/src/services/litestream/commands.js.map +1 -1
- package/out/zero-cache/src/services/mutagen/mutagen.js +1 -1
- package/out/zero-cache/src/services/mutagen/pusher.d.ts +28 -28
- package/out/zero-cache/src/services/replicator/change-processor.js +2 -2
- package/out/zero-cache/src/services/replicator/incremental-sync.js +1 -1
- package/out/zero-cache/src/services/replicator/schema/replication-state.js +1 -1
- package/out/zero-cache/src/services/replicator/write-worker-client.js.map +1 -1
- package/out/zero-cache/src/services/replicator/write-worker.js +3 -3
- package/out/zero-cache/src/services/replicator/write-worker.js.map +1 -1
- package/out/zero-cache/src/services/run-ast.d.ts.map +1 -1
- package/out/zero-cache/src/services/run-ast.js +2 -2
- package/out/zero-cache/src/services/run-ast.js.map +1 -1
- package/out/zero-cache/src/services/statz.d.ts.map +1 -1
- package/out/zero-cache/src/services/statz.js +2 -2
- package/out/zero-cache/src/services/statz.js.map +1 -1
- package/out/zero-cache/src/services/view-syncer/active-users-gauge.js +1 -1
- package/out/zero-cache/src/services/view-syncer/connection-context-manager.d.ts +2 -2
- package/out/zero-cache/src/services/view-syncer/connection-context-manager.d.ts.map +1 -1
- package/out/zero-cache/src/services/view-syncer/connection-context-manager.js.map +1 -1
- package/out/zero-cache/src/services/view-syncer/cvr-purger.js +1 -1
- package/out/zero-cache/src/services/view-syncer/cvr-store.js +2 -2
- package/out/zero-cache/src/services/view-syncer/cvr-store.js.map +1 -1
- package/out/zero-cache/src/services/view-syncer/inspect-handler.js +1 -1
- package/out/zero-cache/src/services/view-syncer/pipeline-driver.d.ts +16 -6
- 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 +37 -29
- package/out/zero-cache/src/services/view-syncer/pipeline-driver.js.map +1 -1
- package/out/zero-cache/src/services/view-syncer/row-record-cache.d.ts.map +1 -1
- package/out/zero-cache/src/services/view-syncer/row-record-cache.js +3 -3
- package/out/zero-cache/src/services/view-syncer/row-record-cache.js.map +1 -1
- package/out/zero-cache/src/services/view-syncer/snapshotter.js +2 -2
- 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 +6 -6
- package/out/zero-cache/src/services/view-syncer/view-syncer.js.map +1 -1
- package/out/zero-cache/src/types/profiler.d.ts.map +1 -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.map +1 -1
- package/out/zero-cache/src/types/streams.d.ts +1 -1
- package/out/zero-cache/src/types/streams.d.ts.map +1 -1
- package/out/zero-cache/src/types/streams.js.map +1 -1
- package/out/zero-cache/src/types/websocket-handoff.d.ts +1 -1
- package/out/zero-cache/src/types/websocket-handoff.d.ts.map +1 -1
- package/out/zero-cache/src/types/websocket-handoff.js.map +1 -1
- package/out/zero-cache/src/workers/connection.d.ts +1 -1
- package/out/zero-cache/src/workers/connection.d.ts.map +1 -1
- package/out/zero-cache/src/workers/connection.js.map +1 -1
- package/out/zero-cache/src/workers/mutator.js.map +1 -1
- package/out/zero-cache/src/workers/syncer.d.ts +1 -1
- package/out/zero-cache/src/workers/syncer.d.ts.map +1 -1
- package/out/zero-cache/src/workers/syncer.js +2 -2
- package/out/zero-cache/src/workers/syncer.js.map +1 -1
- package/out/zero-client/src/client/crud-impl.d.ts.map +1 -1
- package/out/zero-client/src/client/crud-impl.js +13 -4
- package/out/zero-client/src/client/crud-impl.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 +13 -4
- package/out/zero-client/src/client/ivm-branch.js.map +1 -1
- package/out/zero-client/src/client/version.js +1 -1
- package/out/zero-protocol/src/error.d.ts.map +1 -1
- package/out/zero-protocol/src/error.js +1 -1
- package/out/zero-protocol/src/error.js.map +1 -1
- package/out/zero-solid/src/solid-view.d.ts.map +1 -1
- package/out/zero-solid/src/solid-view.js +13 -13
- package/out/zero-solid/src/solid-view.js.map +1 -1
- package/out/zql/src/builder/builder.d.ts.map +1 -1
- package/out/zql/src/builder/builder.js.map +1 -1
- package/out/zql/src/ivm/array-view.d.ts.map +1 -1
- package/out/zql/src/ivm/array-view.js +1 -26
- package/out/zql/src/ivm/array-view.js.map +1 -1
- package/out/zql/src/ivm/change.d.ts +22 -20
- package/out/zql/src/ivm/change.d.ts.map +1 -1
- package/out/zql/src/ivm/exists.d.ts.map +1 -1
- package/out/zql/src/ivm/exists.js +38 -27
- package/out/zql/src/ivm/exists.js.map +1 -1
- package/out/zql/src/ivm/fan-in.d.ts +2 -3
- package/out/zql/src/ivm/fan-in.d.ts.map +1 -1
- package/out/zql/src/ivm/fan-in.js.map +1 -1
- package/out/zql/src/ivm/fan-out.d.ts +1 -1
- package/out/zql/src/ivm/fan-out.d.ts.map +1 -1
- package/out/zql/src/ivm/fan-out.js +1 -1
- package/out/zql/src/ivm/fan-out.js.map +1 -1
- package/out/zql/src/ivm/filter-operators.d.ts +3 -3
- package/out/zql/src/ivm/filter-operators.d.ts.map +1 -1
- package/out/zql/src/ivm/filter-operators.js.map +1 -1
- package/out/zql/src/ivm/filter-push.d.ts.map +1 -1
- package/out/zql/src/ivm/filter-push.js +7 -7
- package/out/zql/src/ivm/filter-push.js.map +1 -1
- package/out/zql/src/ivm/filter.d.ts +1 -1
- package/out/zql/src/ivm/filter.d.ts.map +1 -1
- package/out/zql/src/ivm/filter.js.map +1 -1
- package/out/zql/src/ivm/flipped-join.d.ts.map +1 -1
- package/out/zql/src/ivm/flipped-join.js +58 -49
- package/out/zql/src/ivm/flipped-join.js.map +1 -1
- package/out/zql/src/ivm/join-utils.d.ts +6 -2
- package/out/zql/src/ivm/join-utils.d.ts.map +1 -1
- package/out/zql/src/ivm/join-utils.js +25 -25
- package/out/zql/src/ivm/join-utils.js.map +1 -1
- package/out/zql/src/ivm/join.d.ts.map +1 -1
- package/out/zql/src/ivm/join.js +51 -32
- package/out/zql/src/ivm/join.js.map +1 -1
- package/out/zql/src/ivm/maybe-split-and-push-edit-change.d.ts +1 -1
- package/out/zql/src/ivm/maybe-split-and-push-edit-change.d.ts.map +1 -1
- package/out/zql/src/ivm/maybe-split-and-push-edit-change.js +10 -5
- package/out/zql/src/ivm/maybe-split-and-push-edit-change.js.map +1 -1
- package/out/zql/src/ivm/memory-source.d.ts.map +1 -1
- package/out/zql/src/ivm/memory-source.js +59 -51
- package/out/zql/src/ivm/memory-source.js.map +1 -1
- package/out/zql/src/ivm/push-accumulated.d.ts +2 -3
- package/out/zql/src/ivm/push-accumulated.d.ts.map +1 -1
- package/out/zql/src/ivm/push-accumulated.js +122 -98
- package/out/zql/src/ivm/push-accumulated.js.map +1 -1
- package/out/zql/src/ivm/skip.d.ts +1 -1
- package/out/zql/src/ivm/skip.d.ts.map +1 -1
- package/out/zql/src/ivm/skip.js +2 -2
- package/out/zql/src/ivm/skip.js.map +1 -1
- package/out/zql/src/ivm/source.d.ts +13 -11
- package/out/zql/src/ivm/source.d.ts.map +1 -1
- package/out/zql/src/ivm/take.d.ts.map +1 -1
- package/out/zql/src/ivm/take.js +50 -27
- package/out/zql/src/ivm/take.js.map +1 -1
- package/out/zql/src/ivm/union-fan-in.d.ts +1 -2
- package/out/zql/src/ivm/union-fan-in.d.ts.map +1 -1
- package/out/zql/src/ivm/union-fan-in.js +3 -3
- package/out/zql/src/ivm/union-fan-in.js.map +1 -1
- package/out/zql/src/ivm/union-fan-out.d.ts.map +1 -1
- package/out/zql/src/ivm/union-fan-out.js +1 -1
- package/out/zql/src/ivm/union-fan-out.js.map +1 -1
- package/out/zql/src/planner/planner-debug.d.ts +2 -2
- package/out/zql/src/planner/planner-debug.d.ts.map +1 -1
- package/out/zql/src/planner/planner-debug.js.map +1 -1
- package/out/zql/src/planner/planner-graph.d.ts +1 -1
- package/out/zql/src/planner/planner-graph.d.ts.map +1 -1
- package/out/zql/src/planner/planner-graph.js.map +1 -1
- package/out/zqlite/src/internal/sql-inline.d.ts.map +1 -1
- package/out/zqlite/src/internal/sql-inline.js.map +1 -1
- package/out/zqlite/src/query-builder.d.ts.map +1 -1
- package/out/zqlite/src/query-builder.js.map +1 -1
- package/out/zqlite/src/table-source.d.ts.map +1 -1
- package/out/zqlite/src/table-source.js +11 -11
- package/out/zqlite/src/table-source.js.map +1 -1
- package/package.json +93 -95
- package/out/zql/src/ivm/change-index-enum.d.ts +0 -9
- package/out/zql/src/ivm/change-index-enum.d.ts.map +0 -1
- package/out/zql/src/ivm/change-index.d.ts +0 -5
- package/out/zql/src/ivm/change-index.d.ts.map +0 -1
- package/out/zql/src/ivm/change-type-enum.d.ts +0 -9
- package/out/zql/src/ivm/change-type-enum.d.ts.map +0 -1
- package/out/zql/src/ivm/change-type.d.ts +0 -5
- package/out/zql/src/ivm/change-type.d.ts.map +0 -1
- package/out/zql/src/ivm/change.js +0 -33
- package/out/zql/src/ivm/change.js.map +0 -1
- package/out/zql/src/ivm/source-change-index-enum.d.ts +0 -7
- package/out/zql/src/ivm/source-change-index-enum.d.ts.map +0 -1
- package/out/zql/src/ivm/source-change-index.d.ts +0 -5
- package/out/zql/src/ivm/source-change-index.d.ts.map +0 -1
- package/out/zql/src/ivm/source.js +0 -26
- package/out/zql/src/ivm/source.js.map +0 -1
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { assert, unreachable } from "../../../shared/src/asserts.js";
|
|
2
2
|
import { areEqual } from "../../../shared/src/arrays.js";
|
|
3
|
-
import { makeAddChange, makeRemoveChange } from "./change.js";
|
|
4
3
|
import { normalizeUndefined } from "./data.js";
|
|
5
4
|
import { throwFilterOutput } from "./filter-operators.js";
|
|
6
5
|
//#region ../zql/src/ivm/exists.ts
|
|
@@ -69,41 +68,53 @@ var Exists = class {
|
|
|
69
68
|
assert(!this.#inPush, "Unexpected re-entrancy");
|
|
70
69
|
this.#inPush = true;
|
|
71
70
|
try {
|
|
72
|
-
switch (change
|
|
73
|
-
case
|
|
74
|
-
case
|
|
75
|
-
case
|
|
71
|
+
switch (change.type) {
|
|
72
|
+
case "add":
|
|
73
|
+
case "edit":
|
|
74
|
+
case "remove":
|
|
76
75
|
yield* this.#pushWithFilter(change);
|
|
77
76
|
return;
|
|
78
|
-
case
|
|
79
|
-
if (change
|
|
77
|
+
case "child":
|
|
78
|
+
if (change.child.relationshipName !== this.#relationshipName || change.child.change.type === "edit" || change.child.change.type === "child") {
|
|
80
79
|
yield* this.#pushWithFilter(change);
|
|
81
80
|
return;
|
|
82
81
|
}
|
|
83
|
-
switch (change
|
|
84
|
-
case
|
|
85
|
-
const size = yield* this.#fetchSize(change
|
|
86
|
-
if (size === 1) if (this.#not) yield* this.#output.push(
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
82
|
+
switch (change.child.change.type) {
|
|
83
|
+
case "add": {
|
|
84
|
+
const size = yield* this.#fetchSize(change.node);
|
|
85
|
+
if (size === 1) if (this.#not) yield* this.#output.push({
|
|
86
|
+
type: "remove",
|
|
87
|
+
node: {
|
|
88
|
+
row: change.node.row,
|
|
89
|
+
relationships: {
|
|
90
|
+
...change.node.relationships,
|
|
91
|
+
[this.#relationshipName]: () => []
|
|
92
|
+
}
|
|
91
93
|
}
|
|
92
|
-
}
|
|
93
|
-
else yield* this.#output.push(
|
|
94
|
+
}, this);
|
|
95
|
+
else yield* this.#output.push({
|
|
96
|
+
type: "add",
|
|
97
|
+
node: change.node
|
|
98
|
+
}, this);
|
|
94
99
|
else yield* this.#pushWithFilter(change, size > 0);
|
|
95
100
|
return;
|
|
96
101
|
}
|
|
97
|
-
case
|
|
98
|
-
const size = yield* this.#fetchSize(change
|
|
99
|
-
if (size === 0) if (this.#not) yield* this.#output.push(
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
102
|
+
case "remove": {
|
|
103
|
+
const size = yield* this.#fetchSize(change.node);
|
|
104
|
+
if (size === 0) if (this.#not) yield* this.#output.push({
|
|
105
|
+
type: "add",
|
|
106
|
+
node: change.node
|
|
107
|
+
}, this);
|
|
108
|
+
else yield* this.#output.push({
|
|
109
|
+
type: "remove",
|
|
110
|
+
node: {
|
|
111
|
+
row: change.node.row,
|
|
112
|
+
relationships: {
|
|
113
|
+
...change.node.relationships,
|
|
114
|
+
[this.#relationshipName]: () => [change.child.change.node]
|
|
115
|
+
}
|
|
105
116
|
}
|
|
106
|
-
}
|
|
117
|
+
}, this);
|
|
107
118
|
else yield* this.#pushWithFilter(change, size > 0);
|
|
108
119
|
return;
|
|
109
120
|
}
|
|
@@ -137,7 +148,7 @@ var Exists = class {
|
|
|
137
148
|
* Pushes a change if this.#filter is true for its row.
|
|
138
149
|
*/
|
|
139
150
|
*#pushWithFilter(change, exists) {
|
|
140
|
-
if (yield* this.#filter(change
|
|
151
|
+
if (yield* this.#filter(change.node, exists)) yield* this.#output.push(change, this);
|
|
141
152
|
}
|
|
142
153
|
*#fetchExists(node) {
|
|
143
154
|
return (yield* this.#fetchSize(node)) > 0;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"exists.js","names":["#input","#relationshipName","#not","#parentJoinKey","#noSizeReuse","#cache","#cacheHitCountsForTesting","#output","#inPush","#getCacheKey","#fetchExists","#filter","#pushWithFilter","#fetchSize"],"sources":["../../../../../zql/src/ivm/exists.ts"],"sourcesContent":["import {areEqual} from '../../../shared/src/arrays.ts';\nimport {assert, unreachable} from '../../../shared/src/asserts.ts';\nimport type {CompoundKey} from '../../../zero-protocol/src/ast.ts';\nimport {ChangeIndex} from './change-index.ts';\nimport {ChangeType} from './change-type.ts';\nimport {makeAddChange, makeRemoveChange, type Change} from './change.ts';\nimport {normalizeUndefined, type Node, type NormalizedValue} from './data.ts';\nimport {\n throwFilterOutput,\n type FilterInput,\n type FilterOperator,\n type FilterOutput,\n} from './filter-operators.ts';\nimport type {SourceSchema} from './schema.ts';\nimport {type Stream} from './stream.ts';\n\n/**\n * The Exists operator filters data based on whether or not a relationship is\n * non-empty.\n */\nexport class Exists implements FilterOperator {\n readonly #input: FilterInput;\n readonly #relationshipName: string;\n readonly #not: boolean;\n readonly #parentJoinKey: CompoundKey;\n readonly #noSizeReuse: boolean;\n #cache: Map<string, boolean>;\n #cacheHitCountsForTesting: Map<string, number> | undefined;\n #output: FilterOutput = throwFilterOutput;\n\n /**\n * This instance variable is `true` when this operator is processing a `push`,\n * and is used to disable reuse of cached sizes across rows with the\n * same parent join key value.\n * This is necessary because during a push relationships can be inconsistent\n * due to push communicating changes (which may change multiple Nodes) one\n * Node at a time.\n */\n #inPush = false;\n\n constructor(\n input: FilterInput,\n relationshipName: string,\n parentJoinKey: CompoundKey,\n type: 'EXISTS' | 'NOT EXISTS',\n cacheHitCountsForTesting?: Map<string, number>,\n ) {\n this.#input = input;\n this.#relationshipName = relationshipName;\n this.#input.setFilterOutput(this);\n this.#cache = new Map();\n this.#cacheHitCountsForTesting = cacheHitCountsForTesting;\n assert(\n this.#input.getSchema().relationships[relationshipName],\n `Input schema missing ${relationshipName}`,\n );\n this.#not = type === 'NOT EXISTS';\n this.#parentJoinKey = parentJoinKey;\n\n // If the parentJoinKey is the primary key, no sense in trying to reuse.\n this.#noSizeReuse = areEqual(\n parentJoinKey,\n this.#input.getSchema().primaryKey,\n );\n }\n\n setFilterOutput(output: FilterOutput): void {\n this.#output = output;\n }\n\n beginFilter() {\n this.#output.beginFilter();\n }\n\n endFilter() {\n this.#cache = new Map();\n this.#output.endFilter();\n }\n\n *filter(node: Node): Generator<'yield', boolean> {\n let exists: boolean | undefined;\n if (!this.#noSizeReuse && !this.#inPush) {\n const key = this.#getCacheKey(node, this.#parentJoinKey);\n exists = this.#cache.get(key);\n if (exists === undefined) {\n exists = yield* this.#fetchExists(node);\n this.#cache.set(key, exists);\n } else if (this.#cacheHitCountsForTesting) {\n this.#cacheHitCountsForTesting.set(\n key,\n (this.#cacheHitCountsForTesting.get(key) ?? 0) + 1,\n );\n }\n }\n\n const result =\n (yield* this.#filter(node, exists)) && (yield* this.#output.filter(node));\n return result;\n }\n\n destroy(): void {\n this.#input.destroy();\n }\n\n getSchema(): SourceSchema {\n return this.#input.getSchema();\n }\n\n *push(change: Change): Stream<'yield'> {\n assert(!this.#inPush, 'Unexpected re-entrancy');\n this.#inPush = true;\n try {\n switch (change[ChangeIndex.TYPE]) {\n // add, remove and edit cannot change the size of the\n // this.#relationshipName relationship, so simply #pushWithFilter\n case ChangeType.ADD:\n case ChangeType.EDIT:\n case ChangeType.REMOVE: {\n yield* this.#pushWithFilter(change);\n return;\n }\n case ChangeType.CHILD:\n // Only add and remove child changes for the\n // this.#relationshipName relationship, can change the size\n // of the this.#relationshipName relationship, for other\n // child changes simply #pushWithFilter\n if (\n change[ChangeIndex.CHILD_DATA].relationshipName !==\n this.#relationshipName ||\n change[ChangeIndex.CHILD_DATA].change[ChangeIndex.TYPE] ===\n ChangeType.EDIT ||\n change[ChangeIndex.CHILD_DATA].change[ChangeIndex.TYPE] ===\n ChangeType.CHILD\n ) {\n yield* this.#pushWithFilter(change);\n return;\n }\n switch (change[ChangeIndex.CHILD_DATA].change[ChangeIndex.TYPE]) {\n case ChangeType.ADD: {\n const size = yield* this.#fetchSize(change[ChangeIndex.NODE]);\n if (size === 1) {\n if (this.#not) {\n // Since the add child change currently being processed is not\n // pushed to output, the added child needs to be excluded from\n // the remove being pushed to output (since the child has\n // never been added to the output).\n yield* this.#output.push(\n makeRemoveChange({\n row: change[ChangeIndex.NODE].row,\n relationships: {\n ...change[ChangeIndex.NODE].relationships,\n [this.#relationshipName]: () => [],\n },\n }),\n this,\n );\n } else {\n yield* this.#output.push(\n makeAddChange(change[ChangeIndex.NODE]),\n this,\n );\n }\n } else {\n yield* this.#pushWithFilter(change, size > 0);\n }\n return;\n }\n case ChangeType.REMOVE: {\n const size = yield* this.#fetchSize(change[ChangeIndex.NODE]);\n if (size === 0) {\n if (this.#not) {\n yield* this.#output.push(\n makeAddChange(change[ChangeIndex.NODE]),\n this,\n );\n } else {\n // Since the remove child change currently being processed is\n // not pushed to output, the removed child needs to be added to\n // the remove being pushed to output.\n yield* this.#output.push(\n makeRemoveChange({\n row: change[ChangeIndex.NODE].row,\n relationships: {\n ...change[ChangeIndex.NODE].relationships,\n [this.#relationshipName]: () => [\n change[ChangeIndex.CHILD_DATA].change[\n ChangeIndex.NODE\n ],\n ],\n },\n }),\n this,\n );\n }\n } else {\n yield* this.#pushWithFilter(change, size > 0);\n }\n return;\n }\n }\n return;\n default:\n unreachable(change);\n }\n } finally {\n this.#inPush = false;\n }\n }\n\n /**\n * Returns whether or not the node's this.#relationshipName\n * relationship passes the exist/not exists filter condition.\n * If the optional `size` is passed it is used.\n * Otherwise, if there is a stored size for the row it is used.\n * Otherwise the size is computed by streaming the node's\n * relationship with this.#relationshipName (this computed size is also\n * stored).\n */\n *#filter(node: Node, exists?: boolean): Generator<'yield', boolean> {\n exists = exists ?? (yield* this.#fetchExists(node));\n return this.#not ? !exists : exists;\n }\n\n #getCacheKey(node: Node, def: CompoundKey): string {\n const values: NormalizedValue[] = [];\n for (const key of def) {\n values.push(normalizeUndefined(node.row[key]));\n }\n return JSON.stringify(values);\n }\n\n /**\n * Pushes a change if this.#filter is true for its row.\n */\n *#pushWithFilter(change: Change, exists?: boolean): Stream<'yield'> {\n if (yield* this.#filter(change[ChangeIndex.NODE], exists)) {\n yield* this.#output.push(change, this);\n }\n }\n\n *#fetchExists(node: Node): Generator<'yield', boolean> {\n // While it seems like this should be able to fetch just 1 node\n // to check for exists, we can't because Take does not support\n // early return during initial fetch.\n return (yield* this.#fetchSize(node)) > 0;\n }\n\n *#fetchSize(node: Node): Generator<'yield', number> {\n const relationship = node.relationships[this.#relationshipName];\n assert(\n relationship,\n () =>\n `Exists: relationship \"${this.#relationshipName}\" not found on node`,\n );\n let size = 0;\n for (const n of relationship()) {\n if (n === 'yield') {\n yield 'yield';\n } else {\n size++;\n }\n }\n return size;\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"exists.js","names":["#input","#relationshipName","#not","#parentJoinKey","#noSizeReuse","#cache","#cacheHitCountsForTesting","#output","#inPush","#getCacheKey","#fetchExists","#filter","#pushWithFilter","#fetchSize"],"sources":["../../../../../zql/src/ivm/exists.ts"],"sourcesContent":["import {areEqual} from '../../../shared/src/arrays.ts';\nimport {assert, unreachable} from '../../../shared/src/asserts.ts';\nimport type {CompoundKey} from '../../../zero-protocol/src/ast.ts';\nimport {type Change} from './change.ts';\nimport {normalizeUndefined, type Node, type NormalizedValue} from './data.ts';\nimport {\n throwFilterOutput,\n type FilterInput,\n type FilterOperator,\n type FilterOutput,\n} from './filter-operators.ts';\nimport type {SourceSchema} from './schema.ts';\nimport {type Stream} from './stream.ts';\n\n/**\n * The Exists operator filters data based on whether or not a relationship is\n * non-empty.\n */\nexport class Exists implements FilterOperator {\n readonly #input: FilterInput;\n readonly #relationshipName: string;\n readonly #not: boolean;\n readonly #parentJoinKey: CompoundKey;\n readonly #noSizeReuse: boolean;\n #cache: Map<string, boolean>;\n #cacheHitCountsForTesting: Map<string, number> | undefined;\n #output: FilterOutput = throwFilterOutput;\n\n /**\n * This instance variable is `true` when this operator is processing a `push`,\n * and is used to disable reuse of cached sizes across rows with the\n * same parent join key value.\n * This is necessary because during a push relationships can be inconsistent\n * due to push communicating changes (which may change multiple Nodes) one\n * Node at a time.\n */\n #inPush = false;\n\n constructor(\n input: FilterInput,\n relationshipName: string,\n parentJoinKey: CompoundKey,\n type: 'EXISTS' | 'NOT EXISTS',\n cacheHitCountsForTesting?: Map<string, number>,\n ) {\n this.#input = input;\n this.#relationshipName = relationshipName;\n this.#input.setFilterOutput(this);\n this.#cache = new Map();\n this.#cacheHitCountsForTesting = cacheHitCountsForTesting;\n assert(\n this.#input.getSchema().relationships[relationshipName],\n `Input schema missing ${relationshipName}`,\n );\n this.#not = type === 'NOT EXISTS';\n this.#parentJoinKey = parentJoinKey;\n\n // If the parentJoinKey is the primary key, no sense in trying to reuse.\n this.#noSizeReuse = areEqual(\n parentJoinKey,\n this.#input.getSchema().primaryKey,\n );\n }\n\n setFilterOutput(output: FilterOutput): void {\n this.#output = output;\n }\n\n beginFilter() {\n this.#output.beginFilter();\n }\n\n endFilter() {\n this.#cache = new Map();\n this.#output.endFilter();\n }\n\n *filter(node: Node): Generator<'yield', boolean> {\n let exists: boolean | undefined;\n if (!this.#noSizeReuse && !this.#inPush) {\n const key = this.#getCacheKey(node, this.#parentJoinKey);\n exists = this.#cache.get(key);\n if (exists === undefined) {\n exists = yield* this.#fetchExists(node);\n this.#cache.set(key, exists);\n } else if (this.#cacheHitCountsForTesting) {\n this.#cacheHitCountsForTesting.set(\n key,\n (this.#cacheHitCountsForTesting.get(key) ?? 0) + 1,\n );\n }\n }\n\n const result =\n (yield* this.#filter(node, exists)) && (yield* this.#output.filter(node));\n return result;\n }\n\n destroy(): void {\n this.#input.destroy();\n }\n\n getSchema(): SourceSchema {\n return this.#input.getSchema();\n }\n\n *push(change: Change): Stream<'yield'> {\n assert(!this.#inPush, 'Unexpected re-entrancy');\n this.#inPush = true;\n try {\n switch (change.type) {\n // add, remove and edit cannot change the size of the\n // this.#relationshipName relationship, so simply #pushWithFilter\n case 'add':\n case 'edit':\n case 'remove': {\n yield* this.#pushWithFilter(change);\n return;\n }\n case 'child':\n // Only add and remove child changes for the\n // this.#relationshipName relationship, can change the size\n // of the this.#relationshipName relationship, for other\n // child changes simply #pushWithFilter\n if (\n change.child.relationshipName !== this.#relationshipName ||\n change.child.change.type === 'edit' ||\n change.child.change.type === 'child'\n ) {\n yield* this.#pushWithFilter(change);\n return;\n }\n switch (change.child.change.type) {\n case 'add': {\n const size = yield* this.#fetchSize(change.node);\n if (size === 1) {\n if (this.#not) {\n // Since the add child change currently being processed is not\n // pushed to output, the added child needs to be excluded from\n // the remove being pushed to output (since the child has\n // never been added to the output).\n yield* this.#output.push(\n {\n type: 'remove',\n node: {\n row: change.node.row,\n relationships: {\n ...change.node.relationships,\n [this.#relationshipName]: () => [],\n },\n },\n },\n this,\n );\n } else {\n yield* this.#output.push(\n {\n type: 'add',\n node: change.node,\n },\n this,\n );\n }\n } else {\n yield* this.#pushWithFilter(change, size > 0);\n }\n return;\n }\n case 'remove': {\n const size = yield* this.#fetchSize(change.node);\n if (size === 0) {\n if (this.#not) {\n yield* this.#output.push(\n {\n type: 'add',\n node: change.node,\n },\n this,\n );\n } else {\n // Since the remove child change currently being processed is\n // not pushed to output, the removed child needs to be added to\n // the remove being pushed to output.\n yield* this.#output.push(\n {\n type: 'remove',\n node: {\n row: change.node.row,\n relationships: {\n ...change.node.relationships,\n [this.#relationshipName]: () => [\n change.child.change.node,\n ],\n },\n },\n },\n this,\n );\n }\n } else {\n yield* this.#pushWithFilter(change, size > 0);\n }\n return;\n }\n }\n return;\n default:\n unreachable(change);\n }\n } finally {\n this.#inPush = false;\n }\n }\n\n /**\n * Returns whether or not the node's this.#relationshipName\n * relationship passes the exist/not exists filter condition.\n * If the optional `size` is passed it is used.\n * Otherwise, if there is a stored size for the row it is used.\n * Otherwise the size is computed by streaming the node's\n * relationship with this.#relationshipName (this computed size is also\n * stored).\n */\n *#filter(node: Node, exists?: boolean): Generator<'yield', boolean> {\n exists = exists ?? (yield* this.#fetchExists(node));\n return this.#not ? !exists : exists;\n }\n\n #getCacheKey(node: Node, def: CompoundKey): string {\n const values: NormalizedValue[] = [];\n for (const key of def) {\n values.push(normalizeUndefined(node.row[key]));\n }\n return JSON.stringify(values);\n }\n\n /**\n * Pushes a change if this.#filter is true for its row.\n */\n *#pushWithFilter(change: Change, exists?: boolean): Stream<'yield'> {\n if (yield* this.#filter(change.node, exists)) {\n yield* this.#output.push(change, this);\n }\n }\n\n *#fetchExists(node: Node): Generator<'yield', boolean> {\n // While it seems like this should be able to fetch just 1 node\n // to check for exists, we can't because Take does not support\n // early return during initial fetch.\n return (yield* this.#fetchSize(node)) > 0;\n }\n\n *#fetchSize(node: Node): Generator<'yield', number> {\n const relationship = node.relationships[this.#relationshipName];\n assert(\n relationship,\n () =>\n `Exists: relationship \"${this.#relationshipName}\" not found on node`,\n );\n let size = 0;\n for (const n of relationship()) {\n if (n === 'yield') {\n yield 'yield';\n } else {\n size++;\n }\n }\n return size;\n }\n}\n"],"mappings":"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"}
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
import { type Change } from './change.ts';
|
|
1
|
+
import type { Change } from './change.ts';
|
|
3
2
|
import { type Node } from './data.ts';
|
|
4
3
|
import type { FanOut } from './fan-out.ts';
|
|
5
4
|
import { type FilterInput, type FilterOperator, type FilterOutput } from './filter-operators.ts';
|
|
@@ -28,6 +27,6 @@ export declare class FanIn implements FilterOperator {
|
|
|
28
27
|
endFilter(): void;
|
|
29
28
|
filter(node: Node): Generator<'yield', boolean>;
|
|
30
29
|
push(change: Change): readonly never[];
|
|
31
|
-
fanOutDonePushingToAllBranches(fanOutChangeType:
|
|
30
|
+
fanOutDonePushingToAllBranches(fanOutChangeType: Change['type']): Generator<"yield", void, any>;
|
|
32
31
|
}
|
|
33
32
|
//# sourceMappingURL=fan-in.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fan-in.d.ts","sourceRoot":"","sources":["../../../../../zql/src/ivm/fan-in.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAC,
|
|
1
|
+
{"version":3,"file":"fan-in.d.ts","sourceRoot":"","sources":["../../../../../zql/src/ivm/fan-in.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAC,MAAM,EAAC,MAAM,aAAa,CAAC;AACxC,OAAO,EAAC,KAAK,IAAI,EAAC,MAAM,WAAW,CAAC;AACpC,OAAO,KAAK,EAAC,MAAM,EAAC,MAAM,cAAc,CAAC;AACzC,OAAO,EAEL,KAAK,WAAW,EAChB,KAAK,cAAc,EACnB,KAAK,YAAY,EAClB,MAAM,uBAAuB,CAAC;AAE/B,OAAO,KAAK,EAAC,YAAY,EAAC,MAAM,aAAa,CAAC;AAE9C;;;;;;;;;;;;;GAaG;AACH,qBAAa,KAAM,YAAW,cAAc;;gBAM9B,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE;IASjD,eAAe,CAAC,MAAM,EAAE,YAAY,GAAG,IAAI;IAI3C,OAAO,IAAI,IAAI;IAMf,SAAS;IAIT,WAAW,IAAI,IAAI;IAInB,SAAS,IAAI,IAAI;IAIhB,MAAM,CAAC,IAAI,EAAE,IAAI,GAAG,SAAS,CAAC,OAAO,EAAE,OAAO,CAAC;IAIhD,IAAI,CAAC,MAAM,EAAE,MAAM;IAKlB,8BAA8B,CAAC,gBAAgB,EAAE,MAAM,CAAC,MAAM,CAAC;CAkBjE"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fan-in.js","names":["#inputs","#schema","#output","#accumulatedPushes"],"sources":["../../../../../zql/src/ivm/fan-in.ts"],"sourcesContent":["import {assert} from '../../../shared/src/asserts.ts';\nimport {emptyArray, identity} from '../../../shared/src/sentinels.ts';\nimport type {
|
|
1
|
+
{"version":3,"file":"fan-in.js","names":["#inputs","#schema","#output","#accumulatedPushes"],"sources":["../../../../../zql/src/ivm/fan-in.ts"],"sourcesContent":["import {assert} from '../../../shared/src/asserts.ts';\nimport {emptyArray, identity} from '../../../shared/src/sentinels.ts';\nimport type {Change} from './change.ts';\nimport {type Node} from './data.ts';\nimport type {FanOut} from './fan-out.ts';\nimport {\n throwFilterOutput,\n type FilterInput,\n type FilterOperator,\n type FilterOutput,\n} from './filter-operators.ts';\nimport {pushAccumulatedChanges} from './push-accumulated.ts';\nimport type {SourceSchema} from './schema.ts';\n\n/**\n * The FanIn operator merges multiple streams into one.\n * It eliminates duplicates and must be paired with a fan-out operator\n * somewhere upstream of the fan-in.\n *\n * issue\n * |\n * fan-out\n * / \\\n * a b\n * \\ /\n * fan-in\n * |\n */\nexport class FanIn implements FilterOperator {\n readonly #inputs: readonly FilterInput[];\n readonly #schema: SourceSchema;\n #output: FilterOutput = throwFilterOutput;\n #accumulatedPushes: Change[] = [];\n\n constructor(fanOut: FanOut, inputs: FilterInput[]) {\n this.#inputs = inputs;\n this.#schema = fanOut.getSchema();\n for (const input of inputs) {\n input.setFilterOutput(this);\n assert(this.#schema === input.getSchema(), `Schema mismatch in fan-in`);\n }\n }\n\n setFilterOutput(output: FilterOutput): void {\n this.#output = output;\n }\n\n destroy(): void {\n for (const input of this.#inputs) {\n input.destroy();\n }\n }\n\n getSchema() {\n return this.#schema;\n }\n\n beginFilter(): void {\n this.#output.beginFilter();\n }\n\n endFilter(): void {\n this.#output.endFilter();\n }\n\n *filter(node: Node): Generator<'yield', boolean> {\n return yield* this.#output.filter(node);\n }\n\n push(change: Change) {\n this.#accumulatedPushes.push(change);\n return emptyArray;\n }\n\n *fanOutDonePushingToAllBranches(fanOutChangeType: Change['type']) {\n if (this.#inputs.length === 0) {\n assert(\n this.#accumulatedPushes.length === 0,\n 'If there are no inputs then fan-in should not receive any pushes.',\n );\n return;\n }\n\n yield* pushAccumulatedChanges(\n this.#accumulatedPushes,\n this.#output,\n this,\n fanOutChangeType,\n identity,\n identity,\n );\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AA4BA,IAAa,QAAb,MAA6C;CAC3C;CACA;CACA,UAAwB;CACxB,qBAA+B,EAAE;CAEjC,YAAY,QAAgB,QAAuB;AACjD,QAAA,SAAe;AACf,QAAA,SAAe,OAAO,WAAW;AACjC,OAAK,MAAM,SAAS,QAAQ;AAC1B,SAAM,gBAAgB,KAAK;AAC3B,UAAO,MAAA,WAAiB,MAAM,WAAW,EAAE,4BAA4B;;;CAI3E,gBAAgB,QAA4B;AAC1C,QAAA,SAAe;;CAGjB,UAAgB;AACd,OAAK,MAAM,SAAS,MAAA,OAClB,OAAM,SAAS;;CAInB,YAAY;AACV,SAAO,MAAA;;CAGT,cAAoB;AAClB,QAAA,OAAa,aAAa;;CAG5B,YAAkB;AAChB,QAAA,OAAa,WAAW;;CAG1B,CAAC,OAAO,MAAyC;AAC/C,SAAO,OAAO,MAAA,OAAa,OAAO,KAAK;;CAGzC,KAAK,QAAgB;AACnB,QAAA,kBAAwB,KAAK,OAAO;AACpC,SAAO;;CAGT,CAAC,+BAA+B,kBAAkC;AAChE,MAAI,MAAA,OAAa,WAAW,GAAG;AAC7B,UACE,MAAA,kBAAwB,WAAW,GACnC,oEACD;AACD;;AAGF,SAAO,uBACL,MAAA,mBACA,MAAA,QACA,MACA,kBACA,UACA,SACD"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { Change } from './change.ts';
|
|
2
|
-
import type { Node } from './data.ts';
|
|
3
2
|
import type { FanIn } from './fan-in.ts';
|
|
3
|
+
import type { Node } from './data.ts';
|
|
4
4
|
import type { FilterInput, FilterOperator, FilterOutput } from './filter-operators.ts';
|
|
5
5
|
/**
|
|
6
6
|
* Forks a stream into multiple streams.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fan-out.d.ts","sourceRoot":"","sources":["../../../../../zql/src/ivm/fan-out.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"fan-out.d.ts","sourceRoot":"","sources":["../../../../../zql/src/ivm/fan-out.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAC,MAAM,EAAC,MAAM,aAAa,CAAC;AACxC,OAAO,KAAK,EAAC,KAAK,EAAC,MAAM,aAAa,CAAC;AACvC,OAAO,KAAK,EAAC,IAAI,EAAC,MAAM,WAAW,CAAC;AACpC,OAAO,KAAK,EACV,WAAW,EACX,cAAc,EACd,YAAY,EACb,MAAM,uBAAuB,CAAC;AAE/B;;;;GAIG;AACH,qBAAa,MAAO,YAAW,cAAc;;gBAM/B,KAAK,EAAE,WAAW;IAK9B,QAAQ,CAAC,KAAK,EAAE,KAAK;IAIrB,eAAe,CAAC,MAAM,EAAE,YAAY,GAAG,IAAI;IAI3C,OAAO,IAAI,IAAI;IAWf,SAAS;IAIT,WAAW,IAAI,IAAI;IAMnB,SAAS,IAAI,IAAI;IAMhB,MAAM,CAAC,IAAI,EAAE,IAAI,GAAG,SAAS,CAAC,OAAO,EAAE,OAAO,CAAC;IAW/C,IAAI,CAAC,MAAM,EAAE,MAAM;CASrB"}
|
|
@@ -45,7 +45,7 @@ var FanOut = class {
|
|
|
45
45
|
}
|
|
46
46
|
*push(change) {
|
|
47
47
|
for (const out of this.#outputs) yield* out.push(change, this);
|
|
48
|
-
yield* must(this.#fanIn, "fan-out must have a corresponding fan-in set!").fanOutDonePushingToAllBranches(change
|
|
48
|
+
yield* must(this.#fanIn, "fan-out must have a corresponding fan-in set!").fanOutDonePushingToAllBranches(change.type);
|
|
49
49
|
}
|
|
50
50
|
};
|
|
51
51
|
//#endregion
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fan-out.js","names":["#input","#outputs","#fanIn","#destroyCount"],"sources":["../../../../../zql/src/ivm/fan-out.ts"],"sourcesContent":["import {must} from '../../../shared/src/must.ts';\nimport
|
|
1
|
+
{"version":3,"file":"fan-out.js","names":["#input","#outputs","#fanIn","#destroyCount"],"sources":["../../../../../zql/src/ivm/fan-out.ts"],"sourcesContent":["import {must} from '../../../shared/src/must.ts';\nimport type {Change} from './change.ts';\nimport type {FanIn} from './fan-in.ts';\nimport type {Node} from './data.ts';\nimport type {\n FilterInput,\n FilterOperator,\n FilterOutput,\n} from './filter-operators.ts';\n\n/**\n * Forks a stream into multiple streams.\n * Is meant to be paired with a `FanIn` operator which will\n * later merge the forks back together.\n */\nexport class FanOut implements FilterOperator {\n readonly #input: FilterInput;\n readonly #outputs: FilterOutput[] = [];\n #fanIn: FanIn | undefined;\n #destroyCount: number = 0;\n\n constructor(input: FilterInput) {\n this.#input = input;\n input.setFilterOutput(this);\n }\n\n setFanIn(fanIn: FanIn) {\n this.#fanIn = fanIn;\n }\n\n setFilterOutput(output: FilterOutput): void {\n this.#outputs.push(output);\n }\n\n destroy(): void {\n if (this.#destroyCount < this.#outputs.length) {\n ++this.#destroyCount;\n if (this.#destroyCount === this.#outputs.length) {\n this.#input.destroy();\n }\n } else {\n throw new Error('FanOut already destroyed once for each output');\n }\n }\n\n getSchema() {\n return this.#input.getSchema();\n }\n\n beginFilter(): void {\n for (const output of this.#outputs) {\n output.beginFilter();\n }\n }\n\n endFilter(): void {\n for (const output of this.#outputs) {\n output.endFilter();\n }\n }\n\n *filter(node: Node): Generator<'yield', boolean> {\n let result = false;\n for (const output of this.#outputs) {\n result = (yield* output.filter(node)) || result;\n if (result) {\n return true;\n }\n }\n return result;\n }\n\n *push(change: Change) {\n for (const out of this.#outputs) {\n yield* out.push(change, this);\n }\n yield* must(\n this.#fanIn,\n 'fan-out must have a corresponding fan-in set!',\n ).fanOutDonePushingToAllBranches(change.type);\n }\n}\n"],"mappings":";;;;;;;AAeA,IAAa,SAAb,MAA8C;CAC5C;CACA,WAAoC,EAAE;CACtC;CACA,gBAAwB;CAExB,YAAY,OAAoB;AAC9B,QAAA,QAAc;AACd,QAAM,gBAAgB,KAAK;;CAG7B,SAAS,OAAc;AACrB,QAAA,QAAc;;CAGhB,gBAAgB,QAA4B;AAC1C,QAAA,QAAc,KAAK,OAAO;;CAG5B,UAAgB;AACd,MAAI,MAAA,eAAqB,MAAA,QAAc,QAAQ;AAC7C,KAAE,MAAA;AACF,OAAI,MAAA,iBAAuB,MAAA,QAAc,OACvC,OAAA,MAAY,SAAS;QAGvB,OAAM,IAAI,MAAM,gDAAgD;;CAIpE,YAAY;AACV,SAAO,MAAA,MAAY,WAAW;;CAGhC,cAAoB;AAClB,OAAK,MAAM,UAAU,MAAA,QACnB,QAAO,aAAa;;CAIxB,YAAkB;AAChB,OAAK,MAAM,UAAU,MAAA,QACnB,QAAO,WAAW;;CAItB,CAAC,OAAO,MAAyC;EAC/C,IAAI,SAAS;AACb,OAAK,MAAM,UAAU,MAAA,SAAe;AAClC,aAAU,OAAO,OAAO,OAAO,KAAK,KAAK;AACzC,OAAI,OACF,QAAO;;AAGX,SAAO;;CAGT,CAAC,KAAK,QAAgB;AACpB,OAAK,MAAM,OAAO,MAAA,QAChB,QAAO,IAAI,KAAK,QAAQ,KAAK;AAE/B,SAAO,KACL,MAAA,OACA,gDACD,CAAC,+BAA+B,OAAO,KAAK"}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import type { BuilderDelegate } from '../builder/builder.ts';
|
|
2
|
-
import type { Change } from './change.ts';
|
|
3
|
-
import { type Node } from './data.ts';
|
|
4
1
|
import type { FetchRequest, Input, InputBase, Output } from './operator.ts';
|
|
2
|
+
import { type Node } from './data.ts';
|
|
3
|
+
import type { Change } from './change.ts';
|
|
5
4
|
import type { SourceSchema } from './schema.ts';
|
|
6
5
|
import { type Stream } from './stream.ts';
|
|
6
|
+
import type { BuilderDelegate } from '../builder/builder.ts';
|
|
7
7
|
/**
|
|
8
8
|
* The `where` clause of a ZQL query is implemented using a sub-graph of
|
|
9
9
|
* `FilterOperators`. This sub-graph starts with a `FilterStart` operator,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"filter-operators.d.ts","sourceRoot":"","sources":["../../../../../zql/src/ivm/filter-operators.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,
|
|
1
|
+
{"version":3,"file":"filter-operators.d.ts","sourceRoot":"","sources":["../../../../../zql/src/ivm/filter-operators.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,YAAY,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,EAAC,MAAM,eAAe,CAAC;AAC1E,OAAO,EAAC,KAAK,IAAI,EAAC,MAAM,WAAW,CAAC;AACpC,OAAO,KAAK,EAAC,MAAM,EAAC,MAAM,aAAa,CAAC;AACxC,OAAO,KAAK,EAAC,YAAY,EAAC,MAAM,aAAa,CAAC;AAC9C,OAAO,EAAC,KAAK,MAAM,EAAC,MAAM,aAAa,CAAC;AACxC,OAAO,KAAK,EAAC,eAAe,EAAC,MAAM,uBAAuB,CAAC;AAE3D;;;;;;;;;;;;;;;;;GAiBG;AAEH,MAAM,WAAW,WAAY,SAAQ,SAAS;IAC5C,+CAA+C;IAC/C,eAAe,CAAC,MAAM,EAAE,YAAY,GAAG,IAAI,CAAC;CAC7C;AAED,MAAM,WAAW,YAAa,SAAQ,MAAM;IAI1C,WAAW,IAAI,IAAI,CAAC;IACpB,MAAM,CAAC,IAAI,EAAE,IAAI,GAAG,SAAS,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;IAChD,SAAS,IAAI,IAAI,CAAC;CACnB;AAED,MAAM,WAAW,cAAe,SAAQ,WAAW,EAAE,YAAY;CAAG;AAEpE;;;;GAIG;AACH,eAAO,MAAM,iBAAiB,EAAE,YAW/B,CAAC;AAEF,qBAAa,WAAY,YAAW,WAAW,EAAE,MAAM;;gBAIzC,KAAK,EAAE,KAAK;IAKxB,eAAe,CAAC,MAAM,EAAE,YAAY;IAIpC,OAAO,IAAI,IAAI;IAIf,SAAS,IAAI,YAAY;IAIxB,IAAI,CAAC,MAAM,EAAE,MAAM;IAInB,KAAK,CAAC,GAAG,EAAE,YAAY,GAAG,MAAM,CAAC,IAAI,GAAG,OAAO,CAAC;CAkBlD;AAED,qBAAa,SAAU,YAAW,KAAK,EAAE,YAAY;;gBAMvC,KAAK,EAAE,WAAW,EAAE,KAAK,EAAE,WAAW;IAMjD,KAAK,CAAC,GAAG,EAAE,YAAY,GAAG,MAAM,CAAC,IAAI,GAAG,OAAO,CAAC;IAMjD,WAAW;IACX,SAAS;IAER,MAAM,CAAC,KAAK,EAAE,IAAI;IAInB,SAAS,CAAC,MAAM,EAAE,MAAM;IAIxB,OAAO,IAAI,IAAI;IAIf,SAAS,IAAI,YAAY;IAIxB,IAAI,CAAC,MAAM,EAAE,MAAM;CAGrB;AAED,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,KAAK,EACZ,QAAQ,EAAE,eAAe,EACzB,QAAQ,EAAE,CAAC,WAAW,EAAE,WAAW,KAAK,WAAW,GAClD,KAAK,CAQP"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"filter-operators.js","names":["#input","#output","#start"],"sources":["../../../../../zql/src/ivm/filter-operators.ts"],"sourcesContent":["import type {
|
|
1
|
+
{"version":3,"file":"filter-operators.js","names":["#input","#output","#start"],"sources":["../../../../../zql/src/ivm/filter-operators.ts"],"sourcesContent":["import type {FetchRequest, Input, InputBase, Output} from './operator.ts';\nimport {type Node} from './data.ts';\nimport type {Change} from './change.ts';\nimport type {SourceSchema} from './schema.ts';\nimport {type Stream} from './stream.ts';\nimport type {BuilderDelegate} from '../builder/builder.ts';\n\n/**\n * The `where` clause of a ZQL query is implemented using a sub-graph of\n * `FilterOperators`. This sub-graph starts with a `FilterStart` operator,\n * that adapts from the normal `Operator` `Output`, to the\n * `FilterOperator` `FilterInput`, and ends with a `FilterEnd` operator that\n * adapts from a `FilterOperator` `FilterOutput` to a normal `Operator` `Input`.\n * `FilterOperator`'s do not have `fetch` instead they have a\n * `filter(node: Node): boolean` method.\n * They also have `push` which is just like normal `Operator` push.\n * Not having a `fetch` means these `FilterOperator`'s cannot modify\n * `Node` `row`s or `relationship`s, but they shouldn't, they should just\n * filter.\n *\n * This `FilterOperator` abstraction enables much more efficient processing of\n * `fetch` for `where` clauses containing OR conditions.\n *\n * See https://github.com/rocicorp/mono/pull/4339\n */\n\nexport interface FilterInput extends InputBase {\n /** Tell the input where to send its output. */\n setFilterOutput(output: FilterOutput): void;\n}\n\nexport interface FilterOutput extends Output {\n // Lets the operator know that we're in a loop of filtering\n // nodes. E.g., so the operator can cache results for the\n // duration of the loop.\n beginFilter(): void;\n filter(node: Node): Generator<'yield', boolean>;\n endFilter(): void;\n}\n\nexport interface FilterOperator extends FilterInput, FilterOutput {}\n\n/**\n * An implementation of FilterOutput that throws if push or filter is called.\n * It is used as the initial value for for an operator's output before it is\n * set.\n */\nexport const throwFilterOutput: FilterOutput = {\n *push(_change: Change): Stream<'yield'> {\n throw new Error('Output not set');\n },\n\n *filter(_node: Node): Generator<'yield', boolean> {\n throw new Error('Output not set');\n },\n\n beginFilter() {},\n endFilter() {},\n};\n\nexport class FilterStart implements FilterInput, Output {\n readonly #input: Input;\n #output: FilterOutput = throwFilterOutput;\n\n constructor(input: Input) {\n this.#input = input;\n input.setOutput(this);\n }\n\n setFilterOutput(output: FilterOutput) {\n this.#output = output;\n }\n\n destroy(): void {\n this.#input.destroy();\n }\n\n getSchema(): SourceSchema {\n return this.#input.getSchema();\n }\n\n *push(change: Change) {\n yield* this.#output.push(change, this);\n }\n\n *fetch(req: FetchRequest): Stream<Node | 'yield'> {\n this.#output.beginFilter();\n try {\n for (const node of this.#input.fetch(req)) {\n if (node === 'yield') {\n yield node;\n continue;\n }\n if (yield* this.#output.filter(node)) {\n yield node;\n }\n }\n } finally {\n // finally is important if an exception is thrown or\n // if the stream is not fully consumed.\n this.#output.endFilter();\n }\n }\n}\n\nexport class FilterEnd implements Input, FilterOutput {\n readonly #start: FilterStart;\n readonly #input: FilterInput;\n\n #output: Output = throwFilterOutput;\n\n constructor(start: FilterStart, input: FilterInput) {\n this.#start = start;\n this.#input = input;\n input.setFilterOutput(this);\n }\n\n *fetch(req: FetchRequest): Stream<Node | 'yield'> {\n for (const node of this.#start.fetch(req)) {\n yield node;\n }\n }\n\n beginFilter() {}\n endFilter() {}\n\n *filter(_node: Node) {\n return true;\n }\n\n setOutput(output: Output) {\n this.#output = output;\n }\n\n destroy(): void {\n this.#input.destroy();\n }\n\n getSchema(): SourceSchema {\n return this.#input.getSchema();\n }\n\n *push(change: Change) {\n yield* this.#output.push(change, this);\n }\n}\n\nexport function buildFilterPipeline(\n input: Input,\n delegate: BuilderDelegate,\n pipeline: (filterInput: FilterInput) => FilterInput,\n): Input {\n const filterStart = new FilterStart(input);\n delegate.addEdge(input, filterStart);\n const middle = pipeline(filterStart);\n delegate.addEdge(filterStart, middle);\n const filterEnd = new FilterEnd(filterStart, middle);\n delegate.addEdge(middle, filterEnd);\n return filterEnd;\n}\n"],"mappings":";;;;;;;AA+CA,IAAa,oBAAkC;CAC7C,CAAC,KAAK,SAAkC;AACtC,QAAM,IAAI,MAAM,iBAAiB;;CAGnC,CAAC,OAAO,OAA0C;AAChD,QAAM,IAAI,MAAM,iBAAiB;;CAGnC,cAAc;CACd,YAAY;CACb;AAED,IAAa,cAAb,MAAwD;CACtD;CACA,UAAwB;CAExB,YAAY,OAAc;AACxB,QAAA,QAAc;AACd,QAAM,UAAU,KAAK;;CAGvB,gBAAgB,QAAsB;AACpC,QAAA,SAAe;;CAGjB,UAAgB;AACd,QAAA,MAAY,SAAS;;CAGvB,YAA0B;AACxB,SAAO,MAAA,MAAY,WAAW;;CAGhC,CAAC,KAAK,QAAgB;AACpB,SAAO,MAAA,OAAa,KAAK,QAAQ,KAAK;;CAGxC,CAAC,MAAM,KAA2C;AAChD,QAAA,OAAa,aAAa;AAC1B,MAAI;AACF,QAAK,MAAM,QAAQ,MAAA,MAAY,MAAM,IAAI,EAAE;AACzC,QAAI,SAAS,SAAS;AACpB,WAAM;AACN;;AAEF,QAAI,OAAO,MAAA,OAAa,OAAO,KAAK,CAClC,OAAM;;YAGF;AAGR,SAAA,OAAa,WAAW;;;;AAK9B,IAAa,YAAb,MAAsD;CACpD;CACA;CAEA,UAAkB;CAElB,YAAY,OAAoB,OAAoB;AAClD,QAAA,QAAc;AACd,QAAA,QAAc;AACd,QAAM,gBAAgB,KAAK;;CAG7B,CAAC,MAAM,KAA2C;AAChD,OAAK,MAAM,QAAQ,MAAA,MAAY,MAAM,IAAI,CACvC,OAAM;;CAIV,cAAc;CACd,YAAY;CAEZ,CAAC,OAAO,OAAa;AACnB,SAAO;;CAGT,UAAU,QAAgB;AACxB,QAAA,SAAe;;CAGjB,UAAgB;AACd,QAAA,MAAY,SAAS;;CAGvB,YAA0B;AACxB,SAAO,MAAA,MAAY,WAAW;;CAGhC,CAAC,KAAK,QAAgB;AACpB,SAAO,MAAA,OAAa,KAAK,QAAQ,KAAK;;;AAI1C,SAAgB,oBACd,OACA,UACA,UACO;CACP,MAAM,cAAc,IAAI,YAAY,MAAM;AAC1C,UAAS,QAAQ,OAAO,YAAY;CACpC,MAAM,SAAS,SAAS,YAAY;AACpC,UAAS,QAAQ,aAAa,OAAO;CACrC,MAAM,YAAY,IAAI,UAAU,aAAa,OAAO;AACpD,UAAS,QAAQ,QAAQ,UAAU;AACnC,QAAO"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"filter-push.d.ts","sourceRoot":"","sources":["../../../../../zql/src/ivm/filter-push.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAC,GAAG,EAAC,MAAM,oCAAoC,CAAC;
|
|
1
|
+
{"version":3,"file":"filter-push.d.ts","sourceRoot":"","sources":["../../../../../zql/src/ivm/filter-push.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAC,GAAG,EAAC,MAAM,oCAAoC,CAAC;AAC5D,OAAO,KAAK,EAAC,MAAM,EAAC,MAAM,aAAa,CAAC;AAExC,OAAO,KAAK,EAAC,SAAS,EAAE,MAAM,EAAC,MAAM,eAAe,CAAC;AACrD,OAAO,KAAK,EAAC,MAAM,EAAC,MAAM,aAAa,CAAC;AAExC,wBAAiB,UAAU,CACzB,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,SAAS,EACjB,SAAS,CAAC,EAAE,CAAC,GAAG,EAAE,GAAG,KAAK,OAAO,GAChC,MAAM,CAAC,OAAO,CAAC,CAuBjB"}
|
|
@@ -6,15 +6,15 @@ function* filterPush(change, output, pusher, predicate) {
|
|
|
6
6
|
yield* output.push(change, pusher);
|
|
7
7
|
return;
|
|
8
8
|
}
|
|
9
|
-
switch (change
|
|
10
|
-
case
|
|
11
|
-
case
|
|
12
|
-
if (predicate(change
|
|
9
|
+
switch (change.type) {
|
|
10
|
+
case "add":
|
|
11
|
+
case "remove":
|
|
12
|
+
if (predicate(change.node.row)) yield* output.push(change, pusher);
|
|
13
13
|
break;
|
|
14
|
-
case
|
|
15
|
-
if (predicate(change
|
|
14
|
+
case "child":
|
|
15
|
+
if (predicate(change.node.row)) yield* output.push(change, pusher);
|
|
16
16
|
break;
|
|
17
|
-
case
|
|
17
|
+
case "edit":
|
|
18
18
|
yield* maybeSplitAndPushEditChange(change, predicate, output, pusher);
|
|
19
19
|
break;
|
|
20
20
|
default: unreachable(change);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"filter-push.js","names":[],"sources":["../../../../../zql/src/ivm/filter-push.ts"],"sourcesContent":["import {unreachable} from '../../../shared/src/asserts.ts';\nimport type {Row} from '../../../zero-protocol/src/data.ts';\nimport
|
|
1
|
+
{"version":3,"file":"filter-push.js","names":[],"sources":["../../../../../zql/src/ivm/filter-push.ts"],"sourcesContent":["import {unreachable} from '../../../shared/src/asserts.ts';\nimport type {Row} from '../../../zero-protocol/src/data.ts';\nimport type {Change} from './change.ts';\nimport {maybeSplitAndPushEditChange} from './maybe-split-and-push-edit-change.ts';\nimport type {InputBase, Output} from './operator.ts';\nimport type {Stream} from './stream.ts';\n\nexport function* filterPush(\n change: Change,\n output: Output,\n pusher: InputBase,\n predicate?: (row: Row) => boolean,\n): Stream<'yield'> {\n if (!predicate) {\n yield* output.push(change, pusher);\n return;\n }\n switch (change.type) {\n case 'add':\n case 'remove':\n if (predicate(change.node.row)) {\n yield* output.push(change, pusher);\n }\n break;\n case 'child':\n if (predicate(change.node.row)) {\n yield* output.push(change, pusher);\n }\n break;\n case 'edit':\n yield* maybeSplitAndPushEditChange(change, predicate, output, pusher);\n break;\n default:\n unreachable(change);\n }\n}\n"],"mappings":";;;AAOA,UAAiB,WACf,QACA,QACA,QACA,WACiB;AACjB,KAAI,CAAC,WAAW;AACd,SAAO,OAAO,KAAK,QAAQ,OAAO;AAClC;;AAEF,SAAQ,OAAO,MAAf;EACE,KAAK;EACL,KAAK;AACH,OAAI,UAAU,OAAO,KAAK,IAAI,CAC5B,QAAO,OAAO,KAAK,QAAQ,OAAO;AAEpC;EACF,KAAK;AACH,OAAI,UAAU,OAAO,KAAK,IAAI,CAC5B,QAAO,OAAO,KAAK,QAAQ,OAAO;AAEpC;EACF,KAAK;AACH,UAAO,4BAA4B,QAAQ,WAAW,QAAQ,OAAO;AACrE;EACF,QACE,aAAY,OAAO"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { Row } from '../../../zero-protocol/src/data.ts';
|
|
2
2
|
import type { Change } from './change.ts';
|
|
3
|
-
import { type Node } from './data.ts';
|
|
4
3
|
import { type FilterInput, type FilterOperator, type FilterOutput } from './filter-operators.ts';
|
|
4
|
+
import { type Node } from './data.ts';
|
|
5
5
|
import type { SourceSchema } from './schema.ts';
|
|
6
6
|
/**
|
|
7
7
|
* The Filter operator filters data through a predicate. It is stateless.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"filter.d.ts","sourceRoot":"","sources":["../../../../../zql/src/ivm/filter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,GAAG,EAAC,MAAM,oCAAoC,CAAC;AAC5D,OAAO,KAAK,EAAC,MAAM,EAAC,MAAM,aAAa,CAAC;AACxC,OAAO,
|
|
1
|
+
{"version":3,"file":"filter.d.ts","sourceRoot":"","sources":["../../../../../zql/src/ivm/filter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,GAAG,EAAC,MAAM,oCAAoC,CAAC;AAC5D,OAAO,KAAK,EAAC,MAAM,EAAC,MAAM,aAAa,CAAC;AACxC,OAAO,EAEL,KAAK,WAAW,EAChB,KAAK,cAAc,EACnB,KAAK,YAAY,EAClB,MAAM,uBAAuB,CAAC;AAE/B,OAAO,EAAC,KAAK,IAAI,EAAC,MAAM,WAAW,CAAC;AACpC,OAAO,KAAK,EAAC,YAAY,EAAC,MAAM,aAAa,CAAC;AAE9C;;;;GAIG;AACH,qBAAa,MAAO,YAAW,cAAc;;gBAM/B,KAAK,EAAE,WAAW,EAAE,SAAS,EAAE,CAAC,GAAG,EAAE,GAAG,KAAK,OAAO;IAMhE,WAAW,IAAI,IAAI;IAInB,SAAS,IAAI,IAAI;IAIhB,MAAM,CAAC,IAAI,EAAE,IAAI,GAAG,SAAS,CAAC,OAAO,EAAE,OAAO,CAAC;IAIhD,eAAe,CAAC,MAAM,EAAE,YAAY;IAIpC,OAAO,IAAI,IAAI;IAIf,SAAS,IAAI,YAAY;IAIxB,IAAI,CAAC,MAAM,EAAE,MAAM;CAGrB"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"filter.js","names":["#input","#predicate","#output"],"sources":["../../../../../zql/src/ivm/filter.ts"],"sourcesContent":["import type {Row} from '../../../zero-protocol/src/data.ts';\nimport type {Change} from './change.ts';\nimport {
|
|
1
|
+
{"version":3,"file":"filter.js","names":["#input","#predicate","#output"],"sources":["../../../../../zql/src/ivm/filter.ts"],"sourcesContent":["import type {Row} from '../../../zero-protocol/src/data.ts';\nimport type {Change} from './change.ts';\nimport {\n throwFilterOutput,\n type FilterInput,\n type FilterOperator,\n type FilterOutput,\n} from './filter-operators.ts';\nimport {filterPush} from './filter-push.ts';\nimport {type Node} from './data.ts';\nimport type {SourceSchema} from './schema.ts';\n\n/**\n * The Filter operator filters data through a predicate. It is stateless.\n *\n * The predicate must be pure.\n */\nexport class Filter implements FilterOperator {\n readonly #input: FilterInput;\n readonly #predicate: (row: Row) => boolean;\n\n #output: FilterOutput = throwFilterOutput;\n\n constructor(input: FilterInput, predicate: (row: Row) => boolean) {\n this.#input = input;\n this.#predicate = predicate;\n input.setFilterOutput(this);\n }\n\n beginFilter(): void {\n this.#output.beginFilter();\n }\n\n endFilter(): void {\n this.#output.endFilter();\n }\n\n *filter(node: Node): Generator<'yield', boolean> {\n return this.#predicate(node.row) && (yield* this.#output.filter(node));\n }\n\n setFilterOutput(output: FilterOutput) {\n this.#output = output;\n }\n\n destroy(): void {\n this.#input.destroy();\n }\n\n getSchema(): SourceSchema {\n return this.#input.getSchema();\n }\n\n *push(change: Change) {\n yield* filterPush(change, this.#output, this, this.#predicate);\n }\n}\n"],"mappings":";;;;;;;;;AAiBA,IAAa,SAAb,MAA8C;CAC5C;CACA;CAEA,UAAwB;CAExB,YAAY,OAAoB,WAAkC;AAChE,QAAA,QAAc;AACd,QAAA,YAAkB;AAClB,QAAM,gBAAgB,KAAK;;CAG7B,cAAoB;AAClB,QAAA,OAAa,aAAa;;CAG5B,YAAkB;AAChB,QAAA,OAAa,WAAW;;CAG1B,CAAC,OAAO,MAAyC;AAC/C,SAAO,MAAA,UAAgB,KAAK,IAAI,KAAK,OAAO,MAAA,OAAa,OAAO,KAAK;;CAGvE,gBAAgB,QAAsB;AACpC,QAAA,SAAe;;CAGjB,UAAgB;AACd,QAAA,MAAY,SAAS;;CAGvB,YAA0B;AACxB,SAAO,MAAA,MAAY,WAAW;;CAGhC,CAAC,KAAK,QAAgB;AACpB,SAAO,WAAW,QAAQ,MAAA,QAAc,MAAM,MAAA,UAAgB"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"flipped-join.d.ts","sourceRoot":"","sources":["../../../../../zql/src/ivm/flipped-join.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAC,WAAW,EAAE,MAAM,EAAC,MAAM,mCAAmC,CAAC;
|
|
1
|
+
{"version":3,"file":"flipped-join.d.ts","sourceRoot":"","sources":["../../../../../zql/src/ivm/flipped-join.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAC,WAAW,EAAE,MAAM,EAAC,MAAM,mCAAmC,CAAC;AAI3E,OAAO,KAAK,EAAC,IAAI,EAAC,MAAM,WAAW,CAAC;AAQpC,OAAO,EAEL,KAAK,YAAY,EACjB,KAAK,KAAK,EACV,KAAK,MAAM,EACZ,MAAM,eAAe,CAAC;AACvB,OAAO,KAAK,EAAC,YAAY,EAAC,MAAM,aAAa,CAAC;AAC9C,OAAO,EAAC,KAAK,MAAM,EAAC,MAAM,aAAa,CAAC;AAExC,KAAK,IAAI,GAAG;IACV,MAAM,EAAE,KAAK,CAAC;IACd,KAAK,EAAE,KAAK,CAAC;IAEb,SAAS,EAAE,WAAW,CAAC;IACvB,QAAQ,EAAE,WAAW,CAAC;IAEtB,gBAAgB,EAAE,MAAM,CAAC;IACzB,MAAM,EAAE,OAAO,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF;;;;;;;GAOG;AACH,qBAAa,WAAY,YAAW,KAAK;;gBAY3B,EACV,MAAM,EACN,KAAK,EACL,SAAS,EACT,QAAQ,EACR,gBAAgB,EAChB,MAAM,EACN,MAAM,GACP,EAAE,IAAI;IAkCP,OAAO,IAAI,IAAI;IAKf,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;IAI/B,SAAS,IAAI,YAAY;IAQxB,KAAK,CAAC,GAAG,EAAE,YAAY,GAAG,MAAM,CAAC,IAAI,GAAG,OAAO,CAAC;CAuXlD"}
|
|
@@ -2,7 +2,6 @@ import { assert, unreachable } from "../../../shared/src/asserts.js";
|
|
|
2
2
|
import { binarySearch } from "../../../shared/src/binary-search.js";
|
|
3
3
|
import { emptyArray } from "../../../shared/src/sentinels.js";
|
|
4
4
|
import { throwOutput } from "./operator.js";
|
|
5
|
-
import { makeAddChange, makeChildChange, makeEditChange, makeRemoveChange } from "./change.js";
|
|
6
5
|
import { constraintsAreCompatible } from "./constraint.js";
|
|
7
6
|
import { buildJoinConstraint, generateWithOverlayNoYield, isJoinMatch, rowEqualsForCompoundKey } from "./join-utils.js";
|
|
8
7
|
//#region ../zql/src/ivm/flipped-join.ts
|
|
@@ -23,7 +22,6 @@ var FlippedJoin = class {
|
|
|
23
22
|
#schema;
|
|
24
23
|
#output = throwOutput;
|
|
25
24
|
#inprogressChildChange;
|
|
26
|
-
#inprogressChildChangePosition;
|
|
27
25
|
constructor({ parent, child, parentKey, childKey, relationshipName, hidden, system }) {
|
|
28
26
|
assert(parent !== child, "Parent and child must be different operators");
|
|
29
27
|
assert(parentKey.length === childKey.length, "The parentKey and childKey keys must have same length");
|
|
@@ -76,8 +74,8 @@ var FlippedJoin = class {
|
|
|
76
74
|
}
|
|
77
75
|
childNodes.push(node);
|
|
78
76
|
}
|
|
79
|
-
if (this.#inprogressChildChange?.
|
|
80
|
-
const removedNode = this.#inprogressChildChange
|
|
77
|
+
if (this.#inprogressChildChange?.change.type === "remove") {
|
|
78
|
+
const removedNode = this.#inprogressChildChange.change.node;
|
|
81
79
|
const compare = this.#child.getSchema().compareRows;
|
|
82
80
|
const insertPos = binarySearch(childNodes.length, (i) => compare(removedNode.row, childNodes[i].row));
|
|
83
81
|
childNodes.splice(insertPos, 0, removedNode);
|
|
@@ -140,11 +138,11 @@ var FlippedJoin = class {
|
|
|
140
138
|
nextParentNodes[minParentNodeChildIndex] = result.done ? null : result.value;
|
|
141
139
|
}
|
|
142
140
|
let overlaidRelatedChildNodes = relatedChildNodes;
|
|
143
|
-
if (this.#inprogressChildChange && this.#
|
|
144
|
-
const hasInprogressChildChangeBeenPushedForMinParentNode = this.#parent.getSchema().compareRows(minParentNode.row, this.#
|
|
145
|
-
if (this.#inprogressChildChange
|
|
146
|
-
if (hasInprogressChildChangeBeenPushedForMinParentNode) overlaidRelatedChildNodes = relatedChildNodes.filter((n) => n !== this.#inprogressChildChange?.
|
|
147
|
-
} else if (!hasInprogressChildChangeBeenPushedForMinParentNode) overlaidRelatedChildNodes = [...generateWithOverlayNoYield(relatedChildNodes, this.#inprogressChildChange, this.#child.getSchema())];
|
|
141
|
+
if (this.#inprogressChildChange && this.#inprogressChildChange.position && isJoinMatch(this.#inprogressChildChange.change.node.row, this.#childKey, minParentNode.row, this.#parentKey)) {
|
|
142
|
+
const hasInprogressChildChangeBeenPushedForMinParentNode = this.#parent.getSchema().compareRows(minParentNode.row, this.#inprogressChildChange.position) <= 0;
|
|
143
|
+
if (this.#inprogressChildChange.change.type === "remove") {
|
|
144
|
+
if (hasInprogressChildChangeBeenPushedForMinParentNode) overlaidRelatedChildNodes = relatedChildNodes.filter((n) => n !== this.#inprogressChildChange?.change.node);
|
|
145
|
+
} else if (!hasInprogressChildChangeBeenPushedForMinParentNode) overlaidRelatedChildNodes = [...generateWithOverlayNoYield(relatedChildNodes, this.#inprogressChildChange.change, this.#child.getSchema())];
|
|
148
146
|
}
|
|
149
147
|
if (overlaidRelatedChildNodes.length > 0) yield {
|
|
150
148
|
...minParentNode,
|
|
@@ -167,33 +165,37 @@ var FlippedJoin = class {
|
|
|
167
165
|
}
|
|
168
166
|
}
|
|
169
167
|
*#pushChild(change) {
|
|
170
|
-
switch (change
|
|
171
|
-
case
|
|
172
|
-
case
|
|
168
|
+
switch (change.type) {
|
|
169
|
+
case "add":
|
|
170
|
+
case "remove":
|
|
173
171
|
yield* this.#pushChildChange(change);
|
|
174
172
|
break;
|
|
175
|
-
case
|
|
176
|
-
assert(rowEqualsForCompoundKey(change
|
|
173
|
+
case "edit":
|
|
174
|
+
assert(rowEqualsForCompoundKey(change.oldNode.row, change.node.row, this.#childKey), `Child edit must not change relationship.`);
|
|
177
175
|
yield* this.#pushChildChange(change, true);
|
|
178
176
|
break;
|
|
179
|
-
case
|
|
177
|
+
case "child":
|
|
180
178
|
yield* this.#pushChildChange(change, true);
|
|
181
179
|
break;
|
|
182
180
|
}
|
|
183
181
|
}
|
|
184
182
|
*#pushChildChange(change, exists) {
|
|
185
|
-
this.#inprogressChildChange =
|
|
186
|
-
|
|
183
|
+
this.#inprogressChildChange = {
|
|
184
|
+
change,
|
|
185
|
+
position: void 0
|
|
186
|
+
};
|
|
187
187
|
try {
|
|
188
|
-
const constraint = buildJoinConstraint(change
|
|
188
|
+
const constraint = buildJoinConstraint(change.node.row, this.#childKey, this.#parentKey);
|
|
189
189
|
const parentNodeStream = constraint ? this.#parent.fetch({ constraint }) : [];
|
|
190
190
|
for (const parentNode of parentNodeStream) {
|
|
191
191
|
if (parentNode === "yield") {
|
|
192
192
|
yield "yield";
|
|
193
193
|
continue;
|
|
194
194
|
}
|
|
195
|
-
this.#inprogressChildChange =
|
|
196
|
-
|
|
195
|
+
this.#inprogressChildChange = {
|
|
196
|
+
change,
|
|
197
|
+
position: parentNode.row
|
|
198
|
+
};
|
|
197
199
|
const childNodeStream = () => {
|
|
198
200
|
const constraint = buildJoinConstraint(parentNode.row, this.#parentKey, this.#childKey);
|
|
199
201
|
return constraint ? this.#child.fetch({ constraint }) : [];
|
|
@@ -203,31 +205,35 @@ var FlippedJoin = class {
|
|
|
203
205
|
yield "yield";
|
|
204
206
|
continue;
|
|
205
207
|
}
|
|
206
|
-
if (this.#child.getSchema().compareRows(childNode.row, change
|
|
208
|
+
if (this.#child.getSchema().compareRows(childNode.row, change.node.row) !== 0) {
|
|
207
209
|
exists = true;
|
|
208
210
|
break;
|
|
209
211
|
}
|
|
210
212
|
}
|
|
211
|
-
if (exists) yield* this.#output.push(
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
...parentNode
|
|
215
|
-
|
|
213
|
+
if (exists) yield* this.#output.push({
|
|
214
|
+
type: "child",
|
|
215
|
+
node: {
|
|
216
|
+
...parentNode,
|
|
217
|
+
relationships: {
|
|
218
|
+
...parentNode.relationships,
|
|
219
|
+
[this.#relationshipName]: childNodeStream
|
|
220
|
+
}
|
|
221
|
+
},
|
|
222
|
+
child: {
|
|
223
|
+
relationshipName: this.#relationshipName,
|
|
224
|
+
change
|
|
216
225
|
}
|
|
217
|
-
},
|
|
218
|
-
|
|
219
|
-
change
|
|
220
|
-
|
|
221
|
-
else {
|
|
222
|
-
const newNode = {
|
|
226
|
+
}, this);
|
|
227
|
+
else yield* this.#output.push({
|
|
228
|
+
...change,
|
|
229
|
+
node: {
|
|
223
230
|
...parentNode,
|
|
224
231
|
relationships: {
|
|
225
232
|
...parentNode.relationships,
|
|
226
|
-
[this.#relationshipName]: () => [change
|
|
233
|
+
[this.#relationshipName]: () => [change.node]
|
|
227
234
|
}
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
}
|
|
235
|
+
}
|
|
236
|
+
}, this);
|
|
231
237
|
}
|
|
232
238
|
} finally {
|
|
233
239
|
this.#inprogressChildChange = void 0;
|
|
@@ -246,7 +252,7 @@ var FlippedJoin = class {
|
|
|
246
252
|
}
|
|
247
253
|
});
|
|
248
254
|
let hasRelatedChild = false;
|
|
249
|
-
for (const node of childNodeStream(change
|
|
255
|
+
for (const node of childNodeStream(change.node)()) if (node === "yield") {
|
|
250
256
|
yield "yield";
|
|
251
257
|
continue;
|
|
252
258
|
} else {
|
|
@@ -254,19 +260,22 @@ var FlippedJoin = class {
|
|
|
254
260
|
break;
|
|
255
261
|
}
|
|
256
262
|
if (!hasRelatedChild) return;
|
|
257
|
-
switch (change
|
|
258
|
-
case
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
yield* this.#output.push(makeChildChange(flip(change[1]), change[2]), this);
|
|
263
|
+
switch (change.type) {
|
|
264
|
+
case "add":
|
|
265
|
+
case "remove":
|
|
266
|
+
case "child":
|
|
267
|
+
yield* this.#output.push({
|
|
268
|
+
...change,
|
|
269
|
+
node: flip(change.node)
|
|
270
|
+
}, this);
|
|
266
271
|
break;
|
|
267
|
-
case
|
|
268
|
-
assert(rowEqualsForCompoundKey(change
|
|
269
|
-
yield* this.#output.push(
|
|
272
|
+
case "edit":
|
|
273
|
+
assert(rowEqualsForCompoundKey(change.oldNode.row, change.node.row, this.#parentKey), `Parent edit must not change relationship.`);
|
|
274
|
+
yield* this.#output.push({
|
|
275
|
+
type: "edit",
|
|
276
|
+
oldNode: flip(change.oldNode),
|
|
277
|
+
node: flip(change.node)
|
|
278
|
+
}, this);
|
|
270
279
|
break;
|
|
271
280
|
default: unreachable(change);
|
|
272
281
|
}
|