@rocicorp/zero 0.25.0-canary.8 → 0.25.0-canary.9
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/shared/src/deep-merge.d.ts +20 -3
- package/out/shared/src/deep-merge.d.ts.map +1 -1
- package/out/shared/src/deep-merge.js +27 -0
- package/out/shared/src/deep-merge.js.map +1 -0
- package/out/shared/src/logging.d.ts.map +1 -1
- package/out/shared/src/logging.js +25 -9
- package/out/shared/src/logging.js.map +1 -1
- package/out/shared/src/object-traversal.d.ts +19 -0
- package/out/shared/src/object-traversal.d.ts.map +1 -0
- package/out/shared/src/object-traversal.js +27 -0
- package/out/shared/src/object-traversal.js.map +1 -0
- package/out/zero/package.json.js +1 -1
- package/out/zero/src/pg.js +0 -2
- package/out/zero/src/pg.js.map +1 -1
- package/out/zero/src/server.js +0 -2
- package/out/zero/src/server.js.map +1 -1
- package/out/zero/src/zero.js +19 -3
- package/out/zero/src/zero.js.map +1 -1
- package/out/zero-cache/src/auth/jwt.d.ts +3 -0
- package/out/zero-cache/src/auth/jwt.d.ts.map +1 -1
- package/out/zero-cache/src/auth/jwt.js.map +1 -1
- package/out/zero-cache/src/auth/write-authorizer.d.ts +2 -1
- package/out/zero-cache/src/auth/write-authorizer.d.ts.map +1 -1
- package/out/zero-cache/src/auth/write-authorizer.js +1 -11
- package/out/zero-cache/src/auth/write-authorizer.js.map +1 -1
- package/out/zero-cache/src/config/zero-config.d.ts +27 -0
- package/out/zero-cache/src/config/zero-config.d.ts.map +1 -1
- package/out/zero-cache/src/config/zero-config.js +35 -7
- package/out/zero-cache/src/config/zero-config.js.map +1 -1
- package/out/zero-cache/src/custom/fetch.d.ts +5 -5
- package/out/zero-cache/src/custom/fetch.d.ts.map +1 -1
- package/out/zero-cache/src/custom/fetch.js +14 -11
- package/out/zero-cache/src/custom/fetch.js.map +1 -1
- package/out/zero-cache/src/custom-queries/transform-query.d.ts.map +1 -1
- package/out/zero-cache/src/custom-queries/transform-query.js +2 -4
- package/out/zero-cache/src/custom-queries/transform-query.js.map +1 -1
- package/out/zero-cache/src/db/specs.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 +9 -9
- package/out/zero-cache/src/server/change-streamer.js.map +1 -1
- package/out/zero-cache/src/server/syncer.d.ts.map +1 -1
- package/out/zero-cache/src/server/syncer.js +20 -8
- package/out/zero-cache/src/server/syncer.js.map +1 -1
- package/out/zero-cache/src/services/analyze.d.ts +1 -1
- package/out/zero-cache/src/services/analyze.d.ts.map +1 -1
- package/out/zero-cache/src/services/analyze.js +10 -1
- package/out/zero-cache/src/services/analyze.js.map +1 -1
- package/out/zero-cache/src/services/change-source/pg/schema/ddl.d.ts +5 -5
- package/out/zero-cache/src/services/change-source/pg/schema/published.d.ts +2 -2
- package/out/zero-cache/src/services/change-source/pg/schema/shard.d.ts +1 -1
- package/out/zero-cache/src/services/change-streamer/change-streamer-http.d.ts +11 -2
- 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 +36 -0
- package/out/zero-cache/src/services/change-streamer/change-streamer-http.js.map +1 -1
- package/out/zero-cache/src/services/http-service.d.ts +5 -4
- package/out/zero-cache/src/services/http-service.d.ts.map +1 -1
- package/out/zero-cache/src/services/http-service.js +15 -10
- package/out/zero-cache/src/services/http-service.js.map +1 -1
- package/out/zero-cache/src/services/mutagen/mutagen.d.ts +2 -1
- package/out/zero-cache/src/services/mutagen/mutagen.d.ts.map +1 -1
- package/out/zero-cache/src/services/mutagen/mutagen.js +3 -2
- package/out/zero-cache/src/services/mutagen/mutagen.js.map +1 -1
- package/out/zero-cache/src/services/mutagen/pusher.d.ts +198 -0
- package/out/zero-cache/src/services/mutagen/pusher.d.ts.map +1 -1
- package/out/zero-cache/src/services/mutagen/pusher.js +5 -5
- package/out/zero-cache/src/services/mutagen/pusher.js.map +1 -1
- package/out/zero-cache/src/services/run-ast.d.ts +4 -0
- package/out/zero-cache/src/services/run-ast.d.ts.map +1 -1
- package/out/zero-cache/src/services/run-ast.js +8 -1
- package/out/zero-cache/src/services/run-ast.js.map +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 -1
- 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.map +1 -1
- package/out/zero-cache/src/services/view-syncer/pipeline-driver.js +15 -8
- package/out/zero-cache/src/services/view-syncer/pipeline-driver.js.map +1 -1
- package/out/zero-cache/src/services/view-syncer/schema/types.d.ts +4 -4
- 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 +48 -25
- package/out/zero-cache/src/services/view-syncer/view-syncer.js.map +1 -1
- package/out/zero-cache/src/workers/connection.js +20 -15
- package/out/zero-cache/src/workers/connection.js.map +1 -1
- package/out/zero-cache/src/workers/syncer.d.ts.map +1 -1
- package/out/zero-cache/src/workers/syncer.js +3 -3
- package/out/zero-cache/src/workers/syncer.js.map +1 -1
- package/out/zero-client/src/client/bindings.d.ts +4 -4
- package/out/zero-client/src/client/bindings.d.ts.map +1 -1
- package/out/zero-client/src/client/bindings.js.map +1 -1
- package/out/zero-client/src/client/connection.d.ts +1 -1
- package/out/zero-client/src/client/connection.d.ts.map +1 -1
- package/out/zero-client/src/client/connection.js +1 -1
- package/out/zero-client/src/client/connection.js.map +1 -1
- package/out/zero-client/src/client/crud.d.ts +7 -5
- package/out/zero-client/src/client/crud.d.ts.map +1 -1
- package/out/zero-client/src/client/crud.js +7 -7
- package/out/zero-client/src/client/crud.js.map +1 -1
- package/out/zero-client/src/client/custom.d.ts +7 -5
- package/out/zero-client/src/client/custom.d.ts.map +1 -1
- package/out/zero-client/src/client/custom.js +12 -7
- package/out/zero-client/src/client/custom.js.map +1 -1
- package/out/zero-client/src/client/inspector/inspector.d.ts +5 -1
- package/out/zero-client/src/client/inspector/inspector.d.ts.map +1 -1
- package/out/zero-client/src/client/inspector/inspector.js +7 -0
- package/out/zero-client/src/client/inspector/inspector.js.map +1 -1
- package/out/zero-client/src/client/inspector/lazy-inspector.d.ts.map +1 -1
- package/out/zero-client/src/client/inspector/lazy-inspector.js +13 -13
- package/out/zero-client/src/client/inspector/lazy-inspector.js.map +1 -1
- package/out/zero-client/src/client/make-mutate-property.d.ts +43 -0
- package/out/zero-client/src/client/make-mutate-property.d.ts.map +1 -0
- package/out/zero-client/src/client/make-mutate-property.js +38 -0
- package/out/zero-client/src/client/make-mutate-property.js.map +1 -0
- package/out/zero-client/src/client/make-replicache-mutators.d.ts +34 -0
- package/out/zero-client/src/client/make-replicache-mutators.d.ts.map +1 -0
- package/out/zero-client/src/client/make-replicache-mutators.js +103 -0
- package/out/zero-client/src/client/make-replicache-mutators.js.map +1 -0
- package/out/zero-client/src/client/options.d.ts +39 -27
- package/out/zero-client/src/client/options.d.ts.map +1 -1
- package/out/zero-client/src/client/options.js.map +1 -1
- package/out/zero-client/src/client/version.js +1 -1
- package/out/zero-client/src/client/zero.d.ts +23 -33
- package/out/zero-client/src/client/zero.d.ts.map +1 -1
- package/out/zero-client/src/client/zero.js +52 -118
- package/out/zero-client/src/client/zero.js.map +1 -1
- package/out/zero-client/src/mod.d.ts +12 -7
- package/out/zero-client/src/mod.d.ts.map +1 -1
- package/out/zero-protocol/src/analyze-query-result.d.ts +236 -0
- package/out/zero-protocol/src/analyze-query-result.d.ts.map +1 -1
- package/out/zero-protocol/src/analyze-query-result.js +128 -2
- package/out/zero-protocol/src/analyze-query-result.js.map +1 -1
- package/out/zero-protocol/src/ast.d.ts +1 -1
- package/out/zero-protocol/src/connect.d.ts.map +1 -1
- package/out/zero-protocol/src/connect.js +4 -0
- package/out/zero-protocol/src/connect.js.map +1 -1
- package/out/zero-protocol/src/custom-queries.d.ts +1 -1
- package/out/zero-protocol/src/down.d.ts +99 -0
- package/out/zero-protocol/src/down.d.ts.map +1 -1
- package/out/zero-protocol/src/error.d.ts +4 -4
- package/out/zero-protocol/src/inspect-down.d.ts +297 -0
- package/out/zero-protocol/src/inspect-down.d.ts.map +1 -1
- package/out/zero-protocol/src/inspect-up.d.ts +4 -0
- package/out/zero-protocol/src/inspect-up.d.ts.map +1 -1
- package/out/zero-protocol/src/inspect-up.js +2 -1
- package/out/zero-protocol/src/inspect-up.js.map +1 -1
- package/out/zero-protocol/src/protocol-version.d.ts +1 -1
- package/out/zero-protocol/src/protocol-version.d.ts.map +1 -1
- package/out/zero-protocol/src/protocol-version.js +1 -1
- package/out/zero-protocol/src/protocol-version.js.map +1 -1
- package/out/zero-protocol/src/push.d.ts +1 -1
- package/out/zero-protocol/src/up.d.ts +1 -0
- package/out/zero-protocol/src/up.d.ts.map +1 -1
- package/out/zero-react/src/components/inspector.d.ts +3 -2
- package/out/zero-react/src/components/inspector.d.ts.map +1 -1
- package/out/zero-react/src/components/inspector.js.map +1 -1
- package/out/zero-react/src/components/zero-inspector.d.ts +3 -2
- package/out/zero-react/src/components/zero-inspector.d.ts.map +1 -1
- package/out/zero-react/src/components/zero-inspector.js.map +1 -1
- package/out/zero-react/src/use-query.d.ts +5 -4
- package/out/zero-react/src/use-query.d.ts.map +1 -1
- package/out/zero-react/src/use-query.js +4 -3
- package/out/zero-react/src/use-query.js.map +1 -1
- package/out/zero-react/src/zero-provider.d.ts +7 -7
- package/out/zero-react/src/zero-provider.d.ts.map +1 -1
- package/out/zero-react/src/zero-provider.js.map +1 -1
- package/out/zero-schema/src/builder/schema-builder.js +1 -1
- package/out/zero-schema/src/builder/schema-builder.js.map +1 -1
- package/out/zero-server/src/custom.d.ts +4 -5
- package/out/zero-server/src/custom.d.ts.map +1 -1
- package/out/zero-server/src/custom.js.map +1 -1
- package/out/zero-server/src/mod.d.ts +0 -1
- package/out/zero-server/src/mod.d.ts.map +1 -1
- package/out/zero-server/src/process-mutations.d.ts +9 -14
- package/out/zero-server/src/process-mutations.d.ts.map +1 -1
- package/out/zero-server/src/process-mutations.js +151 -105
- package/out/zero-server/src/process-mutations.js.map +1 -1
- package/out/zero-server/src/push-processor.d.ts +5 -3
- package/out/zero-server/src/push-processor.d.ts.map +1 -1
- package/out/zero-server/src/push-processor.js +17 -25
- package/out/zero-server/src/push-processor.js.map +1 -1
- package/out/zero-server/src/queries/process-queries.js +1 -1
- package/out/zero-server/src/queries/process-queries.js.map +1 -1
- package/out/zero-server/src/zql-database.d.ts.map +1 -1
- package/out/zero-server/src/zql-database.js +1 -1
- package/out/zero-server/src/zql-database.js.map +1 -1
- package/out/zero-solid/src/use-query.d.ts +3 -3
- package/out/zero-solid/src/use-query.d.ts.map +1 -1
- package/out/zero-solid/src/use-query.js +27 -38
- package/out/zero-solid/src/use-query.js.map +1 -1
- package/out/zero-solid/src/use-zero-connection-state.d.ts.map +1 -1
- package/out/zero-solid/src/use-zero-connection-state.js +7 -5
- package/out/zero-solid/src/use-zero-connection-state.js.map +1 -1
- package/out/zero-solid/src/use-zero-online.d.ts.map +1 -1
- package/out/zero-solid/src/use-zero-online.js +7 -5
- package/out/zero-solid/src/use-zero-online.js.map +1 -1
- package/out/zero-solid/src/use-zero.d.ts +6 -5
- package/out/zero-solid/src/use-zero.d.ts.map +1 -1
- package/out/zero-solid/src/use-zero.js +2 -6
- package/out/zero-solid/src/use-zero.js.map +1 -1
- package/out/zql/src/builder/builder.d.ts +2 -1
- package/out/zql/src/builder/builder.d.ts.map +1 -1
- package/out/zql/src/builder/builder.js +4 -3
- package/out/zql/src/builder/builder.js.map +1 -1
- package/out/zql/src/mutate/custom.d.ts +15 -6
- package/out/zql/src/mutate/custom.d.ts.map +1 -1
- package/out/zql/src/mutate/custom.js +6 -6
- package/out/zql/src/mutate/custom.js.map +1 -1
- package/out/zql/src/mutate/mutator-registry.d.ts +142 -0
- package/out/zql/src/mutate/mutator-registry.d.ts.map +1 -0
- package/out/zql/src/mutate/mutator-registry.js +97 -0
- package/out/zql/src/mutate/mutator-registry.js.map +1 -0
- package/out/zql/src/mutate/mutator.d.ts +98 -0
- package/out/zql/src/mutate/mutator.d.ts.map +1 -0
- package/out/zql/src/mutate/mutator.js +35 -0
- package/out/zql/src/mutate/mutator.js.map +1 -0
- package/out/zql/src/planner/planner-connection.d.ts +7 -15
- package/out/zql/src/planner/planner-connection.d.ts.map +1 -1
- package/out/zql/src/planner/planner-connection.js +30 -24
- package/out/zql/src/planner/planner-connection.js.map +1 -1
- package/out/zql/src/planner/planner-debug.d.ts +37 -43
- package/out/zql/src/planner/planner-debug.d.ts.map +1 -1
- package/out/zql/src/planner/planner-debug.js +242 -0
- package/out/zql/src/planner/planner-debug.js.map +1 -0
- package/out/zql/src/planner/planner-fan-in.d.ts.map +1 -1
- package/out/zql/src/planner/planner-fan-in.js +11 -8
- package/out/zql/src/planner/planner-fan-in.js.map +1 -1
- package/out/zql/src/planner/planner-fan-out.d.ts.map +1 -1
- package/out/zql/src/planner/planner-fan-out.js +11 -8
- package/out/zql/src/planner/planner-fan-out.js.map +1 -1
- package/out/zql/src/planner/planner-graph.d.ts.map +1 -1
- package/out/zql/src/planner/planner-graph.js +13 -5
- package/out/zql/src/planner/planner-graph.js.map +1 -1
- package/out/zql/src/planner/planner-join.d.ts.map +1 -1
- package/out/zql/src/planner/planner-join.js +12 -9
- package/out/zql/src/planner/planner-join.js.map +1 -1
- package/out/zql/src/planner/planner-node.d.ts +4 -0
- package/out/zql/src/planner/planner-node.d.ts.map +1 -1
- package/out/zql/src/planner/planner-node.js +8 -0
- package/out/zql/src/planner/planner-node.js.map +1 -0
- package/out/zql/src/query/create-builder.d.ts +7 -0
- package/out/zql/src/query/create-builder.d.ts.map +1 -0
- package/out/zql/src/query/create-builder.js +44 -0
- package/out/zql/src/query/create-builder.js.map +1 -0
- package/out/zql/src/query/named.d.ts +1 -7
- package/out/zql/src/query/named.d.ts.map +1 -1
- package/out/zql/src/query/named.js +0 -21
- package/out/zql/src/query/named.js.map +1 -1
- package/out/zql/src/query/query-impl.d.ts +4 -3
- package/out/zql/src/query/query-impl.d.ts.map +1 -1
- package/out/zql/src/query/query-impl.js +3 -0
- package/out/zql/src/query/query-impl.js.map +1 -1
- package/out/zql/src/query/query-internals.js +0 -4
- package/out/zql/src/query/query-internals.js.map +1 -1
- package/out/zql/src/query/query-registry.d.ts +253 -0
- package/out/zql/src/query/query-registry.d.ts.map +1 -0
- package/out/zql/src/query/query-registry.js +131 -0
- package/out/zql/src/query/query-registry.js.map +1 -0
- package/out/zql/src/query/query.d.ts +16 -1
- package/out/zql/src/query/query.d.ts.map +1 -1
- package/out/zql/src/query/schema-query.d.ts +6 -0
- package/out/zql/src/query/schema-query.d.ts.map +1 -0
- package/out/zql/src/query/validate-input.js +12 -13
- package/out/zql/src/query/validate-input.js.map +1 -1
- package/package.json +2 -1
- package/out/zero-server/src/query-registry.d.ts +0 -10
- package/out/zero-server/src/query-registry.d.ts.map +0 -1
- package/out/zero-server/src/query-registry.js +0 -35
- package/out/zero-server/src/query-registry.js.map +0 -1
- package/out/zql/src/query/define-query.d.ts +0 -75
- package/out/zql/src/query/define-query.d.ts.map +0 -1
- package/out/zql/src/query/define-query.js +0 -47
- package/out/zql/src/query/define-query.js.map +0 -1
- package/out/zql/src/query/query-definitions.d.ts +0 -32
- package/out/zql/src/query/query-definitions.d.ts.map +0 -1
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { assert } from "../../../shared/src/asserts.js";
|
|
2
2
|
import { mergeConstraints } from "./planner-constraint.js";
|
|
3
|
+
import { omitFanout } from "./planner-node.js";
|
|
3
4
|
function translateConstraintsForFlippedJoin(incomingConstraint, parentConstraint, childConstraint) {
|
|
4
5
|
if (!incomingConstraint) return void 0;
|
|
5
6
|
const parentKeys = Object.keys(parentConstraint);
|
|
@@ -183,15 +184,17 @@ class PlannerJoin {
|
|
|
183
184
|
fanout: parent.fanout
|
|
184
185
|
};
|
|
185
186
|
}
|
|
186
|
-
planDebugger
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
187
|
+
if (planDebugger) {
|
|
188
|
+
planDebugger.log({
|
|
189
|
+
type: "node-cost",
|
|
190
|
+
nodeType: "join",
|
|
191
|
+
node: this.getName(),
|
|
192
|
+
branchPattern,
|
|
193
|
+
downstreamChildSelectivity,
|
|
194
|
+
costEstimate: omitFanout(costEstimate),
|
|
195
|
+
joinType: this.#type
|
|
196
|
+
});
|
|
197
|
+
}
|
|
195
198
|
return costEstimate;
|
|
196
199
|
}
|
|
197
200
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"planner-join.js","sources":["../../../../../zql/src/planner/planner-join.ts"],"sourcesContent":["import {assert} from '../../../shared/src/asserts.ts';\nimport {\n mergeConstraints,\n type PlannerConstraint,\n} from './planner-constraint.ts';\nimport type {PlanDebugger} from './planner-debug.ts';\nimport type {\n CostEstimate,\n JoinOrConnection,\n PlannerNode,\n} from './planner-node.ts';\nimport type {PlannerTerminus} from './planner-terminus.ts';\n\n/**\n * Translate constraints for a flipped join from parent space to child space.\n * Matches the runtime behavior of FlippedJoin.fetch() which translates\n * parent constraints to child constraints using index-based key mapping.\n *\n * Example:\n * parentConstraint = {issueID: undefined, projectID: undefined}\n * childConstraint = {id: undefined, projectID: undefined}\n * incomingConstraint = {issueID: 5}\n * result = {id: 5} // issueID at index 0 maps to id at index 0\n */\nfunction translateConstraintsForFlippedJoin(\n incomingConstraint: PlannerConstraint | undefined,\n parentConstraint: PlannerConstraint,\n childConstraint: PlannerConstraint,\n): PlannerConstraint | undefined {\n if (!incomingConstraint) return undefined;\n\n const parentKeys = Object.keys(parentConstraint);\n const childKeys = Object.keys(childConstraint);\n const translated: PlannerConstraint = {};\n\n for (const [key, value] of Object.entries(incomingConstraint)) {\n const index = parentKeys.indexOf(key);\n if (index !== -1) {\n // Found this key in parent at position `index`\n // Map to child key at same position\n translated[childKeys[index]] = value;\n }\n }\n\n return Object.keys(translated).length > 0 ? translated : undefined;\n}\n\n/**\n * Semi-join overhead multiplier.\n *\n * Semi-joins represent correlated subqueries (EXISTS checks) which have\n * execution overhead compared to flipped joins, even when logical row counts\n * are identical. This overhead comes from:\n * - Need to execute a separate correlation check for each parent row\n * - Cannot leverage combined constraint checking as effectively as flipped joins\n *\n * A multiplier of 1.5 means semi-joins are estimated to be ~50% more expensive\n * than equivalent flipped joins, which empirically matches observed performance\n * differences in production workloads (e.g., 1.7x in zbugs benchmarks).\n *\n * Flipped joins have a different overhead in that they become unlimited. This\n * is accounted for when propagating unlimits rather than here.\n */\n// const SEMI_JOIN_OVERHEAD_MULTIPLIER = 1.5;\n\n/**\n * Represents a join between two data streams (parent and child).\n *\n * # Dual-State Pattern\n * Like all planner nodes, PlannerJoin separates:\n * 1. IMMUTABLE STRUCTURE: Parent/child nodes, constraints, flippability\n * 2. MUTABLE STATE: Join type (semi/flipped), pinned status\n *\n * # Join Flipping\n * A join can be in two states:\n * - 'semi': Parent is outer loop, child is inner (semi-join for EXISTS)\n * - 'flipped': Child is outer loop, parent is inner\n *\n * Flipping is the key optimization: choosing which table scans first.\n * NOT EXISTS joins cannot be flipped (#flippable = false).\n *\n * # Constraint Propagation\n * - Semi-join: Sends childConstraint to child, forwards received constraints to parent\n * - Flipped join: Sends undefined to child, merges parentConstraint with received to parent\n * - Unpinned join: Only forwards constraints to parent (doesn't constrain child yet)\n *\n * # Lifecycle\n * 1. Construct with immutable structure (parent, child, constraints, flippability)\n * 2. Wire to output node during graph construction\n * 3. Planning calls flipIfNeeded() based on connection selection order\n * 4. pin() locks the join type once chosen\n * 5. reset() clears mutable state (type → 'semi', pinned → false)\n */\nexport class PlannerJoin {\n readonly kind = 'join' as const;\n\n readonly #parent: Exclude<PlannerNode, PlannerTerminus>;\n readonly #child: Exclude<PlannerNode, PlannerTerminus>;\n readonly #parentConstraint: PlannerConstraint;\n readonly #childConstraint: PlannerConstraint;\n readonly #flippable: boolean;\n readonly planId: number;\n #output?: PlannerNode | undefined; // Set once during graph construction\n\n // Reset between planning attempts\n #type: 'semi' | 'flipped';\n readonly #initialType: 'semi' | 'flipped';\n\n constructor(\n parent: Exclude<PlannerNode, PlannerTerminus>,\n child: Exclude<PlannerNode, PlannerTerminus>,\n parentConstraint: PlannerConstraint,\n childConstraint: PlannerConstraint,\n flippable: boolean,\n planId: number,\n initialType: 'semi' | 'flipped' = 'semi',\n ) {\n this.#type = initialType;\n this.#initialType = initialType;\n this.#parent = parent;\n this.#child = child;\n this.#childConstraint = childConstraint;\n this.#parentConstraint = parentConstraint;\n this.#flippable = flippable;\n this.planId = planId;\n }\n\n setOutput(node: PlannerNode): void {\n this.#output = node;\n }\n\n get output(): PlannerNode {\n assert(this.#output !== undefined, 'Output not set');\n return this.#output;\n }\n\n closestJoinOrSource(): JoinOrConnection {\n return 'join';\n }\n\n flipIfNeeded(input: PlannerNode): void {\n if (input === this.#child) {\n this.flip();\n } else {\n assert(\n input === this.#parent,\n 'Can only flip a join from one of its inputs',\n );\n }\n }\n\n flip(): void {\n assert(this.#type === 'semi', 'Can only flip a semi-join');\n if (!this.#flippable) {\n throw new UnflippableJoinError(\n 'Cannot flip a non-flippable join (e.g., NOT EXISTS)',\n );\n }\n this.#type = 'flipped';\n }\n\n get type(): 'semi' | 'flipped' {\n return this.#type;\n }\n isFlippable(): boolean {\n return this.#flippable;\n }\n\n /**\n * Propagate unlimiting when this join is flipped.\n * When a join is flipped:\n * 1. Child becomes outer loop → produces all rows (unlimited)\n * 2. Parent is fetched once per child row → effectively unlimited\n *\n * Example: If child produces 896 rows, parent is fetched 896 times.\n * Even if each fetch returns 1 row, parent produces 896 total rows.\n *\n * Propagation rules:\n * - Connection: call unlimit()\n * - Semi-join: continue to parent (outer loop)\n * - Flipped join: stop (already unlimited when it was flipped)\n * - Fan-out/Fan-in: propagate to all inputs\n */\n propagateUnlimit(): void {\n assert(this.#type === 'flipped', 'Can only unlimit a flipped join');\n // Parent stays limited; child becomes unlimited\n this.#child.propagateUnlimitFromFlippedJoin(); // Up the child chain\n }\n\n /**\n * Called when a parent join is flipped and this join is part of its child subgraph.\n * Continue propagation to parent (the outer loop).\n * If we are hitting a semi-join, the parent drives.\n * If we are hitting a flip-join, well now we have to unlimit its parent too!\n */\n propagateUnlimitFromFlippedJoin(): void {\n this.#parent.propagateUnlimitFromFlippedJoin();\n }\n\n propagateConstraints(\n branchPattern: number[],\n constraint: PlannerConstraint | undefined,\n from?: PlannerNode,\n planDebugger?: PlanDebugger,\n ): void {\n planDebugger?.log({\n type: 'node-constraint',\n nodeType: 'join',\n node: this.getName(),\n branchPattern,\n constraint,\n from: from ? getNodeName(from) : 'unknown',\n });\n\n if (this.#type === 'semi') {\n // A semi-join always has constraints for its child.\n // They are defined by the correlation between parent and child.\n this.#child.propagateConstraints(\n branchPattern,\n this.#childConstraint,\n this,\n planDebugger,\n );\n // A semi-join forwards constraints to its parent.\n this.#parent.propagateConstraints(\n branchPattern,\n constraint,\n this,\n planDebugger,\n );\n } else if (this.#type === 'flipped') {\n // A flipped join translates constraints from parent space to child space.\n // This matches FlippedJoin.fetch() runtime behavior where parent constraints\n // on join keys are translated to child constraints.\n // Example: If parent has {issueID: 5} and join maps issueID→id,\n // child gets {id: 5} allowing index usage.\n const translatedConstraint = translateConstraintsForFlippedJoin(\n constraint,\n this.#parentConstraint,\n this.#childConstraint,\n );\n this.#child.propagateConstraints(\n branchPattern,\n translatedConstraint,\n this,\n planDebugger,\n );\n // A flipped join will have constraints to send to its parent.\n // - The constraints its output sent\n // - The constraints its child creates\n this.#parent.propagateConstraints(\n branchPattern,\n mergeConstraints(constraint, this.#parentConstraint),\n this,\n planDebugger,\n );\n }\n }\n\n reset(): void {\n this.#type = this.#initialType;\n }\n\n estimateCost(\n /**\n * This argument is to deal with consecutive `andExists` statements.\n * Each one will constrain how often a parent row passes all constraints.\n * This means that we have to scan more and more parent rows the more\n * constraints we add.\n *\n * DownstreamChildSelectivity factors in fanout factor\n * from parent -> child\n */\n downstreamChildSelectivity: number,\n /**\n * branchPattern uniquely identifies OR branches in the graph.\n * Each path through an OR will have unique constraints to apply to the source\n * connection.\n * branchPattern allows us to correlate a path through the graph\n * to the constraints that should be applied for that path.\n *\n * Example graph:\n * UFO\n * / \\\n * J1 J2\n * \\ /\n * UFI\n *\n * J1 and J2 are joins inside an OR (FO).\n * branchPattern [0] = path through J1\n * branchPattern [1] = path through J2\n *\n * If many ORs are nested, branchPattern will have multiple elements\n * representing each level of OR.\n *\n * If no joins are flipped within the `OR`, then only a single\n * branchPattern element will be needed, as FO represents all sub-joins\n * as a single path.\n */\n branchPattern: number[],\n planDebugger?: PlanDebugger,\n ): CostEstimate {\n /**\n * downstreamChildSelectivity accumulates up a parent chain, not\n * up child chains. Child chains represent independent sub-graphs.\n * So we pass 1 for `downstreamChildSelectivity` when estimating child cost.\n * Put another way, downstreamChildSelectivity impacts how many parent\n * rows are returned.\n */\n const child = this.#child.estimateCost(1, branchPattern, planDebugger);\n\n const fanoutFactor = child.fanout(Object.keys(this.#childConstraint));\n // Factor in how many child rows match a parent row.\n // E.g., if an issue has 10 comments on average then we're more\n // likely to hit a comment compared to if an issue has 1 comment on average.\n // If an index is all nulls (no parents match any children)\n // this will collapse to 0.\n const scaledChildSelectivity =\n 1 - Math.pow(1 - child.selectivity, fanoutFactor.fanout);\n\n /**\n * How selective is the graph from this point forward?\n * If we are _very_ selective then we must scan more parent rows\n * before finding a match.\n * E.g., if childSelectivity = 0.1 and downstreamChildSelectivity = 0.5\n * then we only pass 5% of parent rows (0.1 * 0.5 = 0.05).\n *\n * This is used to estimate how many rows will be pulled from the parent\n * when trying to satisfy downstream constraints and a limit.\n *\n * NOTE: We do not know if the probabilities are correlated so we assume independence.\n * This is a fundamental limitation of the planner.\n */\n const parent = this.#parent.estimateCost(\n // Selectivity flows up the graph from child to parent\n // so we can determine the total selectivity of all ANDed exists checks.\n this.#type === 'flipped'\n ? 1 * downstreamChildSelectivity\n : scaledChildSelectivity * downstreamChildSelectivity,\n branchPattern,\n planDebugger,\n );\n\n let costEstimate: CostEstimate;\n\n if (this.type === 'semi') {\n costEstimate = {\n startupCost: parent.startupCost,\n scanEst:\n parent.limit === undefined\n ? parent.returnedRows\n : Math.min(\n parent.returnedRows,\n downstreamChildSelectivity === 0\n ? 0\n : parent.limit / downstreamChildSelectivity,\n ),\n cost:\n parent.cost +\n parent.scanEst * (child.startupCost + child.cost + child.scanEst),\n returnedRows: parent.returnedRows * child.selectivity,\n selectivity: child.selectivity * parent.selectivity,\n limit: parent.limit,\n fanout: parent.fanout,\n };\n } else {\n costEstimate = {\n startupCost: child.startupCost,\n scanEst:\n parent.limit === undefined\n ? parent.returnedRows * child.returnedRows\n : Math.min(\n parent.returnedRows * child.returnedRows,\n downstreamChildSelectivity === 0\n ? 0\n : parent.limit / downstreamChildSelectivity,\n ),\n cost:\n child.cost +\n child.scanEst * (parent.startupCost + parent.cost + parent.scanEst),\n returnedRows:\n parent.returnedRows * child.returnedRows * child.selectivity,\n selectivity: parent.selectivity * child.selectivity,\n limit: parent.limit,\n fanout: parent.fanout,\n };\n }\n\n planDebugger?.log({\n type: 'node-cost',\n nodeType: 'join',\n node: this.getName(),\n branchPattern,\n downstreamChildSelectivity,\n costEstimate,\n joinType: this.#type,\n });\n\n return costEstimate;\n }\n\n /**\n * Get a human-readable name for this join for debugging.\n * Format: \"parentName ⋈ childName\"\n */\n getName(): string {\n const parentName = getNodeName(this.#parent);\n const childName = getNodeName(this.#child);\n return `${parentName} ⋈ ${childName}`;\n }\n\n /**\n * Get debug information about this join's state.\n */\n getDebugInfo(): {\n name: string;\n type: 'semi' | 'flipped';\n planId: number;\n } {\n return {\n name: this.getName(),\n type: this.#type,\n planId: this.planId,\n };\n }\n}\n\nexport class UnflippableJoinError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'UnflippableJoinError';\n }\n}\n\n/**\n * Get a human-readable name for any planner node.\n * Used for debugging and tracing.\n */\nfunction getNodeName(node: PlannerNode): string {\n switch (node.kind) {\n case 'connection':\n return node.name;\n case 'join':\n return node.getName();\n case 'fan-out':\n return 'FO';\n case 'fan-in':\n return 'FI';\n case 'terminus':\n return 'terminus';\n }\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"planner-join.js","sources":["../../../../../zql/src/planner/planner-join.ts"],"sourcesContent":["import {assert} from '../../../shared/src/asserts.ts';\nimport {\n mergeConstraints,\n type PlannerConstraint,\n} from './planner-constraint.ts';\nimport type {PlanDebugger} from './planner-debug.ts';\nimport {omitFanout} from './planner-node.ts';\nimport type {\n CostEstimate,\n JoinOrConnection,\n PlannerNode,\n} from './planner-node.ts';\nimport type {PlannerTerminus} from './planner-terminus.ts';\n\n/**\n * Translate constraints for a flipped join from parent space to child space.\n * Matches the runtime behavior of FlippedJoin.fetch() which translates\n * parent constraints to child constraints using index-based key mapping.\n *\n * Example:\n * parentConstraint = {issueID: undefined, projectID: undefined}\n * childConstraint = {id: undefined, projectID: undefined}\n * incomingConstraint = {issueID: 5}\n * result = {id: 5} // issueID at index 0 maps to id at index 0\n */\nfunction translateConstraintsForFlippedJoin(\n incomingConstraint: PlannerConstraint | undefined,\n parentConstraint: PlannerConstraint,\n childConstraint: PlannerConstraint,\n): PlannerConstraint | undefined {\n if (!incomingConstraint) return undefined;\n\n const parentKeys = Object.keys(parentConstraint);\n const childKeys = Object.keys(childConstraint);\n const translated: PlannerConstraint = {};\n\n for (const [key, value] of Object.entries(incomingConstraint)) {\n const index = parentKeys.indexOf(key);\n if (index !== -1) {\n // Found this key in parent at position `index`\n // Map to child key at same position\n translated[childKeys[index]] = value;\n }\n }\n\n return Object.keys(translated).length > 0 ? translated : undefined;\n}\n\n/**\n * Semi-join overhead multiplier.\n *\n * Semi-joins represent correlated subqueries (EXISTS checks) which have\n * execution overhead compared to flipped joins, even when logical row counts\n * are identical. This overhead comes from:\n * - Need to execute a separate correlation check for each parent row\n * - Cannot leverage combined constraint checking as effectively as flipped joins\n *\n * A multiplier of 1.5 means semi-joins are estimated to be ~50% more expensive\n * than equivalent flipped joins, which empirically matches observed performance\n * differences in production workloads (e.g., 1.7x in zbugs benchmarks).\n *\n * Flipped joins have a different overhead in that they become unlimited. This\n * is accounted for when propagating unlimits rather than here.\n */\n// const SEMI_JOIN_OVERHEAD_MULTIPLIER = 1.5;\n\n/**\n * Represents a join between two data streams (parent and child).\n *\n * # Dual-State Pattern\n * Like all planner nodes, PlannerJoin separates:\n * 1. IMMUTABLE STRUCTURE: Parent/child nodes, constraints, flippability\n * 2. MUTABLE STATE: Join type (semi/flipped), pinned status\n *\n * # Join Flipping\n * A join can be in two states:\n * - 'semi': Parent is outer loop, child is inner (semi-join for EXISTS)\n * - 'flipped': Child is outer loop, parent is inner\n *\n * Flipping is the key optimization: choosing which table scans first.\n * NOT EXISTS joins cannot be flipped (#flippable = false).\n *\n * # Constraint Propagation\n * - Semi-join: Sends childConstraint to child, forwards received constraints to parent\n * - Flipped join: Sends undefined to child, merges parentConstraint with received to parent\n * - Unpinned join: Only forwards constraints to parent (doesn't constrain child yet)\n *\n * # Lifecycle\n * 1. Construct with immutable structure (parent, child, constraints, flippability)\n * 2. Wire to output node during graph construction\n * 3. Planning calls flipIfNeeded() based on connection selection order\n * 4. pin() locks the join type once chosen\n * 5. reset() clears mutable state (type → 'semi', pinned → false)\n */\nexport class PlannerJoin {\n readonly kind = 'join' as const;\n\n readonly #parent: Exclude<PlannerNode, PlannerTerminus>;\n readonly #child: Exclude<PlannerNode, PlannerTerminus>;\n readonly #parentConstraint: PlannerConstraint;\n readonly #childConstraint: PlannerConstraint;\n readonly #flippable: boolean;\n readonly planId: number;\n #output?: PlannerNode | undefined; // Set once during graph construction\n\n // Reset between planning attempts\n #type: 'semi' | 'flipped';\n readonly #initialType: 'semi' | 'flipped';\n\n constructor(\n parent: Exclude<PlannerNode, PlannerTerminus>,\n child: Exclude<PlannerNode, PlannerTerminus>,\n parentConstraint: PlannerConstraint,\n childConstraint: PlannerConstraint,\n flippable: boolean,\n planId: number,\n initialType: 'semi' | 'flipped' = 'semi',\n ) {\n this.#type = initialType;\n this.#initialType = initialType;\n this.#parent = parent;\n this.#child = child;\n this.#childConstraint = childConstraint;\n this.#parentConstraint = parentConstraint;\n this.#flippable = flippable;\n this.planId = planId;\n }\n\n setOutput(node: PlannerNode): void {\n this.#output = node;\n }\n\n get output(): PlannerNode {\n assert(this.#output !== undefined, 'Output not set');\n return this.#output;\n }\n\n closestJoinOrSource(): JoinOrConnection {\n return 'join';\n }\n\n flipIfNeeded(input: PlannerNode): void {\n if (input === this.#child) {\n this.flip();\n } else {\n assert(\n input === this.#parent,\n 'Can only flip a join from one of its inputs',\n );\n }\n }\n\n flip(): void {\n assert(this.#type === 'semi', 'Can only flip a semi-join');\n if (!this.#flippable) {\n throw new UnflippableJoinError(\n 'Cannot flip a non-flippable join (e.g., NOT EXISTS)',\n );\n }\n this.#type = 'flipped';\n }\n\n get type(): 'semi' | 'flipped' {\n return this.#type;\n }\n isFlippable(): boolean {\n return this.#flippable;\n }\n\n /**\n * Propagate unlimiting when this join is flipped.\n * When a join is flipped:\n * 1. Child becomes outer loop → produces all rows (unlimited)\n * 2. Parent is fetched once per child row → effectively unlimited\n *\n * Example: If child produces 896 rows, parent is fetched 896 times.\n * Even if each fetch returns 1 row, parent produces 896 total rows.\n *\n * Propagation rules:\n * - Connection: call unlimit()\n * - Semi-join: continue to parent (outer loop)\n * - Flipped join: stop (already unlimited when it was flipped)\n * - Fan-out/Fan-in: propagate to all inputs\n */\n propagateUnlimit(): void {\n assert(this.#type === 'flipped', 'Can only unlimit a flipped join');\n // Parent stays limited; child becomes unlimited\n this.#child.propagateUnlimitFromFlippedJoin(); // Up the child chain\n }\n\n /**\n * Called when a parent join is flipped and this join is part of its child subgraph.\n * Continue propagation to parent (the outer loop).\n * If we are hitting a semi-join, the parent drives.\n * If we are hitting a flip-join, well now we have to unlimit its parent too!\n */\n propagateUnlimitFromFlippedJoin(): void {\n this.#parent.propagateUnlimitFromFlippedJoin();\n }\n\n propagateConstraints(\n branchPattern: number[],\n constraint: PlannerConstraint | undefined,\n from?: PlannerNode,\n planDebugger?: PlanDebugger,\n ): void {\n planDebugger?.log({\n type: 'node-constraint',\n nodeType: 'join',\n node: this.getName(),\n branchPattern,\n constraint,\n from: from ? getNodeName(from) : 'unknown',\n });\n\n if (this.#type === 'semi') {\n // A semi-join always has constraints for its child.\n // They are defined by the correlation between parent and child.\n this.#child.propagateConstraints(\n branchPattern,\n this.#childConstraint,\n this,\n planDebugger,\n );\n // A semi-join forwards constraints to its parent.\n this.#parent.propagateConstraints(\n branchPattern,\n constraint,\n this,\n planDebugger,\n );\n } else if (this.#type === 'flipped') {\n // A flipped join translates constraints from parent space to child space.\n // This matches FlippedJoin.fetch() runtime behavior where parent constraints\n // on join keys are translated to child constraints.\n // Example: If parent has {issueID: 5} and join maps issueID→id,\n // child gets {id: 5} allowing index usage.\n const translatedConstraint = translateConstraintsForFlippedJoin(\n constraint,\n this.#parentConstraint,\n this.#childConstraint,\n );\n this.#child.propagateConstraints(\n branchPattern,\n translatedConstraint,\n this,\n planDebugger,\n );\n // A flipped join will have constraints to send to its parent.\n // - The constraints its output sent\n // - The constraints its child creates\n this.#parent.propagateConstraints(\n branchPattern,\n mergeConstraints(constraint, this.#parentConstraint),\n this,\n planDebugger,\n );\n }\n }\n\n reset(): void {\n this.#type = this.#initialType;\n }\n\n estimateCost(\n /**\n * This argument is to deal with consecutive `andExists` statements.\n * Each one will constrain how often a parent row passes all constraints.\n * This means that we have to scan more and more parent rows the more\n * constraints we add.\n *\n * DownstreamChildSelectivity factors in fanout factor\n * from parent -> child\n */\n downstreamChildSelectivity: number,\n /**\n * branchPattern uniquely identifies OR branches in the graph.\n * Each path through an OR will have unique constraints to apply to the source\n * connection.\n * branchPattern allows us to correlate a path through the graph\n * to the constraints that should be applied for that path.\n *\n * Example graph:\n * UFO\n * / \\\n * J1 J2\n * \\ /\n * UFI\n *\n * J1 and J2 are joins inside an OR (FO).\n * branchPattern [0] = path through J1\n * branchPattern [1] = path through J2\n *\n * If many ORs are nested, branchPattern will have multiple elements\n * representing each level of OR.\n *\n * If no joins are flipped within the `OR`, then only a single\n * branchPattern element will be needed, as FO represents all sub-joins\n * as a single path.\n */\n branchPattern: number[],\n planDebugger?: PlanDebugger,\n ): CostEstimate {\n /**\n * downstreamChildSelectivity accumulates up a parent chain, not\n * up child chains. Child chains represent independent sub-graphs.\n * So we pass 1 for `downstreamChildSelectivity` when estimating child cost.\n * Put another way, downstreamChildSelectivity impacts how many parent\n * rows are returned.\n */\n const child = this.#child.estimateCost(1, branchPattern, planDebugger);\n\n const fanoutFactor = child.fanout(Object.keys(this.#childConstraint));\n // Factor in how many child rows match a parent row.\n // E.g., if an issue has 10 comments on average then we're more\n // likely to hit a comment compared to if an issue has 1 comment on average.\n // If an index is all nulls (no parents match any children)\n // this will collapse to 0.\n const scaledChildSelectivity =\n 1 - Math.pow(1 - child.selectivity, fanoutFactor.fanout);\n\n /**\n * How selective is the graph from this point forward?\n * If we are _very_ selective then we must scan more parent rows\n * before finding a match.\n * E.g., if childSelectivity = 0.1 and downstreamChildSelectivity = 0.5\n * then we only pass 5% of parent rows (0.1 * 0.5 = 0.05).\n *\n * This is used to estimate how many rows will be pulled from the parent\n * when trying to satisfy downstream constraints and a limit.\n *\n * NOTE: We do not know if the probabilities are correlated so we assume independence.\n * This is a fundamental limitation of the planner.\n */\n const parent = this.#parent.estimateCost(\n // Selectivity flows up the graph from child to parent\n // so we can determine the total selectivity of all ANDed exists checks.\n this.#type === 'flipped'\n ? 1 * downstreamChildSelectivity\n : scaledChildSelectivity * downstreamChildSelectivity,\n branchPattern,\n planDebugger,\n );\n\n let costEstimate: CostEstimate;\n\n if (this.type === 'semi') {\n costEstimate = {\n startupCost: parent.startupCost,\n scanEst:\n parent.limit === undefined\n ? parent.returnedRows\n : Math.min(\n parent.returnedRows,\n downstreamChildSelectivity === 0\n ? 0\n : parent.limit / downstreamChildSelectivity,\n ),\n cost:\n parent.cost +\n parent.scanEst * (child.startupCost + child.cost + child.scanEst),\n returnedRows: parent.returnedRows * child.selectivity,\n selectivity: child.selectivity * parent.selectivity,\n limit: parent.limit,\n fanout: parent.fanout,\n };\n } else {\n costEstimate = {\n startupCost: child.startupCost,\n scanEst:\n parent.limit === undefined\n ? parent.returnedRows * child.returnedRows\n : Math.min(\n parent.returnedRows * child.returnedRows,\n downstreamChildSelectivity === 0\n ? 0\n : parent.limit / downstreamChildSelectivity,\n ),\n cost:\n child.cost +\n child.scanEst * (parent.startupCost + parent.cost + parent.scanEst),\n returnedRows:\n parent.returnedRows * child.returnedRows * child.selectivity,\n selectivity: parent.selectivity * child.selectivity,\n limit: parent.limit,\n fanout: parent.fanout,\n };\n }\n\n if (planDebugger) {\n planDebugger.log({\n type: 'node-cost',\n nodeType: 'join',\n node: this.getName(),\n branchPattern,\n downstreamChildSelectivity,\n costEstimate: omitFanout(costEstimate),\n joinType: this.#type,\n });\n }\n\n return costEstimate;\n }\n\n /**\n * Get a human-readable name for this join for debugging.\n * Format: \"parentName ⋈ childName\"\n */\n getName(): string {\n const parentName = getNodeName(this.#parent);\n const childName = getNodeName(this.#child);\n return `${parentName} ⋈ ${childName}`;\n }\n\n /**\n * Get debug information about this join's state.\n */\n getDebugInfo(): {\n name: string;\n type: 'semi' | 'flipped';\n planId: number;\n } {\n return {\n name: this.getName(),\n type: this.#type,\n planId: this.planId,\n };\n }\n}\n\nexport class UnflippableJoinError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'UnflippableJoinError';\n }\n}\n\n/**\n * Get a human-readable name for any planner node.\n * Used for debugging and tracing.\n */\nfunction getNodeName(node: PlannerNode): string {\n switch (node.kind) {\n case 'connection':\n return node.name;\n case 'join':\n return node.getName();\n case 'fan-out':\n return 'FO';\n case 'fan-in':\n return 'FI';\n case 'terminus':\n return 'terminus';\n }\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -43,6 +43,10 @@ export type CostEstimate = {
|
|
|
43
43
|
limit: number | undefined;
|
|
44
44
|
fanout: FanoutCostModel;
|
|
45
45
|
};
|
|
46
|
+
/**
|
|
47
|
+
* Omit the fanout function from a cost estimate for serialization.
|
|
48
|
+
*/
|
|
49
|
+
export declare function omitFanout(cost: CostEstimate): Omit<CostEstimate, 'fanout'>;
|
|
46
50
|
export type NodeType = PlannerNode['kind'];
|
|
47
51
|
export type JoinOrConnection = 'join' | 'connection';
|
|
48
52
|
export type JoinType = PlannerJoin['type'];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"planner-node.d.ts","sourceRoot":"","sources":["../../../../../zql/src/planner/planner-node.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,eAAe,EAAE,iBAAiB,EAAC,MAAM,yBAAyB,CAAC;AAChF,OAAO,KAAK,EAAC,YAAY,EAAC,MAAM,qBAAqB,CAAC;AACtD,OAAO,KAAK,EAAC,aAAa,EAAC,MAAM,sBAAsB,CAAC;AACxD,OAAO,KAAK,EAAC,WAAW,EAAC,MAAM,mBAAmB,CAAC;AACnD,OAAO,KAAK,EAAC,eAAe,EAAC,MAAM,uBAAuB,CAAC;AAE3D;;;GAGG;AACH,MAAM,MAAM,WAAW,GACnB,WAAW,GACX,iBAAiB,GACjB,aAAa,GACb,YAAY,GACZ,eAAe,CAAC;AAEpB,MAAM,MAAM,YAAY,GAAG;IACzB,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;IAEhB;;;;;;;;;;OAUG;IACH,IAAI,EAAE,MAAM,CAAC;IAEb;;;;;;;OAOG;IACH,YAAY,EAAE,MAAM,CAAC;IAErB;;;;;;OAMG;IACH,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,MAAM,GAAG,SAAS,CAAC;IAE1B,MAAM,EAAE,eAAe,CAAC;CACzB,CAAC;AAEF,MAAM,MAAM,QAAQ,GAAG,WAAW,CAAC,MAAM,CAAC,CAAC;AAE3C,MAAM,MAAM,gBAAgB,GAAG,MAAM,GAAG,YAAY,CAAC;AAErD,MAAM,MAAM,QAAQ,GAAG,WAAW,CAAC,MAAM,CAAC,CAAC"}
|
|
1
|
+
{"version":3,"file":"planner-node.d.ts","sourceRoot":"","sources":["../../../../../zql/src/planner/planner-node.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,eAAe,EAAE,iBAAiB,EAAC,MAAM,yBAAyB,CAAC;AAChF,OAAO,KAAK,EAAC,YAAY,EAAC,MAAM,qBAAqB,CAAC;AACtD,OAAO,KAAK,EAAC,aAAa,EAAC,MAAM,sBAAsB,CAAC;AACxD,OAAO,KAAK,EAAC,WAAW,EAAC,MAAM,mBAAmB,CAAC;AACnD,OAAO,KAAK,EAAC,eAAe,EAAC,MAAM,uBAAuB,CAAC;AAE3D;;;GAGG;AACH,MAAM,MAAM,WAAW,GACnB,WAAW,GACX,iBAAiB,GACjB,aAAa,GACb,YAAY,GACZ,eAAe,CAAC;AAEpB,MAAM,MAAM,YAAY,GAAG;IACzB,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;IAEhB;;;;;;;;;;OAUG;IACH,IAAI,EAAE,MAAM,CAAC;IAEb;;;;;;;OAOG;IACH,YAAY,EAAE,MAAM,CAAC;IAErB;;;;;;OAMG;IACH,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,MAAM,GAAG,SAAS,CAAC;IAE1B,MAAM,EAAE,eAAe,CAAC;CACzB,CAAC;AAEF;;GAEG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,YAAY,GAAG,IAAI,CAAC,YAAY,EAAE,QAAQ,CAAC,CAG3E;AAED,MAAM,MAAM,QAAQ,GAAG,WAAW,CAAC,MAAM,CAAC,CAAC;AAE3C,MAAM,MAAM,gBAAgB,GAAG,MAAM,GAAG,YAAY,CAAC;AAErD,MAAM,MAAM,QAAQ,GAAG,WAAW,CAAC,MAAM,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"planner-node.js","sources":["../../../../../zql/src/planner/planner-node.ts"],"sourcesContent":["import type {FanoutCostModel, PlannerConnection} from './planner-connection.ts';\nimport type {PlannerFanIn} from './planner-fan-in.ts';\nimport type {PlannerFanOut} from './planner-fan-out.ts';\nimport type {PlannerJoin} from './planner-join.ts';\nimport type {PlannerTerminus} from './planner-terminus.ts';\n\n/**\n * Union of all node types that can appear in the planner graph.\n * All nodes follow the dual-state pattern described above.\n */\nexport type PlannerNode =\n | PlannerJoin\n | PlannerConnection\n | PlannerFanOut\n | PlannerFanIn\n | PlannerTerminus;\n\nexport type CostEstimate = {\n startupCost: number;\n scanEst: number;\n\n /**\n * The cumulative cost to run the pipeline so far.\n *\n * In a semi-join, each row output by the parent is multiplied by the cost to evaluate the child.\n * In a flipped join, each row output by the child is multiplied by the cost to evaluate the parent.\n *\n * \"each row output by the parent\" is determined by the downstreamChildSelectivity parameter in combination\n * with the limit or the rows output by the parent node.\n *\n * We pull on the parent and stop when hitting a limit or exhausting rows.\n */\n cost: number;\n\n /**\n * The number of rows output from a node.\n * - For a connection, this is the estimated number of rows returned by the source query.\n * - For a semi-join, this is the estimated number of rows that pass the semi-join filter.\n * - For a flipped join, this is the estimated number of rows that match all child rows.\n * - For fan-in, this is the sum of the rows from each input.\n * - For fan-out, this is the rows from its input.\n */\n returnedRows: number;\n\n /**\n * The selectivity of the node.\n * For a connection, this is the fraction of rows passing filters (1.0 = no filtering).\n * For joins, this is the fraction of parent rows that match child rows.\n * For fan-in, this is the probability of a match in any branch, assuming independent events.\n * For fan-out, this is the selectivity of its input.\n */\n selectivity: number;\n limit: number | undefined;\n\n fanout: FanoutCostModel;\n};\n\n/**\n * Omit the fanout function from a cost estimate for serialization.\n */\nexport function omitFanout(cost: CostEstimate): Omit<CostEstimate, 'fanout'> {\n const {fanout: _, ...rest} = cost;\n return rest;\n}\n\nexport type NodeType = PlannerNode['kind'];\n\nexport type JoinOrConnection = 'join' | 'connection';\n\nexport type JoinType = PlannerJoin['type'];\n"],"names":[],"mappings":"AA4DO,SAAS,WAAW,MAAkD;AAC3E,QAAM,EAAC,QAAQ,GAAG,GAAG,SAAQ;AAC7B,SAAO;AACT;"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { Schema } from '../../../zero-types/src/schema.ts';
|
|
2
|
+
import type { SchemaQuery } from './schema-query.ts';
|
|
3
|
+
/**
|
|
4
|
+
* Returns a set of query builders for the given schema.
|
|
5
|
+
*/
|
|
6
|
+
export declare function createBuilder<S extends Schema>(schema: S): SchemaQuery<S>;
|
|
7
|
+
//# sourceMappingURL=create-builder.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"create-builder.d.ts","sourceRoot":"","sources":["../../../../../zql/src/query/create-builder.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,MAAM,EAAC,MAAM,mCAAmC,CAAC;AAG9D,OAAO,KAAK,EAAC,WAAW,EAAC,MAAM,mBAAmB,CAAC;AAEnD;;GAEG;AACH,wBAAgB,aAAa,CAAC,CAAC,SAAS,MAAM,EAAE,MAAM,EAAE,CAAC,GAAG,WAAW,CAAC,CAAC,CAAC,CA4CzE"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { newQuery } from "./query-impl.js";
|
|
2
|
+
function createBuilder(schema) {
|
|
3
|
+
const cache = /* @__PURE__ */ new Map();
|
|
4
|
+
const { tables } = schema;
|
|
5
|
+
function getQuery(prop) {
|
|
6
|
+
const cached = cache.get(prop);
|
|
7
|
+
if (cached) {
|
|
8
|
+
return cached;
|
|
9
|
+
}
|
|
10
|
+
if (!Object.hasOwn(schema.tables, prop)) {
|
|
11
|
+
return void 0;
|
|
12
|
+
}
|
|
13
|
+
const q = newQuery(schema, prop);
|
|
14
|
+
cache.set(prop, q);
|
|
15
|
+
return q;
|
|
16
|
+
}
|
|
17
|
+
return new Proxy(tables, {
|
|
18
|
+
get: (_target, prop) => {
|
|
19
|
+
if (typeof prop === "symbol") {
|
|
20
|
+
return void 0;
|
|
21
|
+
}
|
|
22
|
+
const q = getQuery(prop);
|
|
23
|
+
if (!q) {
|
|
24
|
+
throw new Error(`Table ${String(prop)} does not exist in schema`);
|
|
25
|
+
}
|
|
26
|
+
return q;
|
|
27
|
+
},
|
|
28
|
+
getOwnPropertyDescriptor: (_target, prop) => {
|
|
29
|
+
if (typeof prop === "symbol") {
|
|
30
|
+
return void 0;
|
|
31
|
+
}
|
|
32
|
+
const value = getQuery(prop);
|
|
33
|
+
if (!value) {
|
|
34
|
+
return void 0;
|
|
35
|
+
}
|
|
36
|
+
const desc = Reflect.getOwnPropertyDescriptor(tables, prop);
|
|
37
|
+
return { ...desc, value };
|
|
38
|
+
}
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
export {
|
|
42
|
+
createBuilder
|
|
43
|
+
};
|
|
44
|
+
//# sourceMappingURL=create-builder.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"create-builder.js","sources":["../../../../../zql/src/query/create-builder.ts"],"sourcesContent":["import type {Schema} from '../../../zero-types/src/schema.ts';\nimport {newQuery} from './query-impl.ts';\nimport type {Query} from './query.ts';\nimport type {SchemaQuery} from './schema-query.ts';\n\n/**\n * Returns a set of query builders for the given schema.\n */\nexport function createBuilder<S extends Schema>(schema: S): SchemaQuery<S> {\n // oxlint-disable-next-line no-explicit-any\n const cache = new Map<string, Query<S, string, any>>();\n const {tables} = schema;\n\n function getQuery(prop: string) {\n const cached = cache.get(prop);\n if (cached) {\n return cached;\n }\n\n if (!Object.hasOwn(schema.tables, prop)) {\n return undefined;\n }\n\n const q = newQuery(schema, prop);\n cache.set(prop, q);\n return q;\n }\n\n return new Proxy(tables, {\n get: (_target, prop) => {\n if (typeof prop === 'symbol') {\n return undefined;\n }\n const q = getQuery(prop);\n if (!q) {\n throw new Error(`Table ${String(prop)} does not exist in schema`);\n }\n return q;\n },\n\n getOwnPropertyDescriptor: (_target, prop) => {\n if (typeof prop === 'symbol') {\n return undefined;\n }\n const value = getQuery(prop);\n if (!value) {\n return undefined;\n }\n const desc = Reflect.getOwnPropertyDescriptor(tables, prop);\n return {...desc, value};\n },\n }) as unknown as SchemaQuery<S>;\n}\n"],"names":[],"mappings":";AAQO,SAAS,cAAgC,QAA2B;AAEzE,QAAM,4BAAY,IAAA;AAClB,QAAM,EAAC,WAAU;AAEjB,WAAS,SAAS,MAAc;AAC9B,UAAM,SAAS,MAAM,IAAI,IAAI;AAC7B,QAAI,QAAQ;AACV,aAAO;AAAA,IACT;AAEA,QAAI,CAAC,OAAO,OAAO,OAAO,QAAQ,IAAI,GAAG;AACvC,aAAO;AAAA,IACT;AAEA,UAAM,IAAI,SAAS,QAAQ,IAAI;AAC/B,UAAM,IAAI,MAAM,CAAC;AACjB,WAAO;AAAA,EACT;AAEA,SAAO,IAAI,MAAM,QAAQ;AAAA,IACvB,KAAK,CAAC,SAAS,SAAS;AACtB,UAAI,OAAO,SAAS,UAAU;AAC5B,eAAO;AAAA,MACT;AACA,YAAM,IAAI,SAAS,IAAI;AACvB,UAAI,CAAC,GAAG;AACN,cAAM,IAAI,MAAM,SAAS,OAAO,IAAI,CAAC,2BAA2B;AAAA,MAClE;AACA,aAAO;AAAA,IACT;AAAA,IAEA,0BAA0B,CAAC,SAAS,SAAS;AAC3C,UAAI,OAAO,SAAS,UAAU;AAC5B,eAAO;AAAA,MACT;AACA,YAAM,QAAQ,SAAS,IAAI;AAC3B,UAAI,CAAC,OAAO;AACV,eAAO;AAAA,MACT;AACA,YAAM,OAAO,QAAQ,yBAAyB,QAAQ,IAAI;AAC1D,aAAO,EAAC,GAAG,MAAM,MAAA;AAAA,IACnB;AAAA,EAAA,CACD;AACH;"}
|
|
@@ -1,6 +1,4 @@
|
|
|
1
1
|
import type { ReadonlyJSONValue } from '../../../shared/src/json.ts';
|
|
2
|
-
import type { Schema } from '../../../zero-types/src/schema.ts';
|
|
3
|
-
import type { SchemaQuery } from '../mutate/custom.ts';
|
|
4
2
|
import { type AnyQuery } from './query.ts';
|
|
5
3
|
/** @deprecated */
|
|
6
4
|
export type QueryFn<TContext, TTakesContext extends boolean, TArg extends ReadonlyJSONValue[], TReturnQuery extends AnyQuery> = TTakesContext extends false ? {
|
|
@@ -25,7 +23,7 @@ export declare function syncedQueryWithContext<TName extends string, TContext, T
|
|
|
25
23
|
/** @deprecated */
|
|
26
24
|
type AnySyncedQuery = SyncedQuery<any, any, any, any, any>;
|
|
27
25
|
/** @deprecated */
|
|
28
|
-
export declare function withValidation<F extends AnySyncedQuery>(fn: F): F extends SyncedQuery<infer N, infer C, any,
|
|
26
|
+
export declare function withValidation<F extends AnySyncedQuery>(fn: F): F extends SyncedQuery<infer N, infer C, any, any, infer R> ? SyncedQuery<N, C, true, ReadonlyJSONValue[], R> : F;
|
|
29
27
|
/** @deprecated */
|
|
30
28
|
export type ParseFn<T extends ReadonlyJSONValue[]> = (args: unknown[]) => T;
|
|
31
29
|
/** @deprecated */
|
|
@@ -38,9 +36,5 @@ export type CustomQueryID = {
|
|
|
38
36
|
name: string;
|
|
39
37
|
args: ReadonlyArray<ReadonlyJSONValue>;
|
|
40
38
|
};
|
|
41
|
-
/**
|
|
42
|
-
* Returns a set of query builders for the given schema.
|
|
43
|
-
*/
|
|
44
|
-
export declare function createBuilder<S extends Schema>(schema: S): SchemaQuery<S>;
|
|
45
39
|
export {};
|
|
46
40
|
//# sourceMappingURL=named.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"named.d.ts","sourceRoot":"","sources":["../../../../../zql/src/query/named.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,iBAAiB,EAAC,MAAM,6BAA6B,CAAC;
|
|
1
|
+
{"version":3,"file":"named.d.ts","sourceRoot":"","sources":["../../../../../zql/src/query/named.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { QueryParseError } from "./error.js";
|
|
2
|
-
import { newQuery } from "./query-impl.js";
|
|
3
2
|
import { asQueryInternals } from "./query-internals.js";
|
|
4
3
|
import "../../../zero-protocol/src/ast.js";
|
|
5
4
|
function normalizeParser(parser) {
|
|
@@ -55,27 +54,7 @@ function withValidation(fn) {
|
|
|
55
54
|
}
|
|
56
55
|
return fn;
|
|
57
56
|
}
|
|
58
|
-
function createBuilder(schema) {
|
|
59
|
-
return new Proxy(
|
|
60
|
-
{},
|
|
61
|
-
{
|
|
62
|
-
// oxlint-disable-next-line no-explicit-any
|
|
63
|
-
get: (target, prop) => {
|
|
64
|
-
if (prop in target) {
|
|
65
|
-
return target[prop];
|
|
66
|
-
}
|
|
67
|
-
if (!(prop in schema.tables)) {
|
|
68
|
-
throw new Error(`Table ${prop} does not exist in schema`);
|
|
69
|
-
}
|
|
70
|
-
const q = newQuery(schema, prop);
|
|
71
|
-
target[prop] = q;
|
|
72
|
-
return q;
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
);
|
|
76
|
-
}
|
|
77
57
|
export {
|
|
78
|
-
createBuilder,
|
|
79
58
|
syncedQuery,
|
|
80
59
|
syncedQueryWithContext,
|
|
81
60
|
withValidation
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"named.js","sources":["../../../../../zql/src/query/named.ts"],"sourcesContent":["import type {ReadonlyJSONValue} from '../../../shared/src/json.ts';\nimport
|
|
1
|
+
{"version":3,"file":"named.js","sources":["../../../../../zql/src/query/named.ts"],"sourcesContent":["import type {ReadonlyJSONValue} from '../../../shared/src/json.ts';\nimport {QueryParseError} from './error.ts';\nimport {asQueryInternals} from './query-internals.ts';\nimport {type AnyQuery} from './query.ts';\n\n/** @deprecated */\nexport type QueryFn<\n TContext,\n TTakesContext extends boolean,\n TArg extends ReadonlyJSONValue[],\n TReturnQuery extends AnyQuery,\n> = TTakesContext extends false\n ? {(...args: TArg): TReturnQuery}\n : {(context: TContext, ...args: TArg): TReturnQuery};\n\n/** @deprecated */\nexport type SyncedQuery<\n TName extends string,\n TContext,\n TTakesContext extends boolean,\n TArg extends ReadonlyJSONValue[],\n TReturnQuery extends AnyQuery,\n> = QueryFn<TContext, TTakesContext, TArg, TReturnQuery> & {\n queryName: TName;\n parse: ParseFn<TArg> | undefined;\n takesContext: TTakesContext;\n};\n\nfunction normalizeParser<T extends ReadonlyJSONValue[]>(\n parser: ParseFn<T> | HasParseFn<T> | undefined,\n): ParseFn<T> | undefined {\n if (parser) {\n if ('parse' in parser) {\n return parser.parse.bind(parser);\n }\n return parser;\n }\n return undefined;\n}\n\n/**\n * @deprecated Use {@linkcode defineQuery} instead.\n */\nexport function syncedQuery<\n TName extends string,\n TArg extends ReadonlyJSONValue[],\n TReturnQuery extends AnyQuery,\n>(\n name: TName,\n parser: ParseFn<TArg> | HasParseFn<TArg> | undefined,\n fn: QueryFn<unknown, false, TArg, TReturnQuery>,\n): SyncedQuery<TName, unknown, false, TArg, TReturnQuery> {\n const impl = syncedQueryImpl(name, fn, false);\n // oxlint-disable-next-line no-explicit-any\n const ret: any = (...args: TArg) => impl(undefined, args);\n ret.queryName = name;\n ret.parse = normalizeParser(parser);\n ret.takesContext = false;\n return ret;\n}\n\n/**\n * @deprecated Use {@linkcode defineQuery} instead.\n */\nexport function syncedQueryWithContext<\n TName extends string,\n TContext,\n TArg extends ReadonlyJSONValue[],\n TReturnQuery extends AnyQuery,\n>(\n name: TName,\n parser: ParseFn<TArg> | HasParseFn<TArg> | undefined,\n fn: QueryFn<TContext, true, TArg, TReturnQuery>,\n): SyncedQuery<TName, TContext, true, TArg, TReturnQuery> {\n const impl = syncedQueryImpl(name, fn, true);\n // oxlint-disable-next-line no-explicit-any\n const ret: any = (context: TContext, ...args: TArg) => impl(context, args);\n ret.queryName = name;\n ret.parse = normalizeParser(parser);\n ret.takesContext = true;\n return ret;\n}\n\n/** @deprecated */\nfunction syncedQueryImpl<\n TName extends string,\n TContext,\n TArg extends ReadonlyJSONValue[],\n // oxlint-disable-next-line no-explicit-any\n>(name: TName, fn: any, takesContext: boolean) {\n return (context: TContext, args: TArg) => {\n const q = takesContext ? fn(context, ...args) : fn(...args);\n return asQueryInternals(q).nameAndArgs(name, args);\n };\n}\n\n/** @deprecated */\n\n// oxlint-disable-next-line no-explicit-any\ntype AnySyncedQuery = SyncedQuery<any, any, any, any, any>;\n\n/** @deprecated */\nexport function withValidation<F extends AnySyncedQuery>(\n fn: F,\n // oxlint-disable-next-line no-explicit-any\n): F extends SyncedQuery<infer N, infer C, any, any, infer R>\n ? SyncedQuery<N, C, true, ReadonlyJSONValue[], R>\n : F {\n // If we have a parse function this is a SyncedQuery\n if ('parse' in fn) {\n const {parse} = fn;\n if (!parse) {\n throw new Error('ret does not have a parse function defined');\n }\n // oxlint-disable-next-line no-explicit-any\n const ret: any = (context: unknown, ...args: unknown[]) => {\n let parsed;\n try {\n parsed = parse(args);\n } catch (error) {\n throw new QueryParseError({cause: error});\n }\n // oxlint-disable-next-line no-explicit-any\n return fn.takesContext ? fn(context, ...parsed) : (fn as any)(...parsed);\n };\n ret.queryName = fn.queryName;\n ret.parse = fn.parse;\n ret.takesContext = true;\n\n return ret;\n }\n\n // If we don't have a parse function, return the function as-is\n // (this shouldn't happen in practice)\n // oxlint-disable-next-line no-explicit-any\n return fn as any;\n}\n\n/** @deprecated */\nexport type ParseFn<T extends ReadonlyJSONValue[]> = (args: unknown[]) => T;\n\n/** @deprecated */\nexport type HasParseFn<T extends ReadonlyJSONValue[]> = {\n parse: ParseFn<T>;\n};\n\n/** @deprecated */\nexport type Parser<T extends ReadonlyJSONValue[]> = ParseFn<T> | HasParseFn<T>;\n\nexport type CustomQueryID = {\n name: string;\n args: ReadonlyArray<ReadonlyJSONValue>;\n};\n"],"names":[],"mappings":";;;AA4BA,SAAS,gBACP,QACwB;AACxB,MAAI,QAAQ;AACV,QAAI,WAAW,QAAQ;AACrB,aAAO,OAAO,MAAM,KAAK,MAAM;AAAA,IACjC;AACA,WAAO;AAAA,EACT;AACA,SAAO;AACT;AAKO,SAAS,YAKd,MACA,QACA,IACwD;AACxD,QAAM,OAAO,gBAAgB,MAAM,IAAI,KAAK;AAE5C,QAAM,MAAW,IAAI,SAAe,KAAK,QAAW,IAAI;AACxD,MAAI,YAAY;AAChB,MAAI,QAAQ,gBAAgB,MAAM;AAClC,MAAI,eAAe;AACnB,SAAO;AACT;AAKO,SAAS,uBAMd,MACA,QACA,IACwD;AACxD,QAAM,OAAO,gBAAgB,MAAM,IAAI,IAAI;AAE3C,QAAM,MAAW,CAAC,YAAsB,SAAe,KAAK,SAAS,IAAI;AACzE,MAAI,YAAY;AAChB,MAAI,QAAQ,gBAAgB,MAAM;AAClC,MAAI,eAAe;AACnB,SAAO;AACT;AAGA,SAAS,gBAKP,MAAa,IAAS,cAAuB;AAC7C,SAAO,CAAC,SAAmB,SAAe;AACxC,UAAM,IAAI,eAAe,GAAG,SAAS,GAAG,IAAI,IAAI,GAAG,GAAG,IAAI;AAC1D,WAAO,iBAAiB,CAAC,EAAE,YAAY,MAAM,IAAI;AAAA,EACnD;AACF;AAQO,SAAS,eACd,IAII;AAEJ,MAAI,WAAW,IAAI;AACjB,UAAM,EAAC,UAAS;AAChB,QAAI,CAAC,OAAO;AACV,YAAM,IAAI,MAAM,4CAA4C;AAAA,IAC9D;AAEA,UAAM,MAAW,CAAC,YAAqB,SAAoB;AACzD,UAAI;AACJ,UAAI;AACF,iBAAS,MAAM,IAAI;AAAA,MACrB,SAAS,OAAO;AACd,cAAM,IAAI,gBAAgB,EAAC,OAAO,OAAM;AAAA,MAC1C;AAEA,aAAO,GAAG,eAAe,GAAG,SAAS,GAAG,MAAM,IAAK,GAAW,GAAG,MAAM;AAAA,IACzE;AACA,QAAI,YAAY,GAAG;AACnB,QAAI,QAAQ,GAAG;AACf,QAAI,eAAe;AAEnB,WAAO;AAAA,EACT;AAKA,SAAO;AACT;"}
|
|
@@ -6,12 +6,12 @@ import { type ExpressionFactory } from './expression.ts';
|
|
|
6
6
|
import type { CustomQueryID } from './named.ts';
|
|
7
7
|
import type { QueryDelegate } from './query-delegate.ts';
|
|
8
8
|
import { queryInternalsTag, type QueryInternals } from './query-internals.ts';
|
|
9
|
-
import { type AnyQuery, type ExistsOptions, type GetFilterType, type HumanReadable, type MaterializeOptions, type PreloadOptions, type PullRow, type Query, type RunOptions } from './query.ts';
|
|
9
|
+
import { type AnyQuery, type ExistsOptions, type GetFilterType, type HumanReadable, type MaterializeOptions, type PreloadOptions, type PullRow, type Query, type RunOptions, type ToQuery } from './query.ts';
|
|
10
10
|
export declare function newQuery<TSchema extends Schema, TTable extends keyof TSchema['tables'] & string, TReturn = PullRow<TTable, TSchema>>(schema: TSchema, table: TTable): Query<TSchema, TTable, TReturn>;
|
|
11
11
|
export declare function staticParam(anchorClass: 'authData' | 'preMutationRow', field: string | string[]): Parameter;
|
|
12
12
|
type GetFilterTypeAny = GetFilterType<any, any, any>;
|
|
13
13
|
type NewQueryFunction<TSchema extends Schema> = <TTable extends keyof TSchema['tables'] & string, TReturn>(this: unknown, tableName: TTable, ast: AST, format: Format, customQueryID: CustomQueryID | undefined, currentJunction: string | undefined) => Query<TSchema, TTable, TReturn>;
|
|
14
|
-
export declare abstract class AbstractQuery<TSchema extends Schema, TTable extends keyof TSchema['tables'] & string, TReturn = PullRow<TTable, TSchema>> implements Query<TSchema, TTable, TReturn>, QueryInternals<TSchema, TTable, TReturn> {
|
|
14
|
+
export declare abstract class AbstractQuery<TSchema extends Schema, TTable extends keyof TSchema['tables'] & string, TReturn = PullRow<TTable, TSchema>> implements Query<TSchema, TTable, TReturn>, QueryInternals<TSchema, TTable, TReturn>, ToQuery<TSchema, TTable, TReturn, unknown> {
|
|
15
15
|
#private;
|
|
16
16
|
readonly [queryInternalsTag] = true;
|
|
17
17
|
readonly format: Format;
|
|
@@ -30,6 +30,7 @@ export declare abstract class AbstractQuery<TSchema extends Schema, TTable exten
|
|
|
30
30
|
orderBy: <TSelector extends keyof TSchema["tables"][TTable]["columns"]>(field: TSelector, direction: "asc" | "desc") => Query<TSchema, TTable, TReturn>;
|
|
31
31
|
protected _exists: (relationship: string, cb: ((query: AnyQuery) => AnyQuery) | undefined, options?: ExistsOptions) => Condition;
|
|
32
32
|
get ast(): AST;
|
|
33
|
+
toQuery(_context: unknown): this;
|
|
33
34
|
}
|
|
34
35
|
export declare function materializeImpl<TSchema extends Schema, TTable extends keyof TSchema['tables'] & string, TReturn, T>(query: Query<TSchema, TTable, TReturn>, delegate: QueryDelegate, factory?: ViewFactory<TSchema, TTable, TReturn, T>, options?: MaterializeOptions): T;
|
|
35
36
|
export declare function runImpl<TSchema extends Schema, TTable extends keyof TSchema['tables'] & string, TReturn>(query: Query<TSchema, TTable, TReturn>, delegate: QueryDelegate, options?: RunOptions): Promise<HumanReadable<TReturn>>;
|
|
@@ -37,7 +38,7 @@ export declare function preloadImpl<TSchema extends Schema, TTable extends keyof
|
|
|
37
38
|
cleanup: () => void;
|
|
38
39
|
complete: Promise<void>;
|
|
39
40
|
};
|
|
40
|
-
export declare class QueryImpl<TSchema extends Schema, TTable extends keyof TSchema['tables'] & string, TReturn = PullRow<TTable, TSchema>> extends AbstractQuery<TSchema, TTable, TReturn> implements Query<TSchema, TTable, TReturn> {
|
|
41
|
+
export declare class QueryImpl<TSchema extends Schema, TTable extends keyof TSchema['tables'] & string, TReturn = PullRow<TTable, TSchema>> extends AbstractQuery<TSchema, TTable, TReturn> implements Query<TSchema, TTable, TReturn>, ToQuery<TSchema, TTable, TReturn, unknown> {
|
|
41
42
|
constructor(schema: TSchema, tableName: TTable, ast?: AST, format?: Format, system?: System, customQueryID?: CustomQueryID, currentJunction?: string);
|
|
42
43
|
}
|
|
43
44
|
export {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"query-impl.d.ts","sourceRoot":"","sources":["../../../../../zql/src/query/query-impl.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAC,iBAAiB,EAAC,MAAM,6BAA6B,CAAC;AACnE,OAAO,EAEL,KAAK,GAAG,EAER,KAAK,SAAS,EACd,KAAK,SAAS,EACd,KAAK,cAAc,EACnB,KAAK,MAAM,EACZ,MAAM,mCAAmC,CAAC;AAM3C,OAAO,KAAK,EAAC,MAAM,EAAC,MAAM,mCAAmC,CAAC;AAM9D,OAAO,KAAK,EAAC,MAAM,EAAE,WAAW,EAAC,MAAM,gBAAgB,CAAC;AACxD,OAAO,EAKL,KAAK,iBAAiB,EACvB,MAAM,iBAAiB,CAAC;AACzB,OAAO,KAAK,EAAC,aAAa,EAAC,MAAM,YAAY,CAAC;AAC9C,OAAO,KAAK,EAAc,aAAa,EAAC,MAAM,qBAAqB,CAAC;AACpE,OAAO,EAEL,iBAAiB,EACjB,KAAK,cAAc,EACpB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EACL,KAAK,QAAQ,EACb,KAAK,aAAa,EAClB,KAAK,aAAa,EAClB,KAAK,aAAa,EAClB,KAAK,kBAAkB,EACvB,KAAK,cAAc,EACnB,KAAK,OAAO,EACZ,KAAK,KAAK,EACV,KAAK,UAAU,
|
|
1
|
+
{"version":3,"file":"query-impl.d.ts","sourceRoot":"","sources":["../../../../../zql/src/query/query-impl.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"query-impl.js","sources":["../../../../../zql/src/query/query-impl.ts"],"sourcesContent":["import {resolver} from '@rocicorp/resolver';\nimport {assert} from '../../../shared/src/asserts.ts';\nimport type {ReadonlyJSONValue} from '../../../shared/src/json.ts';\nimport {\n SUBQ_PREFIX,\n type AST,\n type CompoundKey,\n type Condition,\n type Parameter,\n type SimpleOperator,\n type System,\n} from '../../../zero-protocol/src/ast.ts';\nimport type {ErroredQuery} from '../../../zero-protocol/src/custom-queries.ts';\nimport {\n hashOfAST,\n hashOfNameAndArgs,\n} from '../../../zero-protocol/src/query-hash.ts';\nimport type {Schema} from '../../../zero-types/src/schema.ts';\nimport {buildPipeline} from '../builder/builder.ts';\nimport {NotImplementedError} from '../error.ts';\nimport {ArrayView} from '../ivm/array-view.ts';\nimport {defaultFormat} from '../ivm/default-format.ts';\nimport type {Input} from '../ivm/operator.ts';\nimport type {Format, ViewFactory} from '../ivm/view.ts';\nimport {\n and,\n cmp,\n ExpressionBuilder,\n simplifyCondition,\n type ExpressionFactory,\n} from './expression.ts';\nimport type {CustomQueryID} from './named.ts';\nimport type {GotCallback, QueryDelegate} from './query-delegate.ts';\nimport {\n asQueryInternals,\n queryInternalsTag,\n type QueryInternals,\n} from './query-internals.ts';\nimport {\n type AnyQuery,\n type ExistsOptions,\n type GetFilterType,\n type HumanReadable,\n type MaterializeOptions,\n type PreloadOptions,\n type PullRow,\n type Query,\n type RunOptions,\n} from './query.ts';\nimport {DEFAULT_PRELOAD_TTL_MS, DEFAULT_TTL_MS, type TTL} from './ttl.ts';\nimport type {TypedView} from './typed-view.ts';\n\nexport function newQuery<\n TSchema extends Schema,\n TTable extends keyof TSchema['tables'] & string,\n TReturn = PullRow<TTable, TSchema>,\n>(schema: TSchema, table: TTable): Query<TSchema, TTable, TReturn> {\n return new QueryImpl(schema, table, {table}, defaultFormat, undefined);\n}\n\nexport function staticParam(\n anchorClass: 'authData' | 'preMutationRow',\n field: string | string[],\n): Parameter {\n return {\n type: 'static',\n anchor: anchorClass,\n // for backwards compatibility\n field: field.length === 1 ? field[0] : field,\n };\n}\n\n// oxlint-disable-next-line no-explicit-any\ntype GetFilterTypeAny = GetFilterType<any, any, any>;\n\ntype NewQueryFunction<TSchema extends Schema> = <\n TTable extends keyof TSchema['tables'] & string,\n TReturn,\n>(\n this: unknown,\n tableName: TTable,\n ast: AST,\n format: Format,\n customQueryID: CustomQueryID | undefined,\n currentJunction: string | undefined,\n) => Query<TSchema, TTable, TReturn>;\n\nexport abstract class AbstractQuery<\n TSchema extends Schema,\n TTable extends keyof TSchema['tables'] & string,\n TReturn = PullRow<TTable, TSchema>,\n >\n implements\n Query<TSchema, TTable, TReturn>,\n QueryInternals<TSchema, TTable, TReturn>\n{\n readonly [queryInternalsTag] = true;\n\n readonly #schema: TSchema;\n readonly #tableName: TTable;\n readonly #ast: AST;\n readonly format: Format;\n #hash: string = '';\n readonly #system: System;\n readonly #currentJunction: string | undefined;\n readonly customQueryID: CustomQueryID | undefined;\n readonly #newQuery: NewQueryFunction<TSchema>;\n\n constructor(\n schema: TSchema,\n tableName: TTable,\n ast: AST,\n format: Format,\n system: System,\n customQueryID: CustomQueryID | undefined,\n currentJunction: string | undefined,\n newQuery: NewQueryFunction<TSchema>,\n ) {\n this.#schema = schema;\n this.#tableName = tableName;\n this.#ast = ast;\n this.format = format;\n this.#system = system;\n this.#currentJunction = currentJunction;\n this.customQueryID = customQueryID;\n this.#newQuery = newQuery;\n }\n\n nameAndArgs(\n name: string,\n args: ReadonlyArray<ReadonlyJSONValue>,\n ): Query<TSchema, TTable, TReturn> {\n return this.#newQuery(\n this.#tableName,\n this.#ast,\n this.format,\n {\n name,\n args,\n },\n this.#currentJunction,\n );\n }\n\n hash(): string {\n if (!this.#hash) {\n this.#hash = hashOfAST(this.#ast);\n }\n return this.#hash;\n }\n\n one = (): Query<TSchema, TTable, TReturn | undefined> =>\n this.#newQuery(\n this.#tableName,\n {\n ...this.#ast,\n limit: 1,\n },\n {\n ...this.format,\n singular: true,\n },\n this.customQueryID,\n this.#currentJunction,\n );\n\n whereExists = (\n relationship: string,\n cbOrOptions?: ((q: AnyQuery) => AnyQuery) | ExistsOptions,\n options?: ExistsOptions,\n ): Query<TSchema, TTable, TReturn> => {\n const cb = typeof cbOrOptions === 'function' ? cbOrOptions : undefined;\n const opts = typeof cbOrOptions === 'function' ? options : cbOrOptions;\n const flipped = opts?.flip;\n return this.where(({exists}) =>\n exists(\n relationship,\n cb,\n flipped !== undefined ? {flip: flipped} : undefined,\n ),\n );\n };\n\n related = (\n relationship: string,\n cb?: (q: AnyQuery) => AnyQuery,\n // oxlint-disable-next-line no-explicit-any\n ): Query<Schema, string, any> => {\n if (relationship.startsWith(SUBQ_PREFIX)) {\n throw new Error(\n `Relationship names may not start with \"${SUBQ_PREFIX}\". That is a reserved prefix.`,\n );\n }\n cb = cb ?? (q => q);\n\n const related = this.#schema.relationships[this.#tableName][relationship];\n assert(related, 'Invalid relationship');\n if (isOneHop(related)) {\n const {destSchema, destField, sourceField, cardinality} = related[0];\n const q: AnyQuery = this.#newQuery(\n destSchema,\n {\n table: destSchema,\n alias: relationship,\n },\n {\n relationships: {},\n singular: cardinality === 'one',\n },\n this.customQueryID,\n undefined,\n ) as AnyQuery;\n // Intentionally not setting to `one` as it is a perf degradation\n // and the user should not be making the mistake of setting cardinality to\n // `one` when it is actually not.\n // if (cardinality === 'one') {\n // q = q.one();\n // }\n const subQuery = asAbstractQuery(cb(q));\n assert(\n isCompoundKey(sourceField),\n 'The source of a relationship must specify at last 1 field',\n );\n assert(\n isCompoundKey(destField),\n 'The destination of a relationship must specify at last 1 field',\n );\n assert(\n sourceField.length === destField.length,\n 'The source and destination of a relationship must have the same number of fields',\n );\n\n return this.#newQuery(\n this.#tableName,\n {\n ...this.#ast,\n related: [\n ...(this.#ast.related ?? []),\n {\n system: this.#system,\n correlation: {\n parentField: sourceField,\n childField: destField,\n },\n subquery: subQuery.#ast,\n },\n ],\n },\n {\n ...this.format,\n relationships: {\n ...this.format.relationships,\n [relationship]: subQuery.format,\n },\n },\n this.customQueryID,\n this.#currentJunction,\n ) as AnyQuery;\n }\n\n if (isTwoHop(related)) {\n const [firstRelation, secondRelation] = related;\n const {destSchema} = secondRelation;\n const junctionSchema = firstRelation.destSchema;\n const sq = asAbstractQuery(\n cb(\n this.#newQuery(\n destSchema,\n {\n table: destSchema,\n alias: relationship,\n },\n {\n relationships: {},\n singular: secondRelation.cardinality === 'one',\n },\n this.customQueryID,\n relationship,\n ),\n ),\n );\n\n assert(isCompoundKey(firstRelation.sourceField), 'Invalid relationship');\n assert(isCompoundKey(firstRelation.destField), 'Invalid relationship');\n assert(isCompoundKey(secondRelation.sourceField), 'Invalid relationship');\n assert(isCompoundKey(secondRelation.destField), 'Invalid relationship');\n\n return this.#newQuery(\n this.#tableName,\n {\n ...this.#ast,\n related: [\n ...(this.#ast.related ?? []),\n {\n system: this.#system,\n correlation: {\n parentField: firstRelation.sourceField,\n childField: firstRelation.destField,\n },\n hidden: true,\n subquery: {\n table: junctionSchema,\n alias: relationship,\n related: [\n {\n system: this.#system,\n correlation: {\n parentField: secondRelation.sourceField,\n childField: secondRelation.destField,\n },\n subquery: sq.#ast,\n },\n ],\n },\n },\n ],\n },\n {\n ...this.format,\n relationships: {\n ...this.format.relationships,\n [relationship]: sq.format,\n },\n },\n this.customQueryID,\n this.#currentJunction,\n ) as AnyQuery;\n }\n\n throw new Error(`Invalid relationship ${relationship}`);\n };\n\n where = (\n fieldOrExpressionFactory: string | ExpressionFactory<TSchema, TTable>,\n opOrValue?: SimpleOperator | GetFilterTypeAny | Parameter,\n value?: GetFilterTypeAny | Parameter,\n ): Query<TSchema, TTable, TReturn> => {\n let cond: Condition;\n\n if (typeof fieldOrExpressionFactory === 'function') {\n cond = fieldOrExpressionFactory(\n new ExpressionBuilder(this._exists) as ExpressionBuilder<\n TSchema,\n TTable\n >,\n );\n } else {\n assert(opOrValue !== undefined, 'Invalid condition');\n cond = cmp(fieldOrExpressionFactory, opOrValue, value);\n }\n\n const existingWhere = this.#ast.where;\n if (existingWhere) {\n cond = and(existingWhere, cond);\n }\n\n const where = simplifyCondition(cond);\n\n return this.#newQuery(\n this.#tableName,\n {\n ...this.#ast,\n where,\n },\n this.format,\n this.customQueryID,\n this.#currentJunction,\n );\n };\n\n start = (\n row: Partial<Record<string, ReadonlyJSONValue | undefined>>,\n opts?: {inclusive: boolean},\n ): Query<TSchema, TTable, TReturn> =>\n this.#newQuery(\n this.#tableName,\n {\n ...this.#ast,\n start: {\n row,\n exclusive: !opts?.inclusive,\n },\n },\n this.format,\n this.customQueryID,\n this.#currentJunction,\n );\n\n limit = (limit: number): Query<TSchema, TTable, TReturn> => {\n if (limit < 0) {\n throw new Error('Limit must be non-negative');\n }\n if ((limit | 0) !== limit) {\n throw new Error('Limit must be an integer');\n }\n if (this.#currentJunction) {\n throw new NotImplementedError(\n 'Limit is not supported in junction relationships yet. Junction relationship being limited: ' +\n this.#currentJunction,\n );\n }\n\n return this.#newQuery(\n this.#tableName,\n {\n ...this.#ast,\n limit,\n },\n this.format,\n this.customQueryID,\n this.#currentJunction,\n );\n };\n\n orderBy = <TSelector extends keyof TSchema['tables'][TTable]['columns']>(\n field: TSelector,\n direction: 'asc' | 'desc',\n ): Query<TSchema, TTable, TReturn> => {\n if (this.#currentJunction) {\n throw new NotImplementedError(\n 'Order by is not supported in junction relationships yet. Junction relationship being ordered: ' +\n this.#currentJunction,\n );\n }\n return this.#newQuery(\n this.#tableName,\n {\n ...this.#ast,\n orderBy: [...(this.#ast.orderBy ?? []), [field as string, direction]],\n },\n this.format,\n this.customQueryID,\n this.#currentJunction,\n );\n };\n\n protected _exists = (\n relationship: string,\n cb: ((query: AnyQuery) => AnyQuery) | undefined,\n options?: ExistsOptions,\n ): Condition => {\n cb = cb ?? (q => q);\n const flip = options?.flip;\n const related = this.#schema.relationships[this.#tableName][relationship];\n assert(related, 'Invalid relationship');\n\n if (isOneHop(related)) {\n const {destSchema: destTableName, sourceField, destField} = related[0];\n assert(isCompoundKey(sourceField), 'Invalid relationship');\n assert(isCompoundKey(destField), 'Invalid relationship');\n\n const subQuery = asAbstractQuery(\n cb(\n this.#newQuery(\n destTableName,\n {\n table: destTableName,\n alias: `${SUBQ_PREFIX}${relationship}`,\n },\n defaultFormat,\n this.customQueryID,\n undefined,\n ),\n ),\n );\n return {\n type: 'correlatedSubquery',\n related: {\n system: this.#system,\n correlation: {\n parentField: sourceField,\n childField: destField,\n },\n subquery: subQuery.#ast,\n },\n op: 'EXISTS',\n flip,\n };\n }\n\n if (isTwoHop(related)) {\n const [firstRelation, secondRelation] = related;\n assert(isCompoundKey(firstRelation.sourceField), 'Invalid relationship');\n assert(isCompoundKey(firstRelation.destField), 'Invalid relationship');\n assert(isCompoundKey(secondRelation.sourceField), 'Invalid relationship');\n assert(isCompoundKey(secondRelation.destField), 'Invalid relationship');\n const {destSchema} = secondRelation;\n const junctionSchema = firstRelation.destSchema;\n const queryToDest = cb(\n this.#newQuery(\n destSchema,\n {\n table: destSchema,\n alias: `${SUBQ_PREFIX}zhidden_${relationship}`,\n },\n defaultFormat,\n this.customQueryID,\n relationship,\n ) as AnyQuery,\n );\n\n return {\n type: 'correlatedSubquery',\n related: {\n system: this.#system,\n correlation: {\n parentField: firstRelation.sourceField,\n childField: firstRelation.destField,\n },\n subquery: {\n table: junctionSchema,\n alias: `${SUBQ_PREFIX}${relationship}`,\n where: {\n type: 'correlatedSubquery',\n related: {\n system: this.#system,\n correlation: {\n parentField: secondRelation.sourceField,\n childField: secondRelation.destField,\n },\n subquery: (queryToDest as QueryImpl<Schema, string, unknown>)\n .#ast,\n },\n op: 'EXISTS',\n flip,\n },\n },\n },\n op: 'EXISTS',\n flip,\n };\n }\n\n throw new Error(`Invalid relationship ${relationship}`);\n };\n\n get ast(): AST {\n return this.#ast;\n }\n}\n\nfunction asAbstractQuery<\n TSchema extends Schema,\n TTable extends keyof TSchema['tables'] & string,\n TReturn,\n>(q: Query<TSchema, TTable, TReturn>): AbstractQuery<TSchema, TTable, TReturn> {\n assert(q instanceof AbstractQuery);\n return q;\n}\n\nexport function materializeImpl<\n TSchema extends Schema,\n TTable extends keyof TSchema['tables'] & string,\n TReturn,\n T,\n>(\n query: Query<TSchema, TTable, TReturn>,\n delegate: QueryDelegate,\n factory: ViewFactory<\n TSchema,\n TTable,\n TReturn,\n T\n // oxlint-disable-next-line no-explicit-any\n > = arrayViewFactory as any,\n options?: MaterializeOptions,\n): T {\n let ttl: TTL = options?.ttl ?? DEFAULT_TTL_MS;\n\n const qi = asQueryInternals(query);\n const {ast, format, customQueryID} = qi;\n const queryHash = qi.hash();\n\n const queryID = customQueryID\n ? hashOfNameAndArgs(customQueryID.name, customQueryID.args)\n : queryHash;\n const queryCompleteResolver = resolver<true>();\n let queryComplete: boolean | ErroredQuery = delegate.defaultQueryComplete;\n const updateTTL = customQueryID\n ? (newTTL: TTL) => delegate.updateCustomQuery(customQueryID, newTTL)\n : (newTTL: TTL) => delegate.updateServerQuery(ast, newTTL);\n\n const gotCallback: GotCallback = (got, error) => {\n if (error) {\n queryCompleteResolver.reject(error);\n queryComplete = error;\n return;\n }\n\n if (got) {\n delegate.addMetric(\n 'query-materialization-end-to-end',\n performance.now() - t0,\n queryID,\n ast,\n );\n queryComplete = true;\n queryCompleteResolver.resolve(true);\n }\n };\n\n let removeCommitObserver: (() => void) | undefined;\n const onDestroy = () => {\n input.destroy();\n removeCommitObserver?.();\n removeAddedQuery();\n };\n\n const t0 = performance.now();\n\n const removeAddedQuery = customQueryID\n ? delegate.addCustomQuery(ast, customQueryID, ttl, gotCallback)\n : delegate.addServerQuery(ast, ttl, gotCallback);\n\n const input = buildPipeline(ast, delegate, queryID);\n\n const view = delegate.batchViewUpdates(() =>\n (factory ?? arrayViewFactory)(\n query,\n input,\n format,\n onDestroy,\n cb => {\n removeCommitObserver = delegate.onTransactionCommit(cb);\n },\n queryComplete || queryCompleteResolver.promise,\n updateTTL,\n ),\n );\n\n delegate.addMetric(\n 'query-materialization-client',\n performance.now() - t0,\n queryID,\n );\n\n return view as T;\n}\n\n// oxlint-disable-next-line require-await\nexport async function runImpl<\n TSchema extends Schema,\n TTable extends keyof TSchema['tables'] & string,\n TReturn,\n>(\n query: Query<TSchema, TTable, TReturn>,\n delegate: QueryDelegate,\n options?: RunOptions,\n): Promise<HumanReadable<TReturn>> {\n delegate.assertValidRunOptions(options);\n const v: TypedView<HumanReadable<TReturn>> = materializeImpl(\n query,\n delegate,\n undefined,\n {\n ttl: options?.ttl,\n },\n );\n if (options?.type === 'complete') {\n return new Promise(resolve => {\n v.addListener((data, type) => {\n if (type === 'complete') {\n v.destroy();\n resolve(data as HumanReadable<TReturn>);\n } else if (type === 'error') {\n v.destroy();\n resolve(Promise.reject(data));\n }\n });\n });\n }\n\n options?.type satisfies 'unknown' | undefined;\n\n const ret = v.data;\n v.destroy();\n return ret;\n}\n\nexport function preloadImpl<\n TSchema extends Schema,\n TTable extends keyof TSchema['tables'] & string,\n TReturn,\n>(\n query: Query<TSchema, TTable, TReturn>,\n delegate: QueryDelegate,\n options?: PreloadOptions,\n): {\n cleanup: () => void;\n complete: Promise<void>;\n} {\n const qi = asQueryInternals(query);\n const ttl = options?.ttl ?? DEFAULT_PRELOAD_TTL_MS;\n const {resolve, promise: complete} = resolver<void>();\n const {customQueryID, ast} = qi;\n if (customQueryID) {\n const cleanup = delegate.addCustomQuery(ast, customQueryID, ttl, got => {\n if (got) {\n resolve();\n }\n });\n return {\n cleanup,\n complete,\n };\n }\n\n const cleanup = delegate.addServerQuery(ast, ttl, got => {\n if (got) {\n resolve();\n }\n });\n return {\n cleanup,\n complete,\n };\n}\n\nexport class QueryImpl<\n TSchema extends Schema,\n TTable extends keyof TSchema['tables'] & string,\n TReturn = PullRow<TTable, TSchema>,\n >\n extends AbstractQuery<TSchema, TTable, TReturn>\n implements Query<TSchema, TTable, TReturn>\n{\n constructor(\n schema: TSchema,\n tableName: TTable,\n ast: AST = {table: tableName},\n format: Format = defaultFormat,\n system: System = 'client',\n customQueryID?: CustomQueryID,\n currentJunction?: string,\n ) {\n super(\n schema,\n tableName,\n ast,\n format,\n system,\n customQueryID,\n currentJunction,\n (tableName, ast, format, customQueryID, currentJunction) =>\n new QueryImpl(\n schema,\n tableName,\n ast,\n format,\n system,\n customQueryID,\n currentJunction,\n ),\n );\n }\n}\n\nfunction arrayViewFactory<\n TSchema extends Schema,\n TTable extends string,\n TReturn,\n>(\n _query: QueryInternals<TSchema, TTable, TReturn>,\n input: Input,\n format: Format,\n onDestroy: () => void,\n onTransactionCommit: (cb: () => void) => void,\n queryComplete: true | ErroredQuery | Promise<true>,\n updateTTL: (ttl: TTL) => void,\n): TypedView<HumanReadable<TReturn>> {\n const v = new ArrayView<HumanReadable<TReturn>>(\n input,\n format,\n queryComplete,\n updateTTL,\n );\n v.onDestroy = onDestroy;\n onTransactionCommit(() => {\n v.flush();\n });\n return v;\n}\n\nfunction isCompoundKey(field: readonly string[]): field is CompoundKey {\n return Array.isArray(field) && field.length >= 1;\n}\n\nfunction isOneHop<T>(r: readonly T[]): r is readonly [T] {\n return r.length === 1;\n}\n\nfunction isTwoHop<T>(r: readonly T[]): r is readonly [T, T] {\n return r.length === 2;\n}\n"],"names":["newQuery","cleanup","tableName","ast","format","customQueryID","currentJunction"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"query-impl.js","sources":["../../../../../zql/src/query/query-impl.ts"],"sourcesContent":["import {resolver} from '@rocicorp/resolver';\nimport {assert} from '../../../shared/src/asserts.ts';\nimport type {ReadonlyJSONValue} from '../../../shared/src/json.ts';\nimport {\n SUBQ_PREFIX,\n type AST,\n type CompoundKey,\n type Condition,\n type Parameter,\n type SimpleOperator,\n type System,\n} from '../../../zero-protocol/src/ast.ts';\nimport type {ErroredQuery} from '../../../zero-protocol/src/custom-queries.ts';\nimport {\n hashOfAST,\n hashOfNameAndArgs,\n} from '../../../zero-protocol/src/query-hash.ts';\nimport type {Schema} from '../../../zero-types/src/schema.ts';\nimport {buildPipeline} from '../builder/builder.ts';\nimport {NotImplementedError} from '../error.ts';\nimport {ArrayView} from '../ivm/array-view.ts';\nimport {defaultFormat} from '../ivm/default-format.ts';\nimport type {Input} from '../ivm/operator.ts';\nimport type {Format, ViewFactory} from '../ivm/view.ts';\nimport {\n and,\n cmp,\n ExpressionBuilder,\n simplifyCondition,\n type ExpressionFactory,\n} from './expression.ts';\nimport type {CustomQueryID} from './named.ts';\nimport type {GotCallback, QueryDelegate} from './query-delegate.ts';\nimport {\n asQueryInternals,\n queryInternalsTag,\n type QueryInternals,\n} from './query-internals.ts';\nimport {\n type AnyQuery,\n type ExistsOptions,\n type GetFilterType,\n type HumanReadable,\n type MaterializeOptions,\n type PreloadOptions,\n type PullRow,\n type Query,\n type RunOptions,\n type ToQuery,\n} from './query.ts';\nimport {DEFAULT_PRELOAD_TTL_MS, DEFAULT_TTL_MS, type TTL} from './ttl.ts';\nimport type {TypedView} from './typed-view.ts';\n\nexport function newQuery<\n TSchema extends Schema,\n TTable extends keyof TSchema['tables'] & string,\n TReturn = PullRow<TTable, TSchema>,\n>(schema: TSchema, table: TTable): Query<TSchema, TTable, TReturn> {\n return new QueryImpl(schema, table, {table}, defaultFormat, undefined);\n}\n\nexport function staticParam(\n anchorClass: 'authData' | 'preMutationRow',\n field: string | string[],\n): Parameter {\n return {\n type: 'static',\n anchor: anchorClass,\n // for backwards compatibility\n field: field.length === 1 ? field[0] : field,\n };\n}\n\n// oxlint-disable-next-line no-explicit-any\ntype GetFilterTypeAny = GetFilterType<any, any, any>;\n\ntype NewQueryFunction<TSchema extends Schema> = <\n TTable extends keyof TSchema['tables'] & string,\n TReturn,\n>(\n this: unknown,\n tableName: TTable,\n ast: AST,\n format: Format,\n customQueryID: CustomQueryID | undefined,\n currentJunction: string | undefined,\n) => Query<TSchema, TTable, TReturn>;\n\nexport abstract class AbstractQuery<\n TSchema extends Schema,\n TTable extends keyof TSchema['tables'] & string,\n TReturn = PullRow<TTable, TSchema>,\n >\n implements\n Query<TSchema, TTable, TReturn>,\n QueryInternals<TSchema, TTable, TReturn>,\n ToQuery<TSchema, TTable, TReturn, unknown>\n{\n readonly [queryInternalsTag] = true;\n\n readonly #schema: TSchema;\n readonly #tableName: TTable;\n readonly #ast: AST;\n readonly format: Format;\n #hash: string = '';\n readonly #system: System;\n readonly #currentJunction: string | undefined;\n readonly customQueryID: CustomQueryID | undefined;\n readonly #newQuery: NewQueryFunction<TSchema>;\n\n constructor(\n schema: TSchema,\n tableName: TTable,\n ast: AST,\n format: Format,\n system: System,\n customQueryID: CustomQueryID | undefined,\n currentJunction: string | undefined,\n newQuery: NewQueryFunction<TSchema>,\n ) {\n this.#schema = schema;\n this.#tableName = tableName;\n this.#ast = ast;\n this.format = format;\n this.#system = system;\n this.#currentJunction = currentJunction;\n this.customQueryID = customQueryID;\n this.#newQuery = newQuery;\n }\n\n nameAndArgs(\n name: string,\n args: ReadonlyArray<ReadonlyJSONValue>,\n ): Query<TSchema, TTable, TReturn> {\n return this.#newQuery(\n this.#tableName,\n this.#ast,\n this.format,\n {\n name,\n args,\n },\n this.#currentJunction,\n );\n }\n\n hash(): string {\n if (!this.#hash) {\n this.#hash = hashOfAST(this.#ast);\n }\n return this.#hash;\n }\n\n one = (): Query<TSchema, TTable, TReturn | undefined> =>\n this.#newQuery(\n this.#tableName,\n {\n ...this.#ast,\n limit: 1,\n },\n {\n ...this.format,\n singular: true,\n },\n this.customQueryID,\n this.#currentJunction,\n );\n\n whereExists = (\n relationship: string,\n cbOrOptions?: ((q: AnyQuery) => AnyQuery) | ExistsOptions,\n options?: ExistsOptions,\n ): Query<TSchema, TTable, TReturn> => {\n const cb = typeof cbOrOptions === 'function' ? cbOrOptions : undefined;\n const opts = typeof cbOrOptions === 'function' ? options : cbOrOptions;\n const flipped = opts?.flip;\n return this.where(({exists}) =>\n exists(\n relationship,\n cb,\n flipped !== undefined ? {flip: flipped} : undefined,\n ),\n );\n };\n\n related = (\n relationship: string,\n cb?: (q: AnyQuery) => AnyQuery,\n // oxlint-disable-next-line no-explicit-any\n ): Query<Schema, string, any> => {\n if (relationship.startsWith(SUBQ_PREFIX)) {\n throw new Error(\n `Relationship names may not start with \"${SUBQ_PREFIX}\". That is a reserved prefix.`,\n );\n }\n cb = cb ?? (q => q);\n\n const related = this.#schema.relationships[this.#tableName][relationship];\n assert(related, 'Invalid relationship');\n if (isOneHop(related)) {\n const {destSchema, destField, sourceField, cardinality} = related[0];\n const q: AnyQuery = this.#newQuery(\n destSchema,\n {\n table: destSchema,\n alias: relationship,\n },\n {\n relationships: {},\n singular: cardinality === 'one',\n },\n this.customQueryID,\n undefined,\n ) as AnyQuery;\n // Intentionally not setting to `one` as it is a perf degradation\n // and the user should not be making the mistake of setting cardinality to\n // `one` when it is actually not.\n // if (cardinality === 'one') {\n // q = q.one();\n // }\n const subQuery = asAbstractQuery(cb(q));\n assert(\n isCompoundKey(sourceField),\n 'The source of a relationship must specify at last 1 field',\n );\n assert(\n isCompoundKey(destField),\n 'The destination of a relationship must specify at last 1 field',\n );\n assert(\n sourceField.length === destField.length,\n 'The source and destination of a relationship must have the same number of fields',\n );\n\n return this.#newQuery(\n this.#tableName,\n {\n ...this.#ast,\n related: [\n ...(this.#ast.related ?? []),\n {\n system: this.#system,\n correlation: {\n parentField: sourceField,\n childField: destField,\n },\n subquery: subQuery.#ast,\n },\n ],\n },\n {\n ...this.format,\n relationships: {\n ...this.format.relationships,\n [relationship]: subQuery.format,\n },\n },\n this.customQueryID,\n this.#currentJunction,\n ) as AnyQuery;\n }\n\n if (isTwoHop(related)) {\n const [firstRelation, secondRelation] = related;\n const {destSchema} = secondRelation;\n const junctionSchema = firstRelation.destSchema;\n const sq = asAbstractQuery(\n cb(\n this.#newQuery(\n destSchema,\n {\n table: destSchema,\n alias: relationship,\n },\n {\n relationships: {},\n singular: secondRelation.cardinality === 'one',\n },\n this.customQueryID,\n relationship,\n ),\n ),\n );\n\n assert(isCompoundKey(firstRelation.sourceField), 'Invalid relationship');\n assert(isCompoundKey(firstRelation.destField), 'Invalid relationship');\n assert(isCompoundKey(secondRelation.sourceField), 'Invalid relationship');\n assert(isCompoundKey(secondRelation.destField), 'Invalid relationship');\n\n return this.#newQuery(\n this.#tableName,\n {\n ...this.#ast,\n related: [\n ...(this.#ast.related ?? []),\n {\n system: this.#system,\n correlation: {\n parentField: firstRelation.sourceField,\n childField: firstRelation.destField,\n },\n hidden: true,\n subquery: {\n table: junctionSchema,\n alias: relationship,\n related: [\n {\n system: this.#system,\n correlation: {\n parentField: secondRelation.sourceField,\n childField: secondRelation.destField,\n },\n subquery: sq.#ast,\n },\n ],\n },\n },\n ],\n },\n {\n ...this.format,\n relationships: {\n ...this.format.relationships,\n [relationship]: sq.format,\n },\n },\n this.customQueryID,\n this.#currentJunction,\n ) as AnyQuery;\n }\n\n throw new Error(`Invalid relationship ${relationship}`);\n };\n\n where = (\n fieldOrExpressionFactory: string | ExpressionFactory<TSchema, TTable>,\n opOrValue?: SimpleOperator | GetFilterTypeAny | Parameter,\n value?: GetFilterTypeAny | Parameter,\n ): Query<TSchema, TTable, TReturn> => {\n let cond: Condition;\n\n if (typeof fieldOrExpressionFactory === 'function') {\n cond = fieldOrExpressionFactory(\n new ExpressionBuilder(this._exists) as ExpressionBuilder<\n TSchema,\n TTable\n >,\n );\n } else {\n assert(opOrValue !== undefined, 'Invalid condition');\n cond = cmp(fieldOrExpressionFactory, opOrValue, value);\n }\n\n const existingWhere = this.#ast.where;\n if (existingWhere) {\n cond = and(existingWhere, cond);\n }\n\n const where = simplifyCondition(cond);\n\n return this.#newQuery(\n this.#tableName,\n {\n ...this.#ast,\n where,\n },\n this.format,\n this.customQueryID,\n this.#currentJunction,\n );\n };\n\n start = (\n row: Partial<Record<string, ReadonlyJSONValue | undefined>>,\n opts?: {inclusive: boolean},\n ): Query<TSchema, TTable, TReturn> =>\n this.#newQuery(\n this.#tableName,\n {\n ...this.#ast,\n start: {\n row,\n exclusive: !opts?.inclusive,\n },\n },\n this.format,\n this.customQueryID,\n this.#currentJunction,\n );\n\n limit = (limit: number): Query<TSchema, TTable, TReturn> => {\n if (limit < 0) {\n throw new Error('Limit must be non-negative');\n }\n if ((limit | 0) !== limit) {\n throw new Error('Limit must be an integer');\n }\n if (this.#currentJunction) {\n throw new NotImplementedError(\n 'Limit is not supported in junction relationships yet. Junction relationship being limited: ' +\n this.#currentJunction,\n );\n }\n\n return this.#newQuery(\n this.#tableName,\n {\n ...this.#ast,\n limit,\n },\n this.format,\n this.customQueryID,\n this.#currentJunction,\n );\n };\n\n orderBy = <TSelector extends keyof TSchema['tables'][TTable]['columns']>(\n field: TSelector,\n direction: 'asc' | 'desc',\n ): Query<TSchema, TTable, TReturn> => {\n if (this.#currentJunction) {\n throw new NotImplementedError(\n 'Order by is not supported in junction relationships yet. Junction relationship being ordered: ' +\n this.#currentJunction,\n );\n }\n return this.#newQuery(\n this.#tableName,\n {\n ...this.#ast,\n orderBy: [...(this.#ast.orderBy ?? []), [field as string, direction]],\n },\n this.format,\n this.customQueryID,\n this.#currentJunction,\n );\n };\n\n protected _exists = (\n relationship: string,\n cb: ((query: AnyQuery) => AnyQuery) | undefined,\n options?: ExistsOptions,\n ): Condition => {\n cb = cb ?? (q => q);\n const flip = options?.flip;\n const related = this.#schema.relationships[this.#tableName][relationship];\n assert(related, 'Invalid relationship');\n\n if (isOneHop(related)) {\n const {destSchema: destTableName, sourceField, destField} = related[0];\n assert(isCompoundKey(sourceField), 'Invalid relationship');\n assert(isCompoundKey(destField), 'Invalid relationship');\n\n const subQuery = asAbstractQuery(\n cb(\n this.#newQuery(\n destTableName,\n {\n table: destTableName,\n alias: `${SUBQ_PREFIX}${relationship}`,\n },\n defaultFormat,\n this.customQueryID,\n undefined,\n ),\n ),\n );\n return {\n type: 'correlatedSubquery',\n related: {\n system: this.#system,\n correlation: {\n parentField: sourceField,\n childField: destField,\n },\n subquery: subQuery.#ast,\n },\n op: 'EXISTS',\n flip,\n };\n }\n\n if (isTwoHop(related)) {\n const [firstRelation, secondRelation] = related;\n assert(isCompoundKey(firstRelation.sourceField), 'Invalid relationship');\n assert(isCompoundKey(firstRelation.destField), 'Invalid relationship');\n assert(isCompoundKey(secondRelation.sourceField), 'Invalid relationship');\n assert(isCompoundKey(secondRelation.destField), 'Invalid relationship');\n const {destSchema} = secondRelation;\n const junctionSchema = firstRelation.destSchema;\n const queryToDest = cb(\n this.#newQuery(\n destSchema,\n {\n table: destSchema,\n alias: `${SUBQ_PREFIX}zhidden_${relationship}`,\n },\n defaultFormat,\n this.customQueryID,\n relationship,\n ) as AnyQuery,\n );\n\n return {\n type: 'correlatedSubquery',\n related: {\n system: this.#system,\n correlation: {\n parentField: firstRelation.sourceField,\n childField: firstRelation.destField,\n },\n subquery: {\n table: junctionSchema,\n alias: `${SUBQ_PREFIX}${relationship}`,\n where: {\n type: 'correlatedSubquery',\n related: {\n system: this.#system,\n correlation: {\n parentField: secondRelation.sourceField,\n childField: secondRelation.destField,\n },\n subquery: (queryToDest as QueryImpl<Schema, string, unknown>)\n .#ast,\n },\n op: 'EXISTS',\n flip,\n },\n },\n },\n op: 'EXISTS',\n flip,\n };\n }\n\n throw new Error(`Invalid relationship ${relationship}`);\n };\n\n get ast(): AST {\n return this.#ast;\n }\n\n toQuery(_context: unknown): this {\n return this;\n }\n}\n\nfunction asAbstractQuery<\n TSchema extends Schema,\n TTable extends keyof TSchema['tables'] & string,\n TReturn,\n>(q: Query<TSchema, TTable, TReturn>): AbstractQuery<TSchema, TTable, TReturn> {\n assert(q instanceof AbstractQuery);\n return q;\n}\n\nexport function materializeImpl<\n TSchema extends Schema,\n TTable extends keyof TSchema['tables'] & string,\n TReturn,\n T,\n>(\n query: Query<TSchema, TTable, TReturn>,\n delegate: QueryDelegate,\n factory: ViewFactory<\n TSchema,\n TTable,\n TReturn,\n T\n // oxlint-disable-next-line no-explicit-any\n > = arrayViewFactory as any,\n options?: MaterializeOptions,\n): T {\n let ttl: TTL = options?.ttl ?? DEFAULT_TTL_MS;\n\n const qi = asQueryInternals(query);\n const {ast, format, customQueryID} = qi;\n const queryHash = qi.hash();\n\n const queryID = customQueryID\n ? hashOfNameAndArgs(customQueryID.name, customQueryID.args)\n : queryHash;\n const queryCompleteResolver = resolver<true>();\n let queryComplete: boolean | ErroredQuery = delegate.defaultQueryComplete;\n const updateTTL = customQueryID\n ? (newTTL: TTL) => delegate.updateCustomQuery(customQueryID, newTTL)\n : (newTTL: TTL) => delegate.updateServerQuery(ast, newTTL);\n\n const gotCallback: GotCallback = (got, error) => {\n if (error) {\n queryCompleteResolver.reject(error);\n queryComplete = error;\n return;\n }\n\n if (got) {\n delegate.addMetric(\n 'query-materialization-end-to-end',\n performance.now() - t0,\n queryID,\n ast,\n );\n queryComplete = true;\n queryCompleteResolver.resolve(true);\n }\n };\n\n let removeCommitObserver: (() => void) | undefined;\n const onDestroy = () => {\n input.destroy();\n removeCommitObserver?.();\n removeAddedQuery();\n };\n\n const t0 = performance.now();\n\n const removeAddedQuery = customQueryID\n ? delegate.addCustomQuery(ast, customQueryID, ttl, gotCallback)\n : delegate.addServerQuery(ast, ttl, gotCallback);\n\n const input = buildPipeline(ast, delegate, queryID);\n\n const view = delegate.batchViewUpdates(() =>\n (factory ?? arrayViewFactory)(\n query,\n input,\n format,\n onDestroy,\n cb => {\n removeCommitObserver = delegate.onTransactionCommit(cb);\n },\n queryComplete || queryCompleteResolver.promise,\n updateTTL,\n ),\n );\n\n delegate.addMetric(\n 'query-materialization-client',\n performance.now() - t0,\n queryID,\n );\n\n return view as T;\n}\n\n// oxlint-disable-next-line require-await\nexport async function runImpl<\n TSchema extends Schema,\n TTable extends keyof TSchema['tables'] & string,\n TReturn,\n>(\n query: Query<TSchema, TTable, TReturn>,\n delegate: QueryDelegate,\n options?: RunOptions,\n): Promise<HumanReadable<TReturn>> {\n delegate.assertValidRunOptions(options);\n const v: TypedView<HumanReadable<TReturn>> = materializeImpl(\n query,\n delegate,\n undefined,\n {\n ttl: options?.ttl,\n },\n );\n if (options?.type === 'complete') {\n return new Promise(resolve => {\n v.addListener((data, type) => {\n if (type === 'complete') {\n v.destroy();\n resolve(data as HumanReadable<TReturn>);\n } else if (type === 'error') {\n v.destroy();\n resolve(Promise.reject(data));\n }\n });\n });\n }\n\n options?.type satisfies 'unknown' | undefined;\n\n const ret = v.data;\n v.destroy();\n return ret;\n}\n\nexport function preloadImpl<\n TSchema extends Schema,\n TTable extends keyof TSchema['tables'] & string,\n TReturn,\n>(\n query: Query<TSchema, TTable, TReturn>,\n delegate: QueryDelegate,\n options?: PreloadOptions,\n): {\n cleanup: () => void;\n complete: Promise<void>;\n} {\n const qi = asQueryInternals(query);\n const ttl = options?.ttl ?? DEFAULT_PRELOAD_TTL_MS;\n const {resolve, promise: complete} = resolver<void>();\n const {customQueryID, ast} = qi;\n if (customQueryID) {\n const cleanup = delegate.addCustomQuery(ast, customQueryID, ttl, got => {\n if (got) {\n resolve();\n }\n });\n return {\n cleanup,\n complete,\n };\n }\n\n const cleanup = delegate.addServerQuery(ast, ttl, got => {\n if (got) {\n resolve();\n }\n });\n return {\n cleanup,\n complete,\n };\n}\n\nexport class QueryImpl<\n TSchema extends Schema,\n TTable extends keyof TSchema['tables'] & string,\n TReturn = PullRow<TTable, TSchema>,\n >\n extends AbstractQuery<TSchema, TTable, TReturn>\n implements\n Query<TSchema, TTable, TReturn>,\n ToQuery<TSchema, TTable, TReturn, unknown>\n{\n constructor(\n schema: TSchema,\n tableName: TTable,\n ast: AST = {table: tableName},\n format: Format = defaultFormat,\n system: System = 'client',\n customQueryID?: CustomQueryID,\n currentJunction?: string,\n ) {\n super(\n schema,\n tableName,\n ast,\n format,\n system,\n customQueryID,\n currentJunction,\n (tableName, ast, format, customQueryID, currentJunction) =>\n new QueryImpl(\n schema,\n tableName,\n ast,\n format,\n system,\n customQueryID,\n currentJunction,\n ),\n );\n }\n}\n\nfunction arrayViewFactory<\n TSchema extends Schema,\n TTable extends string,\n TReturn,\n>(\n _query: QueryInternals<TSchema, TTable, TReturn>,\n input: Input,\n format: Format,\n onDestroy: () => void,\n onTransactionCommit: (cb: () => void) => void,\n queryComplete: true | ErroredQuery | Promise<true>,\n updateTTL: (ttl: TTL) => void,\n): TypedView<HumanReadable<TReturn>> {\n const v = new ArrayView<HumanReadable<TReturn>>(\n input,\n format,\n queryComplete,\n updateTTL,\n );\n v.onDestroy = onDestroy;\n onTransactionCommit(() => {\n v.flush();\n });\n return v;\n}\n\nfunction isCompoundKey(field: readonly string[]): field is CompoundKey {\n return Array.isArray(field) && field.length >= 1;\n}\n\nfunction isOneHop<T>(r: readonly T[]): r is readonly [T] {\n return r.length === 1;\n}\n\nfunction isTwoHop<T>(r: readonly T[]): r is readonly [T, T] {\n return r.length === 2;\n}\n"],"names":["newQuery","cleanup","tableName","ast","format","customQueryID","currentJunction"],"mappings":"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"}
|
|
@@ -4,12 +4,8 @@ function asQueryInternals(query) {
|
|
|
4
4
|
assert(queryInternalsTag in query);
|
|
5
5
|
return query;
|
|
6
6
|
}
|
|
7
|
-
function isQueryInternals(obj) {
|
|
8
|
-
return typeof obj === "object" && obj !== null && queryInternalsTag in obj;
|
|
9
|
-
}
|
|
10
7
|
export {
|
|
11
8
|
asQueryInternals,
|
|
12
|
-
isQueryInternals,
|
|
13
9
|
queryInternalsTag
|
|
14
10
|
};
|
|
15
11
|
//# sourceMappingURL=query-internals.js.map
|