@bjornpagen/bumbledb 0.5.0 → 0.7.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 +140 -136
- package/README.md +24 -11
- package/dist/closed.d.ts +7 -5
- package/dist/closed.d.ts.map +1 -1
- package/dist/closed.js +4 -1
- package/dist/closed.js.map +1 -1
- package/dist/count.js +1 -1
- package/dist/count.js.map +1 -1
- package/dist/db.d.ts +110 -73
- package/dist/db.d.ts.map +1 -1
- package/dist/db.js +172 -116
- package/dist/db.js.map +1 -1
- package/dist/exhume.d.ts +22 -10
- package/dist/exhume.d.ts.map +1 -1
- package/dist/exhume.js +42 -9
- package/dist/exhume.js.map +1 -1
- package/dist/face.d.ts +10 -6
- package/dist/face.d.ts.map +1 -1
- package/dist/face.js.map +1 -1
- package/dist/fields.d.ts +38 -16
- package/dist/fields.d.ts.map +1 -1
- package/dist/fields.js +33 -8
- package/dist/fields.js.map +1 -1
- package/dist/index.d.ts +9 -6
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -2
- package/dist/index.js.map +1 -1
- package/dist/lower.d.ts +9 -9
- package/dist/lower.d.ts.map +1 -1
- package/dist/lower.js +17 -12
- package/dist/lower.js.map +1 -1
- package/dist/marshal.d.ts +17 -7
- package/dist/marshal.d.ts.map +1 -1
- package/dist/marshal.js +32 -10
- package/dist/marshal.js.map +1 -1
- package/dist/native.d.ts +60 -9
- package/dist/native.d.ts.map +1 -1
- package/dist/native.js.map +1 -1
- package/dist/query/atom.d.ts +199 -203
- package/dist/query/atom.d.ts.map +1 -1
- package/dist/query/atom.js +39 -48
- package/dist/query/atom.js.map +1 -1
- package/dist/query/find.d.ts +116 -0
- package/dist/query/find.d.ts.map +1 -0
- package/dist/query/{select.js → find.js} +22 -22
- package/dist/query/find.js.map +1 -0
- package/dist/query/lower.d.ts +131 -158
- package/dist/query/lower.d.ts.map +1 -1
- package/dist/query/lower.js +505 -494
- package/dist/query/lower.js.map +1 -1
- package/dist/query/predicate.d.ts +22 -14
- package/dist/query/predicate.d.ts.map +1 -1
- package/dist/query/predicate.js +35 -42
- package/dist/query/predicate.js.map +1 -1
- package/dist/query/run.d.ts +8 -8
- package/dist/query/run.d.ts.map +1 -1
- package/dist/query/run.js +16 -21
- package/dist/query/run.js.map +1 -1
- package/dist/query/scope.d.ts +139 -74
- package/dist/query/scope.d.ts.map +1 -1
- package/dist/query/scope.js +80 -33
- package/dist/query/scope.js.map +1 -1
- package/dist/relation.d.ts.map +1 -1
- package/dist/relation.js +3 -1
- package/dist/relation.js.map +1 -1
- package/dist/schema.d.ts.map +1 -1
- package/dist/schema.js +12 -2
- package/dist/schema.js.map +1 -1
- package/dist/spec.d.ts +20 -10
- package/dist/spec.d.ts.map +1 -1
- package/dist/spec.js.map +1 -1
- package/dist/statements.d.ts +22 -2
- package/dist/statements.d.ts.map +1 -1
- package/dist/statements.js +26 -5
- package/dist/statements.js.map +1 -1
- package/package.json +3 -3
- package/src/closed.ts +13 -7
- package/src/count.ts +1 -1
- package/src/db.ts +293 -177
- package/src/exhume.ts +48 -11
- package/src/face.ts +13 -6
- package/src/fields.ts +51 -15
- package/src/index.ts +12 -8
- package/src/lower.ts +17 -12
- package/src/marshal.ts +38 -13
- package/src/native.ts +59 -8
- package/src/query/atom.ts +297 -275
- package/src/query/find.ts +212 -0
- package/src/query/lower.ts +692 -724
- package/src/query/predicate.ts +37 -45
- package/src/query/run.ts +17 -22
- package/src/query/scope.ts +184 -90
- package/src/relation.ts +3 -1
- package/src/schema.ts +14 -2
- package/src/spec.ts +21 -9
- package/src/statements.ts +30 -6
- package/dist/query/select.d.ts +0 -128
- package/dist/query/select.d.ts.map +0 -1
- package/dist/query/select.js.map +0 -1
- package/src/query/select.ts +0 -215
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Find entries and aggregates, REFERENCE-IDENTITY edition — the head
|
|
3
|
+
* vocabulary, mirroring the IR's aggregate roster exactly
|
|
4
|
+
* (`bumbledb/crates/bumbledb/src/ir.rs` `AggOp`/`FindTerm`;
|
|
5
|
+
* `docs/architecture/20-query-ir.md` § aggregation): `count` (nullary),
|
|
6
|
+
* `countDistinct`, `sum`/`min`/`max` (over an orderable variable or the
|
|
7
|
+
* measure), `argMax`/`argMin` (arg-restriction: carried value + orderable
|
|
8
|
+
* key), and `pack` (the coalescing fold — RELATION-SHAPED, the result
|
|
9
|
+
* position interval-typed). Aggregates fold VARIABLES by reference —
|
|
10
|
+
* `r.sum(w)` — and are typed by the variable's own descriptor.
|
|
11
|
+
*
|
|
12
|
+
* `select(strings)` is DEAD: the head is a `find` RECORD, whose KEYS name
|
|
13
|
+
* the answer columns (`find({ total: r.count(), owner: h })`). The keys are
|
|
14
|
+
* unique object keys, so a duplicate answer column is unrepresentable and a
|
|
15
|
+
* rename is a real typed key. Grouping is implicit: the non-aggregate
|
|
16
|
+
* entries are the group key; over empty input an all-aggregate find yields
|
|
17
|
+
* the EMPTY SET, never a zero row. The creation quarantine is
|
|
18
|
+
* representational: a head position is a variable, the measure, or an
|
|
19
|
+
* aggregate — no minting or arithmetic term exists to spell (permanent law).
|
|
20
|
+
*/
|
|
21
|
+
|
|
22
|
+
import type { Infer } from "#fields.ts"
|
|
23
|
+
import type { SchemaClasses } from "#law.ts"
|
|
24
|
+
import type { IntervalVarOk, OrderVarOk } from "#query/atom.ts"
|
|
25
|
+
import type { AnyVar, Duration, MintSlotOf } from "#query/scope.ts"
|
|
26
|
+
|
|
27
|
+
/** One aggregate operator name of the find vocabulary. */
|
|
28
|
+
type AggOpName = "count" | "countDistinct" | "sum" | "min" | "max" | "argMax" | "argMin" | "pack"
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* One aggregate find VALUE: the op, the variable (or measure) it folds BY
|
|
32
|
+
* REFERENCE, and — for the Arg forms — the orderable key variable. The
|
|
33
|
+
* variable's own descriptor types the result.
|
|
34
|
+
*/
|
|
35
|
+
interface Agg<
|
|
36
|
+
Op extends AggOpName,
|
|
37
|
+
Over extends AnyVar | Duration | undefined,
|
|
38
|
+
Key extends AnyVar | undefined = undefined
|
|
39
|
+
> {
|
|
40
|
+
readonly agg: Op
|
|
41
|
+
readonly over: Over
|
|
42
|
+
readonly key: Key
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/** Any aggregate find value. */
|
|
46
|
+
type AnyAgg = Agg<AggOpName, AnyVar | Duration | undefined, AnyVar | undefined>
|
|
47
|
+
|
|
48
|
+
/** One find entry: a projected variable, the measure, or an aggregate. */
|
|
49
|
+
type FindEntry = AnyVar | Duration | AnyAgg
|
|
50
|
+
|
|
51
|
+
/** The `find` record: column name → find entry. Keys ARE the answer columns. */
|
|
52
|
+
type FindShape = Readonly<Record<string, FindEntry>>
|
|
53
|
+
|
|
54
|
+
/** Builds one aggregate value. */
|
|
55
|
+
function aggregate<Op extends AggOpName, Over extends AnyVar | Duration | undefined, Key extends AnyVar | undefined>(
|
|
56
|
+
op: Op,
|
|
57
|
+
over: Over,
|
|
58
|
+
key: Key
|
|
59
|
+
): Agg<Op, Over, Key> {
|
|
60
|
+
return Object.freeze({ agg: op, over, key })
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/** Nullary count: |the group's set of distinct full bindings|, `bigint`. */
|
|
64
|
+
function count(): Agg<"count", undefined> {
|
|
65
|
+
return aggregate("count", undefined, undefined)
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/** |the distinct values of the variable across the group|, `bigint`; legal over every type. */
|
|
69
|
+
function countDistinct<const V extends AnyVar>(over: V): Agg<"countDistinct", V> {
|
|
70
|
+
return aggregate("countDistinct", over, undefined)
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Exact checked sum over an orderable (u64/i64) variable — wide
|
|
75
|
+
* accumulator, one finalize range check; overflow is the engine's typed
|
|
76
|
+
* runtime error — or over the measure (`r.sum(r.duration(w))`).
|
|
77
|
+
*/
|
|
78
|
+
function sum<const O extends AnyVar | Duration>(over: O): Agg<"sum", O> {
|
|
79
|
+
return aggregate("sum", over, undefined)
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/** Minimum over an orderable variable or the measure (orderable types only). */
|
|
83
|
+
function min<const O extends AnyVar | Duration>(over: O): Agg<"min", O> {
|
|
84
|
+
return aggregate("min", over, undefined)
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/** Maximum over an orderable variable or the measure (orderable types only). */
|
|
88
|
+
function max<const O extends AnyVar | Duration>(over: O): Agg<"max", O> {
|
|
89
|
+
return aggregate("max", over, undefined)
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Arg-restriction toward the maximum of `key` (`ir::AggOp::ArgMax`): the
|
|
94
|
+
* group's binding set is restricted to the bindings attaining the extreme
|
|
95
|
+
* of the orderable key, and `value` is the carried payload — a tie yields
|
|
96
|
+
* every attaining row. All Arg entries of one query share one key and one
|
|
97
|
+
* direction; Arg and fold aggregates never mix (both the engine's rules).
|
|
98
|
+
*/
|
|
99
|
+
function argMax<const V extends AnyVar, const K extends AnyVar>(value: V, key: K): Agg<"argMax", V, K> {
|
|
100
|
+
return aggregate("argMax", value, key)
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/** Arg-restriction toward the minimum of `key`; rules as {@link argMax}. */
|
|
104
|
+
function argMin<const V extends AnyVar, const K extends AnyVar>(value: V, key: K): Agg<"argMin", V, K> {
|
|
105
|
+
return aggregate("argMin", value, key)
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* The coalescing fold (Snodgrass coalesce, `ir::AggOp::Pack`): per group,
|
|
110
|
+
* the maximal disjoint half-open segments of the union of the group's
|
|
111
|
+
* interval point sets — RELATION-SHAPED, one answer row per (group, maximal
|
|
112
|
+
* segment), the result position carrying one interval of the input's element
|
|
113
|
+
* type. At most one `pack` per find, never beside a fold or an Arg entry.
|
|
114
|
+
*/
|
|
115
|
+
function pack<const V extends AnyVar>(over: V): Agg<"pack", V> {
|
|
116
|
+
return aggregate("pack", over, undefined)
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/** A fold input's judgment: an orderable variable, or the measure of an interval variable. */
|
|
120
|
+
type FoldOverOk<O> = O extends AnyVar
|
|
121
|
+
? OrderVarOk<O>
|
|
122
|
+
: O extends Duration<infer V extends AnyVar>
|
|
123
|
+
? IntervalVarOk<V>
|
|
124
|
+
: false
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* One find entry's judgment (off the entry's own descriptor — no env, no
|
|
128
|
+
* class map needed): a projected variable is ok, the measure and `pack`
|
|
129
|
+
* demand interval-typed variables, folds and Arg keys demand orderable ones.
|
|
130
|
+
*/
|
|
131
|
+
type FindEntryOk<E> = E extends AnyVar
|
|
132
|
+
? true
|
|
133
|
+
: E extends Duration<infer V extends AnyVar>
|
|
134
|
+
? IntervalVarOk<V>
|
|
135
|
+
: E extends Agg<"count", undefined>
|
|
136
|
+
? true
|
|
137
|
+
: E extends Agg<"countDistinct", AnyVar>
|
|
138
|
+
? true
|
|
139
|
+
: E extends Agg<"sum" | "min" | "max", infer O>
|
|
140
|
+
? FoldOverOk<O>
|
|
141
|
+
: E extends Agg<"argMax" | "argMin", AnyVar, infer K extends AnyVar>
|
|
142
|
+
? OrderVarOk<K> extends true
|
|
143
|
+
? true
|
|
144
|
+
: false
|
|
145
|
+
: E extends Agg<"pack", infer V extends AnyVar>
|
|
146
|
+
? IntervalVarOk<V>
|
|
147
|
+
: false
|
|
148
|
+
|
|
149
|
+
/** The validated find record (intersect with the inferred entries — errors land on the offending key). */
|
|
150
|
+
type CheckFind<F extends FindShape> = {
|
|
151
|
+
readonly [K in keyof F]: FindEntryOk<F[K]> extends true ? F[K] : never
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* The validated find record of a RECURSIVE rule: every entry must be a plain
|
|
156
|
+
* variable (aggregates and the measure are unwritable in a recursive head —
|
|
157
|
+
* the strata quarantine).
|
|
158
|
+
*/
|
|
159
|
+
type CheckRecFind<F extends FindShape> = {
|
|
160
|
+
readonly [K in keyof F]: F[K] extends AnyVar ? F[K] : never
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
/**
|
|
164
|
+
* One find entry's answer-column value type: a variable carries its field's
|
|
165
|
+
* type, the measure/count/countDistinct are `bigint`, folds carry their
|
|
166
|
+
* input's type (a measure fold is `bigint`), the Arg forms carry the
|
|
167
|
+
* payload's type, `pack` its interval type.
|
|
168
|
+
*/
|
|
169
|
+
type FindValue<E> = E extends AnyVar
|
|
170
|
+
? Infer<E["field"]>
|
|
171
|
+
: E extends Duration<AnyVar>
|
|
172
|
+
? bigint
|
|
173
|
+
: E extends Agg<"count", undefined>
|
|
174
|
+
? bigint
|
|
175
|
+
: E extends Agg<"countDistinct", AnyVar>
|
|
176
|
+
? bigint
|
|
177
|
+
: E extends Agg<"sum" | "min" | "max", infer O>
|
|
178
|
+
? O extends AnyVar
|
|
179
|
+
? Infer<O["field"]>
|
|
180
|
+
: bigint
|
|
181
|
+
: E extends Agg<"argMax" | "argMin", infer V extends AnyVar, AnyVar>
|
|
182
|
+
? Infer<V["field"]>
|
|
183
|
+
: E extends Agg<"pack", infer V extends AnyVar>
|
|
184
|
+
? Infer<V["field"]>
|
|
185
|
+
: never
|
|
186
|
+
|
|
187
|
+
/** The inferred answer-row object type of a find record — the keys ARE the columns. */
|
|
188
|
+
type RowOfFind<F extends FindShape> = { readonly [K in keyof F]: FindValue<F[K]> }
|
|
189
|
+
|
|
190
|
+
/**
|
|
191
|
+
* The head signature of a recursive rule's find record as classed mint
|
|
192
|
+
* slots (descriptor + law-computed class), keyed by column name — the
|
|
193
|
+
* signature an `idb` join pairs against (`F` is variable-only there).
|
|
194
|
+
*/
|
|
195
|
+
type HeadRecordOf<Classes extends SchemaClasses, F extends FindShape> = {
|
|
196
|
+
readonly [K in keyof F]: F[K] extends AnyVar ? MintSlotOf<Classes, F[K]> : never
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
export type {
|
|
200
|
+
Agg,
|
|
201
|
+
AggOpName,
|
|
202
|
+
AnyAgg,
|
|
203
|
+
CheckFind,
|
|
204
|
+
CheckRecFind,
|
|
205
|
+
FindEntry,
|
|
206
|
+
FindEntryOk,
|
|
207
|
+
FindShape,
|
|
208
|
+
FindValue,
|
|
209
|
+
HeadRecordOf,
|
|
210
|
+
RowOfFind
|
|
211
|
+
}
|
|
212
|
+
export { argMax, argMin, count, countDistinct, max, min, pack, sum }
|