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,386 @@
1
+ import type * as JsonPath from "./path.js"
2
+ import type { JsonPathUsageError } from "./errors.js"
3
+
4
+ export type JsonPrimitive = string | number | boolean | null
5
+
6
+ export type JsonValue =
7
+ | JsonPrimitive
8
+ | readonly JsonValue[]
9
+ | { readonly [key: string]: JsonValue }
10
+
11
+ type OptionalKeyOf<ObjectType extends object, Key extends PropertyKey> =
12
+ Key extends keyof ObjectType
13
+ ? {} extends Pick<ObjectType, Key> ? true : false
14
+ : true
15
+
16
+ type NormalizeJsonTuple<Values extends readonly unknown[]> =
17
+ Values extends readonly []
18
+ ? readonly []
19
+ : Values extends readonly [infer Head, ...infer Tail]
20
+ ? readonly [NormalizeJsonLiteral<Head>, ...NormalizeJsonTuple<Tail>]
21
+ : readonly NormalizeJsonLiteral<Values[number]>[]
22
+
23
+ type NormalizeJsonObject<ObjectType extends object> = {
24
+ readonly [Key in keyof ObjectType as Key extends string ? Key : never]:
25
+ NormalizeJsonLiteral<Exclude<ObjectType[Key], undefined>>
26
+ }
27
+
28
+ export type NormalizeJsonLiteral<Value> =
29
+ [Value] extends [never] ? never :
30
+ Value extends JsonPrimitive ? Value :
31
+ Value extends undefined | bigint | symbol | Date | ((...args: readonly any[]) => any) ? never :
32
+ Value extends readonly unknown[] ? NormalizeJsonTuple<Value> :
33
+ Value extends object ? NormalizeJsonObject<Value> :
34
+ never
35
+
36
+ export type JsonLiteralInput = JsonPrimitive | readonly JsonLiteralInput[] | {
37
+ readonly [key: string]: JsonLiteralInput
38
+ }
39
+
40
+ type StripNull<Value> = Exclude<Value, null>
41
+
42
+ type KeyStep<
43
+ Root,
44
+ Key extends string,
45
+ Operation extends string
46
+ > = Root extends readonly unknown[]
47
+ ? JsonPathUsageError<Operation, Root, JsonPath.KeySegment<Key>, "key segments cannot be applied to arrays">
48
+ : Root extends object
49
+ ? Key extends keyof Root
50
+ ? NormalizeJsonLiteral<Exclude<Root[Key], undefined>> | (OptionalKeyOf<Root, Key> extends true ? null : never)
51
+ : Root extends Record<string, infer Value>
52
+ ? NormalizeJsonLiteral<Value> | null
53
+ : null
54
+ : JsonPathUsageError<Operation, Root, JsonPath.KeySegment<Key>, "key segments require an object-like json value">
55
+
56
+ type TupleIndex<
57
+ Values extends readonly unknown[],
58
+ Index extends number,
59
+ Count extends readonly unknown[] = []
60
+ > = Values extends readonly [infer Head, ...infer Tail]
61
+ ? Count["length"] extends Index
62
+ ? Head
63
+ : TupleIndex<Tail, Index, [...Count, unknown]>
64
+ : never
65
+
66
+ type DropTupleIndex<
67
+ Values extends readonly unknown[],
68
+ Index extends number,
69
+ Count extends readonly unknown[] = []
70
+ > = Values extends readonly [infer Head, ...infer Tail]
71
+ ? Count["length"] extends Index
72
+ ? readonly [...Tail]
73
+ : readonly [Head, ...DropTupleIndex<Tail, Index, [...Count, unknown]>]
74
+ : readonly []
75
+
76
+ type SetTupleIndex<
77
+ Values extends readonly unknown[],
78
+ Index extends number,
79
+ Next,
80
+ Count extends readonly unknown[] = []
81
+ > = Values extends readonly [infer Head, ...infer Tail]
82
+ ? Count["length"] extends Index
83
+ ? readonly [Next, ...Tail]
84
+ : readonly [Head, ...SetTupleIndex<Tail, Index, Next, [...Count, unknown]>]
85
+ : readonly NormalizeJsonLiteral<Next>[]
86
+
87
+ type InsertTupleIndex<
88
+ Values extends readonly unknown[],
89
+ Index extends number,
90
+ Next,
91
+ After extends boolean,
92
+ Count extends readonly unknown[] = []
93
+ > = Values extends readonly [infer Head, ...infer Tail]
94
+ ? Count["length"] extends Index
95
+ ? After extends true
96
+ ? readonly [Head, NormalizeJsonLiteral<Next>, ...Tail]
97
+ : readonly [NormalizeJsonLiteral<Next>, Head, ...Tail]
98
+ : readonly [Head, ...InsertTupleIndex<Tail, Index, Next, After, [...Count, unknown]>]
99
+ : readonly NormalizeJsonLiteral<Next>[]
100
+
101
+ type IndexStep<
102
+ Root,
103
+ Index extends number,
104
+ Operation extends string
105
+ > = Root extends readonly unknown[]
106
+ ? number extends Root["length"]
107
+ ? NormalizeJsonLiteral<Root[number]> | null
108
+ : NormalizeJsonLiteral<TupleIndex<Root, Index>> | (TupleIndex<Root, Index> extends never ? null : never)
109
+ : JsonPathUsageError<Operation, Root, JsonPath.IndexSegment<Index>, "index segments require an array-like json value">
110
+
111
+ type NonExactStep<
112
+ Root,
113
+ Segment extends JsonPath.CanonicalSegment
114
+ > = Segment extends JsonPath.WildcardSegment
115
+ ? NormalizeJsonLiteral<Root> | null
116
+ : Segment extends JsonPath.SliceSegment<any, any>
117
+ ? NormalizeJsonLiteral<Root> | null
118
+ : Segment extends JsonPath.DescendSegment
119
+ ? NormalizeJsonLiteral<Root> | null
120
+ : never
121
+
122
+ type StepValue<
123
+ Root,
124
+ Segment extends JsonPath.CanonicalSegment,
125
+ Operation extends string
126
+ > = Segment extends JsonPath.KeySegment<infer Key extends string>
127
+ ? KeyStep<Root, Key, Operation>
128
+ : Segment extends JsonPath.IndexSegment<infer Index extends number>
129
+ ? IndexStep<Root, Index, Operation>
130
+ : NonExactStep<Root, Segment>
131
+
132
+ type StepSet<
133
+ Root,
134
+ Segment extends JsonPath.CanonicalSegment,
135
+ Next,
136
+ Operation extends string
137
+ > = Segment extends JsonPath.KeySegment<infer Key extends string>
138
+ ? Root extends readonly unknown[]
139
+ ? JsonPathUsageError<Operation, Root, Segment, "key segments cannot update arrays">
140
+ : Root extends object
141
+ ? Omit<Root, Key> & {
142
+ readonly [K in Key]: NormalizeJsonLiteral<Next>
143
+ }
144
+ : JsonPathUsageError<Operation, Root, Segment, "key segments require an object-like json value">
145
+ : Segment extends JsonPath.IndexSegment<infer Index extends number>
146
+ ? Root extends readonly unknown[]
147
+ ? number extends Root["length"]
148
+ ? readonly (NormalizeJsonLiteral<Root[number]> | NormalizeJsonLiteral<Next>)[]
149
+ : SetTupleIndex<Root, Index, Next>
150
+ : JsonPathUsageError<Operation, Root, Segment, "index segments require an array-like json value">
151
+ : NormalizeJsonLiteral<Root>
152
+
153
+ type StepDelete<
154
+ Root,
155
+ Segment extends JsonPath.CanonicalSegment,
156
+ Operation extends string
157
+ > = Segment extends JsonPath.KeySegment<infer Key extends string>
158
+ ? Root extends readonly unknown[]
159
+ ? JsonPathUsageError<Operation, Root, Segment, "key segments cannot delete from arrays">
160
+ : Root extends object
161
+ ? Omit<Root, Key>
162
+ : JsonPathUsageError<Operation, Root, Segment, "key segments require an object-like json value">
163
+ : Segment extends JsonPath.IndexSegment<infer Index extends number>
164
+ ? Root extends readonly unknown[]
165
+ ? number extends Root["length"]
166
+ ? Root
167
+ : DropTupleIndex<Root, Index>
168
+ : JsonPathUsageError<Operation, Root, Segment, "index segments require an array-like json value">
169
+ : NormalizeJsonLiteral<Root>
170
+
171
+ type StepInsert<
172
+ Root,
173
+ Segment extends JsonPath.CanonicalSegment,
174
+ Next,
175
+ After extends boolean,
176
+ Operation extends string
177
+ > = Segment extends JsonPath.IndexSegment<infer Index extends number>
178
+ ? Root extends readonly unknown[]
179
+ ? number extends Root["length"]
180
+ ? readonly (NormalizeJsonLiteral<Root[number]> | NormalizeJsonLiteral<Next>)[]
181
+ : InsertTupleIndex<Root, Index, Next, After>
182
+ : JsonPathUsageError<Operation, Root, Segment, "index segments require an array-like json value">
183
+ : Segment extends JsonPath.KeySegment<infer Key extends string>
184
+ ? Root extends readonly unknown[]
185
+ ? JsonPathUsageError<Operation, Root, Segment, "key segments cannot insert into arrays">
186
+ : Root extends object
187
+ ? Key extends keyof Root
188
+ ? Root
189
+ : Root & {
190
+ readonly [K in Key]: NormalizeJsonLiteral<Next>
191
+ }
192
+ : JsonPathUsageError<Operation, Root, Segment, "key segments require an object-like json value">
193
+ : NormalizeJsonLiteral<Root>
194
+
195
+ type RecurseValue<
196
+ Current,
197
+ Segments extends readonly JsonPath.CanonicalSegment[],
198
+ Operation extends string
199
+ > = Segments extends readonly [infer Head extends JsonPath.CanonicalSegment, ...infer Tail extends readonly JsonPath.CanonicalSegment[]]
200
+ ? StepValue<Current, Head, Operation> extends infer Next
201
+ ? Next extends JsonPathUsageError<any, any, any, any>
202
+ ? Next
203
+ : Tail extends readonly []
204
+ ? Next
205
+ : null extends Next
206
+ ? RecurseValue<StripNull<Next>, Tail, Operation> | null
207
+ : RecurseValue<Next, Tail, Operation>
208
+ : never
209
+ : NormalizeJsonLiteral<Current>
210
+
211
+ type RecurseSet<
212
+ Current,
213
+ Segments extends readonly JsonPath.CanonicalSegment[],
214
+ Next,
215
+ Operation extends string
216
+ > = Segments extends readonly [infer Head extends JsonPath.CanonicalSegment, ...infer Tail extends readonly JsonPath.CanonicalSegment[]]
217
+ ? Tail extends readonly []
218
+ ? StepSet<Current, Head, Next, Operation>
219
+ : StepValue<Current, Head, Operation> extends infer Child
220
+ ? Child extends JsonPathUsageError<any, any, any, any>
221
+ ? Child
222
+ : StepSet<
223
+ Current,
224
+ Head,
225
+ RecurseSet<StripNull<Child>, Tail, Next, Operation>,
226
+ Operation
227
+ >
228
+ : never
229
+ : NormalizeJsonLiteral<Next>
230
+
231
+ type RecurseDelete<
232
+ Current,
233
+ Segments extends readonly JsonPath.CanonicalSegment[],
234
+ Operation extends string
235
+ > = Segments extends readonly [infer Head extends JsonPath.CanonicalSegment, ...infer Tail extends readonly JsonPath.CanonicalSegment[]]
236
+ ? Tail extends readonly []
237
+ ? StepDelete<Current, Head, Operation>
238
+ : StepValue<Current, Head, Operation> extends infer Child
239
+ ? Child extends JsonPathUsageError<any, any, any, any>
240
+ ? Child
241
+ : StepSet<
242
+ Current,
243
+ Head,
244
+ RecurseDelete<StripNull<Child>, Tail, Operation>,
245
+ Operation
246
+ >
247
+ : never
248
+ : NormalizeJsonLiteral<Current>
249
+
250
+ type RecurseInsert<
251
+ Current,
252
+ Segments extends readonly JsonPath.CanonicalSegment[],
253
+ Next,
254
+ After extends boolean,
255
+ Operation extends string
256
+ > = Segments extends readonly [infer Head extends JsonPath.CanonicalSegment, ...infer Tail extends readonly JsonPath.CanonicalSegment[]]
257
+ ? Tail extends readonly []
258
+ ? StepInsert<Current, Head, Next, After, Operation>
259
+ : StepValue<Current, Head, Operation> extends infer Child
260
+ ? Child extends JsonPathUsageError<any, any, any, any>
261
+ ? Child
262
+ : StepSet<
263
+ Current,
264
+ Head,
265
+ RecurseInsert<StripNull<Child>, Tail, Next, After, Operation>,
266
+ Operation
267
+ >
268
+ : never
269
+ : NormalizeJsonLiteral<Current>
270
+
271
+ export type JsonValueAtPath<
272
+ Root,
273
+ PathValue extends JsonPath.Path<any>,
274
+ Operation extends string = "json.get"
275
+ > = RecurseValue<NormalizeJsonLiteral<Root>, JsonPath.SegmentsOf<PathValue>, Operation>
276
+
277
+ export type JsonSetAtPath<
278
+ Root,
279
+ PathValue extends JsonPath.Path<any>,
280
+ Next,
281
+ Operation extends string = "json.set"
282
+ > = RecurseSet<NormalizeJsonLiteral<Root>, JsonPath.SegmentsOf<PathValue>, Next, Operation>
283
+
284
+ export type JsonInsertAtPath<
285
+ Root,
286
+ PathValue extends JsonPath.Path<any>,
287
+ Next,
288
+ After extends boolean = false,
289
+ Operation extends string = "json.insert"
290
+ > = RecurseInsert<NormalizeJsonLiteral<Root>, JsonPath.SegmentsOf<PathValue>, Next, After, Operation>
291
+
292
+ export type JsonDeleteAtPath<
293
+ Root,
294
+ PathValue extends JsonPath.Path<any>,
295
+ Operation extends string = "json.delete"
296
+ > = RecurseDelete<NormalizeJsonLiteral<Root>, JsonPath.SegmentsOf<PathValue>, Operation>
297
+
298
+ type ArrayElement<Value> = Value extends readonly (infer Element)[] ? Element : never
299
+
300
+ type MergeJsonObjects<
301
+ Left extends object,
302
+ Right extends object
303
+ > = Omit<Left, keyof Right> & Right
304
+
305
+ type StripNullsTuple<Values extends readonly unknown[]> =
306
+ Values extends readonly []
307
+ ? readonly []
308
+ : Values extends readonly [infer Head, ...infer Tail]
309
+ ? readonly [JsonStripNullsResult<Head>, ...StripNullsTuple<Tail>]
310
+ : readonly JsonStripNullsResult<Values[number]>[]
311
+
312
+ type StripNullsObject<ObjectType extends object> = (
313
+ {
314
+ readonly [Key in keyof ObjectType as Key extends string
315
+ ? null extends NormalizeJsonLiteral<Exclude<ObjectType[Key], undefined>>
316
+ ? never
317
+ : Key
318
+ : never]-?: JsonStripNullsResult<Exclude<ObjectType[Key], null>>
319
+ } & {
320
+ readonly [Key in keyof ObjectType as Key extends string
321
+ ? null extends NormalizeJsonLiteral<Exclude<ObjectType[Key], undefined>>
322
+ ? Key
323
+ : never
324
+ : never]?: JsonStripNullsResult<Exclude<ObjectType[Key], null>>
325
+ }
326
+ )
327
+
328
+ export type JsonStripNullsResult<Value> =
329
+ Value extends null ? null :
330
+ Value extends readonly unknown[] ? StripNullsTuple<Value> :
331
+ Value extends object ? StripNullsObject<Value> :
332
+ Value
333
+
334
+ export type JsonConcatResult<
335
+ Left,
336
+ Right
337
+ > = NormalizeJsonLiteral<Left> extends infer NormalizedLeft
338
+ ? NormalizeJsonLiteral<Right> extends infer NormalizedRight
339
+ ? NormalizedLeft extends readonly unknown[]
340
+ ? NormalizedRight extends readonly unknown[]
341
+ ? number extends NormalizedLeft["length"] | NormalizedRight["length"]
342
+ ? readonly (ArrayElement<NormalizedLeft> | ArrayElement<NormalizedRight>)[]
343
+ : readonly [...NormalizedLeft, ...NormalizedRight]
344
+ : unknown
345
+ : NormalizedLeft extends object
346
+ ? NormalizedRight extends object
347
+ ? MergeJsonObjects<NormalizedLeft, NormalizedRight>
348
+ : unknown
349
+ : unknown
350
+ : never
351
+ : never
352
+
353
+ export type JsonBuildObject<
354
+ Shape extends Record<string, unknown>
355
+ > = {
356
+ readonly [K in keyof Shape]: NormalizeJsonLiteral<Shape[K]>
357
+ }
358
+
359
+ export type JsonBuildArray<
360
+ Values extends readonly unknown[]
361
+ > = {
362
+ readonly [K in keyof Values]: NormalizeJsonLiteral<Values[K]>
363
+ } & readonly unknown[]
364
+
365
+ export type JsonTextResult<Value> = Value extends JsonPrimitive ? `${Value}` : string
366
+
367
+ export type JsonTypeName<Value> =
368
+ NormalizeJsonLiteral<Value> extends null ? "null"
369
+ : NormalizeJsonLiteral<Value> extends string ? "string"
370
+ : NormalizeJsonLiteral<Value> extends number ? "number"
371
+ : NormalizeJsonLiteral<Value> extends boolean ? "boolean"
372
+ : NormalizeJsonLiteral<Value> extends readonly unknown[] ? "array"
373
+ : NormalizeJsonLiteral<Value> extends object ? "object"
374
+ : "unknown"
375
+
376
+ export type JsonLengthResult<Value> =
377
+ NormalizeJsonLiteral<Value> extends readonly unknown[] ? number :
378
+ NormalizeJsonLiteral<Value> extends object ? number :
379
+ null
380
+
381
+ export type JsonKeysResult<Value> =
382
+ NormalizeJsonLiteral<Value> extends object
383
+ ? NormalizeJsonLiteral<Value> extends readonly unknown[]
384
+ ? readonly []
385
+ : readonly Extract<keyof NormalizeJsonLiteral<Value>, string>[]
386
+ : null
@@ -0,0 +1,39 @@
1
+ import type { RenderState, SqlDialect } from "./dialect.js"
2
+
3
+ const quoteIdentifier = (value: string): string => `\`${value.replaceAll("`", "``")}\``
4
+
5
+ const renderLiteral = (value: unknown, state: RenderState): string => {
6
+ if (value === null) {
7
+ return "null"
8
+ }
9
+ if (typeof value === "boolean") {
10
+ return value ? "true" : "false"
11
+ }
12
+ state.params.push(value)
13
+ return "?"
14
+ }
15
+
16
+ /**
17
+ * Internal runtime dialect sketch for MySQL.
18
+ *
19
+ * This is intentionally not wired into the public renderer surface yet. It
20
+ * exists to pressure-test the current abstraction seam and to document the
21
+ * concrete SQL differences we still need to account for as dialect support
22
+ * grows.
23
+ */
24
+ export const mysqlDialect: SqlDialect<"mysql"> = {
25
+ name: "mysql",
26
+ quoteIdentifier,
27
+ renderLiteral,
28
+ renderTableReference(tableName, baseTableName, schemaName) {
29
+ const renderedBase = schemaName
30
+ ? `${quoteIdentifier(schemaName)}.${quoteIdentifier(baseTableName)}`
31
+ : quoteIdentifier(baseTableName)
32
+ return tableName === baseTableName
33
+ ? renderedBase
34
+ : `${renderedBase} as ${quoteIdentifier(tableName)}`
35
+ },
36
+ renderConcat(values) {
37
+ return `concat(${values.join(", ")})`
38
+ }
39
+ }
@@ -0,0 +1,37 @@
1
+ import * as Query from "./query.js"
2
+ import { type RenderState } from "./dialect.js"
3
+ import { mysqlDialect } from "./mysql-dialect.js"
4
+ import { type Projection } from "./projections.js"
5
+ import { renderQueryAst } from "./sql-expression-renderer.js"
6
+
7
+ /**
8
+ * Internal rendered-query payload produced by the built-in MySQL renderer.
9
+ */
10
+ export interface MysqlRenderResult {
11
+ readonly sql: string
12
+ readonly params: readonly unknown[]
13
+ readonly projections: readonly Projection[]
14
+ }
15
+
16
+ /**
17
+ * Renders the current query AST into MySQL-shaped SQL plus bind parameters.
18
+ */
19
+ export const renderMysqlPlan = <PlanValue extends Query.QueryPlan<any, any, any, any, any, any, any, any, any>>(
20
+ plan: Query.DialectCompatiblePlan<PlanValue, "mysql">
21
+ ): MysqlRenderResult => {
22
+ const state: RenderState = {
23
+ params: [],
24
+ ctes: [],
25
+ cteNames: new Set<string>()
26
+ }
27
+ const rendered = renderQueryAst(
28
+ Query.getAst(plan as Query.QueryPlan<any, any, any, any, any, any, any, any, any>) as any,
29
+ state,
30
+ mysqlDialect
31
+ )
32
+ return {
33
+ sql: rendered.sql,
34
+ params: state.params,
35
+ projections: rendered.projections
36
+ }
37
+ }
@@ -0,0 +1,64 @@
1
+ import type { Pipeable } from "effect/Pipeable"
2
+
3
+ /** Symbol used to attach logical-plan metadata to runtime values. */
4
+ export const TypeId: unique symbol = Symbol.for("effect-qb/Plan")
5
+
6
+ export type TypeId = typeof TypeId
7
+
8
+ /**
9
+ * Source availability mode within a query scope.
10
+ *
11
+ * `required` means the source is guaranteed to produce a row at this point in
12
+ * the plan. `optional` means the source may be absent, such as the nullable
13
+ * side of a left join.
14
+ */
15
+ export type SourceMode = "required" | "optional"
16
+
17
+ /** Source made available to a plan. */
18
+ export interface Source<Name extends string = string, Mode extends SourceMode = SourceMode> {
19
+ readonly name: Name
20
+ readonly mode: Mode
21
+ readonly baseName?: string
22
+ }
23
+
24
+ /**
25
+ * Canonical static metadata stored on a plan.
26
+ *
27
+ * `required` tracks sources that the selection references but which are not yet
28
+ * in scope. `available` tracks sources already in scope for subsequent query
29
+ * operations.
30
+ */
31
+ export interface State<
32
+ Selection,
33
+ Required,
34
+ Available extends Record<string, Source>,
35
+ Dialect extends string
36
+ > {
37
+ readonly selection: Selection
38
+ readonly required: Required
39
+ readonly available: Available
40
+ readonly dialect: Dialect
41
+ }
42
+
43
+ /**
44
+ * A composable logical query plan.
45
+ *
46
+ * Tables implement this interface as already-complete plans. Future query
47
+ * builders such as `select()` and `from()` should produce and transform values
48
+ * with this same structure.
49
+ */
50
+ export interface Plan<
51
+ Selection,
52
+ Required = never,
53
+ Available extends Record<string, Source> = {},
54
+ Dialect extends string = never
55
+ > extends Pipeable {
56
+ readonly [TypeId]: State<Selection, Required, Available, Dialect>
57
+ }
58
+
59
+ /** Convenience alias for any plan-like value. */
60
+ export type Any = Plan<any, any, Record<string, Source>, string>
61
+ /** Extracts a plan's selection shape. */
62
+ export type SelectionOf<Value extends Any> = Value[typeof TypeId]["selection"]
63
+ /** Extracts a plan's effective dialect. */
64
+ export type DialectOf<Value extends Any> = Value[typeof TypeId]["dialect"]
@@ -0,0 +1,34 @@
1
+ import type { RenderState, SqlDialect } from "./dialect.js"
2
+
3
+ const quoteIdentifier = (value: string): string => `"${value.replaceAll("\"", "\"\"")}"`
4
+
5
+ const renderLiteral = (value: unknown, state: RenderState): string => {
6
+ if (value === null) {
7
+ return "null"
8
+ }
9
+ if (typeof value === "boolean") {
10
+ return value ? "true" : "false"
11
+ }
12
+ state.params.push(value)
13
+ return `$${state.params.length}`
14
+ }
15
+
16
+ /**
17
+ * Built-in runtime dialect implementation for Postgres.
18
+ */
19
+ export const postgresDialect: SqlDialect<"postgres"> = {
20
+ name: "postgres",
21
+ quoteIdentifier,
22
+ renderLiteral,
23
+ renderTableReference(tableName, baseTableName, schemaName) {
24
+ const renderedBase = schemaName
25
+ ? `${quoteIdentifier(schemaName)}.${quoteIdentifier(baseTableName)}`
26
+ : quoteIdentifier(baseTableName)
27
+ return tableName === baseTableName
28
+ ? renderedBase
29
+ : `${renderedBase} as ${quoteIdentifier(tableName)}`
30
+ },
31
+ renderConcat(values) {
32
+ return `(${values.join(" || ")})`
33
+ }
34
+ }
@@ -0,0 +1,40 @@
1
+ import * as Query from "./query.js"
2
+ import { type RenderState } from "./dialect.js"
3
+ import { postgresDialect } from "./postgres-dialect.js"
4
+ import { type Projection } from "./projections.js"
5
+ import { renderQueryAst } from "./sql-expression-renderer.js"
6
+
7
+ /**
8
+ * Minimal rendered-query payload produced by the built-in Postgres renderer.
9
+ *
10
+ * The public `Renderer` wrapper adds dialect branding and validates projection
11
+ * metadata before exposing the final `RenderedQuery`.
12
+ */
13
+ export interface PostgresRenderResult {
14
+ readonly sql: string
15
+ readonly params: readonly unknown[]
16
+ readonly projections: readonly Projection[]
17
+ }
18
+
19
+ /**
20
+ * Renders the current query AST into Postgres SQL plus bind parameters.
21
+ */
22
+ export const renderPostgresPlan = <PlanValue extends Query.QueryPlan<any, any, any, any, any, any, any, any, any>>(
23
+ plan: Query.DialectCompatiblePlan<PlanValue, "postgres">
24
+ ): PostgresRenderResult => {
25
+ const state: RenderState = {
26
+ params: [],
27
+ ctes: [],
28
+ cteNames: new Set<string>()
29
+ }
30
+ const rendered = renderQueryAst(
31
+ Query.getAst(plan as Query.QueryPlan<any, any, any, any, any, any, any, any, any>) as any,
32
+ state,
33
+ postgresDialect
34
+ )
35
+ return {
36
+ sql: rendered.sql,
37
+ params: state.params,
38
+ projections: rendered.projections
39
+ }
40
+ }
@@ -0,0 +1,71 @@
1
+ import type { AnalyzeFormula } from "./predicate-context.js"
2
+ import type { FormulaOfPredicate } from "./predicate-normalize.js"
3
+ import type { And, Not, PredicateFormula, TrueFormula } from "./predicate-formula.js"
4
+
5
+ type ContextOf<Formula extends PredicateFormula> = AnalyzeFormula<Formula>
6
+
7
+ export type GuaranteedNonNullKeys<
8
+ Assumptions extends PredicateFormula
9
+ > = ContextOf<Assumptions>["nonNullKeys"]
10
+
11
+ export type GuaranteedNullKeys<
12
+ Assumptions extends PredicateFormula
13
+ > = ContextOf<Assumptions>["nullKeys"]
14
+
15
+ export type GuaranteedSourceNames<
16
+ Assumptions extends PredicateFormula
17
+ > = ContextOf<Assumptions>["sourceNames"]
18
+
19
+ export type GuaranteedEqLiteral<
20
+ Assumptions extends PredicateFormula,
21
+ Key extends string
22
+ > = Key extends keyof ContextOf<Assumptions>["eqLiterals"]
23
+ ? ContextOf<Assumptions>["eqLiterals"][Key]
24
+ : never
25
+
26
+ type IsContradiction<Formula extends PredicateFormula> =
27
+ ContextOf<Formula>["contradiction"] extends true ? true : false
28
+
29
+ type ContradictoryAssumption<
30
+ Assumptions extends PredicateFormula,
31
+ Formula extends PredicateFormula
32
+ > = IsContradiction<And<Assumptions, Formula>>
33
+
34
+ type ContradictionFromNegation<
35
+ Assumptions extends PredicateFormula,
36
+ Formula extends PredicateFormula
37
+ > = IsContradiction<And<Assumptions, Not<Formula>>>
38
+
39
+ export type AssumeFormulaTrue<
40
+ Assumptions extends PredicateFormula,
41
+ Formula extends PredicateFormula
42
+ > = Assumptions extends TrueFormula
43
+ ? Formula
44
+ : And<Assumptions, Formula>
45
+
46
+ export type AssumeFormulaFalse<
47
+ Assumptions extends PredicateFormula,
48
+ Formula extends PredicateFormula
49
+ > = Assumptions extends TrueFormula
50
+ ? Not<Formula>
51
+ : And<Assumptions, Not<Formula>>
52
+
53
+ export type AssumeTrue<
54
+ Assumptions extends PredicateFormula,
55
+ Predicate
56
+ > = AssumeFormulaTrue<Assumptions, FormulaOfPredicate<Predicate>>
57
+
58
+ export type AssumeFalse<
59
+ Assumptions extends PredicateFormula,
60
+ Predicate
61
+ > = AssumeFormulaFalse<Assumptions, FormulaOfPredicate<Predicate>>
62
+
63
+ export type Contradicts<
64
+ Assumptions extends PredicateFormula,
65
+ Predicate
66
+ > = ContradictoryAssumption<Assumptions, FormulaOfPredicate<Predicate>>
67
+
68
+ export type Implies<
69
+ Assumptions extends PredicateFormula,
70
+ Predicate
71
+ > = ContradictionFromNegation<Assumptions, FormulaOfPredicate<Predicate>>