effect-qb 0.12.3

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 (81) hide show
  1. package/README.md +1294 -0
  2. package/dist/mysql.js +57575 -0
  3. package/dist/postgres.js +6303 -0
  4. package/package.json +42 -0
  5. package/src/internal/aggregation-validation.ts +57 -0
  6. package/src/internal/case-analysis.ts +50 -0
  7. package/src/internal/coercion-analysis.ts +30 -0
  8. package/src/internal/coercion-errors.ts +29 -0
  9. package/src/internal/coercion-kind.ts +32 -0
  10. package/src/internal/coercion-normalize.ts +7 -0
  11. package/src/internal/coercion-rules.ts +25 -0
  12. package/src/internal/column-state.ts +453 -0
  13. package/src/internal/column.ts +417 -0
  14. package/src/internal/datatypes/define.ts +44 -0
  15. package/src/internal/datatypes/lookup.ts +280 -0
  16. package/src/internal/datatypes/shape.ts +72 -0
  17. package/src/internal/derived-table.ts +149 -0
  18. package/src/internal/dialect.ts +30 -0
  19. package/src/internal/executor.ts +390 -0
  20. package/src/internal/expression-ast.ts +349 -0
  21. package/src/internal/expression.ts +325 -0
  22. package/src/internal/grouping-key.ts +82 -0
  23. package/src/internal/json/ast.ts +63 -0
  24. package/src/internal/json/errors.ts +13 -0
  25. package/src/internal/json/path.ts +227 -0
  26. package/src/internal/json/shape.ts +1 -0
  27. package/src/internal/json/types.ts +386 -0
  28. package/src/internal/mysql-dialect.ts +39 -0
  29. package/src/internal/mysql-renderer.ts +37 -0
  30. package/src/internal/plan.ts +64 -0
  31. package/src/internal/postgres-dialect.ts +34 -0
  32. package/src/internal/postgres-renderer.ts +40 -0
  33. package/src/internal/predicate-analysis.ts +71 -0
  34. package/src/internal/predicate-atom.ts +43 -0
  35. package/src/internal/predicate-branches.ts +40 -0
  36. package/src/internal/predicate-context.ts +279 -0
  37. package/src/internal/predicate-formula.ts +100 -0
  38. package/src/internal/predicate-key.ts +28 -0
  39. package/src/internal/predicate-nnf.ts +12 -0
  40. package/src/internal/predicate-normalize.ts +202 -0
  41. package/src/internal/projection-alias.ts +15 -0
  42. package/src/internal/projections.ts +101 -0
  43. package/src/internal/query-ast.ts +297 -0
  44. package/src/internal/query-factory.ts +6757 -0
  45. package/src/internal/query-requirements.ts +40 -0
  46. package/src/internal/query.ts +1590 -0
  47. package/src/internal/renderer.ts +102 -0
  48. package/src/internal/runtime-normalize.ts +344 -0
  49. package/src/internal/runtime-schema.ts +428 -0
  50. package/src/internal/runtime-value.ts +85 -0
  51. package/src/internal/schema-derivation.ts +131 -0
  52. package/src/internal/sql-expression-renderer.ts +1353 -0
  53. package/src/internal/table-options.ts +225 -0
  54. package/src/internal/table.ts +674 -0
  55. package/src/mysql/column.ts +30 -0
  56. package/src/mysql/datatypes/index.ts +6 -0
  57. package/src/mysql/datatypes/spec.ts +180 -0
  58. package/src/mysql/errors/catalog.ts +51662 -0
  59. package/src/mysql/errors/fields.ts +21 -0
  60. package/src/mysql/errors/index.ts +18 -0
  61. package/src/mysql/errors/normalize.ts +232 -0
  62. package/src/mysql/errors/requirements.ts +73 -0
  63. package/src/mysql/executor.ts +134 -0
  64. package/src/mysql/query.ts +189 -0
  65. package/src/mysql/renderer.ts +19 -0
  66. package/src/mysql/table.ts +157 -0
  67. package/src/mysql.ts +18 -0
  68. package/src/postgres/column.ts +20 -0
  69. package/src/postgres/datatypes/index.ts +8 -0
  70. package/src/postgres/datatypes/spec.ts +264 -0
  71. package/src/postgres/errors/catalog.ts +452 -0
  72. package/src/postgres/errors/fields.ts +48 -0
  73. package/src/postgres/errors/index.ts +4 -0
  74. package/src/postgres/errors/normalize.ts +209 -0
  75. package/src/postgres/errors/requirements.ts +65 -0
  76. package/src/postgres/errors/types.ts +38 -0
  77. package/src/postgres/executor.ts +131 -0
  78. package/src/postgres/query.ts +189 -0
  79. package/src/postgres/renderer.ts +29 -0
  80. package/src/postgres/table.ts +157 -0
  81. package/src/postgres.ts +18 -0
