@bjornpagen/bumbledb 1.3.1 → 2.0.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/COOKBOOK.md +153 -77
- package/README.md +107 -41
- package/dist/alternatives.d.ts +5 -6
- package/dist/alternatives.d.ts.map +1 -1
- package/dist/alternatives.js +5 -6
- package/dist/alternatives.js.map +1 -1
- package/dist/bin.d.ts +3 -0
- package/dist/bin.d.ts.map +1 -0
- package/dist/bin.js +85 -0
- package/dist/bin.js.map +1 -0
- package/dist/capacity.d.ts +14 -17
- package/dist/capacity.d.ts.map +1 -1
- package/dist/capacity.js +7 -7
- package/dist/capacity.js.map +1 -1
- package/dist/changes.d.ts +32 -40
- package/dist/changes.d.ts.map +1 -1
- package/dist/changes.js +86 -104
- package/dist/changes.js.map +1 -1
- package/dist/closed.d.ts +2 -2
- package/dist/closed.d.ts.map +1 -1
- package/dist/closed.js +5 -5
- package/dist/closed.js.map +1 -1
- package/dist/codec.d.ts +13 -27
- package/dist/codec.d.ts.map +1 -1
- package/dist/codec.js +20 -21
- package/dist/codec.js.map +1 -1
- package/dist/compile.d.ts +26 -50
- package/dist/compile.d.ts.map +1 -1
- package/dist/compile.js +75 -64
- package/dist/compile.js.map +1 -1
- package/dist/database/database.d.ts +98 -0
- package/dist/database/database.d.ts.map +1 -0
- package/dist/database/database.js +249 -0
- package/dist/database/database.js.map +1 -0
- package/dist/database/driver.d.ts +40 -0
- package/dist/database/driver.d.ts.map +1 -0
- package/dist/database/driver.js +68 -0
- package/dist/database/driver.js.map +1 -0
- package/dist/database/fs.d.ts +12 -0
- package/dist/database/fs.d.ts.map +1 -0
- package/dist/database/fs.js +120 -0
- package/dist/database/fs.js.map +1 -0
- package/dist/database/generate.d.ts +26 -0
- package/dist/database/generate.d.ts.map +1 -0
- package/dist/database/generate.js +102 -0
- package/dist/database/generate.js.map +1 -0
- package/dist/database/hosted.d.ts +32 -0
- package/dist/database/hosted.d.ts.map +1 -0
- package/dist/database/hosted.js +44 -0
- package/dist/database/hosted.js.map +1 -0
- package/dist/database/io.d.ts +94 -0
- package/dist/database/io.d.ts.map +1 -0
- package/dist/database/io.js +35 -0
- package/dist/database/io.js.map +1 -0
- package/dist/database/mem.d.ts +26 -0
- package/dist/database/mem.d.ts.map +1 -0
- package/dist/database/mem.js +67 -0
- package/dist/database/mem.js.map +1 -0
- package/dist/database/migration.d.ts +55 -0
- package/dist/database/migration.d.ts.map +1 -0
- package/dist/database/migration.js +46 -0
- package/dist/database/migration.js.map +1 -0
- package/dist/database/s3.d.ts +36 -0
- package/dist/database/s3.d.ts.map +1 -0
- package/dist/database/s3.js +141 -0
- package/dist/database/s3.js.map +1 -0
- package/dist/db.d.ts +44 -128
- package/dist/db.d.ts.map +1 -1
- package/dist/db.js +163 -287
- package/dist/db.js.map +1 -1
- package/dist/engine.d.ts +7 -0
- package/dist/engine.d.ts.map +1 -0
- package/dist/engine.js +2 -0
- package/dist/engine.js.map +1 -0
- package/dist/errors.d.ts +152 -46
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +107 -19
- package/dist/errors.js.map +1 -1
- package/dist/face.d.ts +5 -5
- package/dist/face.d.ts.map +1 -1
- package/dist/face.js +6 -6
- package/dist/face.js.map +1 -1
- package/dist/fields.d.ts +4 -5
- package/dist/fields.d.ts.map +1 -1
- package/dist/fields.js +3 -3
- package/dist/fields.js.map +1 -1
- package/dist/index.d.ts +60 -57
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +27 -28
- package/dist/index.js.map +1 -1
- package/dist/judgment.d.ts +1 -1
- package/dist/judgment.js +1 -1
- package/dist/law.d.ts +16 -68
- package/dist/law.d.ts.map +1 -1
- package/dist/law.js +3 -3
- package/dist/law.js.map +1 -1
- package/dist/lower.d.ts +3 -3
- package/dist/lower.d.ts.map +1 -1
- package/dist/lower.js +35 -39
- package/dist/lower.js.map +1 -1
- package/dist/native/addon.d.ts +23 -0
- package/dist/native/addon.d.ts.map +1 -0
- package/dist/native/addon.js +15 -0
- package/dist/native/addon.js.map +1 -0
- package/dist/native/binding.d.ts +996 -0
- package/dist/native/json.d.ts +14 -0
- package/dist/native/json.d.ts.map +1 -0
- package/dist/native/json.js +73 -0
- package/dist/native/json.js.map +1 -0
- package/dist/native/load.d.ts +9 -0
- package/dist/native/load.d.ts.map +1 -0
- package/dist/native/load.js +30 -0
- package/dist/native/load.js.map +1 -0
- package/dist/native/op.d.ts +29 -0
- package/dist/native/op.d.ts.map +1 -0
- package/dist/native/op.js +50 -0
- package/dist/native/op.js.map +1 -0
- package/dist/query/atom.d.ts +13 -14
- package/dist/query/atom.d.ts.map +1 -1
- package/dist/query/atom.js +2 -2
- package/dist/query/atom.js.map +1 -1
- package/dist/query/compute.d.ts +4 -4
- package/dist/query/compute.d.ts.map +1 -1
- package/dist/query/compute.js +4 -4
- package/dist/query/compute.js.map +1 -1
- package/dist/query/find.d.ts +8 -8
- package/dist/query/find.d.ts.map +1 -1
- package/dist/query/find.js +1 -1
- package/dist/query/lower.d.ts +22 -17
- package/dist/query/lower.d.ts.map +1 -1
- package/dist/query/lower.js +230 -343
- package/dist/query/lower.js.map +1 -1
- package/dist/query/run.d.ts +5 -5
- package/dist/query/run.d.ts.map +1 -1
- package/dist/query/run.js +32 -15
- package/dist/query/run.js.map +1 -1
- package/dist/query/scope.d.ts +20 -28
- package/dist/query/scope.d.ts.map +1 -1
- package/dist/query/scope.js +7 -7
- package/dist/query/scope.js.map +1 -1
- package/dist/query/segments.d.ts +2 -2
- package/dist/query/segments.d.ts.map +1 -1
- package/dist/query/segments.js +3 -3
- package/dist/query/segments.js.map +1 -1
- package/dist/relation.d.ts +1 -1
- package/dist/relation.d.ts.map +1 -1
- package/dist/relation.js +4 -4
- package/dist/relation.js.map +1 -1
- package/dist/result.d.ts +15 -22
- package/dist/result.d.ts.map +1 -1
- package/dist/result.js +30 -39
- package/dist/result.js.map +1 -1
- package/dist/rows.d.ts +9 -33
- package/dist/rows.d.ts.map +1 -1
- package/dist/rows.js +8 -12
- package/dist/rows.js.map +1 -1
- package/dist/runtime.d.ts +17 -20
- package/dist/runtime.d.ts.map +1 -1
- package/dist/runtime.js +41 -205
- package/dist/runtime.js.map +1 -1
- package/dist/scalar.d.ts +4 -4
- package/dist/scalar.d.ts.map +1 -1
- package/dist/scalar.js +24 -8
- package/dist/scalar.js.map +1 -1
- package/dist/schema.d.ts +7 -18
- package/dist/schema.d.ts.map +1 -1
- package/dist/schema.js +18 -228
- package/dist/schema.js.map +1 -1
- package/dist/selection.d.ts +4 -4
- package/dist/selection.d.ts.map +1 -1
- package/dist/selection.js +5 -5
- package/dist/selection.js.map +1 -1
- package/dist/shape.d.ts +5 -5
- package/dist/shape.d.ts.map +1 -1
- package/dist/spec.d.ts +7 -79
- package/dist/spec.d.ts.map +1 -1
- package/dist/spec.js.map +1 -1
- package/dist/statements.d.ts +3 -3
- package/dist/statements.d.ts.map +1 -1
- package/dist/statements.js +10 -10
- package/dist/statements.js.map +1 -1
- package/dist/uuid.d.ts +1 -1
- package/dist/uuid.d.ts.map +1 -1
- package/dist/uuid.js +1 -1
- package/dist/uuid.js.map +1 -1
- package/dist/values.d.ts +2 -2
- package/dist/values.d.ts.map +1 -1
- package/dist/values.js +2 -2
- package/dist/values.js.map +1 -1
- package/package.json +18 -18
- package/src/alternatives.ts +7 -8
- package/src/bin.ts +82 -0
- package/src/capacity.ts +20 -23
- package/src/changes.ts +134 -191
- package/src/closed.ts +5 -5
- package/src/codec.ts +35 -49
- package/src/compile.ts +91 -113
- package/src/database/database.ts +413 -0
- package/src/database/driver.ts +134 -0
- package/src/database/fs.ts +119 -0
- package/src/database/generate.ts +116 -0
- package/src/database/hosted.ts +102 -0
- package/src/database/io.ts +134 -0
- package/src/database/mem.ts +113 -0
- package/src/database/migration.ts +107 -0
- package/src/database/s3.ts +231 -0
- package/src/db.ts +290 -547
- package/src/engine.ts +14 -0
- package/src/errors.ts +118 -39
- package/src/face.ts +9 -9
- package/src/fields.ts +6 -7
- package/src/index.ts +92 -105
- package/src/judgment.ts +1 -1
- package/src/law.ts +18 -70
- package/src/lower.ts +61 -72
- package/src/native/addon.ts +54 -0
- package/src/native/binding.d.ts +996 -0
- package/src/native/json.ts +100 -0
- package/src/native/load.ts +31 -0
- package/src/native/op.ts +73 -0
- package/src/query/atom.ts +15 -16
- package/src/query/compute.ts +7 -7
- package/src/query/find.ts +8 -8
- package/src/query/lower.ts +270 -392
- package/src/query/run.ts +42 -21
- package/src/query/scope.ts +29 -37
- package/src/query/segments.ts +4 -4
- package/src/relation.ts +4 -4
- package/src/result.ts +53 -80
- package/src/rows.ts +18 -46
- package/src/runtime.ts +50 -277
- package/src/scalar.ts +32 -12
- package/src/schema.ts +23 -284
- package/src/selection.ts +6 -6
- package/src/shape.ts +5 -5
- package/src/spec.ts +7 -85
- package/src/statements.ts +11 -11
- package/src/uuid.ts +1 -1
- package/src/values.ts +4 -4
- package/dist/close.d.ts +0 -24
- package/dist/close.d.ts.map +0 -1
- package/dist/close.js +0 -34
- package/dist/close.js.map +0 -1
- package/dist/db-native.d.ts +0 -189
- package/dist/db-native.d.ts.map +0 -1
- package/dist/db-native.js +0 -13
- package/dist/db-native.js.map +0 -1
- package/dist/internal/log.d.ts +0 -26
- package/dist/internal/log.d.ts.map +0 -1
- package/dist/internal/log.js +0 -12
- package/dist/internal/log.js.map +0 -1
- package/dist/native.d.ts +0 -562
- package/dist/native.d.ts.map +0 -1
- package/dist/native.js +0 -123
- package/dist/native.js.map +0 -1
- package/dist/query/description.d.ts +0 -41
- package/dist/query/description.d.ts.map +0 -1
- package/dist/query/description.js +0 -311
- package/dist/query/description.js.map +0 -1
- package/dist/query/parse-ir.d.ts +0 -10
- package/dist/query/parse-ir.d.ts.map +0 -1
- package/dist/query/parse-ir.js +0 -280
- package/dist/query/parse-ir.js.map +0 -1
- package/dist/runtime-codes.d.ts +0 -2
- package/dist/runtime-codes.d.ts.map +0 -1
- package/dist/runtime-codes.js +0 -19
- package/dist/runtime-codes.js.map +0 -1
- package/dist/runtime-errors.d.ts +0 -138
- package/dist/runtime-errors.d.ts.map +0 -1
- package/dist/runtime-errors.js +0 -111
- package/dist/runtime-errors.js.map +0 -1
- package/dist/runtime-native.d.ts +0 -136
- package/dist/runtime-native.d.ts.map +0 -1
- package/dist/runtime-native.js +0 -5
- package/dist/runtime-native.js.map +0 -1
- package/dist/schema-file.d.ts +0 -7
- package/dist/schema-file.d.ts.map +0 -1
- package/dist/schema-file.js +0 -24
- package/dist/schema-file.js.map +0 -1
- package/pack-provenance.json +0 -7
- package/src/close.ts +0 -53
- package/src/db-native.ts +0 -235
- package/src/internal/log.ts +0 -46
- package/src/native.ts +0 -736
- package/src/query/description.ts +0 -424
- package/src/query/parse-ir.ts +0 -293
- package/src/runtime-codes.ts +0 -18
- package/src/runtime-errors.ts +0 -122
- package/src/runtime-native.ts +0 -181
- package/src/schema-file.ts +0 -38
package/src/query/run.ts
CHANGED
|
@@ -1,11 +1,34 @@
|
|
|
1
|
-
import { AuthoringError,
|
|
2
|
-
import type {
|
|
3
|
-
import type {
|
|
4
|
-
import {
|
|
5
|
-
import type {
|
|
6
|
-
import
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
1
|
+
import { AuthoringError, internalError } from "../errors.ts"
|
|
2
|
+
import type { CellIn, ParamIn } from "../native/binding.d.ts"
|
|
3
|
+
import type { CellValue } from "../rows.ts"
|
|
4
|
+
import { decodeCell, handleOf, setOwnField } from "../rows.ts"
|
|
5
|
+
import type { QueryParam, TaggedValue } from "../spec.ts"
|
|
6
|
+
import { arrayValue, recordValue } from "../values.ts"
|
|
7
|
+
import type { FindColumn } from "./atom.ts"
|
|
8
|
+
import { taggedCmpLiteral } from "./lower.ts"
|
|
9
|
+
import type { ParamEntry } from "./scope.ts"
|
|
10
|
+
|
|
11
|
+
const CELL = {
|
|
12
|
+
bool: "Bool",
|
|
13
|
+
u64: "U64",
|
|
14
|
+
i64: "I64",
|
|
15
|
+
f64: "F64",
|
|
16
|
+
string: "String",
|
|
17
|
+
uuid: "Uuid",
|
|
18
|
+
fixedBytes: "FixedBytes",
|
|
19
|
+
intervalU64: "IntervalU64",
|
|
20
|
+
intervalI64: "IntervalI64",
|
|
21
|
+
intervalF64: "IntervalF64"
|
|
22
|
+
} as const
|
|
23
|
+
|
|
24
|
+
/** One tagged value as the addon's data-plane `CellIn`. */
|
|
25
|
+
function cellIn(value: TaggedValue): CellIn {
|
|
26
|
+
return { ...value, kind: CELL[value.kind] } as CellIn
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function paramIn(param: QueryParam): ParamIn {
|
|
30
|
+
return param.kind === "set" ? { kind: "Set", values: param.values.map(cellIn) } : cellIn(param)
|
|
31
|
+
}
|
|
9
32
|
|
|
10
33
|
function wireValue(entry: ParamEntry, context: string, value: unknown): TaggedValue {
|
|
11
34
|
if (entry.anchor === undefined) {
|
|
@@ -16,15 +39,15 @@ function wireValue(entry: ParamEntry, context: string, value: unknown): TaggedVa
|
|
|
16
39
|
return taggedCmpLiteral(context, entry.anchor, value, entry.op)
|
|
17
40
|
}
|
|
18
41
|
|
|
19
|
-
function wireParams(entries: readonly ParamEntry[], supplied: Readonly<Record<string, unknown>>):
|
|
42
|
+
function wireParams(entries: readonly ParamEntry[], supplied: Readonly<Record<string, unknown>>): ParamIn[] {
|
|
20
43
|
const input = recordValue(
|
|
21
44
|
"query parameters",
|
|
22
45
|
supplied,
|
|
23
46
|
entries.filter((entry) => entry.membership === undefined).map((entry) => entry.name)
|
|
24
47
|
)
|
|
25
|
-
return entries.map(function wireOne(entry):
|
|
48
|
+
return entries.map(function wireOne(entry): ParamIn {
|
|
26
49
|
if (entry.membership !== undefined) {
|
|
27
|
-
return entry.membership
|
|
50
|
+
return paramIn(entry.membership)
|
|
28
51
|
}
|
|
29
52
|
const value = input[entry.name]
|
|
30
53
|
if (value === undefined) {
|
|
@@ -32,13 +55,13 @@ function wireParams(entries: readonly ParamEntry[], supplied: Readonly<Record<st
|
|
|
32
55
|
}
|
|
33
56
|
if (entry.shape === "set") {
|
|
34
57
|
return {
|
|
35
|
-
kind: "
|
|
36
|
-
values:
|
|
37
|
-
|
|
38
|
-
|
|
58
|
+
kind: "Set",
|
|
59
|
+
values: [
|
|
60
|
+
...arrayValue(`param ${entry.name}`, value, (context, element) => cellIn(wireValue(entry, context, element)))
|
|
61
|
+
]
|
|
39
62
|
}
|
|
40
63
|
}
|
|
41
|
-
return wireValue(entry, `param ${entry.name}`, value)
|
|
64
|
+
return cellIn(wireValue(entry, `param ${entry.name}`, value))
|
|
42
65
|
})
|
|
43
66
|
}
|
|
44
67
|
|
|
@@ -63,15 +86,13 @@ function isAnswerRow<Row>(
|
|
|
63
86
|
function decodeAnswers<Row>(finds: readonly FindColumn[], rows: readonly (readonly CellValue[])[]): Row[] {
|
|
64
87
|
return rows.map(function decodeRow(row) {
|
|
65
88
|
if (row.length !== finds.length) {
|
|
66
|
-
throw
|
|
67
|
-
message: `query answer arity ${row.length} does not match the ${finds.length} find columns`
|
|
68
|
-
})
|
|
89
|
+
throw internalError(`query answer arity ${row.length} does not match the ${finds.length} find columns`)
|
|
69
90
|
}
|
|
70
91
|
const decoded: Record<string, unknown> = {}
|
|
71
92
|
finds.forEach(function decodeColumn(column, ordinal) {
|
|
72
93
|
const cell = row[ordinal]
|
|
73
94
|
if (cell === undefined) {
|
|
74
|
-
throw
|
|
95
|
+
throw internalError(`query answer cell ${ordinal} (${column.name}) is absent`)
|
|
75
96
|
}
|
|
76
97
|
if (column.slot !== undefined) {
|
|
77
98
|
setOwnField(decoded, column.name, decodeCell(`query answer column ${column.name}`, column.slot.field, cell))
|
|
@@ -85,7 +106,7 @@ function decodeAnswers<Row>(finds: readonly FindColumn[], rows: readonly (readon
|
|
|
85
106
|
})
|
|
86
107
|
Object.freeze(decoded)
|
|
87
108
|
if (!isAnswerRow<Row>(finds, decoded)) {
|
|
88
|
-
throw
|
|
109
|
+
throw internalError("query answer row is not a complete find record")
|
|
89
110
|
}
|
|
90
111
|
return decoded
|
|
91
112
|
})
|
package/src/query/scope.ts
CHANGED
|
@@ -1,18 +1,18 @@
|
|
|
1
|
-
import type { AnyClosed } from "
|
|
2
|
-
import { memberDescriptor, sealedFieldsOf } from "
|
|
3
|
-
import { AuthoringError,
|
|
4
|
-
import type { AnyField, Infer, SignatureOf } from "
|
|
5
|
-
import { rosterOf, signaturesAgree } from "
|
|
6
|
-
import type { Same, SameLen } from "
|
|
7
|
-
import type { ClassLookup, ClassRecordOf, SchemaClasses } from "
|
|
8
|
-
import type {
|
|
9
|
-
import type {
|
|
10
|
-
import type {
|
|
11
|
-
import type {
|
|
12
|
-
|
|
13
|
-
const term: unique symbol = Symbol("
|
|
14
|
-
|
|
15
|
-
const inferred: unique symbol = Symbol("
|
|
1
|
+
import type { AnyClosed } from "../closed.ts"
|
|
2
|
+
import { memberDescriptor, sealedFieldsOf } from "../closed.ts"
|
|
3
|
+
import { AuthoringError, internalError } from "../errors.ts"
|
|
4
|
+
import type { AnyField, Infer, SignatureOf } from "../fields.ts"
|
|
5
|
+
import { rosterOf, signaturesAgree } from "../fields.ts"
|
|
6
|
+
import type { Same, SameLen } from "../judgment.ts"
|
|
7
|
+
import type { ClassLookup, ClassRecordOf, SchemaClasses } from "../law.ts"
|
|
8
|
+
import type { AnyRelation } from "../relation.ts"
|
|
9
|
+
import type { FieldsOf } from "../selection.ts"
|
|
10
|
+
import type { QueryParam } from "../spec.ts"
|
|
11
|
+
import type { FindColumn } from "./atom.ts"
|
|
12
|
+
|
|
13
|
+
const term: unique symbol = Symbol("bdb.query.term")
|
|
14
|
+
|
|
15
|
+
const inferred: unique symbol = Symbol("bdb.query.inferred")
|
|
16
16
|
|
|
17
17
|
type MatchOwner = AnyRelation | AnyClosed
|
|
18
18
|
|
|
@@ -58,11 +58,10 @@ type VarsOf<R extends MatchOwner> = {
|
|
|
58
58
|
* mintable variable inhabits. So an aliased or function-returned record
|
|
59
59
|
* carrying an extra key (`{...v(Account), extra: otherVar }` — shapes
|
|
60
60
|
* excess-property checking never sees, it covers inline literals only)
|
|
61
|
-
* fails the intersection and falls to the general form's
|
|
62
|
-
*
|
|
63
|
-
*
|
|
64
|
-
*
|
|
65
|
-
* law (50-generic-binding.md, "The ruling") stands untouched.
|
|
61
|
+
* fails the intersection and falls to the general form's compile refusal.
|
|
62
|
+
* The identity record `v(rel)` still unifies for GENERIC `R`: the judgment
|
|
63
|
+
* is intersections and index constraints only, with no deferred
|
|
64
|
+
* conditional, so the full-binding law holds.
|
|
66
65
|
*/
|
|
67
66
|
type ExactVars<R extends MatchOwner, B> = {
|
|
68
67
|
readonly [K in keyof B]: Var<AnyField, R["name"], K & keyof MatchFields<R> & string>
|
|
@@ -80,21 +79,9 @@ function varsMinted<R extends MatchOwner>(owner: R, record: Readonly<Record<stri
|
|
|
80
79
|
})
|
|
81
80
|
}
|
|
82
81
|
|
|
83
|
-
/**
|
|
84
|
-
* Mints a FRESH batch of query variables over an atom owner's
|
|
85
|
-
* statically-known columns — one variable per sealed column
|
|
86
|
-
* (`sealedFieldsOf`: a closed owner mints `id` first, then payload columns),
|
|
87
|
-
* each frozen and each defined by OWN-property definition (object-protocol
|
|
88
|
-
* column names must work, the `closed` precedent). Every `v` call mints
|
|
89
|
-
* new objects, so two batches are two variables; property access within one
|
|
90
|
-
* batch is stable by construction (the record is an eager frozen record,
|
|
91
|
-
* never a Proxy). Variable identity is the object reference: destructure
|
|
92
|
-
* what you need (`const { id, holder } = v(Account)`) and reuse a value
|
|
93
|
-
* across binding positions to join.
|
|
94
|
-
*/
|
|
95
82
|
/**
|
|
96
83
|
* A schema-bound query template used as a relation-expression source
|
|
97
|
-
* (
|
|
84
|
+
* (nonrecursive composition): structurally, the query value's
|
|
98
85
|
* own frozen data. Detection is structural so `scope.ts` needs no runtime
|
|
99
86
|
* import of the query module.
|
|
100
87
|
*/
|
|
@@ -194,6 +181,11 @@ function importFacadeOfOwner(owner: object): ImportFacade | undefined {
|
|
|
194
181
|
return facadeByOwner.get(owner)
|
|
195
182
|
}
|
|
196
183
|
|
|
184
|
+
/**
|
|
185
|
+
* Mints fresh query variables, one per column of a relation, closed roster or imported query
|
|
186
|
+
* (a closed owner's `id` first). Each call mints new variables; reusing one across binding
|
|
187
|
+
* positions joins, so destructure what you need: `const { id, holder } = v(Account)`.
|
|
188
|
+
*/
|
|
197
189
|
function v<R extends MatchOwner>(owner: R): VarsOf<R>
|
|
198
190
|
function v<Q extends ImportedSource>(imported: Q): ImportVars<Q>
|
|
199
191
|
function v(owner: MatchOwner | ImportedSource): Readonly<Record<string, AnyVar>> {
|
|
@@ -203,7 +195,7 @@ function v(owner: MatchOwner | ImportedSource): Readonly<Record<string, AnyVar>>
|
|
|
203
195
|
for (const [columnName, column] of facade.columns) {
|
|
204
196
|
const slot = column.slot
|
|
205
197
|
if (slot === undefined) {
|
|
206
|
-
throw
|
|
198
|
+
throw internalError(`v(query): facade column ${columnName} lost its slot`)
|
|
207
199
|
}
|
|
208
200
|
const variable: AnyVar = Object.freeze({
|
|
209
201
|
[term]: "var" as const,
|
|
@@ -230,7 +222,7 @@ function v(owner: MatchOwner | ImportedSource): Readonly<Record<string, AnyVar>>
|
|
|
230
222
|
}
|
|
231
223
|
Object.freeze(record)
|
|
232
224
|
if (!varsMinted(member, record)) {
|
|
233
|
-
throw
|
|
225
|
+
throw internalError(`v(${member.name}): variable-record minting incomplete`)
|
|
234
226
|
}
|
|
235
227
|
return record
|
|
236
228
|
}
|
|
@@ -305,8 +297,8 @@ type ClosedHandles<F extends AnyField> = F extends {
|
|
|
305
297
|
|
|
306
298
|
/**
|
|
307
299
|
* Two closed ids anti-join when their handle vectors carry the same Peano
|
|
308
|
-
* length ({@link SameLen}: zero equals zero,
|
|
309
|
-
*
|
|
300
|
+
* length ({@link SameLen}: zero equals zero, n + 1 recurses on n). A bare
|
|
301
|
+
* field has no vector and proves nothing.
|
|
310
302
|
*/
|
|
311
303
|
type ClosedIdOk<A extends AnyField, B extends AnyField> = [ClosedHandles<A>] extends [never]
|
|
312
304
|
? false
|
package/src/query/segments.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { AuthoringError } from "
|
|
2
|
-
import type { IntervalElementKind, IntervalField } from "
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
1
|
+
import { AuthoringError } from "../errors.ts"
|
|
2
|
+
import type { IntervalElementKind, IntervalField } from "../fields.ts"
|
|
3
|
+
import { recordValue } from "../values.ts"
|
|
4
|
+
import { type AnyVar, isTerm, term } from "./scope.ts"
|
|
5
5
|
|
|
6
6
|
type IntervalVar<E extends IntervalElementKind = IntervalElementKind> = AnyVar & { readonly field: IntervalField<E> }
|
|
7
7
|
type SegmentOp = "intersection" | "difference"
|
package/src/relation.ts
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
import { AuthoringError } from "
|
|
1
|
+
import { AuthoringError } from "./errors.ts"
|
|
2
2
|
import {
|
|
3
3
|
type AnyField,
|
|
4
4
|
assertDeclarationOrderKey,
|
|
5
5
|
assertDeclarationRecord,
|
|
6
6
|
fieldDescriptor,
|
|
7
7
|
type Infer
|
|
8
|
-
} from "
|
|
9
|
-
import { descriptorCache } from "
|
|
10
|
-
import { recordValue } from "
|
|
8
|
+
} from "./fields.ts"
|
|
9
|
+
import { descriptorCache } from "./immutable.ts"
|
|
10
|
+
import { recordValue } from "./values.ts"
|
|
11
11
|
|
|
12
12
|
/** Ordinary relations are structural declarations. Field order defines native ordinals. */
|
|
13
13
|
interface Relation<Name extends string = string, Fields extends FieldsShape = FieldsShape> {
|
package/src/result.ts
CHANGED
|
@@ -1,101 +1,74 @@
|
|
|
1
1
|
import { Effect, Option, Stream } from "effect"
|
|
2
|
-
import {
|
|
3
|
-
import type {
|
|
4
|
-
import {
|
|
5
|
-
import
|
|
6
|
-
import {
|
|
7
|
-
import
|
|
8
|
-
import {
|
|
9
|
-
import type { CloseReport, DbError } from "#runtime-errors.ts"
|
|
2
|
+
import type { DbError } from "./errors.ts"
|
|
3
|
+
import type { CursorRef, ResultRef } from "./native/addon.ts"
|
|
4
|
+
import { addon } from "./native/addon.ts"
|
|
5
|
+
import { call, scoped } from "./native/op.ts"
|
|
6
|
+
import type { FindColumn } from "./query/atom.ts"
|
|
7
|
+
import { decodeAnswers } from "./query/run.ts"
|
|
8
|
+
import type { CellValue } from "./rows.ts"
|
|
10
9
|
|
|
11
10
|
/**
|
|
12
|
-
* One complete answer set, sealed after evaluation and independent of its
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
* The stream owns its cursor through Effect scope. Early termination,
|
|
18
|
-
* failure, interruption and EOF close/drain it. Creating the stream does
|
|
19
|
-
* not spend the result; running it twice fails with SpentHandle.
|
|
11
|
+
* One complete answer set, sealed after evaluation and independent of its snapshot. `collect`
|
|
12
|
+
* reads every row and leaves the result readable. `pages` spends the result once through
|
|
13
|
+
* bounded batches; the stream owns its cursor, so ending it early releases the cursor, and
|
|
14
|
+
* running it a second time fails with `SpentHandle`.
|
|
20
15
|
*/
|
|
21
16
|
interface CompleteResult<A> {
|
|
22
17
|
collect(): Effect.Effect<ReadonlyArray<A>, DbError>
|
|
23
18
|
pages(): Stream.Stream<ReadonlyArray<A>, DbError>
|
|
24
|
-
close(): Effect.Effect<CloseReport>
|
|
25
19
|
}
|
|
26
20
|
|
|
27
|
-
|
|
28
|
-
|
|
21
|
+
function decodePage<A>(finds: readonly FindColumn[], rows: readonly (readonly CellValue[])[]): ReadonlyArray<A> {
|
|
22
|
+
return Object.freeze(decodeAnswers<A>(finds, rows))
|
|
29
23
|
}
|
|
30
24
|
|
|
31
|
-
|
|
25
|
+
class CompleteResultLive<A> implements CompleteResult<A> {
|
|
26
|
+
readonly #handle: ResultRef
|
|
27
|
+
readonly #finds: readonly FindColumn[]
|
|
32
28
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
}
|
|
29
|
+
constructor(handle: ResultRef, finds: readonly FindColumn[]) {
|
|
30
|
+
this.#handle = handle
|
|
31
|
+
this.#finds = finds
|
|
32
|
+
}
|
|
37
33
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
34
|
+
collect(): Effect.Effect<ReadonlyArray<A>, DbError> {
|
|
35
|
+
const handle = this.#handle
|
|
36
|
+
const finds = this.#finds
|
|
37
|
+
return call(
|
|
38
|
+
"CompleteResult.collect",
|
|
39
|
+
(done) => addon.runtimeResultCollect(handle, done),
|
|
40
|
+
(lease) => decodePage<A>(finds, addon.runtimeRowsTake(lease))
|
|
41
|
+
).pipe(Effect.withSpan("CompleteResult.collect"))
|
|
42
|
+
}
|
|
43
43
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
function
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
"CompleteResult.collect",
|
|
54
|
-
(callback) => dbNative.runtimeResultCollect(handle, callback),
|
|
55
|
-
dbNative.runtimeRowsTake,
|
|
56
|
-
(rows) => decodePage<A>(finds, rows)
|
|
44
|
+
pages(): Stream.Stream<ReadonlyArray<A>, DbError> {
|
|
45
|
+
const handle = this.#handle
|
|
46
|
+
const finds = this.#finds
|
|
47
|
+
return Stream.unwrap(
|
|
48
|
+
Effect.gen(function* () {
|
|
49
|
+
const cursor: CursorRef = yield* scoped(
|
|
50
|
+
"ResultCursor.release",
|
|
51
|
+
call("CompleteResult.pages", (done) => addon.runtimeResultCursor(handle, done), addon.runtimeCursorTake),
|
|
52
|
+
(owned) => (done) => addon.runtimeCursorClose(owned, done)
|
|
57
53
|
)
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
nativeOperationWith(
|
|
65
|
-
"CompleteResult.pages",
|
|
66
|
-
(callback) => dbNative.runtimeResultCursor(handle, callback),
|
|
67
|
-
dbNative.runtimeCursorTake,
|
|
68
|
-
(taken) => taken
|
|
69
|
-
),
|
|
70
|
-
(taken) => releaseOwner("ResultCursor.close", (callback) => dbNative.runtimeCursorClose(taken, callback)),
|
|
71
|
-
{ interruptible: true }
|
|
72
|
-
)
|
|
73
|
-
return Stream.paginate(undefined, () =>
|
|
74
|
-
nativeOperationWith(
|
|
75
|
-
"CompleteResult.page",
|
|
76
|
-
(callback) => dbNative.runtimeCursorNext(cursor, callback),
|
|
77
|
-
dbNative.runtimePageTake,
|
|
78
|
-
(page) => page
|
|
79
|
-
).pipe(
|
|
80
|
-
Effect.map((page) => {
|
|
81
|
-
if (page === null) {
|
|
82
|
-
return [[], Option.none<undefined>()] as const
|
|
83
|
-
}
|
|
84
|
-
return [[decodePage<A>(finds, page)], Option.some(undefined)] as const
|
|
85
|
-
})
|
|
54
|
+
return Stream.paginate(undefined, () =>
|
|
55
|
+
call("CompleteResult.page", (done) => addon.runtimeCursorNext(cursor, done), addon.runtimePageTake).pipe(
|
|
56
|
+
Effect.map((page) =>
|
|
57
|
+
page === null
|
|
58
|
+
? ([[], Option.none<undefined>()] as const)
|
|
59
|
+
: ([[decodePage<A>(finds, page)], Option.some(undefined)] as const)
|
|
86
60
|
)
|
|
87
61
|
)
|
|
88
|
-
|
|
89
|
-
)
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
62
|
+
)
|
|
63
|
+
})
|
|
64
|
+
).pipe(Stream.withSpan("CompleteResult.pages"))
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/** The native result behind `value`, when `value` is a result this SDK made. */
|
|
68
|
+
static handle(value: object): ResultRef | undefined {
|
|
69
|
+
return #handle in value ? (value as CompleteResultLive<unknown>).#handle : undefined
|
|
94
70
|
}
|
|
95
|
-
Object.freeze(value)
|
|
96
|
-
resultInternals.set(value, { handle })
|
|
97
|
-
return value
|
|
98
71
|
}
|
|
99
72
|
|
|
100
73
|
export type { CompleteResult }
|
|
101
|
-
export {
|
|
74
|
+
export { CompleteResultLive }
|
package/src/rows.ts
CHANGED
|
@@ -1,46 +1,20 @@
|
|
|
1
|
-
import { AuthoringError,
|
|
1
|
+
import { AuthoringError, internalError } from "./errors.ts"
|
|
2
2
|
/**
|
|
3
|
-
* The row
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
* objects of BARE structural values. This module is the one fact⇄row
|
|
8
|
-
* projector. It covers all value types: bool, u64, i64,
|
|
9
|
-
* f64, uuid, str, bytes<N>, discrete intervals and dense float intervals,
|
|
10
|
-
* plus the closed-handle bijection (name ⇄ declaration-order row id).
|
|
11
|
-
*
|
|
12
|
-
* Cells here are OWNED plain host values; the native boundary re-judges
|
|
13
|
-
* every crossing against its resident sealed roster. Shape misuse throws
|
|
14
|
-
* the pure {@link AuthoringError}; the Effect ingestion boundary catches
|
|
15
|
-
* and types it (never an untracked partial draft). SharedArrayBuffer-backed
|
|
16
|
-
* views are refused before any copy. Host length is judged before string
|
|
17
|
-
* scans and byte copies.
|
|
3
|
+
* The one fact ⇄ row projector: named host objects to positional cells in field-declaration order
|
|
4
|
+
* and back, for every value type plus the closed-handle bijection (name ⇄ declaration-order id).
|
|
5
|
+
* Cells are owned host values that the native boundary checks again; shape misuse throws
|
|
6
|
+
* `AuthoringError`. SharedArrayBuffer-backed views are refused before any copy.
|
|
18
7
|
*/
|
|
19
|
-
import type { AnyClosedRoster, AnyField } from "
|
|
20
|
-
import { literalShapeError, rosterOf } from "
|
|
21
|
-
import
|
|
22
|
-
import {
|
|
23
|
-
|
|
24
|
-
/**
|
|
25
|
-
* One owned cell at the private bridge boundary. The declared sealed field
|
|
26
|
-
* type disambiguates the union: `string` is text, an `uuid` in its
|
|
27
|
-
* canonical hyphenated UUID spelling, or a closed handle
|
|
28
|
-
* before lowering (closed handles cross as `bigint` row ids),
|
|
29
|
-
* `Uint8Array` is `bytes<N>`, `{ start, end }` bigints are a discrete
|
|
30
|
-
* interval and numbers a dense float interval.
|
|
31
|
-
*/
|
|
32
|
-
type CellValue =
|
|
33
|
-
| boolean
|
|
34
|
-
| bigint
|
|
35
|
-
| number
|
|
36
|
-
| string
|
|
37
|
-
| Uint8Array
|
|
38
|
-
| { readonly start: bigint; readonly end: bigint }
|
|
39
|
-
| { readonly start: number; readonly end: number }
|
|
8
|
+
import type { AnyClosedRoster, AnyField } from "./fields.ts"
|
|
9
|
+
import { literalShapeError, rosterOf } from "./fields.ts"
|
|
10
|
+
import type { CellValue } from "./native/binding.d.ts"
|
|
11
|
+
import { type AnyRelation, type Fact, relationFields } from "./relation.ts"
|
|
12
|
+
import { fieldValue, recordValue } from "./values.ts"
|
|
40
13
|
|
|
14
|
+
/** Row-major cells for `rows` rows, in sealed field order. */
|
|
41
15
|
interface FlatRows {
|
|
42
16
|
readonly rows: bigint
|
|
43
|
-
readonly cells:
|
|
17
|
+
readonly cells: CellValue[]
|
|
44
18
|
}
|
|
45
19
|
|
|
46
20
|
function recordOf(fact: object): Readonly<Record<string, unknown>> {
|
|
@@ -141,7 +115,7 @@ function decodeCell(context: string, field: AnyField, cell: unknown): unknown {
|
|
|
141
115
|
try {
|
|
142
116
|
return fieldValue(context, field, cell)
|
|
143
117
|
} catch (cause) {
|
|
144
|
-
if (cause instanceof AuthoringError) throw
|
|
118
|
+
if (cause instanceof AuthoringError) throw internalError(cause.message)
|
|
145
119
|
throw cause
|
|
146
120
|
}
|
|
147
121
|
}
|
|
@@ -162,24 +136,22 @@ function isCompleteFact<R extends AnyRelation>(
|
|
|
162
136
|
function factOfCells<R extends AnyRelation>(relation: R, row: readonly unknown[]): Fact<R> {
|
|
163
137
|
const data = relation
|
|
164
138
|
if (row.length !== relationFields(data).length) {
|
|
165
|
-
throw
|
|
166
|
-
|
|
167
|
-
|
|
139
|
+
throw internalError(
|
|
140
|
+
`relation ${data.name}: row arity ${row.length} does not match the ${relationFields(data).length} declared fields`
|
|
141
|
+
)
|
|
168
142
|
}
|
|
169
143
|
const decoded: Record<string, unknown> = {}
|
|
170
144
|
relationFields(data).forEach(function decodeOne(declared, ordinal) {
|
|
171
145
|
const cell = row[ordinal]
|
|
172
146
|
if (cell === undefined) {
|
|
173
|
-
throw
|
|
174
|
-
message: `relation ${data.name}: row cell ${ordinal} (${declared.name}) is absent`
|
|
175
|
-
})
|
|
147
|
+
throw internalError(`relation ${data.name}: row cell ${ordinal} (${declared.name}) is absent`)
|
|
176
148
|
}
|
|
177
149
|
const value = decodeCell(`relation ${data.name} field ${declared.name}`, declared.field, cell)
|
|
178
150
|
setOwnField(decoded, declared.name, value)
|
|
179
151
|
})
|
|
180
152
|
Object.freeze(decoded)
|
|
181
153
|
if (!isCompleteFact(relation, decoded)) {
|
|
182
|
-
throw
|
|
154
|
+
throw internalError(`relation ${data.name}: decoded row is not a complete fact`)
|
|
183
155
|
}
|
|
184
156
|
return decoded
|
|
185
157
|
}
|