@bjornpagen/bumbledb 1.3.0 → 1.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/COOKBOOK.md +72 -19
- package/README.md +9 -6
- package/dist/changes.d.ts +0 -1
- package/dist/changes.d.ts.map +1 -1
- package/dist/changes.js +2 -8
- package/dist/changes.js.map +1 -1
- package/dist/codec.d.ts +8 -1
- package/dist/codec.d.ts.map +1 -1
- package/dist/codec.js +29 -2
- package/dist/codec.js.map +1 -1
- package/dist/db-native.d.ts +2 -9
- package/dist/db-native.d.ts.map +1 -1
- package/dist/db-native.js.map +1 -1
- package/dist/index.d.ts +2 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -2
- package/dist/index.js.map +1 -1
- package/dist/internal/log.d.ts +4 -4
- package/dist/internal/log.d.ts.map +1 -1
- package/dist/internal/log.js +2 -2
- package/dist/internal/log.js.map +1 -1
- package/dist/native.d.ts +9 -9
- package/dist/native.d.ts.map +1 -1
- package/dist/query/compute.d.ts +3 -3
- package/dist/query/compute.d.ts.map +1 -1
- package/dist/query/compute.js +3 -12
- package/dist/query/compute.js.map +1 -1
- package/dist/query/description.js +4 -4
- package/dist/query/description.js.map +1 -1
- package/dist/query/lower.d.ts +11 -2
- package/dist/query/lower.d.ts.map +1 -1
- package/dist/query/lower.js +31 -26
- package/dist/query/lower.js.map +1 -1
- package/dist/query/parse-ir.d.ts.map +1 -1
- package/dist/query/parse-ir.js +4 -4
- package/dist/query/parse-ir.js.map +1 -1
- package/dist/query/scope.d.ts.map +1 -1
- package/dist/query/scope.js +6 -1
- package/dist/query/scope.js.map +1 -1
- package/dist/runtime-codes.d.ts +1 -1
- package/dist/runtime-codes.d.ts.map +1 -1
- package/dist/runtime-codes.js +1 -0
- package/dist/runtime-codes.js.map +1 -1
- package/dist/runtime-errors.d.ts +23 -3
- package/dist/runtime-errors.d.ts.map +1 -1
- package/dist/runtime-errors.js +16 -3
- package/dist/runtime-errors.js.map +1 -1
- package/dist/runtime-native.d.ts +3 -8
- package/dist/runtime-native.d.ts.map +1 -1
- package/dist/runtime-native.js.map +1 -1
- package/dist/runtime.d.ts +0 -23
- package/dist/runtime.d.ts.map +1 -1
- package/dist/runtime.js +0 -36
- package/dist/runtime.js.map +1 -1
- package/dist/scalar.d.ts +34 -104
- package/dist/scalar.d.ts.map +1 -1
- package/dist/scalar.js +12 -177
- package/dist/scalar.js.map +1 -1
- package/dist/schema-file.d.ts +7 -0
- package/dist/schema-file.d.ts.map +1 -0
- package/dist/schema-file.js +24 -0
- package/dist/schema-file.js.map +1 -0
- package/pack-provenance.json +4 -4
- package/package.json +4 -4
- package/src/changes.ts +2 -8
- package/src/codec.ts +43 -3
- package/src/db-native.ts +2 -10
- package/src/index.ts +11 -5
- package/src/internal/log.ts +2 -4
- package/src/native.ts +7 -7
- package/src/query/compute.ts +6 -15
- package/src/query/description.ts +4 -4
- package/src/query/lower.ts +56 -25
- package/src/query/parse-ir.ts +6 -4
- package/src/query/scope.ts +8 -1
- package/src/runtime-codes.ts +1 -0
- package/src/runtime-errors.ts +16 -3
- package/src/runtime-native.ts +1 -9
- package/src/runtime.ts +1 -70
- package/src/scalar.ts +49 -329
- package/src/schema-file.ts +38 -0
- package/dist/migration.d.ts +0 -31
- package/dist/migration.d.ts.map +0 -1
- package/dist/migration.js +0 -47
- package/dist/migration.js.map +0 -1
- package/src/migration.ts +0 -61
package/src/scalar.ts
CHANGED
|
@@ -1,34 +1,16 @@
|
|
|
1
|
-
/**
|
|
2
|
-
*
|
|
3
|
-
* operator roster, parameterized by {@link ScalarLeafScope}. TypeScript never
|
|
4
|
-
* evaluates — the native compiler binds source fields and the engine
|
|
5
|
-
* `ScalarEvaluator` executes. Construction is constant work against cached
|
|
6
|
-
* depth/kind summaries; it does not re-walk the tree.
|
|
7
|
-
*
|
|
8
|
-
* Query-var leaves carry a known schema kind. Source-field leaves stay
|
|
9
|
-
* `unresolved` until native snapshot binding. A result kind is recorded only
|
|
10
|
-
* when it is derivable from known operands; otherwise it stays unresolved.
|
|
11
|
-
* Known incompatible kinds refuse here. Unresolved trees are inert metadata,
|
|
12
|
-
* not typechecked programs.
|
|
13
|
-
*
|
|
14
|
-
* Wire spellings (the grammar arms, not a second flattened interpretation):
|
|
15
|
-
* migration plan JSON — field/literal/operator nodes; one-arm literals (`{ u64: n }`)
|
|
16
|
-
* query IR — `{ kind: "literal", value: ValueSpec }` via `literalWireOf`
|
|
17
|
-
*/
|
|
1
|
+
/** Query scalar nodes, with cached kind and depth. Construction is constant
|
|
2
|
+
* work; native preparation binds variables and evaluates the expressions. */
|
|
18
3
|
import { AuthoringError } from "#errors.ts"
|
|
19
4
|
import type { ScalarExprIr } from "#native.ts"
|
|
20
5
|
import type { ValueSpec } from "#spec.ts"
|
|
21
6
|
|
|
22
|
-
/** F0: leaf scope for the shared AST (C1). Query vars are typed; source fields stay unresolved. */
|
|
23
|
-
export type ScalarLeafScope = "query-var" | "source-field"
|
|
24
|
-
|
|
25
7
|
/** The engine's scalar result vocabulary — distinct at the type level. */
|
|
26
8
|
type ScalarKind = "u64" | "i64" | "f64" | "bool"
|
|
27
9
|
|
|
28
10
|
/** Cached result kind: known only when derivable; otherwise honestly unresolved. */
|
|
29
11
|
type IntervalKind = "intervalU64" | "intervalI64" | "intervalF64"
|
|
30
12
|
type ScalarInputKind = ScalarKind | IntervalKind
|
|
31
|
-
type ScalarResultKind = ScalarInputKind
|
|
13
|
+
type ScalarResultKind = ScalarInputKind
|
|
32
14
|
type Rounding = "towardZero" | "nearestTiesAwayFromZero" | "nearestTiesToEven"
|
|
33
15
|
|
|
34
16
|
/** Host value for a derived scalar kind. */
|
|
@@ -38,26 +20,6 @@ type NumericCast = "toF64" | "toF64Exact" | "toI64Exact" | "toU64Exact"
|
|
|
38
20
|
|
|
39
21
|
type NumericKind = "u64" | "i64" | "f64"
|
|
40
22
|
|
|
41
|
-
type NumericOrUnresolved = NumericKind | "unresolved"
|
|
42
|
-
|
|
43
|
-
/**
|
|
44
|
-
* Combine known numeric kinds, or stay unresolved when a source-field leaf
|
|
45
|
-
* still needs native binding. Distinct known kinds collapse to `never`
|
|
46
|
-
* (static refusal) and throw at the constructor.
|
|
47
|
-
*/
|
|
48
|
-
type CombineNumeric<L, R> = L extends "unresolved"
|
|
49
|
-
? R extends "bool"
|
|
50
|
-
? never
|
|
51
|
-
: "unresolved"
|
|
52
|
-
: R extends "unresolved"
|
|
53
|
-
? L extends "bool"
|
|
54
|
-
? never
|
|
55
|
-
: "unresolved"
|
|
56
|
-
: L extends R
|
|
57
|
-
? L
|
|
58
|
-
: never
|
|
59
|
-
|
|
60
|
-
/** The tagged literal subset shared by every leaf scope. */
|
|
61
23
|
type ScalarLiteral =
|
|
62
24
|
| { readonly bool: boolean }
|
|
63
25
|
| { readonly u64: bigint }
|
|
@@ -89,54 +51,32 @@ interface ScalarQueryVar {
|
|
|
89
51
|
|
|
90
52
|
type QueryVarLeaf = { readonly kind: "var"; readonly ref: ScalarQueryVar }
|
|
91
53
|
|
|
92
|
-
type
|
|
93
|
-
|
|
94
|
-
type ScalarLeaf<S extends ScalarLeafScope> = S extends "query-var" ? QueryVarLeaf : SourceFieldLeaf
|
|
95
|
-
|
|
96
|
-
type ScalarNodeBody<S extends ScalarLeafScope> =
|
|
97
|
-
| { readonly kind: "measure"; readonly expr: ScalarNode<S> }
|
|
54
|
+
type ScalarNodeBody =
|
|
55
|
+
| { readonly kind: "measure"; readonly expr: ScalarNode }
|
|
98
56
|
| {
|
|
99
57
|
readonly kind: "mulDiv"
|
|
100
|
-
readonly a: ScalarNode
|
|
101
|
-
readonly b: ScalarNode
|
|
102
|
-
readonly divisor: ScalarNode
|
|
58
|
+
readonly a: ScalarNode
|
|
59
|
+
readonly b: ScalarNode
|
|
60
|
+
readonly divisor: ScalarNode
|
|
103
61
|
readonly rounding: Rounding
|
|
104
62
|
}
|
|
105
|
-
|
|
|
63
|
+
| QueryVarLeaf
|
|
106
64
|
| { readonly kind: "literal"; readonly value: ScalarLiteral }
|
|
107
|
-
| { readonly kind: "negate"; readonly expr: ScalarNode
|
|
108
|
-
| { readonly kind: "isNaN"; readonly expr: ScalarNode
|
|
109
|
-
| { readonly kind: "isFinite"; readonly expr: ScalarNode
|
|
110
|
-
| { readonly kind: "add"; readonly left: ScalarNode
|
|
111
|
-
| { readonly kind: "subtract"; readonly left: ScalarNode
|
|
112
|
-
| { readonly kind: "multiply"; readonly left: ScalarNode
|
|
113
|
-
| { readonly kind: "divide"; readonly left: ScalarNode
|
|
114
|
-
| { readonly kind: "cast"; readonly cast: NumericCast; readonly expr: ScalarNode
|
|
115
|
-
|
|
116
|
-
/**
|
|
117
|
-
|
|
118
|
-
* Summaries are construction metadata; lowering and L17 serialization read
|
|
119
|
-
* the grammar arms and ignore the summaries.
|
|
120
|
-
*/
|
|
121
|
-
type ScalarNode<
|
|
122
|
-
S extends ScalarLeafScope = ScalarLeafScope,
|
|
123
|
-
K extends ScalarResultKind = ScalarResultKind
|
|
124
|
-
> = ScalarNodeBody<S> & {
|
|
125
|
-
readonly scope: S
|
|
65
|
+
| { readonly kind: "negate"; readonly expr: ScalarNode }
|
|
66
|
+
| { readonly kind: "isNaN"; readonly expr: ScalarNode }
|
|
67
|
+
| { readonly kind: "isFinite"; readonly expr: ScalarNode }
|
|
68
|
+
| { readonly kind: "add"; readonly left: ScalarNode; readonly right: ScalarNode }
|
|
69
|
+
| { readonly kind: "subtract"; readonly left: ScalarNode; readonly right: ScalarNode }
|
|
70
|
+
| { readonly kind: "multiply"; readonly left: ScalarNode; readonly right: ScalarNode }
|
|
71
|
+
| { readonly kind: "divide"; readonly left: ScalarNode; readonly right: ScalarNode }
|
|
72
|
+
| { readonly kind: "cast"; readonly cast: NumericCast; readonly expr: ScalarNode }
|
|
73
|
+
|
|
74
|
+
/** Cached summaries never replace the expression grammar. */
|
|
75
|
+
type ScalarNode<K extends ScalarResultKind = ScalarResultKind> = ScalarNodeBody & {
|
|
126
76
|
readonly result: K
|
|
127
77
|
readonly depth: number
|
|
128
78
|
}
|
|
129
79
|
|
|
130
|
-
/**
|
|
131
|
-
* Migration authoring expression (source-field scope). `K` is the cached
|
|
132
|
-
* result kind, not a host value type: I64 and U64 remain distinct even
|
|
133
|
-
* though both use bigint in JavaScript.
|
|
134
|
-
*/
|
|
135
|
-
type ScalarExpr<K extends ScalarResultKind = ScalarResultKind> = ScalarNode<"source-field", K>
|
|
136
|
-
|
|
137
|
-
/** A migration field read: unresolved until native snapshot binding. */
|
|
138
|
-
type ScalarFieldRef = ScalarNode<"source-field", "unresolved"> & SourceFieldLeaf
|
|
139
|
-
|
|
140
80
|
const MAX_SCALAR_DEPTH = 128
|
|
141
81
|
const U64_MAX = (1n << 64n) - 1n
|
|
142
82
|
const I64_MIN = -(1n << 63n)
|
|
@@ -149,9 +89,10 @@ function scalarAuthoringWork(): number {
|
|
|
149
89
|
return authoringWork
|
|
150
90
|
}
|
|
151
91
|
|
|
152
|
-
function admit<
|
|
153
|
-
|
|
154
|
-
|
|
92
|
+
function admit<const Node extends { readonly result: ScalarResultKind; readonly depth: number }>(
|
|
93
|
+
where: string,
|
|
94
|
+
node: Node
|
|
95
|
+
): Readonly<Node> {
|
|
155
96
|
authoringWork += 1
|
|
156
97
|
assertDepth(where, node.depth)
|
|
157
98
|
return Object.freeze(node)
|
|
@@ -229,40 +170,19 @@ function assertNumeric(where: string, kind: ScalarInputKind): asserts kind is Nu
|
|
|
229
170
|
function assertSameKind(where: string, left: ScalarInputKind, right: ScalarInputKind): ScalarInputKind {
|
|
230
171
|
if (left !== right) {
|
|
231
172
|
throw new AuthoringError({
|
|
232
|
-
message: `${where}: operand kinds differ (${left} vs ${right}) — the engine has no mixed promotion; cast explicitly (
|
|
173
|
+
message: `${where}: operand kinds differ (${left} vs ${right}) — the engine has no mixed promotion; cast explicitly (Compute.toF64/ toF64Exact/ toI64Exact/ toU64Exact)`
|
|
233
174
|
})
|
|
234
175
|
}
|
|
235
176
|
return left
|
|
236
177
|
}
|
|
237
178
|
|
|
238
|
-
function assertScope<S extends ScalarLeafScope>(where: string, left: ScalarNode<S>, right: ScalarNode<S>): S {
|
|
239
|
-
if (left.scope !== right.scope) {
|
|
240
|
-
throw new AuthoringError({
|
|
241
|
-
message: `${where}: leaf scopes differ (${left.scope} vs ${right.scope}) — query-var and source-field trees do not mix`
|
|
242
|
-
})
|
|
243
|
-
}
|
|
244
|
-
return left.scope
|
|
245
|
-
}
|
|
246
|
-
|
|
247
179
|
function combineNumeric(where: string, left: ScalarResultKind, right: ScalarResultKind): ScalarResultKind {
|
|
248
|
-
if (left === "unresolved" || right === "unresolved") {
|
|
249
|
-
if (left !== "unresolved") {
|
|
250
|
-
assertNumeric(where, left)
|
|
251
|
-
}
|
|
252
|
-
if (right !== "unresolved") {
|
|
253
|
-
assertNumeric(where, right)
|
|
254
|
-
}
|
|
255
|
-
return "unresolved"
|
|
256
|
-
}
|
|
257
180
|
assertNumeric(where, left)
|
|
258
181
|
assertNumeric(where, right)
|
|
259
182
|
return assertSameKind(where, left, right)
|
|
260
183
|
}
|
|
261
184
|
|
|
262
185
|
function negateKind(where: string, inner: ScalarResultKind): ScalarResultKind {
|
|
263
|
-
if (inner === "unresolved") {
|
|
264
|
-
return "unresolved"
|
|
265
|
-
}
|
|
266
186
|
if (inner !== "i64" && inner !== "f64") {
|
|
267
187
|
throw new AuthoringError({
|
|
268
188
|
message: `${where}: the operand is ${inner} — negation is defined over i64 and f64 only`
|
|
@@ -272,86 +192,46 @@ function negateKind(where: string, inner: ScalarResultKind): ScalarResultKind {
|
|
|
272
192
|
}
|
|
273
193
|
|
|
274
194
|
function assertCastOperand(where: string, inner: ScalarResultKind): void {
|
|
275
|
-
if (inner === "unresolved") {
|
|
276
|
-
return
|
|
277
|
-
}
|
|
278
195
|
assertNumeric(where, inner)
|
|
279
196
|
}
|
|
280
197
|
|
|
281
198
|
function assertFloatOperand(where: string, inner: ScalarResultKind): void {
|
|
282
|
-
if (inner === "unresolved") {
|
|
283
|
-
return
|
|
284
|
-
}
|
|
285
199
|
if (inner !== "f64") {
|
|
286
200
|
throw new AuthoringError({ message: `${where}: the operand is ${inner} — the float predicates read f64` })
|
|
287
201
|
}
|
|
288
202
|
}
|
|
289
203
|
|
|
290
204
|
function isScalarNode(value: unknown): value is ScalarNode {
|
|
291
|
-
return
|
|
292
|
-
typeof value === "object" &&
|
|
293
|
-
value !== null &&
|
|
294
|
-
"kind" in value &&
|
|
295
|
-
"scope" in value &&
|
|
296
|
-
"result" in value &&
|
|
297
|
-
"depth" in value
|
|
298
|
-
)
|
|
299
|
-
}
|
|
300
|
-
|
|
301
|
-
function isUnresolvedScalar(node: ScalarNode): boolean {
|
|
302
|
-
return node.result === "unresolved"
|
|
303
|
-
}
|
|
304
|
-
|
|
305
|
-
/** Source-field leaf — unresolved until L14 binds it against the verified snapshot. */
|
|
306
|
-
function sourceField(name: string): ScalarFieldRef {
|
|
307
|
-
if (typeof name !== "string" || name.length === 0) {
|
|
308
|
-
throw new AuthoringError({ message: "scalar field(...) names a nonempty source field" })
|
|
309
|
-
}
|
|
310
|
-
return admit("Scalar.field", {
|
|
311
|
-
kind: "field",
|
|
312
|
-
name,
|
|
313
|
-
scope: "source-field",
|
|
314
|
-
result: "unresolved",
|
|
315
|
-
depth: 1
|
|
316
|
-
})
|
|
205
|
+
return typeof value === "object" && value !== null && "kind" in value && "result" in value && "depth" in value
|
|
317
206
|
}
|
|
318
207
|
|
|
319
208
|
/** Query-var leaf — kind is the variable's schema kind, already known. */
|
|
320
|
-
function queryVarLeaf<K extends ScalarInputKind>(ref: ScalarQueryVar, kind: K): ScalarNode<
|
|
321
|
-
return admit("
|
|
209
|
+
function queryVarLeaf<K extends ScalarInputKind>(ref: ScalarQueryVar, kind: K): ScalarNode<K> {
|
|
210
|
+
return admit("Compute.variable", {
|
|
322
211
|
kind: "var",
|
|
323
212
|
ref,
|
|
324
|
-
scope: "query-var",
|
|
325
213
|
result: kind,
|
|
326
214
|
depth: 1
|
|
327
215
|
})
|
|
328
216
|
}
|
|
329
217
|
|
|
330
|
-
function scalarLiteral
|
|
218
|
+
function scalarLiteral(value: ScalarLiteral): ScalarNode<ScalarKind> {
|
|
331
219
|
const kind = literalKindOf(value)
|
|
332
|
-
return admit("
|
|
220
|
+
return admit("Compute.literal", {
|
|
333
221
|
kind: "literal",
|
|
334
222
|
value: literalValue(value),
|
|
335
|
-
scope,
|
|
336
223
|
result: kind,
|
|
337
224
|
depth: 1
|
|
338
|
-
}) as ScalarNode<
|
|
225
|
+
}) as ScalarNode<ScalarKind>
|
|
339
226
|
}
|
|
340
227
|
|
|
341
228
|
type BinaryOp = "add" | "subtract" | "multiply" | "divide"
|
|
342
229
|
|
|
343
|
-
function scalarBinary
|
|
344
|
-
where: string,
|
|
345
|
-
op: BinaryOp,
|
|
346
|
-
left: ScalarNode<S>,
|
|
347
|
-
right: ScalarNode<S>
|
|
348
|
-
): ScalarNode<S, ScalarResultKind> {
|
|
349
|
-
const scope = assertScope(where, left, right)
|
|
230
|
+
function scalarBinary(where: string, op: BinaryOp, left: ScalarNode, right: ScalarNode): ScalarNode {
|
|
350
231
|
return admit(where, {
|
|
351
232
|
kind: op,
|
|
352
233
|
left,
|
|
353
234
|
right,
|
|
354
|
-
scope,
|
|
355
235
|
result: combineNumeric(where, left.result, right.result),
|
|
356
236
|
depth: Math.max(left.depth, right.depth) + 1
|
|
357
237
|
})
|
|
@@ -363,18 +243,15 @@ function roundingMode(value: unknown): Rounding {
|
|
|
363
243
|
return value
|
|
364
244
|
}
|
|
365
245
|
|
|
366
|
-
function scalarMulDiv
|
|
246
|
+
function scalarMulDiv(
|
|
367
247
|
where: string,
|
|
368
|
-
a: ScalarNode
|
|
369
|
-
b: ScalarNode
|
|
370
|
-
divisor: ScalarNode
|
|
248
|
+
a: ScalarNode,
|
|
249
|
+
b: ScalarNode,
|
|
250
|
+
divisor: ScalarNode,
|
|
371
251
|
rounding: Rounding
|
|
372
|
-
): ScalarNode
|
|
373
|
-
const scope = assertScope(where, a, b)
|
|
374
|
-
assertScope(where, a, divisor)
|
|
252
|
+
): ScalarNode {
|
|
375
253
|
let known: "i64" | "u64" | undefined
|
|
376
254
|
for (const operand of [a, b, divisor]) {
|
|
377
|
-
if (operand.result === "unresolved") continue
|
|
378
255
|
if ((operand.result !== "i64" && operand.result !== "u64") || (known !== undefined && known !== operand.result))
|
|
379
256
|
throw new AuthoringError({ message: `${where}: operands must have one matching integer kind` })
|
|
380
257
|
known = operand.result
|
|
@@ -385,74 +262,57 @@ function scalarMulDiv<S extends ScalarLeafScope>(
|
|
|
385
262
|
b,
|
|
386
263
|
divisor,
|
|
387
264
|
rounding: roundingMode(rounding),
|
|
388
|
-
|
|
389
|
-
result:
|
|
390
|
-
a.result === "unresolved" || b.result === "unresolved" || divisor.result === "unresolved"
|
|
391
|
-
? "unresolved"
|
|
392
|
-
: a.result,
|
|
265
|
+
result: a.result,
|
|
393
266
|
depth: Math.max(a.depth, b.depth, divisor.depth) + 1
|
|
394
267
|
})
|
|
395
268
|
}
|
|
396
269
|
|
|
397
|
-
function scalarMeasure
|
|
270
|
+
function scalarMeasure(where: string, expr: ScalarNode): ScalarNode {
|
|
398
271
|
const kind = expr.result
|
|
399
|
-
if (kind !== "
|
|
272
|
+
if (kind !== "intervalU64" && kind !== "intervalI64" && kind !== "intervalF64")
|
|
400
273
|
throw new AuthoringError({ message: `${where}: measure requires an interval` })
|
|
401
274
|
return admit(where, {
|
|
402
275
|
kind: "measure",
|
|
403
276
|
expr,
|
|
404
|
-
|
|
405
|
-
result: ({ unresolved: "unresolved", intervalF64: "f64", intervalI64: "u64", intervalU64: "u64" } as const)[kind],
|
|
277
|
+
result: ({ intervalF64: "f64", intervalI64: "u64", intervalU64: "u64" } as const)[kind],
|
|
406
278
|
depth: expr.depth + 1
|
|
407
279
|
})
|
|
408
280
|
}
|
|
409
281
|
|
|
410
|
-
function scalarNegate
|
|
282
|
+
function scalarNegate(where: string, expr: ScalarNode): ScalarNode {
|
|
411
283
|
return admit(where, {
|
|
412
284
|
kind: "negate",
|
|
413
285
|
expr,
|
|
414
|
-
scope: expr.scope,
|
|
415
286
|
result: negateKind(where, expr.result),
|
|
416
287
|
depth: expr.depth + 1
|
|
417
288
|
})
|
|
418
289
|
}
|
|
419
290
|
|
|
420
|
-
function scalarCast
|
|
421
|
-
where: string,
|
|
422
|
-
cast: NumericCast,
|
|
423
|
-
result: ScalarKind,
|
|
424
|
-
expr: ScalarNode<S>
|
|
425
|
-
): ScalarNode<S, ScalarKind> {
|
|
291
|
+
function scalarCast(where: string, cast: NumericCast, result: ScalarKind, expr: ScalarNode): ScalarNode<ScalarKind> {
|
|
426
292
|
assertCastOperand(where, expr.result)
|
|
427
293
|
return admit(where, {
|
|
428
294
|
kind: "cast",
|
|
429
295
|
cast,
|
|
430
296
|
expr,
|
|
431
|
-
scope: expr.scope,
|
|
432
297
|
result,
|
|
433
298
|
depth: expr.depth + 1
|
|
434
299
|
})
|
|
435
300
|
}
|
|
436
301
|
|
|
437
|
-
function scalarFloatPredicate
|
|
438
|
-
where: string,
|
|
439
|
-
op: "isNaN" | "isFinite",
|
|
440
|
-
expr: ScalarNode<S>
|
|
441
|
-
): ScalarNode<S, "bool"> {
|
|
302
|
+
function scalarFloatPredicate(where: string, op: "isNaN" | "isFinite", expr: ScalarNode): ScalarNode<"bool"> {
|
|
442
303
|
assertFloatOperand(where, expr.result)
|
|
443
304
|
return admit(where, {
|
|
444
305
|
kind: op,
|
|
445
306
|
expr,
|
|
446
|
-
scope: expr.scope,
|
|
447
307
|
result: "bool",
|
|
448
308
|
depth: expr.depth + 1
|
|
449
309
|
})
|
|
450
310
|
}
|
|
451
311
|
|
|
452
312
|
/** Query-var leaves collected once at find-binding time — not during construction. */
|
|
453
|
-
function queryVarsOf(node: ScalarNode
|
|
313
|
+
function queryVarsOf(node: ScalarNode): readonly ScalarQueryVar[] {
|
|
454
314
|
const vars: ScalarQueryVar[] = []
|
|
455
|
-
const pending: ScalarNode
|
|
315
|
+
const pending: ScalarNode[] = [node]
|
|
456
316
|
while (pending.length > 0) {
|
|
457
317
|
const next = pending.pop()
|
|
458
318
|
if (next === undefined) {
|
|
@@ -480,126 +340,16 @@ function queryVarsOf(node: ScalarNode<"query-var">): readonly ScalarQueryVar[] {
|
|
|
480
340
|
case "divide":
|
|
481
341
|
pending.push(next.left, next.right)
|
|
482
342
|
break
|
|
483
|
-
default:
|
|
484
|
-
throw new AuthoringError({
|
|
485
|
-
message: "queryVarsOf: a query-var tree cannot carry a source-field leaf"
|
|
486
|
-
})
|
|
487
343
|
}
|
|
488
344
|
}
|
|
489
345
|
return vars
|
|
490
346
|
}
|
|
491
347
|
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
}
|
|
495
|
-
|
|
496
|
-
function literal(value: ScalarLiteral): ScalarExpr<ScalarKind> {
|
|
497
|
-
return scalarLiteral("source-field", value)
|
|
498
|
-
}
|
|
499
|
-
|
|
500
|
-
function u64(value: bigint): ScalarExpr<"u64"> {
|
|
501
|
-
checkU64(value, "Scalar.u64")
|
|
502
|
-
return scalarLiteral("source-field", { u64: value }) as ScalarExpr<"u64">
|
|
503
|
-
}
|
|
504
|
-
|
|
505
|
-
function i64(value: bigint): ScalarExpr<"i64"> {
|
|
506
|
-
checkI64(value, "Scalar.i64")
|
|
507
|
-
return scalarLiteral("source-field", { i64: value }) as ScalarExpr<"i64">
|
|
508
|
-
}
|
|
509
|
-
|
|
510
|
-
function f64(value: number): ScalarExpr<"f64"> {
|
|
511
|
-
checkF64(value, "Scalar.f64")
|
|
512
|
-
return scalarLiteral("source-field", { f64: value }) as ScalarExpr<"f64">
|
|
513
|
-
}
|
|
514
|
-
|
|
515
|
-
function bool(value: boolean): ScalarExpr<"bool"> {
|
|
516
|
-
checkBool(value, "Scalar.bool")
|
|
517
|
-
return scalarLiteral("source-field", { bool: value }) as ScalarExpr<"bool">
|
|
518
|
-
}
|
|
519
|
-
|
|
520
|
-
function negate<K extends "i64" | "f64" | "unresolved">(expr: ScalarExpr<K>): ScalarExpr<K> {
|
|
521
|
-
return scalarNegate("Scalar.negate", expr) as ScalarExpr<K>
|
|
522
|
-
}
|
|
523
|
-
|
|
524
|
-
function add<L extends NumericOrUnresolved, R extends CombineNumeric<L, R> extends never ? never : NumericOrUnresolved>(
|
|
525
|
-
left: ScalarExpr<L>,
|
|
526
|
-
right: ScalarExpr<R>
|
|
527
|
-
): ScalarExpr<CombineNumeric<L, R>> {
|
|
528
|
-
return scalarBinary("Scalar.add", "add", left, right) as ScalarExpr<CombineNumeric<L, R>>
|
|
529
|
-
}
|
|
530
|
-
|
|
531
|
-
function subtract<
|
|
532
|
-
L extends NumericOrUnresolved,
|
|
533
|
-
R extends CombineNumeric<L, R> extends never ? never : NumericOrUnresolved
|
|
534
|
-
>(left: ScalarExpr<L>, right: ScalarExpr<R>): ScalarExpr<CombineNumeric<L, R>> {
|
|
535
|
-
return scalarBinary("Scalar.subtract", "subtract", left, right) as ScalarExpr<CombineNumeric<L, R>>
|
|
536
|
-
}
|
|
537
|
-
|
|
538
|
-
function multiply<
|
|
539
|
-
L extends NumericOrUnresolved,
|
|
540
|
-
R extends CombineNumeric<L, R> extends never ? never : NumericOrUnresolved
|
|
541
|
-
>(left: ScalarExpr<L>, right: ScalarExpr<R>): ScalarExpr<CombineNumeric<L, R>> {
|
|
542
|
-
return scalarBinary("Scalar.multiply", "multiply", left, right) as ScalarExpr<CombineNumeric<L, R>>
|
|
543
|
-
}
|
|
544
|
-
|
|
545
|
-
function divide<
|
|
546
|
-
L extends NumericOrUnresolved,
|
|
547
|
-
R extends CombineNumeric<L, R> extends never ? never : NumericOrUnresolved
|
|
548
|
-
>(left: ScalarExpr<L>, right: ScalarExpr<R>): ScalarExpr<CombineNumeric<L, R>> {
|
|
549
|
-
return scalarBinary("Scalar.divide", "divide", left, right) as ScalarExpr<CombineNumeric<L, R>>
|
|
550
|
-
}
|
|
551
|
-
|
|
552
|
-
function mulDiv<
|
|
553
|
-
L extends "i64" | "u64" | "unresolved",
|
|
554
|
-
R extends CombineNumeric<L, R> extends never ? never : "i64" | "u64" | "unresolved",
|
|
555
|
-
D extends CombineNumeric<L, D> extends never
|
|
556
|
-
? never
|
|
557
|
-
: CombineNumeric<R, D> extends never
|
|
558
|
-
? never
|
|
559
|
-
: "i64" | "u64" | "unresolved"
|
|
560
|
-
>(
|
|
561
|
-
a: ScalarExpr<L>,
|
|
562
|
-
b: ScalarExpr<R>,
|
|
563
|
-
divisor: ScalarExpr<D>,
|
|
564
|
-
rounding: Rounding
|
|
565
|
-
): ScalarExpr<CombineNumeric<CombineNumeric<L, R>, D>> {
|
|
566
|
-
return scalarMulDiv("Scalar.mulDiv", a, b, divisor, rounding) as ScalarExpr<CombineNumeric<CombineNumeric<L, R>, D>>
|
|
567
|
-
}
|
|
568
|
-
|
|
569
|
-
function measure(expr: ScalarFieldRef): ScalarExpr<"unresolved"> {
|
|
570
|
-
return scalarMeasure("Scalar.measure", expr) as ScalarExpr<"unresolved">
|
|
571
|
-
}
|
|
572
|
-
|
|
573
|
-
function toF64(expr: ScalarExpr<NumericOrUnresolved>): ScalarExpr<"f64"> {
|
|
574
|
-
return scalarCast("Scalar.toF64", "toF64", "f64", expr) as ScalarExpr<"f64">
|
|
575
|
-
}
|
|
576
|
-
|
|
577
|
-
function toF64Exact(expr: ScalarExpr<NumericOrUnresolved>): ScalarExpr<"f64"> {
|
|
578
|
-
return scalarCast("Scalar.toF64Exact", "toF64Exact", "f64", expr) as ScalarExpr<"f64">
|
|
579
|
-
}
|
|
580
|
-
|
|
581
|
-
function toI64Exact(expr: ScalarExpr<NumericOrUnresolved>): ScalarExpr<"i64"> {
|
|
582
|
-
return scalarCast("Scalar.toI64Exact", "toI64Exact", "i64", expr) as ScalarExpr<"i64">
|
|
583
|
-
}
|
|
584
|
-
|
|
585
|
-
function toU64Exact(expr: ScalarExpr<NumericOrUnresolved>): ScalarExpr<"u64"> {
|
|
586
|
-
return scalarCast("Scalar.toU64Exact", "toU64Exact", "u64", expr) as ScalarExpr<"u64">
|
|
587
|
-
}
|
|
588
|
-
|
|
589
|
-
function isNaNExpr(expr: ScalarExpr<"f64" | "unresolved">): ScalarExpr<"bool"> {
|
|
590
|
-
return scalarFloatPredicate("Scalar.isNaN", "isNaN", expr)
|
|
591
|
-
}
|
|
592
|
-
|
|
593
|
-
function isFiniteExpr(expr: ScalarExpr<"f64" | "unresolved">): ScalarExpr<"bool"> {
|
|
594
|
-
return scalarFloatPredicate("Scalar.isFinite", "isFinite", expr)
|
|
595
|
-
}
|
|
596
|
-
|
|
597
|
-
/** One lowering walk for query variables and row-field bindings. */
|
|
598
|
-
function scalarWire(node: ScalarNode, leaf: (node: QueryVarLeaf | SourceFieldLeaf) => number): ScalarExprIr {
|
|
348
|
+
/** Lower each query variable through its existing binding. */
|
|
349
|
+
function scalarWire(node: ScalarNode, leaf: (node: QueryVarLeaf) => number): ScalarExprIr {
|
|
599
350
|
const walk = (expr: ScalarNode): ScalarExprIr => scalarWire(expr, leaf)
|
|
600
351
|
switch (node.kind) {
|
|
601
352
|
case "var":
|
|
602
|
-
case "field":
|
|
603
353
|
return { kind: "var", var: leaf(node) }
|
|
604
354
|
case "literal":
|
|
605
355
|
return { kind: "literal", value: literalWireOf(node.value) }
|
|
@@ -620,39 +370,12 @@ function scalarWire(node: ScalarNode, leaf: (node: QueryVarLeaf | SourceFieldLea
|
|
|
620
370
|
}
|
|
621
371
|
}
|
|
622
372
|
|
|
623
|
-
/** The authoring namespace: `Scalar.field("units")`, `Scalar.add(...)`. */
|
|
624
|
-
const Scalar = Object.freeze({
|
|
625
|
-
field,
|
|
626
|
-
literal,
|
|
627
|
-
u64,
|
|
628
|
-
i64,
|
|
629
|
-
f64,
|
|
630
|
-
bool,
|
|
631
|
-
negate,
|
|
632
|
-
add,
|
|
633
|
-
subtract,
|
|
634
|
-
multiply,
|
|
635
|
-
divide,
|
|
636
|
-
mulDiv,
|
|
637
|
-
measure,
|
|
638
|
-
toF64,
|
|
639
|
-
toF64Exact,
|
|
640
|
-
toI64Exact,
|
|
641
|
-
toU64Exact,
|
|
642
|
-
isNaN: isNaNExpr,
|
|
643
|
-
isFinite: isFiniteExpr
|
|
644
|
-
})
|
|
645
|
-
|
|
646
373
|
export type {
|
|
647
|
-
CombineNumeric,
|
|
648
374
|
IntervalKind,
|
|
649
375
|
NumericCast,
|
|
650
376
|
NumericKind,
|
|
651
|
-
NumericOrUnresolved,
|
|
652
377
|
QueryVarLeaf,
|
|
653
378
|
Rounding,
|
|
654
|
-
ScalarExpr,
|
|
655
|
-
ScalarFieldRef,
|
|
656
379
|
ScalarInputKind,
|
|
657
380
|
ScalarKind,
|
|
658
381
|
ScalarLiteral,
|
|
@@ -660,8 +383,7 @@ export type {
|
|
|
660
383
|
ScalarOpKind,
|
|
661
384
|
ScalarQueryVar,
|
|
662
385
|
ScalarResultKind,
|
|
663
|
-
ScalarValue
|
|
664
|
-
SourceFieldLeaf
|
|
386
|
+
ScalarValue
|
|
665
387
|
}
|
|
666
388
|
export {
|
|
667
389
|
assertDepth,
|
|
@@ -672,7 +394,6 @@ export {
|
|
|
672
394
|
checkI64,
|
|
673
395
|
checkU64,
|
|
674
396
|
isScalarNode,
|
|
675
|
-
isUnresolvedScalar,
|
|
676
397
|
literalKindOf,
|
|
677
398
|
literalValue,
|
|
678
399
|
literalWireOf,
|
|
@@ -680,7 +401,6 @@ export {
|
|
|
680
401
|
queryVarLeaf,
|
|
681
402
|
queryVarsOf,
|
|
682
403
|
roundingMode,
|
|
683
|
-
Scalar,
|
|
684
404
|
scalarAuthoringWork,
|
|
685
405
|
scalarBinary,
|
|
686
406
|
scalarCast,
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { Effect } from "effect"
|
|
2
|
+
import { dbNative } from "#db-native.ts"
|
|
3
|
+
import { nativeOperationWith, runtimeHandle } from "#runtime.ts"
|
|
4
|
+
import { DbError, dbError } from "#runtime-errors.ts"
|
|
5
|
+
import type { SchemaSpec } from "#spec.ts"
|
|
6
|
+
|
|
7
|
+
const decoder = new TextDecoder("utf-8", { fatal: true })
|
|
8
|
+
|
|
9
|
+
function text(operation: string, bytes: Uint8Array | null): string {
|
|
10
|
+
if (bytes === null) throw dbError(operation, { _tag: "Internal" })
|
|
11
|
+
return decoder.decode(bytes)
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
const internalSchemaSnapshot = Effect.fn("internalSchemaSnapshot")(function* (spec: SchemaSpec) {
|
|
15
|
+
const runtime = yield* runtimeHandle()
|
|
16
|
+
return yield* nativeOperationWith(
|
|
17
|
+
"internalSchemaSnapshot",
|
|
18
|
+
(callback) => dbNative.runtimeSchemaSnapshot(runtime, spec, callback),
|
|
19
|
+
dbNative.runtimeBytesTake,
|
|
20
|
+
(bytes) => text("internalSchemaSnapshot", bytes)
|
|
21
|
+
)
|
|
22
|
+
})
|
|
23
|
+
|
|
24
|
+
const internalSchemaBindings = Effect.fn("internalSchemaBindings")(function* (snapshot: string) {
|
|
25
|
+
if (typeof snapshot !== "string" || !snapshot.isWellFormed()) {
|
|
26
|
+
return yield* Effect.fail(new DbError({ operation: "internalSchemaBindings", reason: { _tag: "InvalidArgument" } }))
|
|
27
|
+
}
|
|
28
|
+
const runtime = yield* runtimeHandle()
|
|
29
|
+
const bytes = new TextEncoder().encode(snapshot)
|
|
30
|
+
return yield* nativeOperationWith(
|
|
31
|
+
"internalSchemaBindings",
|
|
32
|
+
(callback) => dbNative.runtimeSchemaBindings(runtime, bytes, callback),
|
|
33
|
+
dbNative.runtimeBytesTake,
|
|
34
|
+
(bytes) => text("internalSchemaBindings", bytes)
|
|
35
|
+
)
|
|
36
|
+
})
|
|
37
|
+
|
|
38
|
+
export { internalSchemaBindings, internalSchemaSnapshot }
|
package/dist/migration.d.ts
DELETED
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Private log-migration integration entrypoints: the two read-only
|
|
3
|
-
* native migration-codec verbs the `@bjornpagen/bumbledb-log/migrations`
|
|
4
|
-
* generator imports, wired over the shared executor onto the native
|
|
5
|
-
* `schema_file`, `migration::plan` and `migration::manifest` modules.
|
|
6
|
-
*
|
|
7
|
-
* Both follow `hashChunk`'s shape: bounded owned input, bounded owned JSON
|
|
8
|
-
* response bytes, ONE registered cancellable operation under the acquired
|
|
9
|
-
* `NativeRuntime`. The schema verb takes the SDK `SchemaSpec` object — the
|
|
10
|
-
* same wire that already crosses the bridge for open/create — never a
|
|
11
|
-
* respelled text form. Neither verb opens, initializes, freezes or migrates
|
|
12
|
-
* a database; the durable migrate/activate/abort workflow is the log's
|
|
13
|
-
* admin surface, not this seam.
|
|
14
|
-
*/
|
|
15
|
-
import { Effect } from "effect";
|
|
16
|
-
import { DbError } from "./runtime-errors.js";
|
|
17
|
-
import type { SchemaSpec } from "./spec.js";
|
|
18
|
-
/**
|
|
19
|
-
* Canonical schema admission for the migration generator: validates the
|
|
20
|
-
* spec natively and yields bounded JSON bytes carrying the canonical
|
|
21
|
-
* `schemaId` and the rendered schema snapshot.
|
|
22
|
-
*/
|
|
23
|
-
declare const internalMigrationSchema: (spec: SchemaSpec) => Effect.Effect<Uint8Array<ArrayBufferLike>, DbError, import("./runtime.js").NativeRuntime>;
|
|
24
|
-
/**
|
|
25
|
-
* One bounded read-only migration-codec request (plan parse/validate/
|
|
26
|
-
* render/digest, manifest verify/append preview, plan-set digests): owned
|
|
27
|
-
* JSON request bytes in, owned JSON response bytes out.
|
|
28
|
-
*/
|
|
29
|
-
declare const internalMigrationRead: (request: Uint8Array<ArrayBufferLike>) => Effect.Effect<Uint8Array<ArrayBufferLike>, DbError, import("./runtime.js").NativeRuntime>;
|
|
30
|
-
export { internalMigrationRead, internalMigrationSchema };
|
|
31
|
-
//# sourceMappingURL=migration.d.ts.map
|
package/dist/migration.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"migration.d.ts","sourceRoot":"","sources":["../src/migration.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AACH,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAA;AAG/B,OAAO,EAAE,OAAO,EAAW,MAAM,oBAAoB,CAAA;AACrD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,UAAU,CAAA;AAS1C;;;;GAIG;AACH,QAAA,MAAM,uBAAuB,gHAQ3B,CAAA;AAEF;;;;GAIG;AACH,QAAA,MAAM,qBAAqB,oIAWzB,CAAA;AAEF,OAAO,EAAE,qBAAqB,EAAE,uBAAuB,EAAE,CAAA"}
|