@@ -0,0 +1,1590 @@
1
+ import { pipeArguments, type Pipeable } from "effect/Pipeable"
2
+
3
+ import * as Expression from "./expression.js"
4
+ import * as Plan from "./plan.js"
5
+ import * as Table from "./table.js"
6
+ import * as ExpressionAst from "./expression-ast.js"
7
+ import * as QueryAst from "./query-ast.js"
8
+ import type { JsonNode } from "./json/ast.js"
9
+ import type * as JsonPath from "./json/path.js"
10
+ import type { QueryCapability } from "./query-requirements.js"
11
+ import type { CaseBranchAssumeFalse, CaseBranchAssumeTrue, CaseBranchDecision } from "./case-analysis.js"
12
+ import type { GuaranteedNonNullKeys, GuaranteedNullKeys, GuaranteedSourceNames } from "./predicate-analysis.js"
13
+ import type { PredicateFormula, TrueFormula } from "./predicate-formula.js"
14
+
15
+ export type {
16
+ MergeCapabilities,
17
+ MergeCapabilityTuple,
18
+ QueryCapability,
19
+ QueryRequirement
20
+ } from "./query-requirements.js"
21
+ export type {
22
+ ComparableDbType,
23
+ RuntimeOfDbType,
24
+ TextCompatibleDbType,
25
+ CastableDbType
26
+ } from "./coercion-analysis.js"
27
+ export type {
28
+ CanonicalSegment as JsonPathSegment,
29
+ DescendSegment as JsonPathDescendSegment,
30
+ ExactSegment as JsonExactPathSegment,
31
+ IndexSegment as JsonPathIndexSegment,
32
+ IsExactPath as IsExactJsonPath,
33
+ IsExactSegment as IsExactJsonPathSegment,
34
+ KeySegment as JsonPathKeySegment,
35
+ Path as JsonPath,
36
+ SegmentsOf as JsonPathSegments,
37
+ SliceSegment as JsonPathSliceSegment,
38
+ WildcardSegment as JsonPathWildcardSegment
39
+ } from "./json/path.js"
40
+ export type {
41
+ JsonPathUsageError
42
+ } from "./json/errors.js"
43
+ export type {
44
+ JsonConcatResult,
45
+ JsonDeleteAtPath,
46
+ JsonInsertAtPath,
47
+ JsonKeysResult,
48
+ JsonLengthResult,
49
+ JsonLiteralInput,
50
+ JsonPrimitive,
51
+ JsonSetAtPath,
52
+ JsonTextResult,
53
+ JsonTypeName,
54
+ JsonValue,
55
+ JsonValueAtPath,
56
+ NormalizeJsonLiteral
57
+ } from "./json/types.js"
58
+ export type {
59
+ CoercionKind,
60
+ CoercionKindOf
61
+ } from "./coercion-kind.js"
62
+ export type {
63
+ CanCastDbType,
64
+ CanCompareDbTypes,
65
+ CanContainDbTypes
66
+ } from "./coercion-rules.js"
67
+ export type {
68
+ ConflictClause,
69
+ LockClause,
70
+ QueryStatement,
71
+ SetOperatorKind as SetOperator
72
+ } from "./query-ast.js"
73
+ export { union_query_capabilities } from "./query-requirements.js"
74
+
75
+ /**
76
+ * Shared prototype for runtime expression values created by query helpers.
77
+ *
78
+ * These objects are intentionally minimal. They only need to support
79
+ * `Pipeable.pipe(...)` plus the metadata stored under `Expression.TypeId`.
80
+ */
81
+ const ExpressionProto = {
82
+ pipe(this: unknown) {
83
+ return pipeArguments(this, arguments)
84
+ }
85
+ }
86
+
87
+ /**
88
+ * Shared prototype for runtime plan values created by query helpers.
89
+ *
90
+ * Query plans behave like other Effect-style pipeable values so builders can be
91
+ * chained through `.pipe(...)`.
92
+ */
93
+ const PlanProto = {
94
+ pipe(this: unknown) {
95
+ return pipeArguments(this, arguments)
96
+ }
97
+ }
98
+
99
+ /** Internal symbol used to preserve query-only phantom metadata through inference. */
100
+ const QueryTypeId: unique symbol = Symbol.for("effect-qb/Query/internal")
101
+
102
+ type InsertSourceState = "ready" | "missing"
103
+
104
+ /** Internal phantom state tracked on query plans. */
105
+ interface QueryState<
106
+ Outstanding extends string,
107
+ AvailableNames extends string,
108
+ Grouped extends string,
109
+ Assumptions extends PredicateFormula,
110
+ Capabilities extends QueryCapability,
111
+ Statement extends QueryAst.QueryStatement,
112
+ Target,
113
+ InsertState extends InsertSourceState
114
+ > {
115
+ readonly required: Outstanding
116
+ readonly availableNames: AvailableNames
117
+ readonly grouped: Grouped
118
+ readonly assumptions: Assumptions
119
+ readonly capabilities: Capabilities
120
+ readonly statement: Statement
121
+ readonly target: Target
122
+ readonly insertSource: InsertState
123
+ }
124
+
125
+ /** Source provenance attached to an expression. */
126
+ export type SourceOf<Value extends Expression.Any> = Value[typeof Expression.TypeId]["source"]
127
+ /** Effective SQL dialect carried by an expression. */
128
+ export type DialectOf<Value extends Expression.Any> = Value[typeof Expression.TypeId]["dialect"]
129
+ /** Source dependency map carried by an expression. */
130
+ export type DependenciesOf<Value extends Expression.Any> = Expression.DependenciesOf<Value>
131
+ /** Aggregation kind carried by an expression. */
132
+ export type AggregationOf<Value extends Expression.Any> = Value[typeof Expression.TypeId]["aggregation"]
133
+ type AstOf<Value extends Expression.Any> = Value extends { readonly [ExpressionAst.TypeId]: infer Ast extends ExpressionAst.Any } ? Ast : never
134
+
135
+ /**
136
+ * Primitive values that can be lifted directly into constant SQL expressions.
137
+ *
138
+ * This is the explicit surface today. Later coercion helpers can accept these
139
+ * primitives and normalize them through `literal(...)`.
140
+ */
141
+ export type LiteralValue = string | number | boolean | null | Date
142
+
143
+ /** Runtime expression type produced by `literal(...)` for a primitive value. */
144
+ type LiteralExpression<Value extends LiteralValue> = Expression.Expression<
145
+ Value,
146
+ LiteralDbType<Value>,
147
+ LiteralNullability<Value>,
148
+ "postgres",
149
+ "scalar",
150
+ never
151
+ >
152
+
153
+ /**
154
+ * Values accepted by scalar query operators.
155
+ *
156
+ * Raw primitives are automatically lifted into constant SQL expressions at the
157
+ * operator boundary.
158
+ */
159
+ export type ExpressionInput = Expression.Any | LiteralValue
160
+
161
+ /** Input accepted by numeric clauses such as `limit(...)` and `offset(...)`. */
162
+ export type NumericExpressionInput = Expression.Expression<
163
+ number,
164
+ Expression.DbType.Any,
165
+ Expression.Nullability,
166
+ string,
167
+ "scalar",
168
+ any,
169
+ Expression.SourceDependencies,
170
+ Expression.SourceNullabilityMode
171
+ > | number
172
+
173
+ /** Values accepted by mutation payload fields. */
174
+ export type MutationValueInput<Value> =
175
+ | Value
176
+ | Expression.Expression<Value, Expression.DbType.Any, Expression.Nullability, string, Expression.AggregationKind, any, any, any>
177
+
178
+ /** Maps a payload shape to values or expressions of the same runtime type. */
179
+ export type MutationInputOf<Shape> = {
180
+ readonly [K in keyof Shape]: MutationValueInput<Shape[K]>
181
+ }
182
+
183
+ type Simplify<T> = { readonly [K in keyof T]: T[K] } & {}
184
+
185
+ /** Input accepted by boolean plan clauses such as `where(...)` and joins. */
186
+ export type PredicateInput = Expression.Expression<
187
+ boolean,
188
+ Expression.DbType.Any,
189
+ Expression.Nullability,
190
+ string,
191
+ "scalar",
192
+ any,
193
+ Expression.SourceDependencies,
194
+ Expression.SourceNullabilityMode
195
+ > | boolean
196
+
197
+ /** Input accepted by `having(...)`. */
198
+ export type HavingPredicateInput = Expression.Expression<
199
+ boolean,
200
+ Expression.DbType.Any,
201
+ Expression.Nullability,
202
+ string,
203
+ "scalar" | "aggregate",
204
+ any,
205
+ Expression.SourceDependencies,
206
+ Expression.SourceNullabilityMode
207
+ > | boolean
208
+
209
+ /** Input accepted by `GROUP BY`. */
210
+ export type GroupByInput = Expression.Expression<
211
+ any,
212
+ Expression.DbType.Any,
213
+ Expression.Nullability,
214
+ string,
215
+ "scalar",
216
+ any
217
+ >
218
+
219
+ /** Maps a literal runtime value to its SQL-level DB type descriptor. */
220
+ type LiteralDbType<Value extends LiteralValue> =
221
+ Value extends string ? Expression.DbType.PgText :
222
+ Value extends number ? Expression.DbType.PgNumeric :
223
+ Value extends boolean ? Expression.DbType.PgBool :
224
+ Value extends Date ? Expression.DbType.PgTimestamp :
225
+ Expression.DbType.Base<"postgres", "null">
226
+
227
+ /** Maps a literal runtime value to its static nullability state. */
228
+ type LiteralNullability<Value extends LiteralValue> = Value extends null ? "always" : "never"
229
+ /** Converts a supported input into its canonical expression type. */
230
+ type AsExpression<Value extends ExpressionInput> = Value extends Expression.Any ? Value : LiteralExpression<Extract<Value, LiteralValue>>
231
+ /** Extracts provenance from an operator input after coercion. */
232
+ type SourceOfInput<Value extends ExpressionInput> = SourceOf<AsExpression<Value>>
233
+ /** Extracts dialect from an operator input after coercion. */
234
+ type DialectOfInput<Value extends ExpressionInput> = DialectOf<AsExpression<Value>>
235
+ /** Extracts dependencies from an operator input after coercion. */
236
+ type DependenciesOfInput<Value extends ExpressionInput> = DependenciesOf<AsExpression<Value>>
237
+ /** Extracts required sources from an operator input after coercion. */
238
+ type RequiredFromInput<Value extends ExpressionInput> = RequiredFromDependencies<DependenciesOfInput<Value>>
239
+ /** String-valued expressions accepted by text operators. */
240
+ export type StringExpressionInput = Expression.Expression<
241
+ string | null,
242
+ Expression.DbType.Any,
243
+ Expression.Nullability,
244
+ string,
245
+ Expression.AggregationKind,
246
+ any,
247
+ Expression.SourceDependencies,
248
+ Expression.SourceNullabilityMode
249
+ > | string
250
+ /** Converts a string operator input into its canonical expression type. */
251
+ type AsStringExpression<Value extends StringExpressionInput> = Value extends Expression.Any ? Value : LiteralExpression<Extract<Value, string>>
252
+ /** Extracts provenance from a string operator input after coercion. */
253
+ type SourceOfStringInput<Value extends StringExpressionInput> = SourceOf<AsStringExpression<Value>>
254
+ /** Extracts dialect from a string operator input after coercion. */
255
+ type DialectOfStringInput<Value extends StringExpressionInput> = DialectOf<AsStringExpression<Value>>
256
+ /** Extracts dependencies from a string operator input after coercion. */
257
+ type DependenciesOfStringInput<Value extends StringExpressionInput> = DependenciesOf<AsStringExpression<Value>>
258
+ /** Extracts intrinsic nullability from a string operator input after coercion. */
259
+ type NullabilityOfStringInput<Value extends StringExpressionInput> = Expression.NullabilityOf<AsStringExpression<Value>>
260
+
261
+ /** Extracts a required table name from expression provenance. */
262
+ type RequiredFromSource<Source> = Source extends { readonly tableName: infer Name extends string } ? Name : never
263
+ /** Extracts required table names from an expression dependency map. */
264
+ export type RequiredFromDependencies<Dependencies extends Expression.SourceDependencies> = Extract<keyof Dependencies, string>
265
+
266
+ type LiteralGroupingKey<Value> =
267
+ Value extends string ? `string:${Value}` :
268
+ Value extends number ? `number:${Value}` :
269
+ Value extends boolean ? `boolean:${Value}` :
270
+ Value extends null ? "null" :
271
+ Value extends Date ? `date:${string}` :
272
+ "unknown"
273
+
274
+ type JoinGroupingKeys<Keys extends readonly string[]> = Keys extends readonly []
275
+ ? ""
276
+ : Keys extends readonly [infer Head extends string]
277
+ ? Head
278
+ : Keys extends readonly [infer Head extends string, ...infer Tail extends readonly string[]]
279
+ ? `${Head},${JoinGroupingKeys<Tail>}`
280
+ : string
281
+
282
+ type JsonSegmentGroupingKey<Segment> =
283
+ Segment extends JsonPath.KeySegment<infer Key extends string> ? `key:${Key}` :
284
+ Segment extends JsonPath.IndexSegment<infer Index extends number> ? `index:${Index}` :
285
+ Segment extends JsonPath.WildcardSegment ? "wildcard" :
286
+ Segment extends JsonPath.SliceSegment<infer Start extends number | undefined, infer End extends number | undefined>
287
+ ? `slice:${Start extends number ? Start : ""}:${End extends number ? End : ""}`
288
+ : Segment extends JsonPath.DescendSegment
289
+ ? "descend"
290
+ : Segment extends string
291
+ ? `key:${Segment}`
292
+ : Segment extends number
293
+ ? `index:${Segment}`
294
+ : "unknown"
295
+
296
+ type JsonPathGroupingKey<Segments extends readonly any[]> = Segments extends readonly []
297
+ ? ""
298
+ : Segments extends readonly [infer Head]
299
+ ? JsonSegmentGroupingKey<Head>
300
+ : Segments extends readonly [infer Head, ...infer Tail extends readonly any[]]
301
+ ? `${JsonSegmentGroupingKey<Head>},${JsonPathGroupingKey<Tail>}`
302
+ : string
303
+
304
+ type JsonOpaquePathGroupingKey<Value> =
305
+ Value extends JsonPath.Path<infer Segments extends readonly JsonPath.CanonicalSegment[]>
306
+ ? `jsonpath:${JsonPathGroupingKey<Segments>}` :
307
+ Value extends string ? `jsonpath:${Value}` :
308
+ Value extends Expression.Any ? `jsonpath:${GroupingKeyOfExpression<Value>}` :
309
+ "jsonpath:unknown"
310
+
311
+ type JsonEntryGroupingKey<Entry> =
312
+ Entry extends { readonly key: infer Key extends string; readonly value: infer Value extends Expression.Any }
313
+ ? `${Key}=>${GroupingKeyOfExpression<Value>}`
314
+ : "entry:unknown"
315
+
316
+ type JsonEntriesGroupingKey<Entries extends readonly { readonly key: string; readonly value: Expression.Any }[]> = Entries extends readonly []
317
+ ? ""
318
+ : Entries extends readonly [infer Head]
319
+ ? JsonEntryGroupingKey<Head>
320
+ : Entries extends readonly [infer Head, ...infer Tail extends readonly { readonly key: string; readonly value: Expression.Any }[]]
321
+ ? `${JsonEntryGroupingKey<Head>}|${JsonEntriesGroupingKey<Tail>}`
322
+ : string
323
+
324
+ type BranchGroupingKeys<
325
+ Branches extends readonly ExpressionAst.CaseBranchNode[]
326
+ > = Branches extends readonly []
327
+ ? ""
328
+ : Branches extends readonly [infer Head extends ExpressionAst.CaseBranchNode]
329
+ ? `when:${GroupingKeyOfExpression<Head["when"]>}=>${GroupingKeyOfExpression<Head["then"]>}`
330
+ : Branches extends readonly [
331
+ infer Head extends ExpressionAst.CaseBranchNode,
332
+ ...infer Tail extends readonly ExpressionAst.CaseBranchNode[]
333
+ ]
334
+ ? `when:${GroupingKeyOfExpression<Head["when"]>}=>${GroupingKeyOfExpression<Head["then"]>}|${BranchGroupingKeys<Tail>}`
335
+ : string
336
+
337
+ type GroupingKeyOfAst<Ast extends ExpressionAst.Any> =
338
+ Ast extends ExpressionAst.ColumnNode<infer TableName extends string, infer ColumnName extends string>
339
+ ? `column:${TableName}.${ColumnName}`
340
+ : Ast extends ExpressionAst.LiteralNode<infer Value>
341
+ ? `literal:${LiteralGroupingKey<Value>}`
342
+ : Ast extends ExpressionAst.ExcludedNode<infer ColumnName extends string>
343
+ ? `excluded:${ColumnName}`
344
+ : Ast extends ExpressionAst.CastNode<infer Value extends Expression.Any, infer Target extends Expression.DbType.Any>
345
+ ? `cast(${GroupingKeyOfExpression<Value>} as ${Target["dialect"]}:${Target["kind"]})`
346
+ : Ast extends ExpressionAst.UnaryNode<infer Kind extends ExpressionAst.UnaryKind, infer Value extends Expression.Any>
347
+ ? `${Kind}(${GroupingKeyOfExpression<Value>})`
348
+ : Ast extends ExpressionAst.BinaryNode<infer Kind extends ExpressionAst.BinaryKind, infer Left extends Expression.Any, infer Right extends Expression.Any>
349
+ ? `${Kind}(${GroupingKeyOfExpression<Left>},${GroupingKeyOfExpression<Right>})`
350
+ : Ast extends ExpressionAst.VariadicNode<infer Kind extends ExpressionAst.VariadicKind, infer Values extends readonly Expression.Any[]>
351
+ ? `${Kind}(${JoinGroupingKeys<{
352
+ readonly [K in keyof Values]: Values[K] extends Expression.Any ? GroupingKeyOfExpression<Values[K]> : never
353
+ } & readonly string[]>})`
354
+ : Ast extends JsonNode<infer Kind>
355
+ ? Kind extends "jsonGet" | "jsonPath" | "jsonAccess" | "jsonTraverse" | "jsonGetText" | "jsonPathText" | "jsonAccessText" | "jsonTraverseText"
356
+ ? `json(${Kind},${GroupingKeyOfExpression<Extract<Ast["value"] | Ast["base"] | Ast["left"], Expression.Any>>},${JsonPathGroupingKey<Extract<Ast["segments"] | Ast["path"], readonly any[]>>})`
357
+ : Kind extends "jsonHasKey" | "jsonKeyExists" | "jsonHasAnyKeys" | "jsonHasAllKeys"
358
+ ? `json(${Kind},${GroupingKeyOfExpression<Extract<Ast["value"] | Ast["base"] | Ast["left"], Expression.Any>>},${JoinGroupingKeys<Extract<Ast["keys"], readonly string[]> & readonly string[]>})`
359
+ : Kind extends "jsonConcat" | "jsonMerge" | "jsonDelete" | "jsonDeletePath" | "jsonRemove" | "jsonSet" | "jsonInsert"
360
+ ? `json(${Kind},${GroupingKeyOfExpression<Extract<Ast["left"] | Ast["base"] | Ast["value"], Expression.Any>>},${GroupingKeyOfExpression<Extract<Ast["right"] | Ast["newValue"] | Ast["insert"], Expression.Any>>},${JsonPathGroupingKey<Extract<Ast["segments"] | Ast["path"], readonly any[]>>})`
361
+ : Kind extends "jsonPathExists" | "jsonPathMatch"
362
+ ? `json(${Kind},${GroupingKeyOfExpression<Extract<Ast["value"] | Ast["base"], Expression.Any>>},${JsonOpaquePathGroupingKey<Ast["query"] | Ast["path"]>})`
363
+ : Kind extends "jsonBuildObject"
364
+ ? `json(${Kind},${JsonEntriesGroupingKey<Extract<Ast["entries"], readonly { readonly key: string; readonly value: Expression.Any }[]>>})`
365
+ : Kind extends "jsonBuildArray"
366
+ ? `json(${Kind},${JoinGroupingKeys<{
367
+ readonly [K in keyof Extract<Ast["values"], readonly Expression.Any[]>]:
368
+ Extract<Ast["values"], readonly Expression.Any[]>[K] extends Expression.Any ? GroupingKeyOfExpression<Extract<Ast["values"], readonly Expression.Any[]>[K]> : never
369
+ } & readonly string[]>})`
370
+ : Kind extends "jsonToJson" | "jsonToJsonb" | "jsonTypeOf" | "jsonLength" | "jsonKeys" | "jsonStripNulls"
371
+ ? `json(${Kind},${GroupingKeyOfExpression<Extract<Ast["value"], Expression.Any>>})`
372
+ : never
373
+ : Ast extends ExpressionAst.CaseNode<infer Branches extends readonly ExpressionAst.CaseBranchNode[], infer Else extends Expression.Any>
374
+ ? `case(${BranchGroupingKeys<Branches>};else:${GroupingKeyOfExpression<Else>})`
375
+ : Ast extends ExpressionAst.ExistsNode
376
+ ? "exists(subquery)"
377
+ : never
378
+
379
+ /** Canonical grouping identity for an expression AST. */
380
+ export type GroupingKeyOfExpression<Value extends Expression.Any> = GroupingKeyOfAst<AstOf<Value>>
381
+
382
+ /**
383
+ * Recursive selection tree accepted by `select(...)`.
384
+ *
385
+ * A selection can be either:
386
+ * - a leaf SQL expression
387
+ * - a nested object whose leaves are expressions
388
+ */
389
+ export type SelectionShape =
390
+ | Expression.Any
391
+ | {
392
+ readonly [key: string]: SelectionShape
393
+ }
394
+
395
+ /** Walks a selection tree and unions the table names referenced by its leaves. */
396
+ export type ExtractRequired<Selection> = Selection extends Expression.Any
397
+ ? RequiredFromDependencies<DependenciesOf<Selection>>
398
+ : Selection extends Record<string, any>
399
+ ? {
400
+ [K in keyof Selection]: ExtractRequired<Selection[K]>
401
+ }[keyof Selection]
402
+ : never
403
+
404
+ /** Walks a selection tree and unions the dialects referenced by its leaves. */
405
+ export type ExtractDialect<Selection> = Selection extends Expression.Any
406
+ ? DialectOf<Selection>
407
+ : Selection extends Record<string, any>
408
+ ? {
409
+ [K in keyof Selection]: ExtractDialect<Selection[K]>
410
+ }[keyof Selection]
411
+ : never
412
+
413
+ /**
414
+ * Minimal table-like shape required by `from(...)` and joins.
415
+ *
416
+ * The query layer only needs the plan metadata and the static table name. It
417
+ * deliberately avoids depending on the full table-definition surface.
418
+ */
419
+ export type TableLike<Name extends string = string, Dialect extends string = string> = Plan.Plan<any, any, Record<string, Plan.Source>, Dialect> & {
420
+ readonly [Table.TypeId]: {
421
+ readonly name: Name
422
+ readonly baseName: string
423
+ readonly schemaName?: string
424
+ }
425
+ }
426
+
427
+ /** Concrete schema table accepted by DDL builders. */
428
+ export type SchemaTableLike =
429
+ | Table.TableDefinition<any, any, any, "schema", any>
430
+ | Table.TableClassStatic<any, any, any, any>
431
+
432
+ /**
433
+ * Wrapper returned by `as(subquery, alias)` for derived-table composition.
434
+ *
435
+ * The derived source exposes the subquery output under the new alias and can
436
+ * be passed to `from(...)` or join builders.
437
+ */
438
+ export type DerivedSource<
439
+ PlanValue extends QueryPlan<any, any, any, any, any, any, any, any, any, any>,
440
+ Alias extends string
441
+ > = DerivedSelectionOf<SelectionOfPlan<PlanValue>, Alias> & {
442
+ readonly kind: "derived"
443
+ readonly name: Alias
444
+ readonly baseName: Alias
445
+ readonly dialect: PlanDialectOf<PlanValue>
446
+ readonly plan: CompletePlan<PlanValue>
447
+ readonly required?: never
448
+ readonly columns: DerivedSelectionOf<SelectionOfPlan<PlanValue>, Alias>
449
+ }
450
+
451
+ /** Wrapper returned by `with(subquery, alias)` for common table expression composition. */
452
+ export type CteSource<
453
+ PlanValue extends QueryPlan<any, any, any, any, any, any, any, any, any, any>,
454
+ Alias extends string
455
+ > = DerivedSelectionOf<SelectionOfPlan<PlanValue>, Alias> & {
456
+ readonly kind: "cte"
457
+ readonly name: Alias
458
+ readonly baseName: Alias
459
+ readonly dialect: PlanDialectOf<PlanValue>
460
+ readonly plan: CompletePlan<PlanValue>
461
+ readonly recursive?: boolean
462
+ readonly columns: DerivedSelectionOf<SelectionOfPlan<PlanValue>, Alias>
463
+ }
464
+
465
+ /** Wrapper returned by `lateral(subquery, alias)` for correlated derived sources. */
466
+ export type LateralSource<
467
+ PlanValue extends QueryPlan<any, any, any, any, any, any, any, any, any, any>,
468
+ Alias extends string
469
+ > = DerivedSelectionOf<SelectionOfPlan<PlanValue>, Alias> & {
470
+ readonly kind: "lateral"
471
+ readonly name: Alias
472
+ readonly baseName: Alias
473
+ readonly dialect: PlanDialectOf<PlanValue>
474
+ readonly plan: PlanValue
475
+ readonly required: RequiredOfPlan<PlanValue>
476
+ readonly columns: DerivedSelectionOf<SelectionOfPlan<PlanValue>, Alias>
477
+ }
478
+
479
+ type ValuesRowInput = Record<string, ExpressionInput>
480
+
481
+ /** Anonymous `values(...)` input that must be aliased through `as(...)` before use as a source. */
482
+ export type ValuesInput<
483
+ Rows extends readonly [ValuesRowInput, ...ValuesRowInput[]],
484
+ Selection extends SelectionShape,
485
+ Dialect extends string
486
+ > = Pipeable & {
487
+ readonly kind: "values"
488
+ readonly dialect: Dialect
489
+ readonly rows: readonly [Record<string, Expression.Any>, ...Record<string, Expression.Any>[]]
490
+ readonly selection: Selection
491
+ }
492
+
493
+ /** Wrapper returned by `as(values(rows), alias)` for standalone row sources and insert sources. */
494
+ export type ValuesSource<
495
+ Rows extends readonly [ValuesRowInput, ...ValuesRowInput[]],
496
+ Selection extends SelectionShape,
497
+ Alias extends string,
498
+ Dialect extends string
499
+ > = DerivedSelectionOf<Selection, Alias> & {
500
+ readonly kind: "values"
501
+ readonly name: Alias
502
+ readonly baseName: Alias
503
+ readonly dialect: Dialect
504
+ readonly rows: readonly [Record<string, Expression.Any>, ...Record<string, Expression.Any>[]]
505
+ readonly columns: DerivedSelectionOf<Selection, Alias>
506
+ }
507
+
508
+ /** Broad structural shape for anonymous `values(...)` inputs before aliasing. */
509
+ export type AnyValuesInput = {
510
+ readonly kind: "values"
511
+ readonly dialect: string
512
+ readonly rows: readonly Record<string, Expression.Any>[]
513
+ readonly selection: Record<string, Expression.Any>
514
+ }
515
+
516
+ /** Broad structural shape for `values(...)` sources when used as composable inputs. */
517
+ export type AnyValuesSource = {
518
+ readonly kind: "values"
519
+ readonly name: string
520
+ readonly baseName: string
521
+ readonly dialect: string
522
+ readonly rows: readonly Record<string, Expression.Any>[]
523
+ readonly columns: Record<string, Expression.Any>
524
+ }
525
+
526
+ /** Wrapper returned by `unnest(columns, alias)` for standalone array sources. */
527
+ export type UnnestSource<
528
+ Selection extends SelectionShape,
529
+ Alias extends string,
530
+ Dialect extends string
531
+ > = DerivedSelectionOf<Selection, Alias> & {
532
+ readonly kind: "unnest"
533
+ readonly name: Alias
534
+ readonly baseName: Alias
535
+ readonly dialect: Dialect
536
+ readonly values: Readonly<Record<string, readonly ExpressionInput[]>>
537
+ readonly arrays: Readonly<Record<string, readonly Expression.Any[]>>
538
+ readonly columns: DerivedSelectionOf<Selection, Alias>
539
+ }
540
+
541
+ /** Wrapper returned by `generateSeries(...)` and similar table functions. */
542
+ export type TableFunctionSource<
543
+ Selection extends SelectionShape,
544
+ Alias extends string,
545
+ Dialect extends string,
546
+ FunctionName extends string = string
547
+ > = DerivedSelectionOf<Selection, Alias> & {
548
+ readonly kind: "tableFunction"
549
+ readonly name: Alias
550
+ readonly baseName: Alias
551
+ readonly dialect: Dialect
552
+ readonly functionName: FunctionName
553
+ readonly args: readonly Expression.Any[]
554
+ readonly columns: DerivedSelectionOf<Selection, Alias>
555
+ }
556
+
557
+ /** Accepts either a physical table or a derived table source. */
558
+ type DerivedSourceShape = {
559
+ readonly kind: "derived"
560
+ readonly name: string
561
+ readonly baseName: string
562
+ readonly dialect: string
563
+ readonly plan: QueryPlan<any, any, any, any, any, any, any, any, any, any>
564
+ readonly columns: Record<string, unknown>
565
+ }
566
+
567
+ type CteSourceShape = {
568
+ readonly kind: "cte"
569
+ readonly name: string
570
+ readonly baseName: string
571
+ readonly dialect: string
572
+ readonly plan: QueryPlan<any, any, any, any, any, any, any, any, any, any>
573
+ readonly recursive?: boolean
574
+ readonly required?: never
575
+ readonly columns: Record<string, unknown>
576
+ }
577
+
578
+ type LateralSourceShape = {
579
+ readonly kind: "lateral"
580
+ readonly name: string
581
+ readonly baseName: string
582
+ readonly dialect: string
583
+ readonly plan: QueryPlan<any, any, any, any, any, any, any, any, any, any>
584
+ readonly required: string
585
+ readonly columns: Record<string, unknown>
586
+ }
587
+
588
+ type ValuesSourceShape = {
589
+ readonly kind: "values"
590
+ readonly name: string
591
+ readonly baseName: string
592
+ readonly dialect: string
593
+ readonly rows: readonly Record<string, Expression.Any>[]
594
+ readonly columns: Record<string, unknown>
595
+ }
596
+
597
+ type UnnestSourceShape = {
598
+ readonly kind: "unnest"
599
+ readonly name: string
600
+ readonly baseName: string
601
+ readonly dialect: string
602
+ readonly values: Readonly<Record<string, readonly ExpressionInput[]>>
603
+ readonly arrays: Readonly<Record<string, readonly Expression.Any[]>>
604
+ readonly columns: Record<string, unknown>
605
+ }
606
+
607
+ /** Broad structural shape for `unnest(...)` sources when used as composable inputs. */
608
+ export type AnyUnnestSource = {
609
+ readonly kind: "unnest"
610
+ readonly name: string
611
+ readonly baseName: string
612
+ readonly dialect: string
613
+ readonly values: Readonly<Record<string, readonly ExpressionInput[]>>
614
+ readonly arrays: Readonly<Record<string, readonly Expression.Any[]>>
615
+ readonly columns: Record<string, Expression.Any>
616
+ }
617
+
618
+ type TableFunctionSourceShape = {
619
+ readonly kind: "tableFunction"
620
+ readonly name: string
621
+ readonly baseName: string
622
+ readonly dialect: string
623
+ readonly functionName: string
624
+ readonly args: readonly Expression.Any[]
625
+ readonly columns: Record<string, unknown>
626
+ }
627
+
628
+ type DerivedSourceAliasError = DerivedSourceRequiredError<QueryPlan<any, any, any, any, any, any, any, any, any, any>>
629
+
630
+ export type SourceLike =
631
+ | TableLike<any, any>
632
+ | DerivedSourceShape
633
+ | CteSourceShape
634
+ | LateralSourceShape
635
+ | ValuesSourceShape
636
+ | UnnestSourceShape
637
+ | TableFunctionSourceShape
638
+ | DerivedSourceAliasError
639
+
640
+ /** Concrete table sources that can be targeted by mutation statements. */
641
+ export type MutationTargetLike = Table.AnyTable
642
+ export type MutationTargetTuple = readonly [MutationTargetLike, MutationTargetLike, ...MutationTargetLike[]]
643
+ export type MutationTargetInput = MutationTargetLike | MutationTargetTuple
644
+
645
+ /** Extracts a source name from either a table or a derived source. */
646
+ export type SourceNameOf<Source extends SourceLike> =
647
+ Source extends TableLike<infer Name, any> ? Name :
648
+ Source extends { readonly kind: "derived"; readonly name: infer Alias extends string } ? Alias :
649
+ Source extends { readonly kind: "cte"; readonly name: infer Alias extends string } ? Alias :
650
+ Source extends { readonly kind: "lateral"; readonly name: infer Alias extends string } ? Alias :
651
+ Source extends { readonly kind: "values"; readonly name: infer Alias extends string } ? Alias :
652
+ Source extends { readonly kind: "unnest"; readonly name: infer Alias extends string } ? Alias :
653
+ Source extends { readonly kind: "tableFunction"; readonly name: infer Alias extends string } ? Alias :
654
+ never
655
+
656
+ type MutationTargetByName<
657
+ Targets extends MutationTargetTuple,
658
+ Name extends string
659
+ > = Extract<Targets[number], { readonly [Table.TypeId]: { readonly name: Name } }>
660
+
661
+ export type MutationTargetNamesOf<Target extends MutationTargetInput> =
662
+ Target extends MutationTargetLike
663
+ ? SourceNameOf<Target>
664
+ : Target extends MutationTargetTuple
665
+ ? SourceNameOf<Target[number]>
666
+ : never
667
+
668
+ export type UpdateInputOfTarget<Target extends MutationTargetInput> =
669
+ Target extends MutationTargetLike
670
+ ? MutationInputOf<Table.UpdateOf<Target>>
671
+ : Target extends MutationTargetTuple
672
+ ? Simplify<{
673
+ readonly [K in MutationTargetNamesOf<Target>]?: MutationInputOf<Table.UpdateOf<MutationTargetByName<Target, K>>>
674
+ }>
675
+ : never
676
+
677
+ /** Extracts the effective dialect from a source. */
678
+ export type SourceDialectOf<Source extends SourceLike> =
679
+ Source extends TableLike<any, infer Dialect> ? Dialect :
680
+ Source extends { readonly kind: "derived"; readonly plan: infer PlanValue extends QueryPlan<any, any, any, any, any, any, any, any, any, any> } ? PlanDialectOf<PlanValue> :
681
+ Source extends { readonly kind: "cte"; readonly plan: infer PlanValue extends QueryPlan<any, any, any, any, any, any, any, any, any, any> } ? PlanDialectOf<PlanValue> :
682
+ Source extends { readonly kind: "lateral"; readonly plan: infer PlanValue extends QueryPlan<any, any, any, any, any, any, any, any, any, any> } ? PlanDialectOf<PlanValue> :
683
+ Source extends { readonly dialect: infer Dialect extends string } ? Dialect :
684
+ never
685
+
686
+ /** Extracts the base table name from a source. */
687
+ export type SourceBaseNameOf<Source extends SourceLike> =
688
+ Source extends TableLike<any, any> ? Source[typeof Table.TypeId]["baseName"] :
689
+ Source extends { readonly kind: "derived"; readonly baseName: infer BaseName extends string } ? BaseName :
690
+ Source extends { readonly kind: "cte"; readonly baseName: infer BaseName extends string } ? BaseName :
691
+ Source extends { readonly kind: "lateral"; readonly baseName: infer BaseName extends string } ? BaseName :
692
+ Source extends { readonly baseName: infer BaseName extends string } ? BaseName :
693
+ never
694
+
695
+ /** Extracts the outer-scope requirements carried by a source. */
696
+ export type SourceRequiredOf<Source extends SourceLike> =
697
+ Source extends TableLike<any, any> ? never :
698
+ Source extends { readonly kind: "derived" } ? never :
699
+ Source extends { readonly kind: "cte" } ? never :
700
+ Source extends { readonly kind: "lateral"; readonly required: infer Required extends string } ? Required :
701
+ never
702
+
703
+ /** Helper type used when a correlated source is used before its outer dependencies are in scope. */
704
+ export type SourceRequirementError<
705
+ Source extends SourceLike
706
+ > = Source & {
707
+ readonly __effect_qb_error__: "effect-qb: correlated source requires outer-scope tables to be in scope first"
708
+ readonly __effect_qb_required_sources__: SourceRequiredOf<Source>
709
+ readonly __effect_qb_hint__: "Join the outer tables first, then wrap the correlated plan in lateral(...)"
710
+ }
711
+
712
+ /** Helper type used when a raw plan is passed where `as(...)` is required. */
713
+ export type DerivedSourceRequiredError<
714
+ PlanValue extends QueryPlan<any, any, any, any, any, any, any, any, any, any>
715
+ > = PlanValue & {
716
+ readonly __effect_qb_error__: "effect-qb: subqueries must be aliased before they can be used as a source"
717
+ readonly __effect_qb_hint__: "Wrap the nested plan in as(subquery, alias) before passing it to from(...) or a join"
718
+ }
719
+
720
+ type JoinPath<Segments extends readonly string[]> = Segments extends readonly []
721
+ ? ""
722
+ : Segments extends readonly [infer Head extends string]
723
+ ? Head
724
+ : Segments extends readonly [infer Head extends string, ...infer Tail extends readonly string[]]
725
+ ? `${Head}__${JoinPath<Tail>}`
726
+ : string
727
+
728
+ type DerivedLeafExpression<
729
+ Value extends Expression.Any,
730
+ Alias extends string,
731
+ ColumnName extends string
732
+ > = Expression.Expression<
733
+ Expression.RuntimeOf<Value>,
734
+ Expression.DbTypeOf<Value>,
735
+ Expression.NullabilityOf<Value>,
736
+ DialectOf<Value>,
737
+ "scalar",
738
+ Expression.ColumnSource<Alias, ColumnName, Alias>,
739
+ Record<Alias, true>,
740
+ "propagate"
741
+ > & {
742
+ readonly [ExpressionAst.TypeId]: ExpressionAst.ColumnNode<Alias, ColumnName>
743
+ }
744
+
745
+ /** Rebinds a nested selection tree to a derived-table alias. */
746
+ export type DerivedSelectionOf<
747
+ Selection,
748
+ Alias extends string,
749
+ Path extends readonly string[] = []
750
+ > = Selection extends Expression.Any
751
+ ? DerivedLeafExpression<Selection, Alias, JoinPath<Path>>
752
+ : Selection extends Record<string, any>
753
+ ? {
754
+ readonly [K in keyof Selection]: DerivedSelectionOf<Selection[K], Alias, [...Path, Extract<K, string>]>
755
+ }
756
+ : never
757
+
758
+ /** Extracts the static SQL table name from a table-like value. */
759
+ export type TableNameOf<T extends TableLike> = T[typeof Table.TypeId]["name"]
760
+ /** Extracts the effective dialect from a table-like value. */
761
+ export type TableDialectOf<T extends TableLike> = T[typeof Plan.TypeId]["dialect"]
762
+ /** Names of sources already available to a plan. */
763
+ type AvailableNames<Available extends Record<string, Plan.Source>> = Extract<keyof Available, string>
764
+ /** Availability mode of a named source within the current plan scope. */
765
+ type SourceModeOf<
766
+ Available extends Record<string, Plan.Source>,
767
+ Name extends string
768
+ > = Name extends keyof Available ? Available[Name]["mode"] : never
769
+ type TrueAssumptions = TrueFormula
770
+
771
+ /** Extracts the selection carried by a query plan. */
772
+ export type SelectionOfPlan<PlanValue extends QueryPlan<any, any, any, any, any, any, any, any, any, any>> =
773
+ PlanValue[typeof Plan.TypeId]["selection"]
774
+ /** Extracts the public required-source state carried by a query plan. */
775
+ export type RequiredOfPlan<PlanValue extends QueryPlan<any, any, any, any, any, any, any, any, any, any>> =
776
+ PlanValue[typeof Plan.TypeId]["required"]
777
+ /** Extracts the available-source scope carried by a query plan. */
778
+ export type AvailableOfPlan<PlanValue extends QueryPlan<any, any, any, any, any, any, any, any, any, any>> =
779
+ PlanValue[typeof Plan.TypeId]["available"]
780
+ /** Extracts the effective dialect carried by a query plan. */
781
+ export type PlanDialectOf<PlanValue extends QueryPlan<any, any, any, any, any, any, any, any, any, any>> =
782
+ PlanValue[typeof Plan.TypeId]["dialect"]
783
+ /** Extracts the grouped-source phantom carried by a query plan. */
784
+ export type GroupedOfPlan<PlanValue extends QueryPlan<any, any, any, any, any, any, any, any, any, any>> =
785
+ PlanValue extends QueryPlan<any, any, any, any, infer Grouped, any, any, any, any, any> ? Grouped : never
786
+ /** Extracts the available-name phantom carried by a query plan. */
787
+ export type ScopedNamesOfPlan<PlanValue extends QueryPlan<any, any, any, any, any, any, any, any, any, any>> =
788
+ PlanValue extends QueryPlan<any, any, any, any, any, infer ScopedNames, any, any, any, any> ? ScopedNames : never
789
+ /** Extracts the outstanding-required-source phantom carried by a query plan. */
790
+ export type OutstandingOfPlan<PlanValue extends QueryPlan<any, any, any, any, any, any, any, any, any, any>> =
791
+ PlanValue extends QueryPlan<any, any, any, any, any, any, infer Outstanding, any, any, any> ? Outstanding : never
792
+ export type AssumptionsOfPlan<PlanValue extends QueryPlan<any, any, any, any, any, any, any, any, any, any>> =
793
+ PlanValue extends QueryPlan<any, any, any, any, any, any, any, infer Assumptions, any, any> ? Assumptions : TrueAssumptions
794
+ export type CapabilitiesOfPlan<PlanValue extends QueryPlan<any, any, any, any, any, any, any, any, any, any>> =
795
+ PlanValue extends QueryPlan<any, any, any, any, any, any, any, any, infer Capabilities, any> ? Capabilities : never
796
+ /** Extracts capabilities contributed by a source wrapper. */
797
+ export type SourceCapabilitiesOf<Source extends SourceLike> =
798
+ Source extends TableLike<any, any> ? never :
799
+ Source extends { readonly kind: "derived"; readonly plan: infer PlanValue extends QueryPlan<any, any, any, any, any, any, any, any, any, any> } ? CapabilitiesOfPlan<PlanValue> :
800
+ Source extends { readonly kind: "cte"; readonly plan: infer PlanValue extends QueryPlan<any, any, any, any, any, any, any, any, any, any> } ? CapabilitiesOfPlan<PlanValue> :
801
+ Source extends { readonly kind: "lateral"; readonly plan: infer PlanValue extends QueryPlan<any, any, any, any, any, any, any, any, any, any> } ? CapabilitiesOfPlan<PlanValue> :
802
+ never
803
+ /** Extracts the statement kind carried by a query plan. */
804
+ export type StatementOfPlan<PlanValue extends QueryPlan<any, any, any, any, any, any, any, any, any, any>> =
805
+ PlanValue extends QueryPlan<any, any, any, any, any, any, any, any, any, infer Statement> ? Statement : never
806
+ /** Extracts the mutation target phantom carried by a query plan. */
807
+ export type MutationTargetOfPlan<PlanValue extends QueryPlan<any, any, any, any, any, any, any, any, any, any>> =
808
+ PlanValue extends QueryPlan<any, any, any, any, any, any, any, any, any, any, infer Target> ? Target : never
809
+ /** Extracts whether an insert plan still needs a source attached. */
810
+ export type InsertSourceStateOfPlan<PlanValue extends QueryPlan<any, any, any, any, any, any, any, any, any, any>> =
811
+ PlanValue extends QueryPlan<any, any, any, any, any, any, any, any, any, any, any, infer InsertState> ? InsertState : "ready"
812
+
813
+ /**
814
+ * Adds a single source entry to the set of available sources.
815
+ *
816
+ * This is used by `from(...)` and the join builders.
817
+ */
818
+ export type AddAvailable<
819
+ Available extends Record<string, Plan.Source>,
820
+ Name extends string,
821
+ Mode extends Plan.SourceMode = "required"
822
+ > = Available & Record<Name, Plan.Source<Name, Mode>>
823
+
824
+ export type AddAvailableMany<
825
+ Available extends Record<string, Plan.Source>,
826
+ Names extends string,
827
+ Mode extends Plan.SourceMode = "required"
828
+ > = Available & {
829
+ readonly [K in Names]: Plan.Source<K, Mode>
830
+ }
831
+
832
+ /** Join mode projected into the plan's source-scope mode lattice. */
833
+ export type JoinSourceMode<Kind extends QueryAst.JoinKind> = Kind extends "left" | "full"
834
+ ? "optional"
835
+ : "required"
836
+
837
+ type DemoteAllAvailable<
838
+ Available extends Record<string, Plan.Source>
839
+ > = {
840
+ readonly [K in keyof Available]: Available[K] extends Plan.Source<infer Name extends string, any>
841
+ ? Plan.Source<Name, "optional">
842
+ : never
843
+ }
844
+
845
+ export type ExistingAvailableAfterJoin<
846
+ Available extends Record<string, Plan.Source>,
847
+ Kind extends QueryAst.JoinKind
848
+ > = Kind extends "right" | "full"
849
+ ? DemoteAllAvailable<Available>
850
+ : Available
851
+
852
+ export type AvailableAfterJoin<
853
+ Available extends Record<string, Plan.Source>,
854
+ JoinedName extends string,
855
+ Kind extends QueryAst.JoinKind
856
+ > = AddAvailable<ExistingAvailableAfterJoin<Available, Kind>, JoinedName, JoinSourceMode<Kind>>
857
+
858
+ /**
859
+ * Computes the next `required` set after introducing an additional expression.
860
+ *
861
+ * Any sources already present in `available` are considered satisfied.
862
+ */
863
+ export type AddExpressionRequired<
864
+ Required,
865
+ Available extends Record<string, Plan.Source>,
866
+ Value extends ExpressionInput
867
+ > = Exclude<Required | RequiredFromInput<Value>, AvailableNames<Available>>
868
+
869
+ /**
870
+ * Computes the next `required` set after a join is applied.
871
+ *
872
+ * The joined table becomes available immediately, so references to it are
873
+ * removed from the outstanding requirement set.
874
+ */
875
+ export type AddJoinRequired<
876
+ Required,
877
+ Available extends Record<string, Plan.Source>,
878
+ JoinedName extends string,
879
+ Predicate extends PredicateInput | never,
880
+ Kind extends QueryAst.JoinKind = "inner"
881
+ > = Exclude<
882
+ Required | (Predicate extends never ? never : RequiredFromInput<Predicate>),
883
+ AvailableNames<AvailableAfterJoin<Available, JoinedName, Kind>>
884
+ >
885
+
886
+ /** Merges two aggregation kinds through a derived expression. */
887
+ export type MergeAggregation<
888
+ Left extends Expression.AggregationKind,
889
+ Right extends Expression.AggregationKind
890
+ > = Left extends "window"
891
+ ? "window"
892
+ : Right extends "window"
893
+ ? "window"
894
+ : Left extends "aggregate"
895
+ ? "aggregate"
896
+ : Right extends "aggregate"
897
+ ? "aggregate"
898
+ : "scalar"
899
+
900
+ /** Folds aggregation kinds across a tuple of expressions. */
901
+ type MergeAggregationTuple<
902
+ Values extends readonly Expression.Any[],
903
+ Current extends Expression.AggregationKind = "scalar"
904
+ > = Values extends readonly [infer Head extends Expression.Any, ...infer Tail extends readonly Expression.Any[]]
905
+ ? MergeAggregationTuple<Tail, MergeAggregation<Current, AggregationOf<Head>>>
906
+ : Current
907
+
908
+ /** Merges two nullability states for null-propagating scalar operators. */
909
+ type MergeNullability<
910
+ Left extends Expression.Nullability,
911
+ Right extends Expression.Nullability
912
+ > = Left extends "always"
913
+ ? "always"
914
+ : Right extends "always"
915
+ ? "always"
916
+ : Left extends "maybe"
917
+ ? "maybe"
918
+ : Right extends "maybe"
919
+ ? "maybe"
920
+ : "never"
921
+
922
+ /** Folds nullability across a tuple for null-propagating scalar operators. */
923
+ export type MergeNullabilityTuple<
924
+ Values extends readonly Expression.Any[],
925
+ Current extends Expression.Nullability = "never"
926
+ > = Values extends readonly [infer Head extends Expression.Any, ...infer Tail extends readonly Expression.Any[]]
927
+ ? MergeNullabilityTuple<Tail, MergeNullability<Current, Expression.NullabilityOf<Head>>>
928
+ : Current
929
+
930
+ /** Dialect union across a tuple of expressions. */
931
+ export type TupleDialect<
932
+ Values extends readonly Expression.Any[]
933
+ > = Values[number] extends never ? never : DialectOf<Values[number]>
934
+
935
+ /** Source union across a tuple of expressions. */
936
+ export type TupleSource<
937
+ Values extends readonly Expression.Any[]
938
+ > = Values[number] extends never ? never : SourceOf<Values[number]>
939
+
940
+ /** Converts a union into an intersection. */
941
+ type UnionToIntersection<Union> = (
942
+ Union extends any ? (value: Union) => void : never
943
+ ) extends (value: infer Intersection) => void ? Intersection : never
944
+
945
+ /** Dependency-map intersection suitable for provenance unions across a tuple. */
946
+ export type TupleDependencies<
947
+ Values extends readonly Expression.Any[]
948
+ > = DependencyRecord<Values[number] extends never ? never : Extract<keyof DependenciesOf<Values[number]>, string>>
949
+
950
+ /** Builds a canonical dependency map from a string union of table names. */
951
+ export type DependencyRecord<Keys extends string> = [Keys] extends [never] ? {} : Record<Keys, true>
952
+
953
+ /** Grouped expression identities carried by a tuple of scalar expressions. */
954
+ export type GroupedKeysFromValues<
955
+ Values extends readonly Expression.Any[]
956
+ > = Values[number] extends never ? never : {
957
+ [K in keyof Values]: Values[K] extends Expression.Any ? GroupingKeyOfExpression<Values[K]> : never
958
+ }[number]
959
+
960
+ /** Whether a selection contains any aggregate expressions. */
961
+ type SelectionHasAggregate<Selection> = Selection extends Expression.Any
962
+ ? AggregationOf<Selection> extends "aggregate" ? true : false
963
+ : Selection extends Record<string, any>
964
+ ? Extract<{
965
+ [K in keyof Selection]: SelectionHasAggregate<Selection[K]>
966
+ }[keyof Selection], true> extends never ? false : true
967
+ : false
968
+
969
+ /** Whether a selection is valid for a specific grouped-column set. */
970
+ type IsGroupedSelectionValid<
971
+ Selection,
972
+ Grouped extends string
973
+ > = Selection extends Expression.Any
974
+ ? AggregationOf<Selection> extends "aggregate"
975
+ ? true
976
+ : AggregationOf<Selection> extends "window"
977
+ ? false
978
+ : RequiredFromDependencies<DependenciesOf<Selection>> extends never
979
+ ? true
980
+ : [GroupingKeyOfExpression<Selection>] extends [Grouped] ? true : false
981
+ : Selection extends Record<string, any>
982
+ ? Extract<{
983
+ [K in keyof Selection]: IsGroupedSelectionValid<Selection[K], Grouped> extends true ? never : true
984
+ }[keyof Selection], true> extends never ? true : false
985
+ : false
986
+
987
+ /** Whether a selection is aggregation-safe for the current grouping state. */
988
+ type IsAggregationCompatibleSelection<
989
+ Selection,
990
+ Grouped extends string
991
+ > = SelectionHasAggregate<Selection> extends true
992
+ ? IsGroupedSelectionValid<Selection, Grouped>
993
+ : [Grouped] extends [never]
994
+ ? true
995
+ : IsGroupedSelectionValid<Selection, Grouped>
996
+
997
+ type MergeNullabilityStates<
998
+ Left extends Expression.Nullability,
999
+ Right extends Expression.Nullability
1000
+ > = Left extends "always"
1001
+ ? "always"
1002
+ : Right extends "always"
1003
+ ? "always"
1004
+ : Left extends "maybe"
1005
+ ? "maybe"
1006
+ : Right extends "maybe"
1007
+ ? "maybe"
1008
+ : "never"
1009
+
1010
+ type FoldEffectiveNullability<
1011
+ Values extends readonly Expression.Any[],
1012
+ Available extends Record<string, Plan.Source>,
1013
+ Assumptions extends PredicateFormula
1014
+ > = Extract<{
1015
+ [K in keyof Values]: Values[K] extends Expression.Any ? EffectiveNullability<Values[K], Available, Assumptions> : never
1016
+ }[number], "always"> extends never
1017
+ ? Extract<{
1018
+ [K in keyof Values]: Values[K] extends Expression.Any ? EffectiveNullability<Values[K], Available, Assumptions> : never
1019
+ }[number], "maybe"> extends never
1020
+ ? "never"
1021
+ : "maybe"
1022
+ : "always"
1023
+
1024
+ type CoalesceEffectiveNullability<
1025
+ Values extends readonly Expression.Any[],
1026
+ Available extends Record<string, Plan.Source>,
1027
+ Assumptions extends PredicateFormula
1028
+ > = Extract<{
1029
+ [K in keyof Values]: Values[K] extends Expression.Any ? EffectiveNullability<Values[K], Available, Assumptions> : never
1030
+ }[number], "never"> extends never
1031
+ ? Extract<{
1032
+ [K in keyof Values]: Values[K] extends Expression.Any ? EffectiveNullability<Values[K], Available, Assumptions> : never
1033
+ }[number], "maybe"> extends never
1034
+ ? "always"
1035
+ : "maybe"
1036
+ : "never"
1037
+
1038
+ type NullabilityOfOutput<Output> =
1039
+ null extends Output
1040
+ ? Exclude<Output, null> extends never ? "always" : "maybe"
1041
+ : "never"
1042
+
1043
+ type RequiredTablesFromAssumptions<Assumptions extends PredicateFormula> =
1044
+ GuaranteedSourceNames<Assumptions>
1045
+
1046
+ type EffectiveAvailable<
1047
+ Available extends Record<string, Plan.Source>,
1048
+ Assumptions extends PredicateFormula
1049
+ > = {
1050
+ readonly [K in keyof Available]: Available[K] & {
1051
+ readonly mode: K extends RequiredTablesFromAssumptions<Assumptions> ? "required" : Available[K]["mode"]
1052
+ }
1053
+ }
1054
+
1055
+ type BaseEffectiveNullability<
1056
+ Value extends Expression.Any,
1057
+ Available extends Record<string, Plan.Source>,
1058
+ Assumptions extends PredicateFormula
1059
+ > = AstOf<Value> extends ExpressionAst.ColumnNode<infer TableName extends string, infer ColumnName extends string>
1060
+ ? `${TableName}.${ColumnName}` extends GuaranteedNullKeys<Assumptions>
1061
+ ? "always"
1062
+ : `${TableName}.${ColumnName}` extends GuaranteedNonNullKeys<Assumptions>
1063
+ ? "never"
1064
+ : Expression.NullabilityOf<Value> extends "always" ? "always"
1065
+ : Expression.SourceNullabilityOf<Value> extends "resolved"
1066
+ ? Expression.NullabilityOf<Value>
1067
+ : HasOptionalSource<DependenciesOf<Value>, Available> extends true ? "maybe"
1068
+ : Expression.NullabilityOf<Value>
1069
+ : Expression.NullabilityOf<Value> extends "always" ? "always"
1070
+ : Expression.SourceNullabilityOf<Value> extends "resolved"
1071
+ ? Expression.NullabilityOf<Value>
1072
+ : HasOptionalSource<DependenciesOf<Value>, Available> extends true ? "maybe"
1073
+ : Expression.NullabilityOf<Value>
1074
+
1075
+ type CaseOutputOf<
1076
+ Branches extends readonly ExpressionAst.CaseBranchNode[],
1077
+ Else extends Expression.Any,
1078
+ Available extends Record<string, Plan.Source>,
1079
+ Assumptions extends PredicateFormula
1080
+ > = Branches extends readonly [
1081
+ infer Head extends ExpressionAst.CaseBranchNode,
1082
+ ...infer Tail extends readonly ExpressionAst.CaseBranchNode[]
1083
+ ]
1084
+ ? Head extends ExpressionAst.CaseBranchNode<infer Predicate extends Expression.Any, infer Then extends Expression.Any>
1085
+ ? CaseBranchDecision<Assumptions, Predicate> extends "skip"
1086
+ ? CaseOutputOf<Tail, Else, Available, Assumptions>
1087
+ : CaseBranchDecision<Assumptions, Predicate> extends "take"
1088
+ ? ExpressionOutput<Then, EffectiveAvailable<Available, CaseBranchAssumeTrue<Assumptions, Predicate>>, CaseBranchAssumeTrue<Assumptions, Predicate>>
1089
+ : ExpressionOutput<Then, EffectiveAvailable<Available, CaseBranchAssumeTrue<Assumptions, Predicate>>, CaseBranchAssumeTrue<Assumptions, Predicate>> |
1090
+ CaseOutputOf<Tail, Else, Available, CaseBranchAssumeFalse<Assumptions, Predicate>>
1091
+ : never
1092
+ : ExpressionOutput<Else, EffectiveAvailable<Available, Assumptions>, Assumptions>
1093
+
1094
+ /** Effective nullability of an expression after source-scope nullability is applied. */
1095
+ export type EffectiveNullability<
1096
+ Value extends Expression.Any,
1097
+ Available extends Record<string, Plan.Source>,
1098
+ Assumptions extends PredicateFormula = TrueAssumptions
1099
+ > =
1100
+ AstOf<Value> extends infer Ast extends ExpressionAst.Any
1101
+ ? Ast extends ExpressionAst.ColumnNode<any, any>
1102
+ ? BaseEffectiveNullability<Value, Available, Assumptions>
1103
+ : Ast extends ExpressionAst.LiteralNode<any>
1104
+ ? Expression.NullabilityOf<Value>
1105
+ : Ast extends ExpressionAst.UnaryNode<infer Kind, infer UnaryValue extends Expression.Any>
1106
+ ? Kind extends "upper" | "lower" | "not"
1107
+ ? EffectiveNullability<UnaryValue, Available, Assumptions>
1108
+ : Kind extends "isNull" | "isNotNull" | "count"
1109
+ ? "never"
1110
+ : Expression.NullabilityOf<Value>
1111
+ : Ast extends ExpressionAst.BinaryNode<"eq", infer Left extends Expression.Any, infer Right extends Expression.Any>
1112
+ ? EffectiveNullability<Left, Available, Assumptions> extends "never"
1113
+ ? EffectiveNullability<Right, Available, Assumptions> extends "never" ? "never" : "maybe"
1114
+ : "maybe"
1115
+ : Ast extends ExpressionAst.VariadicNode<infer Kind, infer Values extends readonly Expression.Any[]>
1116
+ ? Kind extends "coalesce"
1117
+ ? CoalesceEffectiveNullability<Values, Available, Assumptions>
1118
+ : Kind extends "and" | "or" | "concat"
1119
+ ? FoldEffectiveNullability<Values, Available, Assumptions>
1120
+ : BaseEffectiveNullability<Value, Available, Assumptions>
1121
+ : Ast extends ExpressionAst.CaseNode<infer Branches extends readonly ExpressionAst.CaseBranchNode[], infer Else extends Expression.Any>
1122
+ ? NullabilityOfOutput<CaseOutputOf<Branches, Else, Available, Assumptions>>
1123
+ : BaseEffectiveNullability<Value, Available, Assumptions>
1124
+ : BaseEffectiveNullability<Value, Available, Assumptions>
1125
+
1126
+ /** Result runtime type of an expression after effective nullability is resolved. */
1127
+ export type ExpressionOutput<
1128
+ Value extends Expression.Any,
1129
+ Available extends Record<string, Plan.Source>,
1130
+ Assumptions extends PredicateFormula = TrueAssumptions
1131
+ > = AstOf<Value> extends ExpressionAst.CaseNode<infer Branches extends readonly ExpressionAst.CaseBranchNode[], infer Else extends Expression.Any>
1132
+ ? CaseOutputOf<Branches, Else, Available, Assumptions>
1133
+ : EffectiveNullability<Value, Available, Assumptions> extends "never"
1134
+ ? Expression.RuntimeOf<Value>
1135
+ : EffectiveNullability<Value, Available, Assumptions> extends "always"
1136
+ ? null
1137
+ : Expression.RuntimeOf<Value> | null
1138
+
1139
+ /** Result runtime type of a nested selection after source-scope nullability is resolved. */
1140
+ export type OutputOfSelection<
1141
+ Selection,
1142
+ Available extends Record<string, Plan.Source>,
1143
+ Assumptions extends PredicateFormula = TrueAssumptions
1144
+ > = Selection extends Expression.Any
1145
+ ? ExpressionOutput<Selection, Available, Assumptions>
1146
+ : Selection extends Record<string, any>
1147
+ ? {
1148
+ readonly [K in keyof Selection]: OutputOfSelection<Selection[K], Available, Assumptions>
1149
+ }
1150
+ : never
1151
+
1152
+ /** Resolved row type produced by a concrete query plan. */
1153
+ export type ResultRow<PlanValue extends QueryPlan<any, any, any, any, any, any, any, any, any, any>> = OutputOfSelection<
1154
+ PlanValue[typeof Plan.TypeId]["selection"],
1155
+ EffectiveAvailable<PlanValue[typeof Plan.TypeId]["available"], AssumptionsOfPlan<PlanValue>>,
1156
+ AssumptionsOfPlan<PlanValue>
1157
+ >
1158
+
1159
+ /** Resolved row collection type produced by a concrete query plan. */
1160
+ export type ResultRows<PlanValue extends QueryPlan<any, any, any, any, any, any, any, any, any, any>> = ReadonlyArray<ResultRow<PlanValue>>
1161
+
1162
+ /** Conservative runtime row shape produced by remapping projection aliases. */
1163
+ export type RuntimeResultRow<PlanValue extends QueryPlan<any, any, any, any, any, any, any, any, any, any>> = OutputOfSelection<
1164
+ PlanValue[typeof Plan.TypeId]["selection"],
1165
+ PlanValue[typeof Plan.TypeId]["available"],
1166
+ TrueAssumptions
1167
+ >
1168
+
1169
+ /** Conservative runtime row collection type. */
1170
+ export type RuntimeResultRows<PlanValue extends QueryPlan<any, any, any, any, any, any, any, any, any, any>> = ReadonlyArray<RuntimeResultRow<PlanValue>>
1171
+
1172
+ /** Narrows a query plan to aggregate-compatible selections. */
1173
+ type HasKnownOutstanding<Required> = [Required] extends [never]
1174
+ ? false
1175
+ : string extends Required
1176
+ ? false
1177
+ : true
1178
+
1179
+ type SourceCompletenessError<
1180
+ PlanValue extends QueryPlan<any, any, any, any, any, any, any, any, any, any>,
1181
+ MissingSources extends string
1182
+ > = PlanValue & {
1183
+ readonly __effect_qb_error__: "effect-qb: query references sources that are not yet in scope"
1184
+ readonly __effect_qb_missing_sources__: MissingSources
1185
+ readonly __effect_qb_hint__: "Add from(...) or a join for each referenced source before render or execute"
1186
+ }
1187
+
1188
+ type AggregationCompatibilityError<
1189
+ PlanValue extends QueryPlan<any, any, any, any, any, any, any, any, any, any>
1190
+ > = PlanValue & {
1191
+ readonly __effect_qb_error__: "effect-qb: invalid grouped selection"
1192
+ readonly __effect_qb_hint__: "Scalar selections must be covered by groupBy(...) when aggregates are present"
1193
+ }
1194
+
1195
+ type DialectCompatibilityError<
1196
+ PlanValue extends QueryPlan<any, any, any, any, any, any, any, any, any, any>,
1197
+ EngineDialect extends string
1198
+ > = PlanValue & {
1199
+ readonly __effect_qb_error__: "effect-qb: plan dialect is not compatible with the target renderer or executor"
1200
+ readonly __effect_qb_plan_dialect__: PlanValue[typeof Plan.TypeId]["dialect"]
1201
+ readonly __effect_qb_target_dialect__: EngineDialect
1202
+ readonly __effect_qb_hint__: "Use the matching dialect module or renderer/executor"
1203
+ }
1204
+
1205
+ type InsertSourceCompletenessError<
1206
+ PlanValue extends QueryPlan<any, any, any, any, any, any, any, any, any, any>
1207
+ > = PlanValue & {
1208
+ readonly __effect_qb_error__: "effect-qb: insert plan is missing inline values or a source"
1209
+ readonly __effect_qb_hint__: "Pass values directly to insert(...), use defaultValues(...), or pipe the insert plan into from(...)"
1210
+ }
1211
+
1212
+ /** Narrows a query plan to aggregate-compatible selections. */
1213
+ export type AggregationCompatiblePlan<
1214
+ PlanValue extends QueryPlan<any, any, any, any, any, any, any, any, any, any>
1215
+ > = PlanValue extends QueryPlan<infer Selection, any, any, any, infer Grouped, any, any, any, any, any>
1216
+ ? IsAggregationCompatibleSelection<Selection, Grouped> extends true ? PlanValue : AggregationCompatibilityError<PlanValue>
1217
+ : never
1218
+
1219
+ /** Narrows a query plan to aggregate-compatible, source-complete plans. */
1220
+ export type CompletePlan<PlanValue extends QueryPlan<any, any, any, any, any, any, any, any, any, any>> =
1221
+ PlanValue extends QueryPlan<infer Selection, infer Required, any, any, infer Grouped, any, any, any, any, infer Statement, any, infer InsertState>
1222
+ ? Statement extends "insert"
1223
+ ? InsertState extends "missing"
1224
+ ? InsertSourceCompletenessError<PlanValue>
1225
+ : HasKnownOutstanding<Required> extends true
1226
+ ? SourceCompletenessError<PlanValue, Extract<Required, string>>
1227
+ : IsAggregationCompatibleSelection<Selection, Grouped> extends true ? PlanValue : AggregationCompatibilityError<PlanValue>
1228
+ : HasKnownOutstanding<Required> extends true
1229
+ ? SourceCompletenessError<PlanValue, Extract<Required, string>>
1230
+ : IsAggregationCompatibleSelection<Selection, Grouped> extends true ? PlanValue : AggregationCompatibilityError<PlanValue>
1231
+ : never
1232
+
1233
+ /** Whether a plan dialect is compatible with a target engine dialect. */
1234
+ type IsDialectCompatible<
1235
+ PlanDialect extends string,
1236
+ EngineDialect extends string
1237
+ > = [PlanDialect] extends [never]
1238
+ ? true
1239
+ : Extract<PlanDialect, EngineDialect> extends never
1240
+ ? false
1241
+ : true
1242
+
1243
+ /** Narrows a complete plan to those compatible with a target engine dialect. */
1244
+ export type DialectCompatiblePlan<
1245
+ PlanValue extends QueryPlan<any, any, any, any, any, any, any, any, any, any>,
1246
+ EngineDialect extends string
1247
+ > = IsDialectCompatible<PlanValue[typeof Plan.TypeId]["dialect"], EngineDialect> extends true
1248
+ ? CompletePlan<PlanValue>
1249
+ : DialectCompatibilityError<PlanValue, EngineDialect>
1250
+
1251
+ /** Nested-plan compatibility used by subquery expressions such as `exists(...)`. */
1252
+ export type DialectCompatibleNestedPlan<
1253
+ PlanValue extends QueryPlan<any, any, any, any, any, any, any, any, any, any>,
1254
+ EngineDialect extends string
1255
+ > = IsDialectCompatible<PlanValue[typeof Plan.TypeId]["dialect"], EngineDialect> extends true
1256
+ ? AggregationCompatiblePlan<PlanValue>
1257
+ : DialectCompatibilityError<PlanValue, EngineDialect>
1258
+
1259
+ type SetOperandStatement = "select" | "set"
1260
+ type IsUnion<Value, All = Value> = Value extends any ? ([All] extends [Value] ? false : true) : never
1261
+
1262
+ type SingleSelectedExpressionError<
1263
+ PlanValue extends QueryPlan<any, any, any, any, any, any, any, any, any, any>
1264
+ > = PlanValue & {
1265
+ readonly __effect_qb_error__: "effect-qb: scalar and quantified subqueries must project exactly one top-level expression"
1266
+ readonly __effect_qb_hint__: "Project exactly one scalar expression like select({ value: expr }) before using this subquery as a scalar operand"
1267
+ }
1268
+
1269
+ type SingleSelectedExpression<
1270
+ PlanValue extends QueryPlan<any, any, any, any, any, any, any, any, any, any>
1271
+ > = SelectionOfPlan<PlanValue> extends Record<string, infer Value>
1272
+ ? IsUnion<Extract<keyof SelectionOfPlan<PlanValue>, string>> extends true
1273
+ ? SingleSelectedExpressionError<PlanValue>
1274
+ : Value extends Expression.Any
1275
+ ? Value
1276
+ : SingleSelectedExpressionError<PlanValue>
1277
+ : SingleSelectedExpressionError<PlanValue>
1278
+
1279
+ export type ScalarSubqueryPlan<
1280
+ PlanValue extends QueryPlan<any, any, any, any, any, any, any, any, any, any>,
1281
+ EngineDialect extends string
1282
+ > = DialectCompatibleNestedPlan<PlanValue, EngineDialect> extends infer Compatible
1283
+ ? Compatible extends QueryPlan<any, any, any, any, any, any, any, any, any, any>
1284
+ ? SingleSelectedExpression<Compatible> extends Expression.Any ? Compatible : SingleSelectedExpression<Compatible>
1285
+ : Compatible
1286
+ : never
1287
+
1288
+ export type ScalarOutputOfPlan<
1289
+ PlanValue extends QueryPlan<any, any, any, any, any, any, any, any, any, any>
1290
+ > = SingleSelectedExpression<PlanValue> extends infer Value
1291
+ ? Value extends Expression.Any ? Value : never
1292
+ : never
1293
+
1294
+ type SetOperandStatementError<
1295
+ PlanValue extends QueryPlan<any, any, any, any, any, any, any, any, any, any>
1296
+ > = PlanValue & {
1297
+ readonly __effect_qb_error__: "effect-qb: set operators only accept select-like query plans"
1298
+ readonly __effect_qb_statement__: StatementOfPlan<PlanValue>
1299
+ readonly __effect_qb_hint__: "Use select(...) or another set operator as each operand"
1300
+ }
1301
+
1302
+ type SetOperandShapeError<
1303
+ Left extends QueryPlan<any, any, any, any, any, any, any, any, any, any>,
1304
+ Right extends QueryPlan<any, any, any, any, any, any, any, any, any, any>
1305
+ > = Right & {
1306
+ readonly __effect_qb_error__: "effect-qb: set operator operands must have matching result rows"
1307
+ readonly __effect_qb_expected_selection__: SelectionOfPlan<Left>
1308
+ readonly __effect_qb_actual_selection__: SelectionOfPlan<Right>
1309
+ readonly __effect_qb_hint__: "Project the same nested object shape and compatible nullability from each operand"
1310
+ }
1311
+
1312
+ type IsSameSelection<
1313
+ Left extends QueryPlan<any, any, any, any, any, any, any, any, any, any>,
1314
+ Right extends QueryPlan<any, any, any, any, any, any, any, any, any, any>
1315
+ > = [SelectionOfPlan<Left>] extends [SelectionOfPlan<Right>]
1316
+ ? [SelectionOfPlan<Right>] extends [SelectionOfPlan<Left>] ? true : false
1317
+ : false
1318
+
1319
+ /** Set-operator compatibility used by `union(...)`, `intersect(...)`, and `except(...)`. */
1320
+ export type SetCompatiblePlan<
1321
+ PlanValue extends QueryPlan<any, any, any, any, any, any, any, any, any, any>,
1322
+ EngineDialect extends string
1323
+ > = StatementOfPlan<PlanValue> extends SetOperandStatement
1324
+ ? DialectCompatiblePlan<PlanValue, EngineDialect>
1325
+ : SetOperandStatementError<PlanValue>
1326
+
1327
+ /** Right-hand operand compatibility for set operators. */
1328
+ export type SetCompatibleRightPlan<
1329
+ Left extends QueryPlan<any, any, any, any, any, any, any, any, any, any>,
1330
+ Right extends QueryPlan<any, any, any, any, any, any, any, any, any, any>,
1331
+ EngineDialect extends string
1332
+ > = StatementOfPlan<Right> extends SetOperandStatement
1333
+ ? IsSameSelection<Left, Right> extends true
1334
+ ? DialectCompatiblePlan<Right, EngineDialect>
1335
+ : SetOperandShapeError<Left, Right>
1336
+ : SetOperandStatementError<Right>
1337
+
1338
+ /** True when any of an expression's dependencies are optional in the current scope. */
1339
+ type HasOptionalSource<
1340
+ Dependencies extends Expression.SourceDependencies,
1341
+ Available extends Record<string, Plan.Source>
1342
+ > = Extract<{
1343
+ [K in keyof Dependencies & string]: SourceModeOf<Available, K> extends "optional" ? true : never
1344
+ }[keyof Dependencies & string], true> extends never ? false : true
1345
+
1346
+ /**
1347
+ * Concrete query-plan value produced by the query DSL.
1348
+ *
1349
+ * `Selection` is the output shape being built, `Required` tracks referenced
1350
+ * sources that are not yet in scope, `Available` tracks sources already in
1351
+ * scope, and `Dialect` tracks the effective SQL dialect for the plan.
1352
+ */
1353
+ export type QueryPlan<
1354
+ Selection,
1355
+ Required = never,
1356
+ Available extends Record<string, Plan.Source> = {},
1357
+ Dialect extends string = never,
1358
+ Grouped extends string = never,
1359
+ ScopedNames extends string = Extract<keyof Available, string>,
1360
+ Outstanding extends string = Extract<Required, string>,
1361
+ Assumptions extends PredicateFormula = TrueAssumptions,
1362
+ Capabilities extends QueryCapability = "read",
1363
+ Statement extends QueryAst.QueryStatement = "select",
1364
+ Target = unknown,
1365
+ InsertState extends InsertSourceState = InsertSourceState
1366
+ > = Plan.Plan<Selection, Required, Available, Dialect> & {
1367
+ readonly [Plan.TypeId]: Plan.State<Selection, Required, Available, Dialect>
1368
+ readonly [QueryAst.TypeId]: QueryAst.Ast<Selection, Grouped, Statement>
1369
+ readonly [QueryTypeId]: QueryState<Outstanding, ScopedNames, Grouped, Assumptions, Capabilities, Statement, Target, InsertState>
1370
+ }
1371
+
1372
+ /**
1373
+ * Normalizes expression provenance into a flat list.
1374
+ *
1375
+ * Single-source expressions store one provenance object, while derived
1376
+ * operators may carry multiple sources. This helper hides that shape
1377
+ * difference.
1378
+ */
1379
+ const normalizeSources = (source: unknown): readonly unknown[] =>
1380
+ source === undefined ? [] : Array.isArray(source) ? source : [source]
1381
+
1382
+ /**
1383
+ * Merges the provenance of two expressions into one normalized runtime value.
1384
+ *
1385
+ * The result is:
1386
+ * - `undefined` when neither side is sourced
1387
+ * - a single provenance object when exactly one source exists
1388
+ * - an array when multiple sources are involved
1389
+ */
1390
+ export const mergeSources = (left: unknown, right?: unknown): unknown => {
1391
+ const values = [...normalizeSources(left), ...normalizeSources(right)]
1392
+ if (values.length === 0) {
1393
+ return undefined
1394
+ }
1395
+ if (values.length === 1) {
1396
+ return values[0]
1397
+ }
1398
+ return values
1399
+ }
1400
+
1401
+ /** Merges two expression dependency maps into a single normalized record. */
1402
+ export const mergeDependencies = (
1403
+ left: Expression.SourceDependencies,
1404
+ right: Expression.SourceDependencies = {}
1405
+ ): Expression.SourceDependencies => ({
1406
+ ...left,
1407
+ ...right
1408
+ })
1409
+
1410
+ /** Merges expression aggregation kinds at runtime. */
1411
+ export const mergeAggregationRuntime = (
1412
+ left: Expression.AggregationKind,
1413
+ right: Expression.AggregationKind = "scalar"
1414
+ ): Expression.AggregationKind =>
1415
+ left === "window" || right === "window"
1416
+ ? "window"
1417
+ : left === "aggregate" || right === "aggregate"
1418
+ ? "aggregate"
1419
+ : "scalar"
1420
+
1421
+ /** Folds runtime aggregation across a list of expressions. */
1422
+ export const mergeAggregationManyRuntime = (
1423
+ values: readonly Expression.Any[]
1424
+ ): Expression.AggregationKind =>
1425
+ values.reduce(
1426
+ (current, value) => mergeAggregationRuntime(current, value[Expression.TypeId].aggregation),
1427
+ "scalar" as Expression.AggregationKind
1428
+ )
1429
+
1430
+ /** Merges expression nullability for null-propagating scalar operators. */
1431
+ const mergeNullabilityRuntime = (
1432
+ left: Expression.Nullability,
1433
+ right: Expression.Nullability = "never"
1434
+ ): Expression.Nullability =>
1435
+ left === "always" || right === "always"
1436
+ ? "always"
1437
+ : left === "maybe" || right === "maybe"
1438
+ ? "maybe"
1439
+ : "never"
1440
+
1441
+ /** Folds runtime nullability across a list of expressions. */
1442
+ export const mergeNullabilityManyRuntime = (
1443
+ values: readonly Expression.Any[]
1444
+ ): Expression.Nullability =>
1445
+ values.reduce(
1446
+ (current, value) => mergeNullabilityRuntime(current, value[Expression.TypeId].nullability),
1447
+ "never" as Expression.Nullability
1448
+ )
1449
+
1450
+ /** Merges provenance across a variadic expression input list. */
1451
+ export const mergeManySources = (values: readonly Expression.Any[]): unknown =>
1452
+ values.reduce<unknown>(
1453
+ (current, value) => mergeSources(current, value[Expression.TypeId].source),
1454
+ undefined
1455
+ )
1456
+
1457
+ /** Merges dependency maps across a variadic expression input list. */
1458
+ export const mergeManyDependencies = (values: readonly Expression.Any[]): Expression.SourceDependencies =>
1459
+ values.reduce(
1460
+ (current, value) => mergeDependencies(current, value[Expression.TypeId].dependencies),
1461
+ {} as Expression.SourceDependencies
1462
+ )
1463
+
1464
+ /**
1465
+ * Creates a runtime expression object from fully computed static metadata.
1466
+ *
1467
+ * The query helpers use this instead of exposing ad hoc object shapes, so every
1468
+ * produced expression has the same structural contract as bound columns.
1469
+ */
1470
+ export const makeExpression = <
1471
+ Runtime,
1472
+ Db extends Expression.DbType.Any,
1473
+ Nullable extends Expression.Nullability,
1474
+ Dialect extends string,
1475
+ Aggregation extends Expression.AggregationKind,
1476
+ Source,
1477
+ Dependencies extends Expression.SourceDependencies = {},
1478
+ SourceNullability extends Expression.SourceNullabilityMode = "propagate",
1479
+ Ast extends ExpressionAst.Any = ExpressionAst.Any
1480
+ >(
1481
+ state: Expression.State<Runtime, Db, Nullable, Dialect, Aggregation, Source, Dependencies, SourceNullability>,
1482
+ ast: Ast
1483
+ ): Expression.Expression<Runtime, Db, Nullable, Dialect, Aggregation, Source, Dependencies, SourceNullability> & {
1484
+ readonly [ExpressionAst.TypeId]: Ast
1485
+ } => {
1486
+ const expression = Object.create(ExpressionProto)
1487
+ expression[Expression.TypeId] = state
1488
+ expression[ExpressionAst.TypeId] = ast
1489
+ return expression
1490
+ }
1491
+
1492
+ /**
1493
+ * Creates a runtime query-plan value from public plan metadata plus the
1494
+ * internal clause AST.
1495
+ */
1496
+ export const makePlan = <
1497
+ Selection,
1498
+ Required,
1499
+ Available extends Record<string, Plan.Source>,
1500
+ Dialect extends string,
1501
+ Grouped extends string = never,
1502
+ ScopedNames extends string = Extract<keyof Available, string>,
1503
+ Outstanding extends string = Extract<Required, string>,
1504
+ Assumptions extends PredicateFormula = TrueAssumptions,
1505
+ Capabilities extends QueryCapability = "read",
1506
+ Statement extends QueryAst.QueryStatement = "select",
1507
+ Target = never,
1508
+ InsertState extends InsertSourceState = "ready"
1509
+ >(
1510
+ state: Plan.State<Selection, Required, Available, Dialect>,
1511
+ ast: QueryAst.Ast<Selection, Grouped, Statement>,
1512
+ _assumptions?: Assumptions,
1513
+ _capabilities?: Capabilities,
1514
+ _statement?: Statement,
1515
+ _target?: Target,
1516
+ _insertState?: InsertState
1517
+ ): QueryPlan<Selection, Required, Available, Dialect, Grouped, ScopedNames, Outstanding, Assumptions, Capabilities, Statement, Target, InsertState> => {
1518
+ const plan = Object.create(PlanProto)
1519
+ plan[Plan.TypeId] = state
1520
+ plan[QueryAst.TypeId] = ast
1521
+ plan[QueryTypeId] = {
1522
+ required: undefined as unknown as Outstanding,
1523
+ availableNames: undefined as unknown as ScopedNames,
1524
+ grouped: undefined as unknown as Grouped,
1525
+ assumptions: undefined as unknown as Assumptions,
1526
+ capabilities: undefined as unknown as Capabilities,
1527
+ statement: (_statement ?? ("select" as Statement)) as Statement,
1528
+ target: (_target ?? (undefined as unknown as Target)) as Target,
1529
+ insertSource: (_insertState ?? ("ready" as InsertState)) as InsertState
1530
+ }
1531
+ return plan
1532
+ }
1533
+
1534
+ /** Returns the internal AST carried by a query plan. */
1535
+ export const getAst = <
1536
+ Selection,
1537
+ Grouped extends string,
1538
+ Statement extends QueryAst.QueryStatement
1539
+ >(
1540
+ plan: QueryPlan<Selection, any, any, any, Grouped, any, any, any, any, Statement>
1541
+ ): QueryAst.Ast<Selection, Grouped, Statement> => plan[QueryAst.TypeId]
1542
+
1543
+ /** Returns the internal phantom query state carried by a query plan. */
1544
+ export const getQueryState = (
1545
+ plan: QueryPlan<any, any, any, any, any, any, any, any, any, any>
1546
+ ): QueryState<any, any, any, any, any, any, any, any> => plan[QueryTypeId]
1547
+
1548
+ /**
1549
+ * Collects the required table names referenced by a runtime selection object.
1550
+ *
1551
+ * This mirrors the `ExtractRequired<...>` type-level computation so runtime plan
1552
+ * metadata stays aligned with the static model.
1553
+ */
1554
+ export const extractRequiredRuntime = (selection: SelectionShape): readonly string[] => {
1555
+ const required = new Set<string>()
1556
+ const visit = (value: SelectionShape): void => {
1557
+ if (Expression.TypeId in value) {
1558
+ for (const tableName of Object.keys(value[Expression.TypeId].dependencies)) {
1559
+ required.add(tableName)
1560
+ }
1561
+ return
1562
+ }
1563
+ for (const nested of Object.values(value)) {
1564
+ visit(nested)
1565
+ }
1566
+ }
1567
+ visit(selection)
1568
+ return [...required]
1569
+ }
1570
+
1571
+ /** Extracts the single top-level expression from a scalar subquery selection. */
1572
+ export const extractSingleSelectedExpressionRuntime = (selection: SelectionShape): Expression.Any => {
1573
+ const keys = Object.keys(selection)
1574
+ if (keys.length !== 1) {
1575
+ throw new Error("scalar subqueries must select exactly one top-level expression")
1576
+ }
1577
+ const record = selection as Record<string, unknown>
1578
+ const value = record[keys[0]!]
1579
+ if (value === null || typeof value !== "object" || !(Expression.TypeId in (value as object))) {
1580
+ throw new Error("scalar subqueries must select a scalar expression")
1581
+ }
1582
+ return value as unknown as Expression.Any
1583
+ }
1584
+
1585
+ /** Converts the plan's runtime `required` metadata into a mutable string list. */
1586
+ export const currentRequiredList = (required: unknown): string[] =>
1587
+ Array.isArray(required) ? [...required] : required === undefined ? [] : [required as string]
1588
+
1589
+ /** Sort direction accepted by `orderBy(...)`. */
1590
+ export type OrderDirection = QueryAst.OrderDirection