@rocicorp/zero 1.0.0 → 1.1.0
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/_virtual/{_@oxc-project_runtime@0.115.0 → _@oxc-project_runtime@0.122.0}/helpers/usingCtx.js +1 -1
- package/out/analyze-query/src/bin-analyze.js +19 -7
- package/out/analyze-query/src/bin-analyze.js.map +1 -1
- package/out/replicache/src/mutation-recovery.js +0 -3
- package/out/zero/package.js +7 -6
- package/out/zero/package.js.map +1 -1
- package/out/zero-cache/src/config/zero-config.d.ts +6 -0
- package/out/zero-cache/src/config/zero-config.d.ts.map +1 -1
- package/out/zero-cache/src/config/zero-config.js +12 -0
- package/out/zero-cache/src/config/zero-config.js.map +1 -1
- package/out/zero-cache/src/server/anonymous-otel-start.d.ts.map +1 -1
- package/out/zero-cache/src/server/anonymous-otel-start.js +1 -14
- package/out/zero-cache/src/server/anonymous-otel-start.js.map +1 -1
- package/out/zero-cache/src/server/change-streamer.d.ts.map +1 -1
- package/out/zero-cache/src/server/change-streamer.js +2 -2
- package/out/zero-cache/src/server/change-streamer.js.map +1 -1
- package/out/zero-cache/src/services/analyze.js +2 -2
- package/out/zero-cache/src/services/change-source/change-source.d.ts +7 -0
- package/out/zero-cache/src/services/change-source/change-source.d.ts.map +1 -1
- package/out/zero-cache/src/services/change-source/common/change-stream-multiplexer.d.ts.map +1 -1
- package/out/zero-cache/src/services/change-source/common/change-stream-multiplexer.js +1 -1
- package/out/zero-cache/src/services/change-source/common/change-stream-multiplexer.js.map +1 -1
- package/out/zero-cache/src/services/change-source/custom/change-source.d.ts.map +1 -1
- package/out/zero-cache/src/services/change-source/custom/change-source.js +3 -0
- package/out/zero-cache/src/services/change-source/custom/change-source.js.map +1 -1
- package/out/zero-cache/src/services/change-source/pg/change-source.d.ts +9 -1
- package/out/zero-cache/src/services/change-source/pg/change-source.d.ts.map +1 -1
- package/out/zero-cache/src/services/change-source/pg/change-source.js +172 -46
- package/out/zero-cache/src/services/change-source/pg/change-source.js.map +1 -1
- package/out/zero-cache/src/services/change-source/pg/lsn.js +1 -1
- package/out/zero-cache/src/services/change-source/protocol/current/downstream.d.ts +8 -0
- package/out/zero-cache/src/services/change-source/protocol/current/downstream.d.ts.map +1 -1
- package/out/zero-cache/src/services/change-source/protocol/current/status.d.ts +26 -1
- package/out/zero-cache/src/services/change-source/protocol/current/status.d.ts.map +1 -1
- package/out/zero-cache/src/services/change-source/protocol/current/status.js +7 -2
- package/out/zero-cache/src/services/change-source/protocol/current/status.js.map +1 -1
- package/out/zero-cache/src/services/change-source/protocol/current/upstream.d.ts +8 -0
- package/out/zero-cache/src/services/change-source/protocol/current/upstream.d.ts.map +1 -1
- package/out/zero-cache/src/services/change-streamer/change-streamer-service.d.ts.map +1 -1
- package/out/zero-cache/src/services/change-streamer/change-streamer-service.js +10 -2
- package/out/zero-cache/src/services/change-streamer/change-streamer-service.js.map +1 -1
- package/out/zero-cache/src/services/change-streamer/change-streamer.d.ts +25 -0
- package/out/zero-cache/src/services/change-streamer/change-streamer.d.ts.map +1 -1
- package/out/zero-cache/src/services/change-streamer/change-streamer.js +8 -1
- package/out/zero-cache/src/services/change-streamer/change-streamer.js.map +1 -1
- package/out/zero-cache/src/services/change-streamer/forwarder.d.ts +2 -0
- package/out/zero-cache/src/services/change-streamer/forwarder.d.ts.map +1 -1
- package/out/zero-cache/src/services/change-streamer/forwarder.js +3 -0
- package/out/zero-cache/src/services/change-streamer/forwarder.js.map +1 -1
- package/out/zero-cache/src/services/change-streamer/subscriber.d.ts +3 -2
- package/out/zero-cache/src/services/change-streamer/subscriber.d.ts.map +1 -1
- package/out/zero-cache/src/services/change-streamer/subscriber.js +17 -8
- package/out/zero-cache/src/services/change-streamer/subscriber.js.map +1 -1
- package/out/zero-cache/src/services/life-cycle.d.ts.map +1 -1
- package/out/zero-cache/src/services/life-cycle.js +6 -2
- package/out/zero-cache/src/services/life-cycle.js.map +1 -1
- package/out/zero-cache/src/services/replicator/incremental-sync.d.ts +2 -2
- package/out/zero-cache/src/services/replicator/incremental-sync.d.ts.map +1 -1
- package/out/zero-cache/src/services/replicator/incremental-sync.js +19 -4
- package/out/zero-cache/src/services/replicator/incremental-sync.js.map +1 -1
- package/out/zero-cache/src/services/replicator/replicator.d.ts.map +1 -1
- package/out/zero-cache/src/services/replicator/replicator.js +2 -2
- package/out/zero-cache/src/services/replicator/replicator.js.map +1 -1
- package/out/zero-cache/src/services/replicator/reporter/recorder.d.ts +12 -0
- package/out/zero-cache/src/services/replicator/reporter/recorder.d.ts.map +1 -0
- package/out/zero-cache/src/services/replicator/reporter/recorder.js +58 -0
- package/out/zero-cache/src/services/replicator/reporter/recorder.js.map +1 -0
- package/out/zero-cache/src/services/replicator/reporter/report-schema.d.ts +35 -0
- package/out/zero-cache/src/services/replicator/reporter/report-schema.d.ts.map +1 -0
- package/out/zero-cache/src/services/replicator/reporter/report-schema.js +20 -0
- package/out/zero-cache/src/services/replicator/reporter/report-schema.js.map +1 -0
- package/out/zero-cache/src/services/run-ast.js +1 -1
- package/out/zero-cache/src/services/view-syncer/inspect-handler.js +1 -1
- package/out/zero-cache/src/types/pg.d.ts.map +1 -1
- package/out/zero-cache/src/types/pg.js +2 -0
- package/out/zero-cache/src/types/pg.js.map +1 -1
- package/out/zero-cache/src/workers/replicator.d.ts.map +1 -1
- package/out/zero-cache/src/workers/replicator.js +1 -0
- package/out/zero-cache/src/workers/replicator.js.map +1 -1
- package/out/zero-client/src/client/version.js +1 -1
- package/out/zql/src/builder/builder.d.ts.map +1 -1
- package/out/zql/src/builder/builder.js +15 -5
- package/out/zql/src/builder/builder.js.map +1 -1
- package/out/zql/src/ivm/cap.d.ts +32 -0
- package/out/zql/src/ivm/cap.d.ts.map +1 -0
- package/out/zql/src/ivm/cap.js +226 -0
- package/out/zql/src/ivm/cap.js.map +1 -0
- package/out/zql/src/ivm/join-utils.d.ts +2 -0
- package/out/zql/src/ivm/join-utils.d.ts.map +1 -1
- package/out/zql/src/ivm/join-utils.js +35 -1
- package/out/zql/src/ivm/join-utils.js.map +1 -1
- package/out/zql/src/ivm/join.d.ts.map +1 -1
- package/out/zql/src/ivm/join.js +6 -2
- package/out/zql/src/ivm/join.js.map +1 -1
- package/out/zql/src/ivm/memory-source.d.ts +15 -2
- package/out/zql/src/ivm/memory-source.d.ts.map +1 -1
- package/out/zql/src/ivm/memory-source.js +69 -8
- package/out/zql/src/ivm/memory-source.js.map +1 -1
- package/out/zql/src/ivm/schema.d.ts +1 -1
- package/out/zql/src/ivm/schema.d.ts.map +1 -1
- package/out/zql/src/ivm/skip.d.ts.map +1 -1
- package/out/zql/src/ivm/skip.js +3 -0
- package/out/zql/src/ivm/skip.js.map +1 -1
- package/out/zql/src/ivm/source.d.ts +1 -1
- package/out/zql/src/ivm/source.d.ts.map +1 -1
- package/out/zql/src/ivm/take.d.ts +4 -1
- package/out/zql/src/ivm/take.d.ts.map +1 -1
- package/out/zql/src/ivm/take.js +4 -2
- package/out/zql/src/ivm/take.js.map +1 -1
- package/out/zql/src/ivm/union-fan-in.d.ts.map +1 -1
- package/out/zql/src/ivm/union-fan-in.js +1 -0
- package/out/zql/src/ivm/union-fan-in.js.map +1 -1
- package/out/zqlite/src/query-builder.d.ts +1 -1
- package/out/zqlite/src/query-builder.d.ts.map +1 -1
- package/out/zqlite/src/query-builder.js +7 -2
- package/out/zqlite/src/query-builder.js.map +1 -1
- package/out/zqlite/src/table-source.d.ts +1 -1
- package/out/zqlite/src/table-source.d.ts.map +1 -1
- package/out/zqlite/src/table-source.js +15 -10
- package/out/zqlite/src/table-source.js.map +1 -1
- package/package.json +7 -6
- package/out/analyze-query/src/run-ast.d.ts +0 -22
- package/out/analyze-query/src/run-ast.d.ts.map +0 -1
- package/out/analyze-query/src/run-ast.js +0 -75
- package/out/analyze-query/src/run-ast.js.map +0 -1
- package/out/replicache/src/mutation-recovery.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"join.js","names":["#parent","#child","#parentKey","#childKey","#relationshipName","#schema","#pushParent","#pushChild","#output","#processParentNode","#pushChildChange","#inprogressChildChange"],"sources":["../../../../../zql/src/ivm/join.ts"],"sourcesContent":["import {assert, unreachable} from '../../../shared/src/asserts.ts';\nimport type {CompoundKey, System} from '../../../zero-protocol/src/ast.ts';\nimport type {Row} from '../../../zero-protocol/src/data.ts';\nimport type {Change, ChildChange} from './change.ts';\nimport type {Node} from './data.ts';\nimport {\n buildJoinConstraint,\n generateWithOverlay,\n isJoinMatch,\n rowEqualsForCompoundKey,\n type JoinChangeOverlay,\n} from './join-utils.ts';\nimport {\n throwOutput,\n type FetchRequest,\n type Input,\n type Output,\n} from './operator.ts';\nimport type {SourceSchema} from './schema.ts';\nimport {type Stream} from './stream.ts';\n\ntype Args = {\n parent: Input;\n child: Input;\n // The nth key in parentKey corresponds to the nth key in childKey.\n parentKey: CompoundKey;\n childKey: CompoundKey;\n relationshipName: string;\n hidden: boolean;\n system: System;\n};\n\n/**\n * The Join operator joins the output from two upstream inputs. Zero's join\n * is a little different from SQL's join in that we output hierarchical data,\n * not a flat table. This makes it a lot more useful for UI programming and\n * avoids duplicating tons of data like left join would.\n *\n * The Nodes output from Join have a new relationship added to them, which has\n * the name #relationshipName. The value of the relationship is a stream of\n * child nodes which are the corresponding values from the child source.\n */\nexport class Join implements Input {\n readonly #parent: Input;\n readonly #child: Input;\n readonly #parentKey: CompoundKey;\n readonly #childKey: CompoundKey;\n readonly #relationshipName: string;\n readonly #schema: SourceSchema;\n\n #output: Output = throwOutput;\n\n #inprogressChildChange: JoinChangeOverlay | undefined;\n\n constructor({\n parent,\n child,\n parentKey,\n childKey,\n relationshipName,\n hidden,\n system,\n }: Args) {\n assert(parent !== child, 'Parent and child must be different operators');\n assert(\n parentKey.length === childKey.length,\n 'The parentKey and childKey keys must have same length',\n );\n this.#parent = parent;\n this.#child = child;\n this.#parentKey = parentKey;\n this.#childKey = childKey;\n this.#relationshipName = relationshipName;\n\n const parentSchema = parent.getSchema();\n const childSchema = child.getSchema();\n this.#schema = {\n ...parentSchema,\n relationships: {\n ...parentSchema.relationships,\n [relationshipName]: {\n ...childSchema,\n isHidden: hidden,\n system,\n },\n },\n };\n\n parent.setOutput({\n push: (change: Change) => this.#pushParent(change),\n });\n child.setOutput({\n push: (change: Change) => this.#pushChild(change),\n });\n }\n\n destroy(): void {\n this.#parent.destroy();\n this.#child.destroy();\n }\n\n setOutput(output: Output): void {\n this.#output = output;\n }\n\n getSchema(): SourceSchema {\n return this.#schema;\n }\n\n *fetch(req: FetchRequest): Stream<Node | 'yield'> {\n for (const parentNode of this.#parent.fetch(req)) {\n if (parentNode === 'yield') {\n yield parentNode;\n continue;\n }\n yield this.#processParentNode(parentNode.row, parentNode.relationships);\n }\n }\n\n *#pushParent(change: Change): Stream<'yield'> {\n switch (change.type) {\n case 'add':\n yield* this.#output.push(\n {\n type: 'add',\n node: this.#processParentNode(\n change.node.row,\n change.node.relationships,\n ),\n },\n this,\n );\n break;\n case 'remove':\n yield* this.#output.push(\n {\n type: 'remove',\n node: this.#processParentNode(\n change.node.row,\n change.node.relationships,\n ),\n },\n this,\n );\n break;\n case 'child':\n yield* this.#output.push(\n {\n type: 'child',\n node: this.#processParentNode(\n change.node.row,\n change.node.relationships,\n ),\n child: change.child,\n },\n this,\n );\n break;\n case 'edit': {\n // Assert the edit could not change the relationship.\n assert(\n rowEqualsForCompoundKey(\n change.oldNode.row,\n change.node.row,\n this.#parentKey,\n ),\n `Parent edit must not change relationship.`,\n );\n yield* this.#output.push(\n {\n type: 'edit',\n oldNode: this.#processParentNode(\n change.oldNode.row,\n change.oldNode.relationships,\n ),\n node: this.#processParentNode(\n change.node.row,\n change.node.relationships,\n ),\n },\n this,\n );\n break;\n }\n default:\n unreachable(change);\n }\n }\n\n *#pushChild(change: Change): Stream<'yield'> {\n switch (change.type) {\n case 'add':\n case 'remove':\n yield* this.#pushChildChange(change.node.row, change);\n break;\n case 'child':\n yield* this.#pushChildChange(change.node.row, change);\n break;\n case 'edit': {\n const childRow = change.node.row;\n const oldChildRow = change.oldNode.row;\n // Assert the edit could not change the relationship.\n assert(\n rowEqualsForCompoundKey(oldChildRow, childRow, this.#childKey),\n 'Child edit must not change relationship.',\n );\n yield* this.#pushChildChange(childRow, change);\n break;\n }\n\n default:\n unreachable(change);\n }\n }\n\n *#pushChildChange(childRow: Row, change: Change): Stream<'yield'> {\n this.#inprogressChildChange = {\n change,\n position: undefined,\n };\n try {\n const constraint = buildJoinConstraint(\n childRow,\n this.#childKey,\n this.#parentKey,\n );\n const parentNodes = constraint ? this.#parent.fetch({constraint}) : [];\n\n for (const parentNode of parentNodes) {\n if (parentNode === 'yield') {\n yield parentNode;\n continue;\n }\n this.#inprogressChildChange.position = parentNode.row;\n const childChange: ChildChange = {\n type: 'child',\n node: this.#processParentNode(\n parentNode.row,\n parentNode.relationships,\n ),\n child: {\n relationshipName: this.#relationshipName,\n change,\n },\n };\n yield* this.#output.push(childChange, this);\n }\n } finally {\n this.#inprogressChildChange = undefined;\n }\n }\n\n #processParentNode(\n parentNodeRow: Row,\n parentNodeRelations: Record<string, () => Stream<Node | 'yield'>>,\n ): Node {\n const childStream = () => {\n const constraint = buildJoinConstraint(\n parentNodeRow,\n this.#parentKey,\n this.#childKey,\n );\n const stream = constraint ? this.#child.fetch({constraint}) : [];\n\n if (\n this.#inprogressChildChange &&\n isJoinMatch(\n parentNodeRow,\n this.#parentKey,\n this.#inprogressChildChange.change.node.row,\n this.#childKey,\n ) &&\n this.#inprogressChildChange.position &&\n this.#schema.compareRows(\n parentNodeRow,\n this.#inprogressChildChange.position,\n ) > 0\n ) {\n return generateWithOverlay(\n stream,\n this.#inprogressChildChange.change,\n this.#child.getSchema(),\n );\n }\n return stream;\n };\n\n return {\n row: parentNodeRow,\n relationships: {\n ...parentNodeRelations,\n [this.#relationshipName]: childStream,\n },\n };\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"join.js","names":["#parent","#child","#parentKey","#childKey","#relationshipName","#schema","#pushParent","#pushChild","#output","#processParentNode","#pushChildChange","#inprogressChildChange"],"sources":["../../../../../zql/src/ivm/join.ts"],"sourcesContent":["import {assert, unreachable} from '../../../shared/src/asserts.ts';\nimport type {CompoundKey, System} from '../../../zero-protocol/src/ast.ts';\nimport type {Row} from '../../../zero-protocol/src/data.ts';\nimport type {Change, ChildChange} from './change.ts';\nimport type {Node} from './data.ts';\nimport {\n buildJoinConstraint,\n generateWithOverlay,\n generateWithOverlayUnordered,\n isJoinMatch,\n rowEqualsForCompoundKey,\n type JoinChangeOverlay,\n} from './join-utils.ts';\nimport {\n throwOutput,\n type FetchRequest,\n type Input,\n type Output,\n} from './operator.ts';\nimport type {SourceSchema} from './schema.ts';\nimport {type Stream} from './stream.ts';\n\ntype Args = {\n parent: Input;\n child: Input;\n // The nth key in parentKey corresponds to the nth key in childKey.\n parentKey: CompoundKey;\n childKey: CompoundKey;\n relationshipName: string;\n hidden: boolean;\n system: System;\n};\n\n/**\n * The Join operator joins the output from two upstream inputs. Zero's join\n * is a little different from SQL's join in that we output hierarchical data,\n * not a flat table. This makes it a lot more useful for UI programming and\n * avoids duplicating tons of data like left join would.\n *\n * The Nodes output from Join have a new relationship added to them, which has\n * the name #relationshipName. The value of the relationship is a stream of\n * child nodes which are the corresponding values from the child source.\n */\nexport class Join implements Input {\n readonly #parent: Input;\n readonly #child: Input;\n readonly #parentKey: CompoundKey;\n readonly #childKey: CompoundKey;\n readonly #relationshipName: string;\n readonly #schema: SourceSchema;\n\n #output: Output = throwOutput;\n\n #inprogressChildChange: JoinChangeOverlay | undefined;\n\n constructor({\n parent,\n child,\n parentKey,\n childKey,\n relationshipName,\n hidden,\n system,\n }: Args) {\n assert(parent !== child, 'Parent and child must be different operators');\n assert(\n parentKey.length === childKey.length,\n 'The parentKey and childKey keys must have same length',\n );\n this.#parent = parent;\n this.#child = child;\n this.#parentKey = parentKey;\n this.#childKey = childKey;\n this.#relationshipName = relationshipName;\n\n const parentSchema = parent.getSchema();\n const childSchema = child.getSchema();\n this.#schema = {\n ...parentSchema,\n relationships: {\n ...parentSchema.relationships,\n [relationshipName]: {\n ...childSchema,\n isHidden: hidden,\n system,\n },\n },\n };\n\n parent.setOutput({\n push: (change: Change) => this.#pushParent(change),\n });\n child.setOutput({\n push: (change: Change) => this.#pushChild(change),\n });\n }\n\n destroy(): void {\n this.#parent.destroy();\n this.#child.destroy();\n }\n\n setOutput(output: Output): void {\n this.#output = output;\n }\n\n getSchema(): SourceSchema {\n return this.#schema;\n }\n\n *fetch(req: FetchRequest): Stream<Node | 'yield'> {\n for (const parentNode of this.#parent.fetch(req)) {\n if (parentNode === 'yield') {\n yield parentNode;\n continue;\n }\n yield this.#processParentNode(parentNode.row, parentNode.relationships);\n }\n }\n\n *#pushParent(change: Change): Stream<'yield'> {\n switch (change.type) {\n case 'add':\n yield* this.#output.push(\n {\n type: 'add',\n node: this.#processParentNode(\n change.node.row,\n change.node.relationships,\n ),\n },\n this,\n );\n break;\n case 'remove':\n yield* this.#output.push(\n {\n type: 'remove',\n node: this.#processParentNode(\n change.node.row,\n change.node.relationships,\n ),\n },\n this,\n );\n break;\n case 'child':\n yield* this.#output.push(\n {\n type: 'child',\n node: this.#processParentNode(\n change.node.row,\n change.node.relationships,\n ),\n child: change.child,\n },\n this,\n );\n break;\n case 'edit': {\n // Assert the edit could not change the relationship.\n assert(\n rowEqualsForCompoundKey(\n change.oldNode.row,\n change.node.row,\n this.#parentKey,\n ),\n `Parent edit must not change relationship.`,\n );\n yield* this.#output.push(\n {\n type: 'edit',\n oldNode: this.#processParentNode(\n change.oldNode.row,\n change.oldNode.relationships,\n ),\n node: this.#processParentNode(\n change.node.row,\n change.node.relationships,\n ),\n },\n this,\n );\n break;\n }\n default:\n unreachable(change);\n }\n }\n\n *#pushChild(change: Change): Stream<'yield'> {\n switch (change.type) {\n case 'add':\n case 'remove':\n yield* this.#pushChildChange(change.node.row, change);\n break;\n case 'child':\n yield* this.#pushChildChange(change.node.row, change);\n break;\n case 'edit': {\n const childRow = change.node.row;\n const oldChildRow = change.oldNode.row;\n // Assert the edit could not change the relationship.\n assert(\n rowEqualsForCompoundKey(oldChildRow, childRow, this.#childKey),\n 'Child edit must not change relationship.',\n );\n yield* this.#pushChildChange(childRow, change);\n break;\n }\n\n default:\n unreachable(change);\n }\n }\n\n *#pushChildChange(childRow: Row, change: Change): Stream<'yield'> {\n this.#inprogressChildChange = {\n change,\n position: undefined,\n };\n try {\n const constraint = buildJoinConstraint(\n childRow,\n this.#childKey,\n this.#parentKey,\n );\n const parentNodes = constraint ? this.#parent.fetch({constraint}) : [];\n\n for (const parentNode of parentNodes) {\n if (parentNode === 'yield') {\n yield parentNode;\n continue;\n }\n this.#inprogressChildChange.position = parentNode.row;\n const childChange: ChildChange = {\n type: 'child',\n node: this.#processParentNode(\n parentNode.row,\n parentNode.relationships,\n ),\n child: {\n relationshipName: this.#relationshipName,\n change,\n },\n };\n yield* this.#output.push(childChange, this);\n }\n } finally {\n this.#inprogressChildChange = undefined;\n }\n }\n\n #processParentNode(\n parentNodeRow: Row,\n parentNodeRelations: Record<string, () => Stream<Node | 'yield'>>,\n ): Node {\n const childStream = () => {\n const constraint = buildJoinConstraint(\n parentNodeRow,\n this.#parentKey,\n this.#childKey,\n );\n const stream = constraint ? this.#child.fetch({constraint}) : [];\n\n if (\n this.#inprogressChildChange &&\n isJoinMatch(\n parentNodeRow,\n this.#parentKey,\n this.#inprogressChildChange.change.node.row,\n this.#childKey,\n ) &&\n this.#inprogressChildChange.position &&\n this.#schema.compareRows(\n parentNodeRow,\n this.#inprogressChildChange.position,\n ) > 0\n ) {\n const childSchema = this.#child.getSchema();\n if (childSchema.sort === undefined) {\n return generateWithOverlayUnordered(\n stream,\n this.#inprogressChildChange.change,\n childSchema,\n );\n }\n return generateWithOverlay(\n stream,\n this.#inprogressChildChange.change,\n childSchema,\n );\n }\n return stream;\n };\n\n return {\n row: parentNodeRow,\n relationships: {\n ...parentNodeRelations,\n [this.#relationshipName]: childStream,\n },\n };\n }\n}\n"],"mappings":";;;;;;;;;;;;;;AA2CA,IAAa,OAAb,MAAmC;CACjC;CACA;CACA;CACA;CACA;CACA;CAEA,UAAkB;CAElB;CAEA,YAAY,EACV,QACA,OACA,WACA,UACA,kBACA,QACA,UACO;AACP,SAAO,WAAW,OAAO,+CAA+C;AACxE,SACE,UAAU,WAAW,SAAS,QAC9B,wDACD;AACD,QAAA,SAAe;AACf,QAAA,QAAc;AACd,QAAA,YAAkB;AAClB,QAAA,WAAiB;AACjB,QAAA,mBAAyB;EAEzB,MAAM,eAAe,OAAO,WAAW;EACvC,MAAM,cAAc,MAAM,WAAW;AACrC,QAAA,SAAe;GACb,GAAG;GACH,eAAe;IACb,GAAG,aAAa;KACf,mBAAmB;KAClB,GAAG;KACH,UAAU;KACV;KACD;IACF;GACF;AAED,SAAO,UAAU,EACf,OAAO,WAAmB,MAAA,WAAiB,OAAO,EACnD,CAAC;AACF,QAAM,UAAU,EACd,OAAO,WAAmB,MAAA,UAAgB,OAAO,EAClD,CAAC;;CAGJ,UAAgB;AACd,QAAA,OAAa,SAAS;AACtB,QAAA,MAAY,SAAS;;CAGvB,UAAU,QAAsB;AAC9B,QAAA,SAAe;;CAGjB,YAA0B;AACxB,SAAO,MAAA;;CAGT,CAAC,MAAM,KAA2C;AAChD,OAAK,MAAM,cAAc,MAAA,OAAa,MAAM,IAAI,EAAE;AAChD,OAAI,eAAe,SAAS;AAC1B,UAAM;AACN;;AAEF,SAAM,MAAA,kBAAwB,WAAW,KAAK,WAAW,cAAc;;;CAI3E,EAAA,WAAa,QAAiC;AAC5C,UAAQ,OAAO,MAAf;GACE,KAAK;AACH,WAAO,MAAA,OAAa,KAClB;KACE,MAAM;KACN,MAAM,MAAA,kBACJ,OAAO,KAAK,KACZ,OAAO,KAAK,cACb;KACF,EACD,KACD;AACD;GACF,KAAK;AACH,WAAO,MAAA,OAAa,KAClB;KACE,MAAM;KACN,MAAM,MAAA,kBACJ,OAAO,KAAK,KACZ,OAAO,KAAK,cACb;KACF,EACD,KACD;AACD;GACF,KAAK;AACH,WAAO,MAAA,OAAa,KAClB;KACE,MAAM;KACN,MAAM,MAAA,kBACJ,OAAO,KAAK,KACZ,OAAO,KAAK,cACb;KACD,OAAO,OAAO;KACf,EACD,KACD;AACD;GACF,KAAK;AAEH,WACE,wBACE,OAAO,QAAQ,KACf,OAAO,KAAK,KACZ,MAAA,UACD,EACD,4CACD;AACD,WAAO,MAAA,OAAa,KAClB;KACE,MAAM;KACN,SAAS,MAAA,kBACP,OAAO,QAAQ,KACf,OAAO,QAAQ,cAChB;KACD,MAAM,MAAA,kBACJ,OAAO,KAAK,KACZ,OAAO,KAAK,cACb;KACF,EACD,KACD;AACD;GAEF,QACE,aAAY,OAAO;;;CAIzB,EAAA,UAAY,QAAiC;AAC3C,UAAQ,OAAO,MAAf;GACE,KAAK;GACL,KAAK;AACH,WAAO,MAAA,gBAAsB,OAAO,KAAK,KAAK,OAAO;AACrD;GACF,KAAK;AACH,WAAO,MAAA,gBAAsB,OAAO,KAAK,KAAK,OAAO;AACrD;GACF,KAAK,QAAQ;IACX,MAAM,WAAW,OAAO,KAAK;IAC7B,MAAM,cAAc,OAAO,QAAQ;AAEnC,WACE,wBAAwB,aAAa,UAAU,MAAA,SAAe,EAC9D,2CACD;AACD,WAAO,MAAA,gBAAsB,UAAU,OAAO;AAC9C;;GAGF,QACE,aAAY,OAAO;;;CAIzB,EAAA,gBAAkB,UAAe,QAAiC;AAChE,QAAA,wBAA8B;GAC5B;GACA,UAAU,KAAA;GACX;AACD,MAAI;GACF,MAAM,aAAa,oBACjB,UACA,MAAA,UACA,MAAA,UACD;GACD,MAAM,cAAc,aAAa,MAAA,OAAa,MAAM,EAAC,YAAW,CAAC,GAAG,EAAE;AAEtE,QAAK,MAAM,cAAc,aAAa;AACpC,QAAI,eAAe,SAAS;AAC1B,WAAM;AACN;;AAEF,UAAA,sBAA4B,WAAW,WAAW;IAClD,MAAM,cAA2B;KAC/B,MAAM;KACN,MAAM,MAAA,kBACJ,WAAW,KACX,WAAW,cACZ;KACD,OAAO;MACL,kBAAkB,MAAA;MAClB;MACD;KACF;AACD,WAAO,MAAA,OAAa,KAAK,aAAa,KAAK;;YAErC;AACR,SAAA,wBAA8B,KAAA;;;CAIlC,mBACE,eACA,qBACM;EACN,MAAM,oBAAoB;GACxB,MAAM,aAAa,oBACjB,eACA,MAAA,WACA,MAAA,SACD;GACD,MAAM,SAAS,aAAa,MAAA,MAAY,MAAM,EAAC,YAAW,CAAC,GAAG,EAAE;AAEhE,OACE,MAAA,yBACA,YACE,eACA,MAAA,WACA,MAAA,sBAA4B,OAAO,KAAK,KACxC,MAAA,SACD,IACD,MAAA,sBAA4B,YAC5B,MAAA,OAAa,YACX,eACA,MAAA,sBAA4B,SAC7B,GAAG,GACJ;IACA,MAAM,cAAc,MAAA,MAAY,WAAW;AAC3C,QAAI,YAAY,SAAS,KAAA,EACvB,QAAO,6BACL,QACA,MAAA,sBAA4B,QAC5B,YACD;AAEH,WAAO,oBACL,QACA,MAAA,sBAA4B,QAC5B,YACD;;AAEH,UAAO;;AAGT,SAAO;GACL,KAAK;GACL,eAAe;IACb,GAAG;KACF,MAAA,mBAAyB;IAC3B;GACF"}
|
|
@@ -21,7 +21,7 @@ export type Overlays = {
|
|
|
21
21
|
export type Connection = {
|
|
22
22
|
input: Input;
|
|
23
23
|
output: Output | undefined;
|
|
24
|
-
sort
|
|
24
|
+
sort?: Ordering | undefined;
|
|
25
25
|
splitEditKeys: Set<string> | undefined;
|
|
26
26
|
compareRows: Comparator;
|
|
27
27
|
filters: {
|
|
@@ -48,7 +48,7 @@ export declare class MemorySource implements Source {
|
|
|
48
48
|
};
|
|
49
49
|
fork(): MemorySource;
|
|
50
50
|
get data(): BTreeSet<Row>;
|
|
51
|
-
connect(sort: Ordering, filters?: Condition, splitEditKeys?: Set<string>): SourceInput;
|
|
51
|
+
connect(sort: Ordering | undefined, filters?: Condition, splitEditKeys?: Set<string>): SourceInput;
|
|
52
52
|
getIndexKeys(): string[];
|
|
53
53
|
push(change: SourceChange): Stream<'yield'>;
|
|
54
54
|
genPush(change: SourceChange): Generator<"yield" | undefined, void, unknown>;
|
|
@@ -79,5 +79,18 @@ export declare function generateWithOverlayInner(rowIterator: Iterable<Row>, ove
|
|
|
79
79
|
row: Readonly<Record<string, import("../../../shared/src/json.ts").ReadonlyJSONValue | undefined>>;
|
|
80
80
|
relationships: {};
|
|
81
81
|
}, void, unknown>;
|
|
82
|
+
/**
|
|
83
|
+
* Like {@link generateWithOverlay} but for unordered streams.
|
|
84
|
+
* No `startAt` or comparator needed. Injects remove/old-edit rows eagerly
|
|
85
|
+
* at the start, and suppresses add/new-edit rows inline by PK match.
|
|
86
|
+
*/
|
|
87
|
+
export declare function generateWithOverlayUnordered(rows: Iterable<Row>, constraint: Constraint | undefined, overlay: Overlay | undefined, lastPushedEpoch: number, primaryKey: PrimaryKey, filterPredicate?: ((row: Row) => boolean) | undefined): Generator<{
|
|
88
|
+
row: Readonly<Record<string, import("../../../shared/src/json.ts").ReadonlyJSONValue | undefined>>;
|
|
89
|
+
relationships: {};
|
|
90
|
+
}, void, unknown>;
|
|
91
|
+
export declare function generateWithOverlayInnerUnordered(rowIterator: Iterable<Row>, overlays: Overlays, primaryKey: PrimaryKey): Generator<{
|
|
92
|
+
row: Readonly<Record<string, import("../../../shared/src/json.ts").ReadonlyJSONValue | undefined>>;
|
|
93
|
+
relationships: {};
|
|
94
|
+
}, void, unknown>;
|
|
82
95
|
export declare function stringify(change: SourceChange): string;
|
|
83
96
|
//# sourceMappingURL=memory-source.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"memory-source.d.ts","sourceRoot":"","sources":["../../../../../zql/src/ivm/memory-source.ts"],"names":[],"mappings":"AACA,OAAO,EAAC,QAAQ,EAAC,MAAM,kCAAkC,CAAC;
|
|
1
|
+
{"version":3,"file":"memory-source.d.ts","sourceRoot":"","sources":["../../../../../zql/src/ivm/memory-source.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { assert, unreachable } from "../../../shared/src/asserts.js";
|
|
2
2
|
import { hasOwn } from "../../../shared/src/has-own.js";
|
|
3
3
|
import { once } from "../../../shared/src/iterables.js";
|
|
4
|
+
import { must } from "../../../shared/src/must.js";
|
|
4
5
|
import { skipYields } from "./operator.js";
|
|
5
6
|
import { compareValues, makeComparator, valuesEqual } from "./data.js";
|
|
6
7
|
import { filterPush } from "./filter-push.js";
|
|
@@ -51,12 +52,12 @@ var MemorySource = class MemorySource {
|
|
|
51
52
|
get data() {
|
|
52
53
|
return this.#getPrimaryIndex().data;
|
|
53
54
|
}
|
|
54
|
-
#getSchema(connection) {
|
|
55
|
+
#getSchema(connection, unordered) {
|
|
55
56
|
return {
|
|
56
57
|
tableName: this.#tableName,
|
|
57
58
|
columns: this.#columns,
|
|
58
59
|
primaryKey: this.#primaryKey,
|
|
59
|
-
sort: connection.sort,
|
|
60
|
+
sort: unordered ? void 0 : connection.sort,
|
|
60
61
|
system: "client",
|
|
61
62
|
relationships: {},
|
|
62
63
|
isHidden: false,
|
|
@@ -65,6 +66,8 @@ var MemorySource = class MemorySource {
|
|
|
65
66
|
}
|
|
66
67
|
connect(sort, filters, splitEditKeys) {
|
|
67
68
|
const transformedFilters = transformFilters(filters);
|
|
69
|
+
const unordered = sort === void 0;
|
|
70
|
+
const internalSort = sort ?? this.#primaryIndexSort;
|
|
68
71
|
const input = {
|
|
69
72
|
getSchema: () => schema,
|
|
70
73
|
fetch: (req) => this.#fetch(req, connection),
|
|
@@ -79,17 +82,17 @@ var MemorySource = class MemorySource {
|
|
|
79
82
|
const connection = {
|
|
80
83
|
input,
|
|
81
84
|
output: void 0,
|
|
82
|
-
sort,
|
|
85
|
+
sort: internalSort,
|
|
83
86
|
splitEditKeys,
|
|
84
|
-
compareRows: makeComparator(
|
|
87
|
+
compareRows: makeComparator(internalSort),
|
|
85
88
|
filters: transformedFilters.filters ? {
|
|
86
89
|
condition: transformedFilters.filters,
|
|
87
90
|
predicate: createPredicate(transformedFilters.filters)
|
|
88
91
|
} : void 0,
|
|
89
92
|
lastPushedEpoch: 0
|
|
90
93
|
};
|
|
91
|
-
const schema = this.#getSchema(connection);
|
|
92
|
-
assertOrderingIncludesPK(
|
|
94
|
+
const schema = this.#getSchema(connection, unordered);
|
|
95
|
+
if (!unordered) assertOrderingIncludesPK(internalSort, this.#primaryKey);
|
|
93
96
|
this.#connections.push(connection);
|
|
94
97
|
return input;
|
|
95
98
|
}
|
|
@@ -125,7 +128,8 @@ var MemorySource = class MemorySource {
|
|
|
125
128
|
return [...this.#indexes.keys()];
|
|
126
129
|
}
|
|
127
130
|
*#fetch(req, conn) {
|
|
128
|
-
const
|
|
131
|
+
const requestedSort = must(conn.sort);
|
|
132
|
+
const { compareRows } = conn;
|
|
129
133
|
const connectionComparator = (r1, r2) => compareRows(r1, r2) * (req.reverse ? -1 : 1);
|
|
130
134
|
const pkConstraint = primaryKeyConstraintFromFilters(conn.filters?.condition, this.#primaryKey);
|
|
131
135
|
const fetchOrPkConstraint = pkConstraint ?? req.constraint;
|
|
@@ -367,6 +371,63 @@ function* generateWithOverlayInner(rowIterator, overlays, compare) {
|
|
|
367
371
|
relationships: {}
|
|
368
372
|
};
|
|
369
373
|
}
|
|
374
|
+
/**
|
|
375
|
+
* Like {@link generateWithOverlay} but for unordered streams.
|
|
376
|
+
* No `startAt` or comparator needed. Injects remove/old-edit rows eagerly
|
|
377
|
+
* at the start, and suppresses add/new-edit rows inline by PK match.
|
|
378
|
+
*/
|
|
379
|
+
function* generateWithOverlayUnordered(rows, constraint, overlay, lastPushedEpoch, primaryKey, filterPredicate) {
|
|
380
|
+
let overlayToApply = void 0;
|
|
381
|
+
if (overlay && lastPushedEpoch >= overlay.epoch) overlayToApply = overlay;
|
|
382
|
+
let overlays = {
|
|
383
|
+
add: void 0,
|
|
384
|
+
remove: void 0
|
|
385
|
+
};
|
|
386
|
+
switch (overlayToApply?.change.type) {
|
|
387
|
+
case "add":
|
|
388
|
+
overlays = {
|
|
389
|
+
add: overlayToApply.change.row,
|
|
390
|
+
remove: void 0
|
|
391
|
+
};
|
|
392
|
+
break;
|
|
393
|
+
case "remove":
|
|
394
|
+
overlays = {
|
|
395
|
+
add: void 0,
|
|
396
|
+
remove: overlayToApply.change.row
|
|
397
|
+
};
|
|
398
|
+
break;
|
|
399
|
+
case "edit":
|
|
400
|
+
overlays = {
|
|
401
|
+
add: overlayToApply.change.row,
|
|
402
|
+
remove: overlayToApply.change.oldRow
|
|
403
|
+
};
|
|
404
|
+
break;
|
|
405
|
+
}
|
|
406
|
+
if (constraint) overlays = overlaysForConstraint(overlays, constraint);
|
|
407
|
+
if (filterPredicate) overlays = overlaysForFilterPredicate(overlays, filterPredicate);
|
|
408
|
+
yield* generateWithOverlayInnerUnordered(rows, overlays, primaryKey);
|
|
409
|
+
}
|
|
410
|
+
function* generateWithOverlayInnerUnordered(rowIterator, overlays, primaryKey) {
|
|
411
|
+
if (overlays.add) yield {
|
|
412
|
+
row: overlays.add,
|
|
413
|
+
relationships: {}
|
|
414
|
+
};
|
|
415
|
+
let removeSkipped = false;
|
|
416
|
+
for (const row of rowIterator) {
|
|
417
|
+
if (!removeSkipped && overlays.remove && rowMatchesPK(overlays.remove, row, primaryKey)) {
|
|
418
|
+
removeSkipped = true;
|
|
419
|
+
continue;
|
|
420
|
+
}
|
|
421
|
+
yield {
|
|
422
|
+
row,
|
|
423
|
+
relationships: {}
|
|
424
|
+
};
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
function rowMatchesPK(a, b, primaryKey) {
|
|
428
|
+
for (const key of primaryKey) if (!valuesEqual(a[key], b[key])) return false;
|
|
429
|
+
return true;
|
|
430
|
+
}
|
|
370
431
|
var minValue = Symbol("min-value");
|
|
371
432
|
var maxValue = Symbol("max-value");
|
|
372
433
|
function makeBoundComparator(sort) {
|
|
@@ -394,6 +455,6 @@ function stringify(change) {
|
|
|
394
455
|
return JSON.stringify(change, (_, v) => typeof v === "bigint" ? v.toString() : v);
|
|
395
456
|
}
|
|
396
457
|
//#endregion
|
|
397
|
-
export { MemorySource, genPushAndWriteWithSplitEdit, generateWithOverlay, generateWithStart };
|
|
458
|
+
export { MemorySource, genPushAndWriteWithSplitEdit, generateWithOverlay, generateWithOverlayUnordered, generateWithStart };
|
|
398
459
|
|
|
399
460
|
//# sourceMappingURL=memory-source.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"memory-source.js","names":["#tableName","#columns","#primaryKey","#primaryIndexSort","#indexes","#connections","#getPrimaryIndex","#fetch","#disconnect","#getSchema","#getOrCreateIndex","#overlay","#writeChange","#pushEpoch"],"sources":["../../../../../zql/src/ivm/memory-source.ts"],"sourcesContent":["import {assert, unreachable} from '../../../shared/src/asserts.ts';\nimport {BTreeSet} from '../../../shared/src/btree-set.ts';\nimport {hasOwn} from '../../../shared/src/has-own.ts';\nimport {once} from '../../../shared/src/iterables.ts';\nimport type {\n Condition,\n Ordering,\n OrderPart,\n} from '../../../zero-protocol/src/ast.ts';\nimport type {Row, Value} from '../../../zero-protocol/src/data.ts';\nimport type {PrimaryKey} from '../../../zero-protocol/src/primary-key.ts';\nimport type {SchemaValue} from '../../../zero-types/src/schema-value.ts';\nimport type {DebugDelegate} from '../builder/debug-delegate.ts';\nimport {\n createPredicate,\n transformFilters,\n type NoSubqueryCondition,\n} from '../builder/filter.ts';\nimport {assertOrderingIncludesPK} from '../query/complete-ordering.ts';\nimport type {Change} from './change.ts';\nimport {\n constraintMatchesPrimaryKey,\n constraintMatchesRow,\n primaryKeyConstraintFromFilters,\n type Constraint,\n} from './constraint.ts';\nimport {\n compareValues,\n makeComparator,\n valuesEqual,\n type Comparator,\n type Node,\n} from './data.ts';\nimport {filterPush} from './filter-push.ts';\nimport {\n skipYields,\n type FetchRequest,\n type Input,\n type Output,\n type Start,\n} from './operator.ts';\nimport type {SourceSchema} from './schema.ts';\nimport type {\n Source,\n SourceChange,\n SourceChangeAdd,\n SourceChangeEdit,\n SourceChangeRemove,\n SourceInput,\n} from './source.ts';\nimport type {Stream} from './stream.ts';\n\nexport type Overlay = {\n epoch: number;\n change: SourceChange;\n};\n\nexport type Overlays = {\n add: Row | undefined;\n remove: Row | undefined;\n};\n\ntype Index = {\n comparator: Comparator;\n data: BTreeSet<Row>;\n usedBy: Set<Connection>;\n};\n\nexport type Connection = {\n input: Input;\n output: Output | undefined;\n sort: Ordering;\n splitEditKeys: Set<string> | undefined;\n compareRows: Comparator;\n filters:\n | {\n condition: NoSubqueryCondition;\n predicate: (row: Row) => boolean;\n }\n | undefined;\n readonly debug?: DebugDelegate | undefined;\n lastPushedEpoch: number;\n};\n\n/**\n * A `MemorySource` is a source that provides data to the pipeline from an\n * in-memory data source.\n *\n * This data is kept in sorted order as downstream pipelines will always expect\n * the data they receive from `pull` to be in sorted order.\n */\nexport class MemorySource implements Source {\n readonly #tableName: string;\n readonly #columns: Record<string, SchemaValue>;\n readonly #primaryKey: PrimaryKey;\n readonly #primaryIndexSort: Ordering;\n readonly #indexes: Map<string, Index> = new Map();\n readonly #connections: Connection[] = [];\n\n #overlay: Overlay | undefined;\n #pushEpoch = 0;\n\n constructor(\n tableName: string,\n columns: Record<string, SchemaValue>,\n primaryKey: PrimaryKey,\n primaryIndexData?: BTreeSet<Row>,\n ) {\n this.#tableName = tableName;\n this.#columns = columns;\n this.#primaryKey = primaryKey;\n this.#primaryIndexSort = primaryKey.map(k => [k, 'asc']);\n const comparator = makeBoundComparator(this.#primaryIndexSort);\n this.#indexes.set(JSON.stringify(this.#primaryIndexSort), {\n comparator,\n data: primaryIndexData ?? new BTreeSet<Row>(comparator),\n usedBy: new Set(),\n });\n }\n\n get tableSchema() {\n return {\n name: this.#tableName,\n columns: this.#columns,\n primaryKey: this.#primaryKey,\n };\n }\n\n fork() {\n const primaryIndex = this.#getPrimaryIndex();\n return new MemorySource(\n this.#tableName,\n this.#columns,\n this.#primaryKey,\n primaryIndex.data.clone(),\n );\n }\n\n get data(): BTreeSet<Row> {\n return this.#getPrimaryIndex().data;\n }\n\n #getSchema(connection: Connection): SourceSchema {\n return {\n tableName: this.#tableName,\n columns: this.#columns,\n primaryKey: this.#primaryKey,\n sort: connection.sort,\n system: 'client',\n relationships: {},\n isHidden: false,\n compareRows: connection.compareRows,\n };\n }\n\n connect(\n sort: Ordering,\n filters?: Condition,\n splitEditKeys?: Set<string>,\n ): SourceInput {\n const transformedFilters = transformFilters(filters);\n\n const input: SourceInput = {\n getSchema: () => schema,\n fetch: req => this.#fetch(req, connection),\n setOutput: output => {\n connection.output = output;\n },\n destroy: () => {\n this.#disconnect(input);\n },\n fullyAppliedFilters: !transformedFilters.conditionsRemoved,\n };\n\n const connection: Connection = {\n input,\n output: undefined,\n sort,\n splitEditKeys,\n compareRows: makeComparator(sort),\n filters: transformedFilters.filters\n ? {\n condition: transformedFilters.filters,\n predicate: createPredicate(transformedFilters.filters),\n }\n : undefined,\n lastPushedEpoch: 0,\n };\n const schema = this.#getSchema(connection);\n assertOrderingIncludesPK(sort, this.#primaryKey);\n this.#connections.push(connection);\n return input;\n }\n\n #disconnect(input: Input): void {\n const idx = this.#connections.findIndex(c => c.input === input);\n assert(idx !== -1, 'Connection not found');\n this.#connections.splice(idx, 1);\n\n // TODO: We used to delete unused indexes here. But in common cases like\n // navigating into issue detail pages it caused a ton of constantly\n // building and destroying indexes.\n //\n // Perhaps some intelligent LRU or something is needed here but for now,\n // the opposite extreme of keeping all indexes for the lifetime of the\n // page seems better.\n }\n\n #getPrimaryIndex(): Index {\n const index = this.#indexes.get(JSON.stringify(this.#primaryIndexSort));\n assert(index, 'Primary index not found');\n return index;\n }\n\n #getOrCreateIndex(sort: Ordering, usedBy: Connection): Index {\n const key = JSON.stringify(sort);\n const index = this.#indexes.get(key);\n // Future optimization could use existing index if it's the same just sorted\n // in reverse of needed.\n if (index) {\n index.usedBy.add(usedBy);\n return index;\n }\n\n const comparator = makeBoundComparator(sort);\n\n // When creating these synchronously becomes a problem, a few options:\n // 1. Allow users to specify needed indexes up front\n // 2. Create indexes in a different thread asynchronously (this would require\n // modifying the BTree to be able to be passed over structured-clone, or using\n // a different library.)\n // 3. We could even theoretically do (2) on multiple threads and then merge the\n // results!\n const data = new BTreeSet<Row>(comparator);\n\n // I checked, there's no special path for adding data in bulk faster.\n // The constructor takes an array, but it just calls add/set over and over.\n for (const row of this.#getPrimaryIndex().data) {\n data.add(row);\n }\n\n const newIndex = {comparator, data, usedBy: new Set([usedBy])};\n this.#indexes.set(key, newIndex);\n return newIndex;\n }\n\n // For unit testing that we correctly clean up indexes.\n getIndexKeys(): string[] {\n return [...this.#indexes.keys()];\n }\n\n *#fetch(req: FetchRequest, conn: Connection): Stream<Node | 'yield'> {\n const {sort: requestedSort, compareRows} = conn;\n const connectionComparator = (r1: Row, r2: Row) =>\n compareRows(r1, r2) * (req.reverse ? -1 : 1);\n\n const pkConstraint = primaryKeyConstraintFromFilters(\n conn.filters?.condition,\n this.#primaryKey,\n );\n // The primary key constraint will be more limiting than the constraint\n // so swap out to that if it exists.\n const fetchOrPkConstraint = pkConstraint ?? req.constraint;\n\n // If there is a constraint, we need an index sorted by it first.\n const indexSort: OrderPart[] = [];\n if (fetchOrPkConstraint) {\n for (const key of Object.keys(fetchOrPkConstraint)) {\n indexSort.push([key, 'asc']);\n }\n }\n\n // For the special case of constraining by PK, we don't need to worry about\n // any requested sort since there can only be one result. Otherwise we also\n // need the index sorted by the requested sort.\n if (\n this.#primaryKey.length > 1 ||\n !fetchOrPkConstraint ||\n !constraintMatchesPrimaryKey(fetchOrPkConstraint, this.#primaryKey)\n ) {\n indexSort.push(...requestedSort);\n }\n\n const index = this.#getOrCreateIndex(indexSort, conn);\n const {data, comparator: compare} = index;\n const indexComparator = (r1: Row, r2: Row) =>\n compare(r1, r2) * (req.reverse ? -1 : 1);\n\n const startAt = req.start?.row;\n\n // If there is a constraint, we want to start our scan at the first row that\n // matches the constraint. But because the next OrderPart can be `desc`,\n // it's not true that {[constraintKey]: constraintValue} is the first\n // matching row. Because in that case, the other fields will all be\n // `undefined`, and in Zero `undefined` is always less than any other value.\n // So if the second OrderPart is descending then `undefined` values will\n // actually be the *last* row. We need a way to stay \"start at the first row\n // with this constraint value\". RowBound with the corresponding compareBound\n // comparator accomplishes this. The right thing is probably to teach the\n // btree library to support this concept.\n let scanStart: RowBound | undefined;\n\n if (fetchOrPkConstraint) {\n scanStart = {};\n for (const [key, dir] of indexSort) {\n if (hasOwn(fetchOrPkConstraint, key)) {\n scanStart[key] = fetchOrPkConstraint[key];\n } else {\n if (req.reverse) {\n scanStart[key] = dir === 'asc' ? maxValue : minValue;\n } else {\n scanStart[key] = dir === 'asc' ? minValue : maxValue;\n }\n }\n }\n } else {\n scanStart = startAt;\n }\n\n const rowsIterable = generateRows(data, scanStart, req.reverse);\n const withOverlay = generateWithOverlay(\n startAt,\n pkConstraint ? once(rowsIterable) : rowsIterable,\n // use `req.constraint` here and not `fetchOrPkConstraint` since `fetchOrPkConstraint` could be the\n // primary key constraint. The primary key constraint comes from filters and is acting as a filter\n // rather than as the fetch constraint.\n req.constraint,\n this.#overlay,\n conn.lastPushedEpoch,\n // Use indexComparator, generateWithOverlayInner has a subtle dependency\n // on this. Since generateWithConstraint is done after\n // generateWithOverlay, the generator consumed by generateWithOverlayInner\n // does not end when the constraint stops matching and so the final\n // check to yield an add overlay if not yet yielded is not reached.\n // However, using the indexComparator the add overlay will be less than\n // the first row that does not match the constraint, and so any\n // not yet yielded add overlay will be yielded when the first row\n // not matching the constraint is reached.\n indexComparator,\n conn.filters?.predicate,\n );\n\n const withConstraint = generateWithConstraint(\n skipYields(\n generateWithStart(withOverlay, req.start, connectionComparator),\n ),\n // we use `req.constraint` and not `fetchOrPkConstraint` here because we need to\n // AND the constraint with what could have been the primary key constraint\n req.constraint,\n );\n\n yield* conn.filters\n ? generateWithFilter(withConstraint, conn.filters.predicate)\n : withConstraint;\n }\n\n *push(change: SourceChange): Stream<'yield'> {\n for (const result of this.genPush(change)) {\n if (result === 'yield') {\n yield result;\n }\n }\n }\n\n *genPush(change: SourceChange) {\n const primaryIndex = this.#getPrimaryIndex();\n const {data} = primaryIndex;\n const exists = (row: Row) => data.has(row);\n const setOverlay = (o: Overlay | undefined) => (this.#overlay = o);\n const writeChange = (c: SourceChange) => this.#writeChange(c);\n yield* genPushAndWriteWithSplitEdit(\n this.#connections,\n change,\n exists,\n setOverlay,\n writeChange,\n () => ++this.#pushEpoch,\n );\n }\n\n #writeChange(change: SourceChange) {\n for (const {data} of this.#indexes.values()) {\n switch (change.type) {\n case 'add': {\n const added = data.add(change.row);\n // must succeed since we checked has() above.\n assert(\n added,\n 'MemorySource: add must succeed since row existence was already checked',\n );\n break;\n }\n case 'remove': {\n const removed = data.delete(change.row);\n // must succeed since we checked has() above.\n assert(\n removed,\n 'MemorySource: remove must succeed since row existence was already checked',\n );\n break;\n }\n case 'edit': {\n // TODO: We could see if the PK (form the index tree's perspective)\n // changed and if not we could use set.\n // We cannot just do `set` with the new value since the `oldRow` might\n // not map to the same entry as the new `row` in the index btree.\n const removed = data.delete(change.oldRow);\n // must succeed since we checked has() above.\n assert(\n removed,\n 'MemorySource: edit remove must succeed since row existence was already checked',\n );\n data.add(change.row);\n break;\n }\n default:\n unreachable(change);\n }\n }\n }\n}\n\nfunction* generateWithConstraint(\n it: Stream<Node>,\n constraint: Constraint | undefined,\n) {\n for (const node of it) {\n if (constraint && !constraintMatchesRow(constraint, node.row)) {\n break;\n }\n yield node;\n }\n}\n\nfunction* generateWithFilter(it: Stream<Node>, filter: (row: Row) => boolean) {\n for (const node of it) {\n if (filter(node.row)) {\n yield node;\n }\n }\n}\n\nexport function* genPushAndWriteWithSplitEdit(\n connections: readonly Connection[],\n change: SourceChange,\n exists: (row: Row) => boolean,\n setOverlay: (o: Overlay | undefined) => Overlay | undefined,\n writeChange: (c: SourceChange) => void,\n getNextEpoch: () => number,\n) {\n let shouldSplitEdit = false;\n if (change.type === 'edit') {\n for (const {splitEditKeys} of connections) {\n if (splitEditKeys) {\n for (const key of splitEditKeys) {\n if (!valuesEqual(change.row[key], change.oldRow[key])) {\n shouldSplitEdit = true;\n break;\n }\n }\n }\n }\n }\n\n if (change.type === 'edit' && shouldSplitEdit) {\n yield* genPushAndWrite(\n connections,\n {\n type: 'remove',\n row: change.oldRow,\n },\n exists,\n setOverlay,\n writeChange,\n getNextEpoch(),\n );\n yield* genPushAndWrite(\n connections,\n {\n type: 'add',\n row: change.row,\n },\n exists,\n setOverlay,\n writeChange,\n getNextEpoch(),\n );\n } else {\n yield* genPushAndWrite(\n connections,\n change,\n exists,\n setOverlay,\n writeChange,\n getNextEpoch(),\n );\n }\n}\n\nfunction* genPushAndWrite(\n connections: readonly Connection[],\n change: SourceChangeAdd | SourceChangeRemove | SourceChangeEdit,\n exists: (row: Row) => boolean,\n setOverlay: (o: Overlay | undefined) => Overlay | undefined,\n writeChange: (c: SourceChange) => void,\n pushEpoch: number,\n) {\n for (const x of genPush(connections, change, exists, setOverlay, pushEpoch)) {\n yield x;\n }\n writeChange(change);\n}\n\nfunction* genPush(\n connections: readonly Connection[],\n change: SourceChange,\n exists: (row: Row) => boolean,\n setOverlay: (o: Overlay | undefined) => void,\n pushEpoch: number,\n) {\n switch (change.type) {\n case 'add':\n assert(\n !exists(change.row),\n () => `Row already exists ${stringify(change)}`,\n );\n break;\n case 'remove':\n assert(exists(change.row), () => `Row not found ${stringify(change)}`);\n break;\n case 'edit':\n assert(exists(change.oldRow), () => `Row not found ${stringify(change)}`);\n break;\n default:\n unreachable(change);\n }\n\n for (const conn of connections) {\n const {output, filters, input} = conn;\n if (output) {\n conn.lastPushedEpoch = pushEpoch;\n setOverlay({epoch: pushEpoch, change});\n const outputChange: Change =\n change.type === 'edit'\n ? {\n type: change.type,\n oldNode: {\n row: change.oldRow,\n relationships: {},\n },\n node: {\n row: change.row,\n relationships: {},\n },\n }\n : {\n type: change.type,\n node: {\n row: change.row,\n relationships: {},\n },\n };\n yield* filterPush(outputChange, output, input, filters?.predicate);\n yield undefined;\n }\n }\n\n setOverlay(undefined);\n}\n\nexport function* generateWithStart(\n nodes: Iterable<Node | 'yield'>,\n start: Start | undefined,\n compare: (r1: Row, r2: Row) => number,\n): Stream<Node | 'yield'> {\n if (!start) {\n yield* nodes;\n return;\n }\n let started = false;\n for (const node of nodes) {\n if (node === 'yield') {\n yield node;\n continue;\n }\n if (!started) {\n if (start.basis === 'at') {\n if (compare(node.row, start.row) >= 0) {\n started = true;\n }\n } else if (start.basis === 'after') {\n if (compare(node.row, start.row) > 0) {\n started = true;\n }\n }\n }\n if (started) {\n yield node;\n }\n }\n}\n\n/**\n * Takes an iterator and overlay.\n * Splices the overlay into the iterator at the correct position.\n *\n * @param startAt - if there is a lower bound to the stream. If the lower bound of the stream\n * is above the overlay, the overlay will be skipped.\n * @param rows - the stream into which the overlay should be spliced\n * @param constraint - constraint that was applied to the rowIterator and should\n * also be applied to the overlay.\n * @param overlay - the overlay values to splice in\n * @param compare - the comparator to use to find the position for the overlay\n */\nexport function* generateWithOverlay(\n startAt: Row | undefined,\n rows: Iterable<Row>,\n constraint: Constraint | undefined,\n overlay: Overlay | undefined,\n lastPushedEpoch: number,\n compare: Comparator,\n filterPredicate?: (row: Row) => boolean | undefined,\n) {\n let overlayToApply: Overlay | undefined = undefined;\n if (overlay && lastPushedEpoch >= overlay.epoch) {\n overlayToApply = overlay;\n }\n const overlays = computeOverlays(\n startAt,\n constraint,\n overlayToApply,\n compare,\n filterPredicate,\n );\n yield* generateWithOverlayInner(rows, overlays, compare);\n}\n\nfunction computeOverlays(\n startAt: Row | undefined,\n constraint: Constraint | undefined,\n overlay: Overlay | undefined,\n compare: Comparator,\n filterPredicate?: (row: Row) => boolean | undefined,\n): Overlays {\n let overlays: Overlays = {\n add: undefined,\n remove: undefined,\n };\n switch (overlay?.change.type) {\n case 'add':\n overlays = {\n add: overlay.change.row,\n remove: undefined,\n };\n break;\n case 'remove':\n overlays = {\n add: undefined,\n remove: overlay.change.row,\n };\n break;\n case 'edit':\n overlays = {\n add: overlay.change.row,\n remove: overlay.change.oldRow,\n };\n break;\n }\n\n if (startAt) {\n overlays = overlaysForStartAt(overlays, startAt, compare);\n }\n\n if (constraint) {\n overlays = overlaysForConstraint(overlays, constraint);\n }\n\n if (filterPredicate) {\n overlays = overlaysForFilterPredicate(overlays, filterPredicate);\n }\n\n return overlays;\n}\n\nexport {overlaysForStartAt as overlaysForStartAtForTest};\n\nfunction overlaysForStartAt(\n {add, remove}: Overlays,\n startAt: Row,\n compare: Comparator,\n): Overlays {\n const undefinedIfBeforeStartAt = (row: Row | undefined) =>\n row === undefined || compare(row, startAt) < 0 ? undefined : row;\n return {\n add: undefinedIfBeforeStartAt(add),\n remove: undefinedIfBeforeStartAt(remove),\n };\n}\n\nexport {overlaysForConstraint as overlaysForConstraintForTest};\n\nfunction overlaysForConstraint(\n {add, remove}: Overlays,\n constraint: Constraint,\n): Overlays {\n const undefinedIfDoesntMatchConstraint = (row: Row | undefined) =>\n row === undefined || !constraintMatchesRow(constraint, row)\n ? undefined\n : row;\n\n return {\n add: undefinedIfDoesntMatchConstraint(add),\n remove: undefinedIfDoesntMatchConstraint(remove),\n };\n}\n\nfunction overlaysForFilterPredicate(\n {add, remove}: Overlays,\n filterPredicate: (row: Row) => boolean | undefined,\n): Overlays {\n const undefinedIfDoesntMatchFilter = (row: Row | undefined) =>\n row === undefined || !filterPredicate(row) ? undefined : row;\n\n return {\n add: undefinedIfDoesntMatchFilter(add),\n remove: undefinedIfDoesntMatchFilter(remove),\n };\n}\n\nexport function* generateWithOverlayInner(\n rowIterator: Iterable<Row>,\n overlays: Overlays,\n compare: (r1: Row, r2: Row) => number,\n) {\n let addOverlayYielded = false;\n let removeOverlaySkipped = false;\n for (const row of rowIterator) {\n if (!addOverlayYielded && overlays.add) {\n const cmp = compare(overlays.add, row);\n if (cmp < 0) {\n addOverlayYielded = true;\n yield {row: overlays.add, relationships: {}};\n }\n }\n\n if (!removeOverlaySkipped && overlays.remove) {\n const cmp = compare(overlays.remove, row);\n if (cmp === 0) {\n removeOverlaySkipped = true;\n continue;\n }\n }\n yield {row, relationships: {}};\n }\n\n if (!addOverlayYielded && overlays.add) {\n yield {row: overlays.add, relationships: {}};\n }\n}\n\n/**\n * A location to begin scanning an index from. Can either be a specific value\n * or the min or max possible value for the type. This is used to start a scan\n * at the beginning of the rows matching a constraint.\n */\ntype Bound = Value | MinValue | MaxValue;\ntype RowBound = Record<string, Bound>;\nconst minValue = Symbol('min-value');\ntype MinValue = typeof minValue;\nconst maxValue = Symbol('max-value');\ntype MaxValue = typeof maxValue;\n\nfunction makeBoundComparator(sort: Ordering) {\n return (a: RowBound, b: RowBound) => {\n // Hot! Do not use destructuring\n for (const entry of sort) {\n const key = entry[0];\n const cmp = compareBounds(a[key], b[key]);\n if (cmp !== 0) {\n return entry[1] === 'asc' ? cmp : -cmp;\n }\n }\n return 0;\n };\n}\n\nfunction compareBounds(a: Bound, b: Bound): number {\n if (a === b) {\n return 0;\n }\n if (a === minValue) {\n return -1;\n }\n if (b === minValue) {\n return 1;\n }\n if (a === maxValue) {\n return 1;\n }\n if (b === maxValue) {\n return -1;\n }\n return compareValues(a, b);\n}\n\nfunction* generateRows(\n data: BTreeSet<Row>,\n scanStart: RowBound | undefined,\n reverse: boolean | undefined,\n) {\n yield* data[reverse ? 'valuesFromReversed' : 'valuesFrom'](\n scanStart as Row | undefined,\n );\n}\n\nexport function stringify(change: SourceChange) {\n return JSON.stringify(change, (_, v) =>\n typeof v === 'bigint' ? v.toString() : v,\n );\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"memory-source.js","names":["#tableName","#columns","#primaryKey","#primaryIndexSort","#indexes","#connections","#getPrimaryIndex","#fetch","#disconnect","#getSchema","#getOrCreateIndex","#overlay","#writeChange","#pushEpoch"],"sources":["../../../../../zql/src/ivm/memory-source.ts"],"sourcesContent":["import {assert, unreachable} from '../../../shared/src/asserts.ts';\nimport {BTreeSet} from '../../../shared/src/btree-set.ts';\nimport {hasOwn} from '../../../shared/src/has-own.ts';\nimport {must} from '../../../shared/src/must.ts';\nimport {once} from '../../../shared/src/iterables.ts';\nimport type {\n Condition,\n Ordering,\n OrderPart,\n} from '../../../zero-protocol/src/ast.ts';\nimport type {Row, Value} from '../../../zero-protocol/src/data.ts';\nimport type {PrimaryKey} from '../../../zero-protocol/src/primary-key.ts';\nimport type {SchemaValue} from '../../../zero-types/src/schema-value.ts';\nimport type {DebugDelegate} from '../builder/debug-delegate.ts';\nimport {\n createPredicate,\n transformFilters,\n type NoSubqueryCondition,\n} from '../builder/filter.ts';\nimport {assertOrderingIncludesPK} from '../query/complete-ordering.ts';\nimport type {Change} from './change.ts';\nimport {\n constraintMatchesPrimaryKey,\n constraintMatchesRow,\n primaryKeyConstraintFromFilters,\n type Constraint,\n} from './constraint.ts';\nimport {\n compareValues,\n makeComparator,\n valuesEqual,\n type Comparator,\n type Node,\n} from './data.ts';\nimport {filterPush} from './filter-push.ts';\nimport {\n skipYields,\n type FetchRequest,\n type Input,\n type Output,\n type Start,\n} from './operator.ts';\nimport type {SourceSchema} from './schema.ts';\nimport type {\n Source,\n SourceChange,\n SourceChangeAdd,\n SourceChangeEdit,\n SourceChangeRemove,\n SourceInput,\n} from './source.ts';\nimport type {Stream} from './stream.ts';\n\nexport type Overlay = {\n epoch: number;\n change: SourceChange;\n};\n\nexport type Overlays = {\n add: Row | undefined;\n remove: Row | undefined;\n};\n\ntype Index = {\n comparator: Comparator;\n data: BTreeSet<Row>;\n usedBy: Set<Connection>;\n};\n\nexport type Connection = {\n input: Input;\n output: Output | undefined;\n sort?: Ordering | undefined;\n splitEditKeys: Set<string> | undefined;\n compareRows: Comparator;\n filters:\n | {\n condition: NoSubqueryCondition;\n predicate: (row: Row) => boolean;\n }\n | undefined;\n readonly debug?: DebugDelegate | undefined;\n lastPushedEpoch: number;\n};\n\n/**\n * A `MemorySource` is a source that provides data to the pipeline from an\n * in-memory data source.\n *\n * This data is kept in sorted order as downstream pipelines will always expect\n * the data they receive from `pull` to be in sorted order.\n */\nexport class MemorySource implements Source {\n readonly #tableName: string;\n readonly #columns: Record<string, SchemaValue>;\n readonly #primaryKey: PrimaryKey;\n readonly #primaryIndexSort: Ordering;\n readonly #indexes: Map<string, Index> = new Map();\n readonly #connections: Connection[] = [];\n\n #overlay: Overlay | undefined;\n #pushEpoch = 0;\n\n constructor(\n tableName: string,\n columns: Record<string, SchemaValue>,\n primaryKey: PrimaryKey,\n primaryIndexData?: BTreeSet<Row>,\n ) {\n this.#tableName = tableName;\n this.#columns = columns;\n this.#primaryKey = primaryKey;\n this.#primaryIndexSort = primaryKey.map(k => [k, 'asc']);\n const comparator = makeBoundComparator(this.#primaryIndexSort);\n this.#indexes.set(JSON.stringify(this.#primaryIndexSort), {\n comparator,\n data: primaryIndexData ?? new BTreeSet<Row>(comparator),\n usedBy: new Set(),\n });\n }\n\n get tableSchema() {\n return {\n name: this.#tableName,\n columns: this.#columns,\n primaryKey: this.#primaryKey,\n };\n }\n\n fork() {\n const primaryIndex = this.#getPrimaryIndex();\n return new MemorySource(\n this.#tableName,\n this.#columns,\n this.#primaryKey,\n primaryIndex.data.clone(),\n );\n }\n\n get data(): BTreeSet<Row> {\n return this.#getPrimaryIndex().data;\n }\n\n #getSchema(connection: Connection, unordered: boolean): SourceSchema {\n return {\n tableName: this.#tableName,\n columns: this.#columns,\n primaryKey: this.#primaryKey,\n sort: unordered ? undefined : connection.sort,\n system: 'client',\n relationships: {},\n isHidden: false,\n compareRows: connection.compareRows,\n };\n }\n\n connect(\n sort: Ordering | undefined,\n filters?: Condition,\n splitEditKeys?: Set<string>,\n ): SourceInput {\n const transformedFilters = transformFilters(filters);\n const unordered = sort === undefined;\n const internalSort = sort ?? this.#primaryIndexSort;\n\n const input: SourceInput = {\n getSchema: () => schema,\n fetch: req => this.#fetch(req, connection),\n setOutput: output => {\n connection.output = output;\n },\n destroy: () => {\n this.#disconnect(input);\n },\n fullyAppliedFilters: !transformedFilters.conditionsRemoved,\n };\n\n const connection: Connection = {\n input,\n output: undefined,\n sort: internalSort,\n splitEditKeys,\n compareRows: makeComparator(internalSort),\n filters: transformedFilters.filters\n ? {\n condition: transformedFilters.filters,\n predicate: createPredicate(transformedFilters.filters),\n }\n : undefined,\n lastPushedEpoch: 0,\n };\n const schema = this.#getSchema(connection, unordered);\n if (!unordered) {\n assertOrderingIncludesPK(internalSort, this.#primaryKey);\n }\n this.#connections.push(connection);\n return input;\n }\n\n #disconnect(input: Input): void {\n const idx = this.#connections.findIndex(c => c.input === input);\n assert(idx !== -1, 'Connection not found');\n this.#connections.splice(idx, 1);\n\n // TODO: We used to delete unused indexes here. But in common cases like\n // navigating into issue detail pages it caused a ton of constantly\n // building and destroying indexes.\n //\n // Perhaps some intelligent LRU or something is needed here but for now,\n // the opposite extreme of keeping all indexes for the lifetime of the\n // page seems better.\n }\n\n #getPrimaryIndex(): Index {\n const index = this.#indexes.get(JSON.stringify(this.#primaryIndexSort));\n assert(index, 'Primary index not found');\n return index;\n }\n\n #getOrCreateIndex(sort: Ordering, usedBy: Connection): Index {\n const key = JSON.stringify(sort);\n const index = this.#indexes.get(key);\n // Future optimization could use existing index if it's the same just sorted\n // in reverse of needed.\n if (index) {\n index.usedBy.add(usedBy);\n return index;\n }\n\n const comparator = makeBoundComparator(sort);\n\n // When creating these synchronously becomes a problem, a few options:\n // 1. Allow users to specify needed indexes up front\n // 2. Create indexes in a different thread asynchronously (this would require\n // modifying the BTree to be able to be passed over structured-clone, or using\n // a different library.)\n // 3. We could even theoretically do (2) on multiple threads and then merge the\n // results!\n const data = new BTreeSet<Row>(comparator);\n\n // I checked, there's no special path for adding data in bulk faster.\n // The constructor takes an array, but it just calls add/set over and over.\n for (const row of this.#getPrimaryIndex().data) {\n data.add(row);\n }\n\n const newIndex = {comparator, data, usedBy: new Set([usedBy])};\n this.#indexes.set(key, newIndex);\n return newIndex;\n }\n\n // For unit testing that we correctly clean up indexes.\n getIndexKeys(): string[] {\n return [...this.#indexes.keys()];\n }\n\n *#fetch(req: FetchRequest, conn: Connection): Stream<Node | 'yield'> {\n const requestedSort = must(conn.sort);\n const {compareRows} = conn;\n const connectionComparator = (r1: Row, r2: Row) =>\n compareRows(r1, r2) * (req.reverse ? -1 : 1);\n\n const pkConstraint = primaryKeyConstraintFromFilters(\n conn.filters?.condition,\n this.#primaryKey,\n );\n // The primary key constraint will be more limiting than the constraint\n // so swap out to that if it exists.\n const fetchOrPkConstraint = pkConstraint ?? req.constraint;\n\n // If there is a constraint, we need an index sorted by it first.\n const indexSort: OrderPart[] = [];\n if (fetchOrPkConstraint) {\n for (const key of Object.keys(fetchOrPkConstraint)) {\n indexSort.push([key, 'asc']);\n }\n }\n\n // For the special case of constraining by PK, we don't need to worry about\n // any requested sort since there can only be one result. Otherwise we also\n // need the index sorted by the requested sort.\n if (\n this.#primaryKey.length > 1 ||\n !fetchOrPkConstraint ||\n !constraintMatchesPrimaryKey(fetchOrPkConstraint, this.#primaryKey)\n ) {\n indexSort.push(...requestedSort);\n }\n\n const index = this.#getOrCreateIndex(indexSort, conn);\n const {data, comparator: compare} = index;\n const indexComparator = (r1: Row, r2: Row) =>\n compare(r1, r2) * (req.reverse ? -1 : 1);\n\n const startAt = req.start?.row;\n\n // If there is a constraint, we want to start our scan at the first row that\n // matches the constraint. But because the next OrderPart can be `desc`,\n // it's not true that {[constraintKey]: constraintValue} is the first\n // matching row. Because in that case, the other fields will all be\n // `undefined`, and in Zero `undefined` is always less than any other value.\n // So if the second OrderPart is descending then `undefined` values will\n // actually be the *last* row. We need a way to stay \"start at the first row\n // with this constraint value\". RowBound with the corresponding compareBound\n // comparator accomplishes this. The right thing is probably to teach the\n // btree library to support this concept.\n let scanStart: RowBound | undefined;\n\n if (fetchOrPkConstraint) {\n scanStart = {};\n for (const [key, dir] of indexSort) {\n if (hasOwn(fetchOrPkConstraint, key)) {\n scanStart[key] = fetchOrPkConstraint[key];\n } else {\n if (req.reverse) {\n scanStart[key] = dir === 'asc' ? maxValue : minValue;\n } else {\n scanStart[key] = dir === 'asc' ? minValue : maxValue;\n }\n }\n }\n } else {\n scanStart = startAt;\n }\n\n const rowsIterable = generateRows(data, scanStart, req.reverse);\n const withOverlay = generateWithOverlay(\n startAt,\n pkConstraint ? once(rowsIterable) : rowsIterable,\n // use `req.constraint` here and not `fetchOrPkConstraint` since `fetchOrPkConstraint` could be the\n // primary key constraint. The primary key constraint comes from filters and is acting as a filter\n // rather than as the fetch constraint.\n req.constraint,\n this.#overlay,\n conn.lastPushedEpoch,\n // Use indexComparator, generateWithOverlayInner has a subtle dependency\n // on this. Since generateWithConstraint is done after\n // generateWithOverlay, the generator consumed by generateWithOverlayInner\n // does not end when the constraint stops matching and so the final\n // check to yield an add overlay if not yet yielded is not reached.\n // However, using the indexComparator the add overlay will be less than\n // the first row that does not match the constraint, and so any\n // not yet yielded add overlay will be yielded when the first row\n // not matching the constraint is reached.\n indexComparator,\n conn.filters?.predicate,\n );\n\n const withConstraint = generateWithConstraint(\n skipYields(\n generateWithStart(withOverlay, req.start, connectionComparator),\n ),\n // we use `req.constraint` and not `fetchOrPkConstraint` here because we need to\n // AND the constraint with what could have been the primary key constraint\n req.constraint,\n );\n\n yield* conn.filters\n ? generateWithFilter(withConstraint, conn.filters.predicate)\n : withConstraint;\n }\n\n *push(change: SourceChange): Stream<'yield'> {\n for (const result of this.genPush(change)) {\n if (result === 'yield') {\n yield result;\n }\n }\n }\n\n *genPush(change: SourceChange) {\n const primaryIndex = this.#getPrimaryIndex();\n const {data} = primaryIndex;\n const exists = (row: Row) => data.has(row);\n const setOverlay = (o: Overlay | undefined) => (this.#overlay = o);\n const writeChange = (c: SourceChange) => this.#writeChange(c);\n yield* genPushAndWriteWithSplitEdit(\n this.#connections,\n change,\n exists,\n setOverlay,\n writeChange,\n () => ++this.#pushEpoch,\n );\n }\n\n #writeChange(change: SourceChange) {\n for (const {data} of this.#indexes.values()) {\n switch (change.type) {\n case 'add': {\n const added = data.add(change.row);\n // must succeed since we checked has() above.\n assert(\n added,\n 'MemorySource: add must succeed since row existence was already checked',\n );\n break;\n }\n case 'remove': {\n const removed = data.delete(change.row);\n // must succeed since we checked has() above.\n assert(\n removed,\n 'MemorySource: remove must succeed since row existence was already checked',\n );\n break;\n }\n case 'edit': {\n // TODO: We could see if the PK (form the index tree's perspective)\n // changed and if not we could use set.\n // We cannot just do `set` with the new value since the `oldRow` might\n // not map to the same entry as the new `row` in the index btree.\n const removed = data.delete(change.oldRow);\n // must succeed since we checked has() above.\n assert(\n removed,\n 'MemorySource: edit remove must succeed since row existence was already checked',\n );\n data.add(change.row);\n break;\n }\n default:\n unreachable(change);\n }\n }\n }\n}\n\nfunction* generateWithConstraint(\n it: Stream<Node>,\n constraint: Constraint | undefined,\n) {\n for (const node of it) {\n if (constraint && !constraintMatchesRow(constraint, node.row)) {\n break;\n }\n yield node;\n }\n}\n\nfunction* generateWithFilter(it: Stream<Node>, filter: (row: Row) => boolean) {\n for (const node of it) {\n if (filter(node.row)) {\n yield node;\n }\n }\n}\n\nexport function* genPushAndWriteWithSplitEdit(\n connections: readonly Connection[],\n change: SourceChange,\n exists: (row: Row) => boolean,\n setOverlay: (o: Overlay | undefined) => Overlay | undefined,\n writeChange: (c: SourceChange) => void,\n getNextEpoch: () => number,\n) {\n let shouldSplitEdit = false;\n if (change.type === 'edit') {\n for (const {splitEditKeys} of connections) {\n if (splitEditKeys) {\n for (const key of splitEditKeys) {\n if (!valuesEqual(change.row[key], change.oldRow[key])) {\n shouldSplitEdit = true;\n break;\n }\n }\n }\n }\n }\n\n if (change.type === 'edit' && shouldSplitEdit) {\n yield* genPushAndWrite(\n connections,\n {\n type: 'remove',\n row: change.oldRow,\n },\n exists,\n setOverlay,\n writeChange,\n getNextEpoch(),\n );\n yield* genPushAndWrite(\n connections,\n {\n type: 'add',\n row: change.row,\n },\n exists,\n setOverlay,\n writeChange,\n getNextEpoch(),\n );\n } else {\n yield* genPushAndWrite(\n connections,\n change,\n exists,\n setOverlay,\n writeChange,\n getNextEpoch(),\n );\n }\n}\n\nfunction* genPushAndWrite(\n connections: readonly Connection[],\n change: SourceChangeAdd | SourceChangeRemove | SourceChangeEdit,\n exists: (row: Row) => boolean,\n setOverlay: (o: Overlay | undefined) => Overlay | undefined,\n writeChange: (c: SourceChange) => void,\n pushEpoch: number,\n) {\n for (const x of genPush(connections, change, exists, setOverlay, pushEpoch)) {\n yield x;\n }\n writeChange(change);\n}\n\nfunction* genPush(\n connections: readonly Connection[],\n change: SourceChange,\n exists: (row: Row) => boolean,\n setOverlay: (o: Overlay | undefined) => void,\n pushEpoch: number,\n) {\n switch (change.type) {\n case 'add':\n assert(\n !exists(change.row),\n () => `Row already exists ${stringify(change)}`,\n );\n break;\n case 'remove':\n assert(exists(change.row), () => `Row not found ${stringify(change)}`);\n break;\n case 'edit':\n assert(exists(change.oldRow), () => `Row not found ${stringify(change)}`);\n break;\n default:\n unreachable(change);\n }\n\n for (const conn of connections) {\n const {output, filters, input} = conn;\n if (output) {\n conn.lastPushedEpoch = pushEpoch;\n setOverlay({epoch: pushEpoch, change});\n const outputChange: Change =\n change.type === 'edit'\n ? {\n type: change.type,\n oldNode: {\n row: change.oldRow,\n relationships: {},\n },\n node: {\n row: change.row,\n relationships: {},\n },\n }\n : {\n type: change.type,\n node: {\n row: change.row,\n relationships: {},\n },\n };\n yield* filterPush(outputChange, output, input, filters?.predicate);\n yield undefined;\n }\n }\n\n setOverlay(undefined);\n}\n\nexport function* generateWithStart(\n nodes: Iterable<Node | 'yield'>,\n start: Start | undefined,\n compare: (r1: Row, r2: Row) => number,\n): Stream<Node | 'yield'> {\n if (!start) {\n yield* nodes;\n return;\n }\n let started = false;\n for (const node of nodes) {\n if (node === 'yield') {\n yield node;\n continue;\n }\n if (!started) {\n if (start.basis === 'at') {\n if (compare(node.row, start.row) >= 0) {\n started = true;\n }\n } else if (start.basis === 'after') {\n if (compare(node.row, start.row) > 0) {\n started = true;\n }\n }\n }\n if (started) {\n yield node;\n }\n }\n}\n\n/**\n * Takes an iterator and overlay.\n * Splices the overlay into the iterator at the correct position.\n *\n * @param startAt - if there is a lower bound to the stream. If the lower bound of the stream\n * is above the overlay, the overlay will be skipped.\n * @param rows - the stream into which the overlay should be spliced\n * @param constraint - constraint that was applied to the rowIterator and should\n * also be applied to the overlay.\n * @param overlay - the overlay values to splice in\n * @param compare - the comparator to use to find the position for the overlay\n */\nexport function* generateWithOverlay(\n startAt: Row | undefined,\n rows: Iterable<Row>,\n constraint: Constraint | undefined,\n overlay: Overlay | undefined,\n lastPushedEpoch: number,\n compare: Comparator,\n filterPredicate?: (row: Row) => boolean | undefined,\n) {\n let overlayToApply: Overlay | undefined = undefined;\n if (overlay && lastPushedEpoch >= overlay.epoch) {\n overlayToApply = overlay;\n }\n const overlays = computeOverlays(\n startAt,\n constraint,\n overlayToApply,\n compare,\n filterPredicate,\n );\n yield* generateWithOverlayInner(rows, overlays, compare);\n}\n\nfunction computeOverlays(\n startAt: Row | undefined,\n constraint: Constraint | undefined,\n overlay: Overlay | undefined,\n compare: Comparator,\n filterPredicate?: (row: Row) => boolean | undefined,\n): Overlays {\n let overlays: Overlays = {\n add: undefined,\n remove: undefined,\n };\n switch (overlay?.change.type) {\n case 'add':\n overlays = {\n add: overlay.change.row,\n remove: undefined,\n };\n break;\n case 'remove':\n overlays = {\n add: undefined,\n remove: overlay.change.row,\n };\n break;\n case 'edit':\n overlays = {\n add: overlay.change.row,\n remove: overlay.change.oldRow,\n };\n break;\n }\n\n if (startAt) {\n overlays = overlaysForStartAt(overlays, startAt, compare);\n }\n\n if (constraint) {\n overlays = overlaysForConstraint(overlays, constraint);\n }\n\n if (filterPredicate) {\n overlays = overlaysForFilterPredicate(overlays, filterPredicate);\n }\n\n return overlays;\n}\n\nexport {overlaysForStartAt as overlaysForStartAtForTest};\n\nfunction overlaysForStartAt(\n {add, remove}: Overlays,\n startAt: Row,\n compare: Comparator,\n): Overlays {\n const undefinedIfBeforeStartAt = (row: Row | undefined) =>\n row === undefined || compare(row, startAt) < 0 ? undefined : row;\n return {\n add: undefinedIfBeforeStartAt(add),\n remove: undefinedIfBeforeStartAt(remove),\n };\n}\n\nexport {overlaysForConstraint as overlaysForConstraintForTest};\n\nfunction overlaysForConstraint(\n {add, remove}: Overlays,\n constraint: Constraint,\n): Overlays {\n const undefinedIfDoesntMatchConstraint = (row: Row | undefined) =>\n row === undefined || !constraintMatchesRow(constraint, row)\n ? undefined\n : row;\n\n return {\n add: undefinedIfDoesntMatchConstraint(add),\n remove: undefinedIfDoesntMatchConstraint(remove),\n };\n}\n\nfunction overlaysForFilterPredicate(\n {add, remove}: Overlays,\n filterPredicate: (row: Row) => boolean | undefined,\n): Overlays {\n const undefinedIfDoesntMatchFilter = (row: Row | undefined) =>\n row === undefined || !filterPredicate(row) ? undefined : row;\n\n return {\n add: undefinedIfDoesntMatchFilter(add),\n remove: undefinedIfDoesntMatchFilter(remove),\n };\n}\n\nexport function* generateWithOverlayInner(\n rowIterator: Iterable<Row>,\n overlays: Overlays,\n compare: (r1: Row, r2: Row) => number,\n) {\n let addOverlayYielded = false;\n let removeOverlaySkipped = false;\n for (const row of rowIterator) {\n if (!addOverlayYielded && overlays.add) {\n const cmp = compare(overlays.add, row);\n if (cmp < 0) {\n addOverlayYielded = true;\n yield {row: overlays.add, relationships: {}};\n }\n }\n\n if (!removeOverlaySkipped && overlays.remove) {\n const cmp = compare(overlays.remove, row);\n if (cmp === 0) {\n removeOverlaySkipped = true;\n continue;\n }\n }\n yield {row, relationships: {}};\n }\n\n if (!addOverlayYielded && overlays.add) {\n yield {row: overlays.add, relationships: {}};\n }\n}\n\n/**\n * Like {@link generateWithOverlay} but for unordered streams.\n * No `startAt` or comparator needed. Injects remove/old-edit rows eagerly\n * at the start, and suppresses add/new-edit rows inline by PK match.\n */\nexport function* generateWithOverlayUnordered(\n rows: Iterable<Row>,\n constraint: Constraint | undefined,\n overlay: Overlay | undefined,\n lastPushedEpoch: number,\n primaryKey: PrimaryKey,\n filterPredicate?: ((row: Row) => boolean) | undefined,\n) {\n let overlayToApply: Overlay | undefined = undefined;\n if (overlay && lastPushedEpoch >= overlay.epoch) {\n overlayToApply = overlay;\n }\n let overlays: Overlays = {add: undefined, remove: undefined};\n switch (overlayToApply?.change.type) {\n case 'add':\n overlays = {add: overlayToApply.change.row, remove: undefined};\n break;\n case 'remove':\n overlays = {add: undefined, remove: overlayToApply.change.row};\n break;\n case 'edit':\n overlays = {\n add: overlayToApply.change.row,\n remove: overlayToApply.change.oldRow,\n };\n break;\n }\n if (constraint) {\n overlays = overlaysForConstraint(overlays, constraint);\n }\n if (filterPredicate) {\n overlays = overlaysForFilterPredicate(overlays, filterPredicate);\n }\n yield* generateWithOverlayInnerUnordered(rows, overlays, primaryKey);\n}\n\nexport function* generateWithOverlayInnerUnordered(\n rowIterator: Iterable<Row>,\n overlays: Overlays,\n primaryKey: PrimaryKey,\n) {\n // Eager inject: yield the add overlay at the start (row not yet in storage)\n if (overlays.add) {\n yield {row: overlays.add, relationships: {}};\n }\n // Stream with inline suppress: skip the remove overlay (row still in storage)\n let removeSkipped = false;\n for (const row of rowIterator) {\n if (\n !removeSkipped &&\n overlays.remove &&\n rowMatchesPK(overlays.remove, row, primaryKey)\n ) {\n removeSkipped = true;\n continue;\n }\n yield {row, relationships: {}};\n }\n}\n\nfunction rowMatchesPK(a: Row, b: Row, primaryKey: PrimaryKey): boolean {\n for (const key of primaryKey) {\n if (!valuesEqual(a[key], b[key])) {\n return false;\n }\n }\n return true;\n}\n\n/**\n * A location to begin scanning an index from. Can either be a specific value\n * or the min or max possible value for the type. This is used to start a scan\n * at the beginning of the rows matching a constraint.\n */\ntype Bound = Value | MinValue | MaxValue;\ntype RowBound = Record<string, Bound>;\nconst minValue = Symbol('min-value');\ntype MinValue = typeof minValue;\nconst maxValue = Symbol('max-value');\ntype MaxValue = typeof maxValue;\n\nfunction makeBoundComparator(sort: Ordering) {\n return (a: RowBound, b: RowBound) => {\n // Hot! Do not use destructuring\n for (const entry of sort) {\n const key = entry[0];\n const cmp = compareBounds(a[key], b[key]);\n if (cmp !== 0) {\n return entry[1] === 'asc' ? cmp : -cmp;\n }\n }\n return 0;\n };\n}\n\nfunction compareBounds(a: Bound, b: Bound): number {\n if (a === b) {\n return 0;\n }\n if (a === minValue) {\n return -1;\n }\n if (b === minValue) {\n return 1;\n }\n if (a === maxValue) {\n return 1;\n }\n if (b === maxValue) {\n return -1;\n }\n return compareValues(a, b);\n}\n\nfunction* generateRows(\n data: BTreeSet<Row>,\n scanStart: RowBound | undefined,\n reverse: boolean | undefined,\n) {\n yield* data[reverse ? 'valuesFromReversed' : 'valuesFrom'](\n scanStart as Row | undefined,\n );\n}\n\nexport function stringify(change: SourceChange) {\n return JSON.stringify(change, (_, v) =>\n typeof v === 'bigint' ? v.toString() : v,\n );\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../../../../zql/src/ivm/schema.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,QAAQ,EAAE,MAAM,EAAC,MAAM,mCAAmC,CAAC;AACxE,OAAO,KAAK,EAAC,UAAU,EAAC,MAAM,2CAA2C,CAAC;AAC1E,OAAO,KAAK,EAAC,WAAW,EAAC,MAAM,yCAAyC,CAAC;AACzE,OAAO,KAAK,EAAC,UAAU,EAAC,MAAM,WAAW,CAAC;AAE1C;;GAEG;AACH,MAAM,MAAM,YAAY,GAAG;IACzB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;IAC9C,QAAQ,CAAC,UAAU,EAAE,UAAU,CAAC;IAChC,QAAQ,CAAC,aAAa,EAAE;QAAC,CAAC,GAAG,EAAE,MAAM,GAAG,YAAY,CAAA;KAAC,CAAC;IACtD,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;IAQ3B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,WAAW,EAAE,UAAU,CAAC;IACjC,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC;
|
|
1
|
+
{"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../../../../zql/src/ivm/schema.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,QAAQ,EAAE,MAAM,EAAC,MAAM,mCAAmC,CAAC;AACxE,OAAO,KAAK,EAAC,UAAU,EAAC,MAAM,2CAA2C,CAAC;AAC1E,OAAO,KAAK,EAAC,WAAW,EAAC,MAAM,yCAAyC,CAAC;AACzE,OAAO,KAAK,EAAC,UAAU,EAAC,MAAM,WAAW,CAAC;AAE1C;;GAEG;AACH,MAAM,MAAM,YAAY,GAAG;IACzB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;IAC9C,QAAQ,CAAC,UAAU,EAAE,UAAU,CAAC;IAChC,QAAQ,CAAC,aAAa,EAAE;QAAC,CAAC,GAAG,EAAE,MAAM,GAAG,YAAY,CAAA;KAAC,CAAC;IACtD,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;IAQ3B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,WAAW,EAAE,UAAU,CAAC;IACjC,QAAQ,CAAC,IAAI,CAAC,EAAE,QAAQ,GAAG,SAAS,CAAC;CACtC,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"skip.d.ts","sourceRoot":"","sources":["../../../../../zql/src/ivm/skip.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"skip.d.ts","sourceRoot":"","sources":["../../../../../zql/src/ivm/skip.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAC,GAAG,EAAC,MAAM,oCAAoC,CAAC;AAC5D,OAAO,KAAK,EAAY,MAAM,EAA4B,MAAM,aAAa,CAAC;AAC9E,OAAO,KAAK,EAAa,IAAI,EAAC,MAAM,WAAW,CAAC;AAEhD,OAAO,EAEL,KAAK,YAAY,EACjB,KAAK,KAAK,EACV,KAAK,QAAQ,EACb,KAAK,MAAM,EAEZ,MAAM,eAAe,CAAC;AACvB,OAAO,KAAK,EAAC,YAAY,EAAC,MAAM,aAAa,CAAC;AAC9C,OAAO,KAAK,EAAC,MAAM,EAAC,MAAM,aAAa,CAAC;AAExC,MAAM,MAAM,KAAK,GAAG;IAClB,GAAG,EAAE,GAAG,CAAC;IACT,SAAS,EAAE,OAAO,CAAC;CACpB,CAAC;AAEF;;;GAGG;AACH,qBAAa,IAAK,YAAW,QAAQ;;gBAOvB,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK;IAStC,SAAS,IAAI,YAAY;IAIxB,KAAK,CAAC,GAAG,EAAE,YAAY,GAAG,MAAM,CAAC,IAAI,GAAG,OAAO,CAAC;IAsBjD,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;IAI/B,OAAO,IAAI,IAAI;IASd,IAAI,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC;CA+EvC"}
|
package/out/zql/src/ivm/skip.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { assert } from "../../../shared/src/asserts.js";
|
|
1
2
|
import { throwOutput } from "./operator.js";
|
|
2
3
|
import { maybeSplitAndPushEditChange } from "./maybe-split-and-push-edit-change.js";
|
|
3
4
|
//#region ../zql/src/ivm/skip.ts
|
|
@@ -11,6 +12,8 @@ var Skip = class {
|
|
|
11
12
|
#comparator;
|
|
12
13
|
#output = throwOutput;
|
|
13
14
|
constructor(input, bound) {
|
|
15
|
+
const { sort } = input.getSchema();
|
|
16
|
+
assert(sort !== void 0, "Skip requires sorted input");
|
|
14
17
|
this.#input = input;
|
|
15
18
|
this.#bound = bound;
|
|
16
19
|
this.#comparator = input.getSchema().compareRows;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"skip.js","names":["#input","#bound","#comparator","#getStart","#shouldBePresent","#output"],"sources":["../../../../../zql/src/ivm/skip.ts"],"sourcesContent":["import type {Row} from '../../../zero-protocol/src/data.ts';\nimport type {AddChange, Change, ChildChange, RemoveChange} from './change.ts';\nimport type {Comparator, Node} from './data.ts';\nimport {maybeSplitAndPushEditChange} from './maybe-split-and-push-edit-change.ts';\nimport {\n throwOutput,\n type FetchRequest,\n type Input,\n type Operator,\n type Output,\n type Start,\n} from './operator.ts';\nimport type {SourceSchema} from './schema.ts';\nimport type {Stream} from './stream.ts';\n\nexport type Bound = {\n row: Row;\n exclusive: boolean;\n};\n\n/**\n * Skip sets the start position for the pipeline. No rows before the bound will\n * be output.\n */\nexport class Skip implements Operator {\n readonly #input: Input;\n readonly #bound: Bound;\n readonly #comparator: Comparator;\n\n #output: Output = throwOutput;\n\n constructor(input: Input, bound: Bound) {\n this.#input = input;\n this.#bound = bound;\n this.#comparator = input.getSchema().compareRows;\n input.setOutput(this);\n }\n\n getSchema(): SourceSchema {\n return this.#input.getSchema();\n }\n\n *fetch(req: FetchRequest): Stream<Node | 'yield'> {\n const start = this.#getStart(req);\n if (start === 'empty') {\n return;\n }\n const nodes = this.#input.fetch({...req, start});\n if (!req.reverse) {\n yield* nodes;\n return;\n }\n for (const node of nodes) {\n if (node === 'yield') {\n yield node;\n continue;\n }\n if (!this.#shouldBePresent(node.row)) {\n return;\n }\n yield node;\n }\n }\n\n setOutput(output: Output): void {\n this.#output = output;\n }\n\n destroy(): void {\n this.#input.destroy();\n }\n\n #shouldBePresent(row: Row): boolean {\n const cmp = this.#comparator(this.#bound.row, row);\n return cmp < 0 || (cmp === 0 && !this.#bound.exclusive);\n }\n\n *push(change: Change): Stream<'yield'> {\n const shouldBePresent = (row: Row) => this.#shouldBePresent(row);\n if (change.type === 'edit') {\n yield* maybeSplitAndPushEditChange(\n change,\n shouldBePresent,\n this.#output,\n this,\n );\n return;\n }\n\n change satisfies AddChange | RemoveChange | ChildChange;\n\n if (shouldBePresent(change.node.row)) {\n yield* this.#output.push(change, this);\n }\n }\n\n #getStart(req: FetchRequest): Start | undefined | 'empty' {\n const boundStart = {\n row: this.#bound.row,\n basis: this.#bound.exclusive ? 'after' : 'at',\n } as const;\n\n if (!req.start) {\n if (req.reverse) {\n return undefined;\n }\n return boundStart;\n }\n\n const cmp = this.#comparator(this.#bound.row, req.start.row);\n\n if (!req.reverse) {\n // The skip bound is after the requested bound. The requested bound cannot\n // be relevant because even if it was basis: 'after', the skip bound is\n // itself after the requested bound. Return the skip bound.\n if (cmp > 0) {\n return boundStart;\n }\n\n // The skip bound and requested bound are equal. If either is exclusive,\n // return that bound with exclusive. Otherwise, return the skip bound.\n if (cmp === 0) {\n if (this.#bound.exclusive || req.start.basis === 'after') {\n return {\n row: this.#bound.row,\n basis: 'after',\n };\n }\n return boundStart;\n }\n\n return req.start;\n }\n\n req.reverse satisfies true;\n\n // bound is after the start, but request is for reverse so results\n // must be empty\n if (cmp > 0) {\n return 'empty';\n }\n\n if (cmp === 0) {\n // if both are inclusive, the result can be the single row at bound\n // return it as start\n if (!this.#bound.exclusive && req.start.basis === 'at') {\n return boundStart;\n }\n // otherwise the results must be empty, one or both are exclusive\n // in opposite directions\n return 'empty';\n }\n\n // bound is before the start, return start\n return req.start;\n }\n}\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"skip.js","names":["#input","#bound","#comparator","#getStart","#shouldBePresent","#output"],"sources":["../../../../../zql/src/ivm/skip.ts"],"sourcesContent":["import {assert} from '../../../shared/src/asserts.ts';\nimport type {Row} from '../../../zero-protocol/src/data.ts';\nimport type {AddChange, Change, ChildChange, RemoveChange} from './change.ts';\nimport type {Comparator, Node} from './data.ts';\nimport {maybeSplitAndPushEditChange} from './maybe-split-and-push-edit-change.ts';\nimport {\n throwOutput,\n type FetchRequest,\n type Input,\n type Operator,\n type Output,\n type Start,\n} from './operator.ts';\nimport type {SourceSchema} from './schema.ts';\nimport type {Stream} from './stream.ts';\n\nexport type Bound = {\n row: Row;\n exclusive: boolean;\n};\n\n/**\n * Skip sets the start position for the pipeline. No rows before the bound will\n * be output.\n */\nexport class Skip implements Operator {\n readonly #input: Input;\n readonly #bound: Bound;\n readonly #comparator: Comparator;\n\n #output: Output = throwOutput;\n\n constructor(input: Input, bound: Bound) {\n const {sort} = input.getSchema();\n assert(sort !== undefined, 'Skip requires sorted input');\n this.#input = input;\n this.#bound = bound;\n this.#comparator = input.getSchema().compareRows;\n input.setOutput(this);\n }\n\n getSchema(): SourceSchema {\n return this.#input.getSchema();\n }\n\n *fetch(req: FetchRequest): Stream<Node | 'yield'> {\n const start = this.#getStart(req);\n if (start === 'empty') {\n return;\n }\n const nodes = this.#input.fetch({...req, start});\n if (!req.reverse) {\n yield* nodes;\n return;\n }\n for (const node of nodes) {\n if (node === 'yield') {\n yield node;\n continue;\n }\n if (!this.#shouldBePresent(node.row)) {\n return;\n }\n yield node;\n }\n }\n\n setOutput(output: Output): void {\n this.#output = output;\n }\n\n destroy(): void {\n this.#input.destroy();\n }\n\n #shouldBePresent(row: Row): boolean {\n const cmp = this.#comparator(this.#bound.row, row);\n return cmp < 0 || (cmp === 0 && !this.#bound.exclusive);\n }\n\n *push(change: Change): Stream<'yield'> {\n const shouldBePresent = (row: Row) => this.#shouldBePresent(row);\n if (change.type === 'edit') {\n yield* maybeSplitAndPushEditChange(\n change,\n shouldBePresent,\n this.#output,\n this,\n );\n return;\n }\n\n change satisfies AddChange | RemoveChange | ChildChange;\n\n if (shouldBePresent(change.node.row)) {\n yield* this.#output.push(change, this);\n }\n }\n\n #getStart(req: FetchRequest): Start | undefined | 'empty' {\n const boundStart = {\n row: this.#bound.row,\n basis: this.#bound.exclusive ? 'after' : 'at',\n } as const;\n\n if (!req.start) {\n if (req.reverse) {\n return undefined;\n }\n return boundStart;\n }\n\n const cmp = this.#comparator(this.#bound.row, req.start.row);\n\n if (!req.reverse) {\n // The skip bound is after the requested bound. The requested bound cannot\n // be relevant because even if it was basis: 'after', the skip bound is\n // itself after the requested bound. Return the skip bound.\n if (cmp > 0) {\n return boundStart;\n }\n\n // The skip bound and requested bound are equal. If either is exclusive,\n // return that bound with exclusive. Otherwise, return the skip bound.\n if (cmp === 0) {\n if (this.#bound.exclusive || req.start.basis === 'after') {\n return {\n row: this.#bound.row,\n basis: 'after',\n };\n }\n return boundStart;\n }\n\n return req.start;\n }\n\n req.reverse satisfies true;\n\n // bound is after the start, but request is for reverse so results\n // must be empty\n if (cmp > 0) {\n return 'empty';\n }\n\n if (cmp === 0) {\n // if both are inclusive, the result can be the single row at bound\n // return it as start\n if (!this.#bound.exclusive && req.start.basis === 'at') {\n return boundStart;\n }\n // otherwise the results must be empty, one or both are exclusive\n // in opposite directions\n return 'empty';\n }\n\n // bound is before the start, return start\n return req.start;\n }\n}\n"],"mappings":";;;;;;;;AAyBA,IAAa,OAAb,MAAsC;CACpC;CACA;CACA;CAEA,UAAkB;CAElB,YAAY,OAAc,OAAc;EACtC,MAAM,EAAC,SAAQ,MAAM,WAAW;AAChC,SAAO,SAAS,KAAA,GAAW,6BAA6B;AACxD,QAAA,QAAc;AACd,QAAA,QAAc;AACd,QAAA,aAAmB,MAAM,WAAW,CAAC;AACrC,QAAM,UAAU,KAAK;;CAGvB,YAA0B;AACxB,SAAO,MAAA,MAAY,WAAW;;CAGhC,CAAC,MAAM,KAA2C;EAChD,MAAM,QAAQ,MAAA,SAAe,IAAI;AACjC,MAAI,UAAU,QACZ;EAEF,MAAM,QAAQ,MAAA,MAAY,MAAM;GAAC,GAAG;GAAK;GAAM,CAAC;AAChD,MAAI,CAAC,IAAI,SAAS;AAChB,UAAO;AACP;;AAEF,OAAK,MAAM,QAAQ,OAAO;AACxB,OAAI,SAAS,SAAS;AACpB,UAAM;AACN;;AAEF,OAAI,CAAC,MAAA,gBAAsB,KAAK,IAAI,CAClC;AAEF,SAAM;;;CAIV,UAAU,QAAsB;AAC9B,QAAA,SAAe;;CAGjB,UAAgB;AACd,QAAA,MAAY,SAAS;;CAGvB,iBAAiB,KAAmB;EAClC,MAAM,MAAM,MAAA,WAAiB,MAAA,MAAY,KAAK,IAAI;AAClD,SAAO,MAAM,KAAM,QAAQ,KAAK,CAAC,MAAA,MAAY;;CAG/C,CAAC,KAAK,QAAiC;EACrC,MAAM,mBAAmB,QAAa,MAAA,gBAAsB,IAAI;AAChE,MAAI,OAAO,SAAS,QAAQ;AAC1B,UAAO,4BACL,QACA,iBACA,MAAA,QACA,KACD;AACD;;AAKF,MAAI,gBAAgB,OAAO,KAAK,IAAI,CAClC,QAAO,MAAA,OAAa,KAAK,QAAQ,KAAK;;CAI1C,UAAU,KAAgD;EACxD,MAAM,aAAa;GACjB,KAAK,MAAA,MAAY;GACjB,OAAO,MAAA,MAAY,YAAY,UAAU;GAC1C;AAED,MAAI,CAAC,IAAI,OAAO;AACd,OAAI,IAAI,QACN;AAEF,UAAO;;EAGT,MAAM,MAAM,MAAA,WAAiB,MAAA,MAAY,KAAK,IAAI,MAAM,IAAI;AAE5D,MAAI,CAAC,IAAI,SAAS;AAIhB,OAAI,MAAM,EACR,QAAO;AAKT,OAAI,QAAQ,GAAG;AACb,QAAI,MAAA,MAAY,aAAa,IAAI,MAAM,UAAU,QAC/C,QAAO;KACL,KAAK,MAAA,MAAY;KACjB,OAAO;KACR;AAEH,WAAO;;AAGT,UAAO,IAAI;;AAGb,MAAI;AAIJ,MAAI,MAAM,EACR,QAAO;AAGT,MAAI,QAAQ,GAAG;AAGb,OAAI,CAAC,MAAA,MAAY,aAAa,IAAI,MAAM,UAAU,KAChD,QAAO;AAIT,UAAO;;AAIT,SAAO,IAAI"}
|
|
@@ -52,7 +52,7 @@ export interface Source {
|
|
|
52
52
|
* keys in splitEditKeys, the source should split the edit change into
|
|
53
53
|
* a remove of the old row followed by an add of the new row.
|
|
54
54
|
*/
|
|
55
|
-
connect(sort: Ordering, filters?: Condition, splitEditKeys?: Set<string>, debug?: DebugDelegate): SourceInput;
|
|
55
|
+
connect(sort: Ordering | undefined, filters?: Condition, splitEditKeys?: Set<string>, debug?: DebugDelegate): SourceInput;
|
|
56
56
|
/**
|
|
57
57
|
* Pushes a change into the source and into all connected outputs.
|
|
58
58
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"source.d.ts","sourceRoot":"","sources":["../../../../../zql/src/ivm/source.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,SAAS,EAAE,QAAQ,EAAC,MAAM,mCAAmC,CAAC;AAC3E,OAAO,KAAK,EAAC,GAAG,EAAC,MAAM,oCAAoC,CAAC;AAC5D,OAAO,KAAK,EAAC,WAAW,EAAC,MAAM,mCAAmC,CAAC;AACnE,OAAO,KAAK,EAAC,aAAa,EAAC,MAAM,8BAA8B,CAAC;AAChE,OAAO,KAAK,EAAC,KAAK,EAAC,MAAM,eAAe,CAAC;AACzC,OAAO,KAAK,EAAC,MAAM,EAAC,MAAM,aAAa,CAAC;AAExC,MAAM,MAAM,eAAe,GAAG;IAC5B,IAAI,EAAE,KAAK,CAAC;IACZ,GAAG,EAAE,GAAG,CAAC;CACV,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG;IAC/B,IAAI,EAAE,QAAQ,CAAC;IACf,GAAG,EAAE,GAAG,CAAC;CACV,CAAC;AAEF,MAAM,MAAM,gBAAgB,GAAG;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,GAAG,CAAC;IACT,MAAM,EAAE,GAAG,CAAC;CACb,CAAC;AAEF,MAAM,MAAM,YAAY,GACpB,eAAe,GACf,kBAAkB,GAClB,gBAAgB,CAAC;AAErB;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,WAAW,MAAM;IACrB,IAAI,WAAW,IAAI,WAAW,CAAC;IAC/B;;;;;;;;;;;OAWG;IACH,OAAO,CACL,IAAI,EAAE,QAAQ,
|
|
1
|
+
{"version":3,"file":"source.d.ts","sourceRoot":"","sources":["../../../../../zql/src/ivm/source.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,SAAS,EAAE,QAAQ,EAAC,MAAM,mCAAmC,CAAC;AAC3E,OAAO,KAAK,EAAC,GAAG,EAAC,MAAM,oCAAoC,CAAC;AAC5D,OAAO,KAAK,EAAC,WAAW,EAAC,MAAM,mCAAmC,CAAC;AACnE,OAAO,KAAK,EAAC,aAAa,EAAC,MAAM,8BAA8B,CAAC;AAChE,OAAO,KAAK,EAAC,KAAK,EAAC,MAAM,eAAe,CAAC;AACzC,OAAO,KAAK,EAAC,MAAM,EAAC,MAAM,aAAa,CAAC;AAExC,MAAM,MAAM,eAAe,GAAG;IAC5B,IAAI,EAAE,KAAK,CAAC;IACZ,GAAG,EAAE,GAAG,CAAC;CACV,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG;IAC/B,IAAI,EAAE,QAAQ,CAAC;IACf,GAAG,EAAE,GAAG,CAAC;CACV,CAAC;AAEF,MAAM,MAAM,gBAAgB,GAAG;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,GAAG,CAAC;IACT,MAAM,EAAE,GAAG,CAAC;CACb,CAAC;AAEF,MAAM,MAAM,YAAY,GACpB,eAAe,GACf,kBAAkB,GAClB,gBAAgB,CAAC;AAErB;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,WAAW,MAAM;IACrB,IAAI,WAAW,IAAI,WAAW,CAAC;IAC/B;;;;;;;;;;;OAWG;IACH,OAAO,CACL,IAAI,EAAE,QAAQ,GAAG,SAAS,EAC1B,OAAO,CAAC,EAAE,SAAS,EACnB,aAAa,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,EAC3B,KAAK,CAAC,EAAE,aAAa,GACpB,WAAW,CAAC;IAEf;;;;;;;;OAQG;IACH,IAAI,CAAC,MAAM,EAAE,YAAY,GAAG,MAAM,CAAC,OAAO,CAAC,CAAC;IAE5C;;;;;;;;;OASG;IACH,OAAO,CAAC,MAAM,EAAE,YAAY,GAAG,MAAM,CAAC,OAAO,GAAG,SAAS,CAAC,CAAC;CAC5D;AAED,MAAM,WAAW,WAAY,SAAQ,KAAK;IACxC,QAAQ,CAAC,mBAAmB,EAAE,OAAO,CAAC;CACvC"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { PrimaryKey } from '../../../zero-protocol/src/primary-key.ts';
|
|
2
2
|
import { type Change } from './change.ts';
|
|
3
|
-
import {
|
|
3
|
+
import type { Constraint } from './constraint.ts';
|
|
4
|
+
import { type Comparator, type Node } from './data.ts';
|
|
4
5
|
import { type FetchRequest, type Input, type Operator, type Output, type Storage } from './operator.ts';
|
|
5
6
|
import type { SourceSchema } from './schema.ts';
|
|
6
7
|
import { type Stream } from './stream.ts';
|
|
@@ -25,4 +26,6 @@ export declare class Take implements Operator {
|
|
|
25
26
|
push(change: Change): Stream<'yield'>;
|
|
26
27
|
destroy(): void;
|
|
27
28
|
}
|
|
29
|
+
export declare function constraintMatchesPartitionKey(constraint: Constraint | undefined, partitionKey: PartitionKey | undefined): boolean;
|
|
30
|
+
export declare function makePartitionKeyComparator(partitionKey: PartitionKey): Comparator;
|
|
28
31
|
//# sourceMappingURL=take.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"take.d.ts","sourceRoot":"","sources":["../../../../../zql/src/ivm/take.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAC,UAAU,EAAC,MAAM,2CAA2C,CAAC;AAE1E,OAAO,EAAC,KAAK,MAAM,EAAqC,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"take.d.ts","sourceRoot":"","sources":["../../../../../zql/src/ivm/take.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAC,UAAU,EAAC,MAAM,2CAA2C,CAAC;AAE1E,OAAO,EAAC,KAAK,MAAM,EAAqC,MAAM,aAAa,CAAC;AAC5E,OAAO,KAAK,EAAC,UAAU,EAAC,MAAM,iBAAiB,CAAC;AAChD,OAAO,EAAgB,KAAK,UAAU,EAAE,KAAK,IAAI,EAAC,MAAM,WAAW,CAAC;AACpE,OAAO,EAEL,KAAK,YAAY,EACjB,KAAK,KAAK,EACV,KAAK,QAAQ,EACb,KAAK,MAAM,EACX,KAAK,OAAO,EACb,MAAM,eAAe,CAAC;AACvB,OAAO,KAAK,EAAC,YAAY,EAAC,MAAM,aAAa,CAAC;AAC9C,OAAO,EAAC,KAAK,MAAM,EAAC,MAAM,aAAa,CAAC;AAiBxC,MAAM,MAAM,YAAY,GAAG,UAAU,CAAC;AAEtC;;;;;;;;;;GAUG;AACH,qBAAa,IAAK,YAAW,QAAQ;;gBAYjC,KAAK,EAAE,KAAK,EACZ,OAAO,EAAE,OAAO,EAChB,KAAK,EAAE,MAAM,EACb,YAAY,CAAC,EAAE,YAAY;IAe7B,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;IAI/B,SAAS,IAAI,YAAY;IAIxB,KAAK,CAAC,GAAG,EAAE,YAAY,GAAG,MAAM,CAAC,IAAI,GAAG,OAAO,CAAC;IAyJhD,IAAI,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC;IA4dtC,OAAO,IAAI,IAAI;CAGhB;AAmBD,wBAAgB,6BAA6B,CAC3C,UAAU,EAAE,UAAU,GAAG,SAAS,EAClC,YAAY,EAAE,YAAY,GAAG,SAAS,GACrC,OAAO,CAaT;AAED,wBAAgB,0BAA0B,CACxC,YAAY,EAAE,YAAY,GACzB,UAAU,CAUZ"}
|
package/out/zql/src/ivm/take.js
CHANGED
|
@@ -26,7 +26,9 @@ var Take = class {
|
|
|
26
26
|
#output = throwOutput;
|
|
27
27
|
constructor(input, storage, limit, partitionKey) {
|
|
28
28
|
assert(limit >= 0, "Limit must be non-negative");
|
|
29
|
-
|
|
29
|
+
const { sort } = input.getSchema();
|
|
30
|
+
assert(sort !== void 0, "Take requires sorted input");
|
|
31
|
+
assertOrderingIncludesPK(sort, input.getSchema().primaryKey);
|
|
30
32
|
input.setOutput(this);
|
|
31
33
|
this.#input = input;
|
|
32
34
|
this.#storage = storage;
|
|
@@ -426,6 +428,6 @@ function makePartitionKeyComparator(partitionKey) {
|
|
|
426
428
|
};
|
|
427
429
|
}
|
|
428
430
|
//#endregion
|
|
429
|
-
export { Take };
|
|
431
|
+
export { Take, constraintMatchesPartitionKey, makePartitionKeyComparator };
|
|
430
432
|
|
|
431
433
|
//# sourceMappingURL=take.js.map
|