@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.
Files changed (100) hide show
  1. package/COOKBOOK.md +140 -136
  2. package/README.md +24 -11
  3. package/dist/closed.d.ts +7 -5
  4. package/dist/closed.d.ts.map +1 -1
  5. package/dist/closed.js +4 -1
  6. package/dist/closed.js.map +1 -1
  7. package/dist/count.js +1 -1
  8. package/dist/count.js.map +1 -1
  9. package/dist/db.d.ts +110 -73
  10. package/dist/db.d.ts.map +1 -1
  11. package/dist/db.js +172 -116
  12. package/dist/db.js.map +1 -1
  13. package/dist/exhume.d.ts +22 -10
  14. package/dist/exhume.d.ts.map +1 -1
  15. package/dist/exhume.js +42 -9
  16. package/dist/exhume.js.map +1 -1
  17. package/dist/face.d.ts +10 -6
  18. package/dist/face.d.ts.map +1 -1
  19. package/dist/face.js.map +1 -1
  20. package/dist/fields.d.ts +38 -16
  21. package/dist/fields.d.ts.map +1 -1
  22. package/dist/fields.js +33 -8
  23. package/dist/fields.js.map +1 -1
  24. package/dist/index.d.ts +9 -6
  25. package/dist/index.d.ts.map +1 -1
  26. package/dist/index.js +5 -2
  27. package/dist/index.js.map +1 -1
  28. package/dist/lower.d.ts +9 -9
  29. package/dist/lower.d.ts.map +1 -1
  30. package/dist/lower.js +17 -12
  31. package/dist/lower.js.map +1 -1
  32. package/dist/marshal.d.ts +17 -7
  33. package/dist/marshal.d.ts.map +1 -1
  34. package/dist/marshal.js +32 -10
  35. package/dist/marshal.js.map +1 -1
  36. package/dist/native.d.ts +60 -9
  37. package/dist/native.d.ts.map +1 -1
  38. package/dist/native.js.map +1 -1
  39. package/dist/query/atom.d.ts +199 -203
  40. package/dist/query/atom.d.ts.map +1 -1
  41. package/dist/query/atom.js +39 -48
  42. package/dist/query/atom.js.map +1 -1
  43. package/dist/query/find.d.ts +116 -0
  44. package/dist/query/find.d.ts.map +1 -0
  45. package/dist/query/{select.js → find.js} +22 -22
  46. package/dist/query/find.js.map +1 -0
  47. package/dist/query/lower.d.ts +131 -158
  48. package/dist/query/lower.d.ts.map +1 -1
  49. package/dist/query/lower.js +505 -494
  50. package/dist/query/lower.js.map +1 -1
  51. package/dist/query/predicate.d.ts +22 -14
  52. package/dist/query/predicate.d.ts.map +1 -1
  53. package/dist/query/predicate.js +35 -42
  54. package/dist/query/predicate.js.map +1 -1
  55. package/dist/query/run.d.ts +8 -8
  56. package/dist/query/run.d.ts.map +1 -1
  57. package/dist/query/run.js +16 -21
  58. package/dist/query/run.js.map +1 -1
  59. package/dist/query/scope.d.ts +139 -74
  60. package/dist/query/scope.d.ts.map +1 -1
  61. package/dist/query/scope.js +80 -33
  62. package/dist/query/scope.js.map +1 -1
  63. package/dist/relation.d.ts.map +1 -1
  64. package/dist/relation.js +3 -1
  65. package/dist/relation.js.map +1 -1
  66. package/dist/schema.d.ts.map +1 -1
  67. package/dist/schema.js +12 -2
  68. package/dist/schema.js.map +1 -1
  69. package/dist/spec.d.ts +20 -10
  70. package/dist/spec.d.ts.map +1 -1
  71. package/dist/spec.js.map +1 -1
  72. package/dist/statements.d.ts +22 -2
  73. package/dist/statements.d.ts.map +1 -1
  74. package/dist/statements.js +26 -5
  75. package/dist/statements.js.map +1 -1
  76. package/package.json +3 -3
  77. package/src/closed.ts +13 -7
  78. package/src/count.ts +1 -1
  79. package/src/db.ts +293 -177
  80. package/src/exhume.ts +48 -11
  81. package/src/face.ts +13 -6
  82. package/src/fields.ts +51 -15
  83. package/src/index.ts +12 -8
  84. package/src/lower.ts +17 -12
  85. package/src/marshal.ts +38 -13
  86. package/src/native.ts +59 -8
  87. package/src/query/atom.ts +297 -275
  88. package/src/query/find.ts +212 -0
  89. package/src/query/lower.ts +692 -724
  90. package/src/query/predicate.ts +37 -45
  91. package/src/query/run.ts +17 -22
  92. package/src/query/scope.ts +184 -90
  93. package/src/relation.ts +3 -1
  94. package/src/schema.ts +14 -2
  95. package/src/spec.ts +21 -9
  96. package/src/statements.ts +30 -6
  97. package/dist/query/select.d.ts +0 -128
  98. package/dist/query/select.d.ts.map +0 -1
  99. package/dist/query/select.js.map +0 -1
  100. package/src/query/select.ts +0 -215
package/src/schema.ts CHANGED
@@ -13,11 +13,11 @@ import * as errors from "@superbuilders/errors"
13
13
  import type { AnyClosed } from "#closed.ts"
14
14
  import { isClosedMember, sealedFieldOf } from "#closed.ts"
15
15
  import type { FaceData } from "#face.ts"
16
- import { assertDeclarationOrderKey, rosterOf } from "#fields.ts"
16
+ import { assertDeclarationOrderKey, assertDeclarationRecord, rosterOf } from "#fields.ts"
17
17
  import { type ClassesOf, classesComplete, computeClasses, type LawfulStatements, type SchemaClasses } from "#law.ts"
18
18
  import type { AnyRelation } from "#relation.ts"
19
19
  import type { LiteralSetSpec, LiteralSpec } from "#spec.ts"
20
- import { renderStatement, type Statement } from "#statements.ts"
20
+ import { isStatement, renderStatement, type Statement } from "#statements.ts"
21
21
 
22
22
  /**
23
23
  * Validates the relation record and collects the implied keys: the
@@ -27,6 +27,7 @@ import { renderStatement, type Statement } from "#statements.ts"
27
27
  * single spelling authority.
28
28
  */
29
29
  function collectImplied(name: string, relations: SchemaRelations): Set<string> {
30
+ assertDeclarationRecord(`schema ${name} relations`, relations)
30
31
  const implied = new Set<string>()
31
32
  for (const [recordKey, member] of Object.entries(relations)) {
32
33
  assertDeclarationOrderKey(`schema ${name} relation`, recordKey)
@@ -297,6 +298,17 @@ function schema<const Rels extends SchemaRelations, const Stmts extends readonly
297
298
  const implied = collectImplied(name, relations)
298
299
  const seen = new Set<string>()
299
300
  for (const statement of statements) {
301
+ /**
302
+ * The untyped caller's half of the admission brand: the type tier
303
+ * already refuses an unbranded structural literal, and this probe
304
+ * refuses the same forgery at runtime — a statement that skipped the
305
+ * construction-time arity and roster walls never enters the theory.
306
+ */
307
+ if (!isStatement(statement)) {
308
+ throw errors.new(
309
+ `schema ${name}: a statement is minted only by key/contained/mirrors/window — a structural literal skips the construction-time arity and roster walls`
310
+ )
311
+ }
300
312
  const rendered = renderStatement(statement)
301
313
  verifyMembership(name, relations, statement, rendered)
302
314
  if (implied.has(rendered)) {
package/src/spec.ts CHANGED
@@ -118,19 +118,30 @@ interface RowSpec {
118
118
  }
119
119
 
120
120
  /**
121
- * One relation. `extension: rows` declares it closed (the option is the
122
- * kind); a closed relation's `fields` are its declared intrinsic columns
123
- * only the synthetic (`id`, u64) handle field is materialized by the
124
- * engine's schema validation. `newtype` is the handle newtype of a closed
125
- * relation (the SDK emits the id's law-computed generator class,
126
- * `` `${name}.id` `` — the same label every referencing field carries by
127
- * law), undefined on an ordinary one.
121
+ * A relation's closedness as ONE sum (ruled 2026-07-23, R7): the handle
122
+ * newtype and the ground axioms travel together the two illegal states
123
+ * (a roster without its newtype, a newtype without its roster) are
124
+ * unspellable on the wire exactly as they are unrepresentable in the
125
+ * fused Rust `RelationSpec`. `newtype` is the id's law-computed generator
126
+ * class (`` `${name}.id` `` — the same label every referencing field
127
+ * carries by law), which is how the engine resolves a handle literal back
128
+ * to its roster.
129
+ */
130
+ interface ClosedSpec {
131
+ readonly newtype: string
132
+ readonly rows: readonly RowSpec[]
133
+ }
134
+
135
+ /**
136
+ * One relation. A present `closed` declares it closed (the option is the
137
+ * kind, one sum — R7); a closed relation's `fields` are its declared
138
+ * intrinsic columns only — the synthetic (`id`, u64) handle field is
139
+ * materialized by the engine's schema validation.
128
140
  */
129
141
  interface RelationSpec {
130
142
  readonly name: string
131
- readonly newtype: string | undefined
132
143
  readonly fields: readonly FieldSpec[]
133
- readonly extension: readonly RowSpec[] | undefined
144
+ readonly closed: ClosedSpec | undefined
134
145
  }
135
146
 
136
147
  /**
@@ -313,6 +324,7 @@ function renderWindow(window: WindowSpec): string {
313
324
  }
314
325
 
315
326
  export type {
327
+ ClosedSpec,
316
328
  FieldSpec,
317
329
  LiteralSetSpec,
318
330
  LiteralSpec,
package/src/statements.ts CHANGED
@@ -74,9 +74,33 @@ interface WindowData<Tgt extends FaceData = FaceData, Src extends FaceData = Fac
74
74
  /** One statement's runtime description, tagged by form. */
75
75
  type StatementData = KeyData<AnyRelation, readonly string[]> | ContainmentData | WindowData
76
76
 
77
- /** An opaque statement value — what `schema()` assembles into a theory. */
77
+ /**
78
+ * The admission brand — a module-private symbol, deliberately unexported
79
+ * (the `count.ts` pattern): `Statement` is a public structural type, so
80
+ * without this brand a forged plain object of the right shape would walk
81
+ * past the construction-time arity and roster walls into `schema()` — and
82
+ * the roster wall is the one the engine cannot backstop (the wire carries
83
+ * plain u64s, no rosters). The symbol makes the four constructors the ONLY
84
+ * mints, so a statement that skipped the walls is unspellable.
85
+ */
86
+ const admitted: unique symbol = Symbol("bumbledb.statement.admitted")
87
+
88
+ /** An opaque statement value — what `schema()` assembles into a theory. Only the four constructors produce one. */
78
89
  interface Statement {
79
90
  readonly data: StatementData
91
+ readonly [admitted]: true
92
+ }
93
+
94
+ /**
95
+ * Narrows any value to an admitted statement — the probe is the
96
+ * module-private {@link admitted} brand only the four constructors set, so
97
+ * no host-built value (fact cells are structurally OPEN — an interval with
98
+ * an excess `kind` property is a legal cell) can ever be misread as one.
99
+ * The keyed-get selector dispatch and `schema()`'s admission both judge
100
+ * through here.
101
+ */
102
+ function isStatement(value: unknown): value is Statement {
103
+ return typeof value === "object" && value !== null && admitted in value
80
104
  }
81
105
 
82
106
  /**
@@ -188,7 +212,7 @@ function key<
188
212
  owner: relation,
189
213
  projection: Object.freeze(fields)
190
214
  })
191
- return Object.freeze({ data })
215
+ return Object.freeze({ data, [admitted]: true as const })
192
216
  }
193
217
 
194
218
  /**
@@ -210,7 +234,7 @@ function contained<A extends AnyFace, B extends AnyFace>(
210
234
  target: target.data,
211
235
  bidirectional: false
212
236
  })
213
- const statement = Object.freeze({ data })
237
+ const statement = Object.freeze({ data, [admitted]: true as const })
214
238
  assertArityAgreement(data.source, data.target, statement)
215
239
  assertRosterAgreement(data.source, data.target, statement)
216
240
  return statement
@@ -235,7 +259,7 @@ function mirrors<A extends AnyFace, B extends AnyFace>(
235
259
  target: target.data,
236
260
  bidirectional: true
237
261
  })
238
- const statement = Object.freeze({ data })
262
+ const statement = Object.freeze({ data, [admitted]: true as const })
239
263
  assertArityAgreement(data.source, data.target, statement)
240
264
  assertRosterAgreement(data.source, data.target, statement)
241
265
  return statement
@@ -262,7 +286,7 @@ function window<B extends AnyFace, A extends AnyFace>(
262
286
  window: count.window,
263
287
  source: source.data
264
288
  })
265
- const statement = Object.freeze({ data })
289
+ const statement = Object.freeze({ data, [admitted]: true as const })
266
290
  assertArityAgreement(data.source, data.target, statement)
267
291
  assertRosterAgreement(data.source, data.target, statement)
268
292
  return statement
@@ -302,4 +326,4 @@ export type {
302
326
  WindowData,
303
327
  WindowStatement
304
328
  }
305
- export { contained, key, mirrors, renderStatement, window }
329
+ export { contained, isStatement, key, mirrors, renderStatement, window }
@@ -1,128 +0,0 @@
1
- /**
2
- * Select entries and aggregates, STRUCTURAL edition — the head vocabulary,
3
- * 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; a tie yields every attaining row), and `pack` (the coalescing fold —
9
- * RELATION-SHAPED: one answer row per (group, maximal segment), the result
10
- * position interval-typed). Aggregates name their variables — `r.sum("m")`
11
- * — and are typed by the rule environment at `.select`. Grouping is
12
- * implicit: the non-aggregate select entries are the group key; over empty
13
- * input an all-aggregate select yields the EMPTY SET, never a zero row.
14
- * The creation quarantine is representational: a head position is a var
15
- * name, the measure, or an aggregate — no minting or arithmetic term
16
- * exists to spell (permanent law).
17
- */
18
- import type { Infer } from "#fields.ts";
19
- import type { IntervalVarOk, OrderVarOk } from "#query/atom.ts";
20
- import type { Duration, EnvShape, ShapeOf } from "#query/scope.ts";
21
- /** One aggregate operator name of the select vocabulary. */
22
- type AggOpName = "count" | "countDistinct" | "sum" | "min" | "max" | "argMax" | "argMin" | "pack";
23
- /**
24
- * One aggregate select VALUE: the op, the variable name (or measure) it
25
- * folds, and — for the Arg forms — the orderable key's variable name. The
26
- * runtime representation carries the types; the rule environment types the
27
- * result at `.select`.
28
- */
29
- interface Agg<Op extends AggOpName, Over extends string | Duration<string> | undefined, Key extends string | undefined = undefined> {
30
- readonly agg: Op;
31
- readonly over: Over;
32
- readonly key: Key;
33
- }
34
- /** Any aggregate select value. */
35
- type AnyAgg = Agg<AggOpName, string | Duration<string> | undefined, string | undefined>;
36
- /** One select entry: a projected var name, the measure, or an aggregate. */
37
- type SelectEntry = string | Duration<string> | AnyAgg;
38
- /** Nullary count: |the group's set of distinct full bindings|, `bigint`; the answer column is named `count`. */
39
- declare function count(): Agg<"count", undefined>;
40
- /** |the distinct values of the named variable across the group|, `bigint`; legal over every type. */
41
- declare function countDistinct<const N extends string>(over: N): Agg<"countDistinct", N>;
42
- /**
43
- * Exact checked sum over an orderable (u64/i64) variable — wide
44
- * accumulator, one finalize range check; overflow is the engine's typed
45
- * runtime error, never a wrap — or over the measure
46
- * (`r.sum(r.duration("w"))`).
47
- */
48
- declare function sum<const N extends string | Duration<string>>(over: N): Agg<"sum", N>;
49
- /** Minimum over an orderable variable or the measure (orderable types only). */
50
- declare function min<const N extends string | Duration<string>>(over: N): Agg<"min", N>;
51
- /** Maximum over an orderable variable or the measure (orderable types only). */
52
- declare function max<const N extends string | Duration<string>>(over: N): Agg<"max", N>;
53
- /**
54
- * Arg-restriction toward the maximum of `key` (`ir::AggOp::ArgMax`): the
55
- * group's binding set is restricted to the bindings attaining the extreme
56
- * of the orderable key, and `value` is the carried payload — a tie yields
57
- * every attaining row. All Arg entries of one query share one key and one
58
- * direction; Arg and fold aggregates never mix (both the engine's typed
59
- * rules).
60
- */
61
- declare function argMax<const V extends string, const K extends string>(value: V, key: K): Agg<"argMax", V, K>;
62
- /** Arg-restriction toward the minimum of `key`; rules as {@link argMax}. */
63
- declare function argMin<const V extends string, const K extends string>(value: V, key: K): Agg<"argMin", V, K>;
64
- /**
65
- * The coalescing fold (Snodgrass coalesce, `ir::AggOp::Pack`): per group,
66
- * the maximal disjoint half-open segments of the union of the group's
67
- * interval point sets — RELATION-SHAPED, one answer row per (group,
68
- * maximal segment), the result position carrying one interval of the
69
- * input's element type. At most one `pack` per select, never beside a
70
- * fold or an Arg entry (the engine's typed rules).
71
- */
72
- declare function pack<const N extends string>(over: N): Agg<"pack", N>;
73
- /** A fold input's judgment: an orderable variable, or the measure of an interval variable. */
74
- type FoldOverOk<Env extends EnvShape, O> = O extends string ? OrderVarOk<Env, O> : O extends Duration<infer N extends string> ? IntervalVarOk<Env, N> : false;
75
- /**
76
- * One select entry's judgment against the rule environment: projected
77
- * names must be bound, the measure and `pack` demand interval-typed
78
- * variables, folds and Arg keys demand orderable ones.
79
- */
80
- type SelectEntryOk<Env extends EnvShape, E> = E extends string ? E extends keyof Env ? true : false : E extends Duration<infer N extends string> ? IntervalVarOk<Env, N> : E extends Agg<"count", undefined> ? true : E extends Agg<"countDistinct", infer O extends string> ? O extends keyof Env ? true : false : E extends Agg<"sum" | "min" | "max", infer O> ? FoldOverOk<Env, O> : E extends Agg<"argMax" | "argMin", infer O extends string, infer K extends string> ? [O extends keyof Env ? true : false, OrderVarOk<Env, K>] extends [true, true] ? true : false : E extends Agg<"pack", infer O extends string> ? IntervalVarOk<Env, O> : false;
81
- /** The validated select tuple (intersect with the inferred entries — errors land on the offending argument). */
82
- type CheckSelect<Env extends EnvShape, S> = {
83
- readonly [I in keyof S]: SelectEntryOk<Env, S[I]> extends true ? S[I] : never;
84
- };
85
- /** The validated names-only select tuple of a RECURSIVE rule (aggregates and the measure are unwritable there). */
86
- type CheckNameSelect<Env extends EnvShape, S> = {
87
- readonly [I in keyof S]: S[I] extends keyof Env ? S[I] : never;
88
- };
89
- /**
90
- * One select entry's answer-column fragment: the column is named by the
91
- * variable it projects or folds (`count` names its column `count`), and
92
- * its type reflects the entry — `count`/`countDistinct` are `bigint`
93
- * whatever they counted, folds carry their input's type, the measure is
94
- * `bigint`, the Arg forms carry the payload's type, `pack` its interval
95
- * type.
96
- */
97
- type SelectEntryRow<Env extends EnvShape, E> = E extends string ? {
98
- readonly [K in E]: Infer<Env[E & keyof Env]["field"]>;
99
- } : E extends Duration<infer N extends string> ? {
100
- readonly [K in N]: bigint;
101
- } : E extends Agg<"count", undefined> ? {
102
- readonly count: bigint;
103
- } : E extends Agg<"countDistinct", infer O extends string> ? {
104
- readonly [K in O]: bigint;
105
- } : E extends Agg<"sum" | "min" | "max", infer O> ? O extends string ? {
106
- readonly [K in O]: Infer<Env[O & keyof Env]["field"]>;
107
- } : O extends Duration<infer N extends string> ? {
108
- readonly [K in N]: bigint;
109
- } : never : E extends Agg<"argMax" | "argMin", infer O extends string, string> ? {
110
- readonly [K in O]: Infer<Env[O & keyof Env]["field"]>;
111
- } : E extends Agg<"pack", infer O extends string> ? {
112
- readonly [K in O]: Infer<Env[O & keyof Env]["field"]>;
113
- } : never;
114
- /** The inferred answer-row object type of a select tuple. */
115
- type RowOfSelect<Env extends EnvShape, S extends readonly SelectEntry[]> = ShapeOf<SelectEntryRow<Env, S[number]>>;
116
- /**
117
- * One projected name's answer-column fragment — a NAKED parameter, so the
118
- * judgment distributes per name (the union of a multi-name select never
119
- * smears into one column's type), mirroring {@link SelectEntryRow}.
120
- */
121
- type NameSelectRow<Env extends EnvShape, N> = N extends string ? {
122
- readonly [K in N]: Infer<Env[K & keyof Env]["field"]>;
123
- } : never;
124
- /** The inferred answer-row object type of a names-only (recursive-rule) select tuple. */
125
- type RowOfNameSelect<Env extends EnvShape, S extends readonly string[]> = ShapeOf<NameSelectRow<Env, S[number]>>;
126
- export type { Agg, AggOpName, AnyAgg, CheckNameSelect, CheckSelect, RowOfNameSelect, RowOfSelect, SelectEntry, SelectEntryOk, SelectEntryRow };
127
- export { argMax, argMin, count, countDistinct, max, min, pack, sum };
128
- //# sourceMappingURL=select.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"select.d.ts","sourceRoot":"","sources":["../../src/query/select.ts"],"names":[],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"select.js","sourceRoot":"","sources":["../../src/query/select.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AA+BH,kCAAkC;AAClC,SAAS,SAAS,CAIhB,EAAM,EAAE,IAAU,EAAE,GAAQ;IAC7B,OAAO,MAAM,CAAC,MAAM,CAAC,EAAE,GAAG,EAAE,EAAE,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC,CAAA;AAC7C,CAAC;AAED,gHAAgH;AAChH,SAAS,KAAK;IACb,OAAO,SAAS,CAAC,OAAO,EAAE,SAAS,EAAE,SAAS,CAAC,CAAA;AAChD,CAAC;AAED,qGAAqG;AACrG,SAAS,aAAa,CAAyB,IAAO;IACrD,OAAO,SAAS,CAAC,eAAe,EAAE,IAAI,EAAE,SAAS,CAAC,CAAA;AACnD,CAAC;AAED;;;;;GAKG;AACH,SAAS,GAAG,CAA4C,IAAO;IAC9D,OAAO,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,SAAS,CAAC,CAAA;AACzC,CAAC;AAED,gFAAgF;AAChF,SAAS,GAAG,CAA4C,IAAO;IAC9D,OAAO,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,SAAS,CAAC,CAAA;AACzC,CAAC;AAED,gFAAgF;AAChF,SAAS,GAAG,CAA4C,IAAO;IAC9D,OAAO,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,SAAS,CAAC,CAAA;AACzC,CAAC;AAED;;;;;;;GAOG;AACH,SAAS,MAAM,CAAiD,KAAQ,EAAE,GAAM;IAC/E,OAAO,SAAS,CAAC,QAAQ,EAAE,KAAK,EAAE,GAAG,CAAC,CAAA;AACvC,CAAC;AAED,4EAA4E;AAC5E,SAAS,MAAM,CAAiD,KAAQ,EAAE,GAAM;IAC/E,OAAO,SAAS,CAAC,QAAQ,EAAE,KAAK,EAAE,GAAG,CAAC,CAAA;AACvC,CAAC;AAED;;;;;;;GAOG;AACH,SAAS,IAAI,CAAyB,IAAO;IAC5C,OAAO,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,SAAS,CAAC,CAAA;AAC1C,CAAC;AAqGD,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,aAAa,EAAE,GAAG,EAAE,GAAG,EAAE,IAAI,EAAE,GAAG,EAAE,CAAA"}
@@ -1,215 +0,0 @@
1
- /**
2
- * Select entries and aggregates, STRUCTURAL edition — the head vocabulary,
3
- * 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; a tie yields every attaining row), and `pack` (the coalescing fold —
9
- * RELATION-SHAPED: one answer row per (group, maximal segment), the result
10
- * position interval-typed). Aggregates name their variables — `r.sum("m")`
11
- * — and are typed by the rule environment at `.select`. Grouping is
12
- * implicit: the non-aggregate select entries are the group key; over empty
13
- * input an all-aggregate select yields the EMPTY SET, never a zero row.
14
- * The creation quarantine is representational: a head position is a var
15
- * name, the measure, or an aggregate — no minting or arithmetic term
16
- * exists to spell (permanent law).
17
- */
18
-
19
- import type { Infer } from "#fields.ts"
20
- import type { IntervalVarOk, OrderVarOk } from "#query/atom.ts"
21
- import type { Duration, EnvShape, ShapeOf } from "#query/scope.ts"
22
-
23
- /** One aggregate operator name of the select vocabulary. */
24
- type AggOpName = "count" | "countDistinct" | "sum" | "min" | "max" | "argMax" | "argMin" | "pack"
25
-
26
- /**
27
- * One aggregate select VALUE: the op, the variable name (or measure) it
28
- * folds, and — for the Arg forms — the orderable key's variable name. The
29
- * runtime representation carries the types; the rule environment types the
30
- * result at `.select`.
31
- */
32
- interface Agg<
33
- Op extends AggOpName,
34
- Over extends string | Duration<string> | undefined,
35
- Key extends string | undefined = undefined
36
- > {
37
- readonly agg: Op
38
- readonly over: Over
39
- readonly key: Key
40
- }
41
-
42
- /** Any aggregate select value. */
43
- type AnyAgg = Agg<AggOpName, string | Duration<string> | undefined, string | undefined>
44
-
45
- /** One select entry: a projected var name, the measure, or an aggregate. */
46
- type SelectEntry = string | Duration<string> | AnyAgg
47
-
48
- /** Builds one aggregate value. */
49
- function aggregate<
50
- Op extends AggOpName,
51
- Over extends string | Duration<string> | undefined,
52
- Key extends string | undefined
53
- >(op: Op, over: Over, key: Key): Agg<Op, Over, Key> {
54
- return Object.freeze({ agg: op, over, key })
55
- }
56
-
57
- /** Nullary count: |the group's set of distinct full bindings|, `bigint`; the answer column is named `count`. */
58
- function count(): Agg<"count", undefined> {
59
- return aggregate("count", undefined, undefined)
60
- }
61
-
62
- /** |the distinct values of the named variable across the group|, `bigint`; legal over every type. */
63
- function countDistinct<const N extends string>(over: N): Agg<"countDistinct", N> {
64
- return aggregate("countDistinct", over, undefined)
65
- }
66
-
67
- /**
68
- * Exact checked sum over an orderable (u64/i64) variable — wide
69
- * accumulator, one finalize range check; overflow is the engine's typed
70
- * runtime error, never a wrap — or over the measure
71
- * (`r.sum(r.duration("w"))`).
72
- */
73
- function sum<const N extends string | Duration<string>>(over: N): Agg<"sum", N> {
74
- return aggregate("sum", over, undefined)
75
- }
76
-
77
- /** Minimum over an orderable variable or the measure (orderable types only). */
78
- function min<const N extends string | Duration<string>>(over: N): Agg<"min", N> {
79
- return aggregate("min", over, undefined)
80
- }
81
-
82
- /** Maximum over an orderable variable or the measure (orderable types only). */
83
- function max<const N extends string | Duration<string>>(over: N): Agg<"max", N> {
84
- return aggregate("max", over, undefined)
85
- }
86
-
87
- /**
88
- * Arg-restriction toward the maximum of `key` (`ir::AggOp::ArgMax`): the
89
- * group's binding set is restricted to the bindings attaining the extreme
90
- * of the orderable key, and `value` is the carried payload — a tie yields
91
- * every attaining row. All Arg entries of one query share one key and one
92
- * direction; Arg and fold aggregates never mix (both the engine's typed
93
- * rules).
94
- */
95
- function argMax<const V extends string, const K extends string>(value: V, key: K): Agg<"argMax", V, K> {
96
- return aggregate("argMax", value, key)
97
- }
98
-
99
- /** Arg-restriction toward the minimum of `key`; rules as {@link argMax}. */
100
- function argMin<const V extends string, const K extends string>(value: V, key: K): Agg<"argMin", V, K> {
101
- return aggregate("argMin", value, key)
102
- }
103
-
104
- /**
105
- * The coalescing fold (Snodgrass coalesce, `ir::AggOp::Pack`): per group,
106
- * the maximal disjoint half-open segments of the union of the group's
107
- * interval point sets — RELATION-SHAPED, one answer row per (group,
108
- * maximal segment), the result position carrying one interval of the
109
- * input's element type. At most one `pack` per select, never beside a
110
- * fold or an Arg entry (the engine's typed rules).
111
- */
112
- function pack<const N extends string>(over: N): Agg<"pack", N> {
113
- return aggregate("pack", over, undefined)
114
- }
115
-
116
- /** A fold input's judgment: an orderable variable, or the measure of an interval variable. */
117
- type FoldOverOk<Env extends EnvShape, O> = O extends string
118
- ? OrderVarOk<Env, O>
119
- : O extends Duration<infer N extends string>
120
- ? IntervalVarOk<Env, N>
121
- : false
122
-
123
- /**
124
- * One select entry's judgment against the rule environment: projected
125
- * names must be bound, the measure and `pack` demand interval-typed
126
- * variables, folds and Arg keys demand orderable ones.
127
- */
128
- type SelectEntryOk<Env extends EnvShape, E> = E extends string
129
- ? E extends keyof Env
130
- ? true
131
- : false
132
- : E extends Duration<infer N extends string>
133
- ? IntervalVarOk<Env, N>
134
- : E extends Agg<"count", undefined>
135
- ? true
136
- : E extends Agg<"countDistinct", infer O extends string>
137
- ? O extends keyof Env
138
- ? true
139
- : false
140
- : E extends Agg<"sum" | "min" | "max", infer O>
141
- ? FoldOverOk<Env, O>
142
- : E extends Agg<"argMax" | "argMin", infer O extends string, infer K extends string>
143
- ? [O extends keyof Env ? true : false, OrderVarOk<Env, K>] extends [true, true]
144
- ? true
145
- : false
146
- : E extends Agg<"pack", infer O extends string>
147
- ? IntervalVarOk<Env, O>
148
- : false
149
-
150
- /** The validated select tuple (intersect with the inferred entries — errors land on the offending argument). */
151
- type CheckSelect<Env extends EnvShape, S> = {
152
- readonly [I in keyof S]: SelectEntryOk<Env, S[I]> extends true ? S[I] : never
153
- }
154
-
155
- /** The validated names-only select tuple of a RECURSIVE rule (aggregates and the measure are unwritable there). */
156
- type CheckNameSelect<Env extends EnvShape, S> = {
157
- readonly [I in keyof S]: S[I] extends keyof Env ? S[I] : never
158
- }
159
-
160
- /**
161
- * One select entry's answer-column fragment: the column is named by the
162
- * variable it projects or folds (`count` names its column `count`), and
163
- * its type reflects the entry — `count`/`countDistinct` are `bigint`
164
- * whatever they counted, folds carry their input's type, the measure is
165
- * `bigint`, the Arg forms carry the payload's type, `pack` its interval
166
- * type.
167
- */
168
- type SelectEntryRow<Env extends EnvShape, E> = E extends string
169
- ? { readonly [K in E]: Infer<Env[E & keyof Env]["field"]> }
170
- : E extends Duration<infer N extends string>
171
- ? { readonly [K in N]: bigint }
172
- : E extends Agg<"count", undefined>
173
- ? { readonly count: bigint }
174
- : E extends Agg<"countDistinct", infer O extends string>
175
- ? { readonly [K in O]: bigint }
176
- : E extends Agg<"sum" | "min" | "max", infer O>
177
- ? O extends string
178
- ? { readonly [K in O]: Infer<Env[O & keyof Env]["field"]> }
179
- : O extends Duration<infer N extends string>
180
- ? { readonly [K in N]: bigint }
181
- : never
182
- : E extends Agg<"argMax" | "argMin", infer O extends string, string>
183
- ? { readonly [K in O]: Infer<Env[O & keyof Env]["field"]> }
184
- : E extends Agg<"pack", infer O extends string>
185
- ? { readonly [K in O]: Infer<Env[O & keyof Env]["field"]> }
186
- : never
187
-
188
- /** The inferred answer-row object type of a select tuple. */
189
- type RowOfSelect<Env extends EnvShape, S extends readonly SelectEntry[]> = ShapeOf<SelectEntryRow<Env, S[number]>>
190
-
191
- /**
192
- * One projected name's answer-column fragment — a NAKED parameter, so the
193
- * judgment distributes per name (the union of a multi-name select never
194
- * smears into one column's type), mirroring {@link SelectEntryRow}.
195
- */
196
- type NameSelectRow<Env extends EnvShape, N> = N extends string
197
- ? { readonly [K in N]: Infer<Env[K & keyof Env]["field"]> }
198
- : never
199
-
200
- /** The inferred answer-row object type of a names-only (recursive-rule) select tuple. */
201
- type RowOfNameSelect<Env extends EnvShape, S extends readonly string[]> = ShapeOf<NameSelectRow<Env, S[number]>>
202
-
203
- export type {
204
- Agg,
205
- AggOpName,
206
- AnyAgg,
207
- CheckNameSelect,
208
- CheckSelect,
209
- RowOfNameSelect,
210
- RowOfSelect,
211
- SelectEntry,
212
- SelectEntryOk,
213
- SelectEntryRow
214
- }
215
- export { argMax, argMin, count, countDistinct, max, min, pack, sum }