effect-qb 0.14.0 → 0.15.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (141) hide show
  1. package/dist/mysql.js +61270 -4259
  2. package/dist/postgres/metadata.js +176 -82
  3. package/dist/postgres.js +5903 -3316
  4. package/package.json +14 -1
  5. package/src/internal/aggregation-validation.ts +3 -3
  6. package/src/internal/case-analysis.d.ts +18 -0
  7. package/src/internal/case-analysis.ts +4 -4
  8. package/src/internal/coercion/analysis.d.ts +7 -0
  9. package/src/internal/{coercion-analysis.ts → coercion/analysis.ts} +3 -3
  10. package/src/internal/coercion/errors.d.ts +17 -0
  11. package/src/internal/{coercion-errors.ts → coercion/errors.ts} +1 -1
  12. package/src/internal/coercion/kind.d.ts +4 -0
  13. package/src/internal/{coercion-kind.ts → coercion/kind.ts} +2 -2
  14. package/src/internal/{coercion-normalize.ts → coercion/normalize.ts} +1 -1
  15. package/src/internal/coercion/rules.d.ts +6 -0
  16. package/src/internal/{coercion-rules.ts → coercion/rules.ts} +2 -2
  17. package/src/internal/column-state.d.ts +190 -0
  18. package/src/internal/column-state.ts +36 -47
  19. package/src/internal/column.ts +21 -305
  20. package/src/internal/datatypes/define.d.ts +17 -0
  21. package/src/internal/datatypes/define.ts +18 -4
  22. package/src/internal/datatypes/lookup.d.ts +44 -0
  23. package/src/internal/datatypes/lookup.ts +61 -152
  24. package/src/internal/datatypes/shape.d.ts +16 -0
  25. package/src/internal/datatypes/shape.ts +1 -1
  26. package/src/internal/derived-table.d.ts +4 -0
  27. package/src/internal/derived-table.ts +21 -16
  28. package/src/internal/dsl-mutation-runtime.ts +378 -0
  29. package/src/internal/dsl-plan-runtime.ts +387 -0
  30. package/src/internal/dsl-query-runtime.ts +160 -0
  31. package/src/internal/dsl-transaction-ddl-runtime.ts +263 -0
  32. package/src/internal/executor.ts +132 -31
  33. package/src/internal/expression-ast.ts +15 -5
  34. package/src/internal/grouping-key.d.ts +3 -0
  35. package/src/internal/grouping-key.ts +1 -1
  36. package/src/internal/implication-runtime.d.ts +15 -0
  37. package/src/internal/implication-runtime.ts +4 -4
  38. package/src/internal/json/ast.d.ts +30 -0
  39. package/src/internal/json/ast.ts +1 -1
  40. package/src/internal/json/errors.d.ts +8 -0
  41. package/src/internal/json/path.d.ts +75 -0
  42. package/src/internal/json/path.ts +1 -1
  43. package/src/internal/json/types.d.ts +62 -0
  44. package/src/internal/predicate/analysis.d.ts +20 -0
  45. package/src/internal/{predicate-analysis.ts → predicate/analysis.ts} +3 -3
  46. package/src/internal/predicate/atom.d.ts +28 -0
  47. package/src/internal/{predicate-branches.ts → predicate/branches.ts} +2 -2
  48. package/src/internal/predicate/context.d.ts +67 -0
  49. package/src/internal/{predicate-context.ts → predicate/context.ts} +8 -5
  50. package/src/internal/predicate/formula.d.ts +35 -0
  51. package/src/internal/{predicate-formula.ts → predicate/formula.ts} +1 -1
  52. package/src/internal/predicate/key.d.ts +11 -0
  53. package/src/internal/{predicate-key.ts → predicate/key.ts} +2 -2
  54. package/src/internal/{predicate-nnf.ts → predicate/nnf.ts} +2 -2
  55. package/src/internal/predicate/normalize.d.ts +53 -0
  56. package/src/internal/{predicate-normalize.ts → predicate/normalize.ts} +19 -19
  57. package/src/internal/predicate/runtime.d.ts +31 -0
  58. package/src/internal/{predicate-runtime.ts → predicate/runtime.ts} +9 -6
  59. package/src/internal/projection-alias.d.ts +13 -0
  60. package/src/internal/projections.d.ts +31 -0
  61. package/src/internal/projections.ts +1 -1
  62. package/src/internal/query-ast.d.ts +217 -0
  63. package/src/internal/query-ast.ts +1 -1
  64. package/src/internal/query-requirements.d.ts +20 -0
  65. package/src/internal/query.d.ts +775 -0
  66. package/src/internal/query.ts +389 -313
  67. package/src/internal/renderer.ts +7 -21
  68. package/src/internal/row-set.d.ts +53 -0
  69. package/src/internal/{plan.ts → row-set.ts} +11 -9
  70. package/src/internal/{runtime-normalize.ts → runtime/normalize.ts} +9 -31
  71. package/src/internal/{runtime-schema.ts → runtime/schema.ts} +13 -38
  72. package/src/internal/runtime/value.d.ts +22 -0
  73. package/src/internal/{runtime-value.ts → runtime/value.ts} +2 -2
  74. package/src/internal/scalar.d.ts +107 -0
  75. package/src/internal/scalar.ts +191 -0
  76. package/src/internal/schema-derivation.d.ts +105 -0
  77. package/src/internal/schema-expression.d.ts +18 -0
  78. package/src/internal/schema-expression.ts +38 -7
  79. package/src/internal/table-options.d.ts +94 -0
  80. package/src/internal/table-options.ts +8 -2
  81. package/src/internal/table.d.ts +173 -0
  82. package/src/internal/table.ts +32 -14
  83. package/src/mysql/column.ts +94 -18
  84. package/src/mysql/datatypes/index.ts +47 -7
  85. package/src/mysql/errors/generated.ts +57336 -0
  86. package/src/mysql/errors/index.ts +1 -0
  87. package/src/mysql/errors/normalize.ts +55 -53
  88. package/src/mysql/errors/types.ts +74 -0
  89. package/src/mysql/executor.ts +69 -7
  90. package/src/mysql/function/aggregate.ts +1 -5
  91. package/src/mysql/function/core.ts +1 -4
  92. package/src/mysql/function/index.ts +0 -1
  93. package/src/mysql/function/string.ts +1 -5
  94. package/src/mysql/function/temporal.ts +12 -15
  95. package/src/mysql/function/window.ts +1 -6
  96. package/src/{internal/mysql-dialect.ts → mysql/internal/dialect.ts} +1 -1
  97. package/src/{internal/mysql-query.ts → mysql/internal/dsl.ts} +1024 -2082
  98. package/src/{internal/mysql-renderer.ts → mysql/internal/renderer.ts} +6 -6
  99. package/src/mysql/internal/sql-expression-renderer.ts +1455 -0
  100. package/src/mysql/json.ts +2 -0
  101. package/src/mysql/query.ts +111 -91
  102. package/src/mysql/renderer.ts +1 -1
  103. package/src/mysql/table.ts +1 -1
  104. package/src/mysql.ts +6 -4
  105. package/src/postgres/cast.ts +11 -12
  106. package/src/postgres/column.ts +178 -46
  107. package/src/postgres/datatypes/index.d.ts +515 -0
  108. package/src/postgres/datatypes/index.ts +22 -13
  109. package/src/postgres/datatypes/spec.d.ts +412 -0
  110. package/src/postgres/errors/generated.ts +2636 -0
  111. package/src/postgres/errors/index.ts +1 -0
  112. package/src/postgres/errors/normalize.ts +47 -62
  113. package/src/postgres/errors/types.ts +92 -34
  114. package/src/postgres/executor.ts +37 -5
  115. package/src/postgres/function/aggregate.ts +1 -5
  116. package/src/postgres/function/core.ts +12 -6
  117. package/src/postgres/function/index.ts +0 -1
  118. package/src/postgres/function/string.ts +1 -5
  119. package/src/postgres/function/temporal.ts +12 -15
  120. package/src/postgres/function/window.ts +1 -6
  121. package/src/{internal/postgres-dialect.ts → postgres/internal/dialect.ts} +1 -1
  122. package/src/{internal/postgres-query.ts → postgres/internal/dsl.ts} +1085 -2089
  123. package/src/{internal/postgres-renderer.ts → postgres/internal/renderer.ts} +6 -6
  124. package/src/postgres/internal/schema-ddl.ts +108 -0
  125. package/src/{internal/postgres-schema-model.ts → postgres/internal/schema-model.ts} +12 -6
  126. package/src/{internal → postgres/internal}/sql-expression-renderer.ts +19 -17
  127. package/src/postgres/{function/json.ts → json.ts} +77 -85
  128. package/src/postgres/metadata.ts +2 -2
  129. package/src/postgres/query.ts +113 -89
  130. package/src/postgres/renderer.ts +3 -13
  131. package/src/postgres/schema-expression.ts +2 -1
  132. package/src/postgres/schema-management.ts +1 -1
  133. package/src/postgres/table.ts +12 -4
  134. package/src/postgres/type.ts +29 -2
  135. package/src/postgres.ts +6 -4
  136. package/src/internal/expression.ts +0 -327
  137. package/src/internal/schema-ddl.ts +0 -55
  138. package/src/mysql/function/json.ts +0 -4
  139. package/src/mysql/private/query.ts +0 -1
  140. package/src/postgres/private/query.ts +0 -1
  141. /package/src/internal/{predicate-atom.ts → predicate/atom.ts} +0 -0
@@ -0,0 +1,263 @@
1
+ import * as Plan from "./row-set.js"
2
+
3
+ type DslTransactionDdlRuntimeContext = {
4
+ readonly profile: {
5
+ readonly dialect: string
6
+ }
7
+ readonly makePlan: (...args: readonly any[]) => any
8
+ readonly targetSourceDetails: (target: any) => { readonly sourceName: string; readonly sourceBaseName: string }
9
+ readonly normalizeColumnList: (columns: string | readonly string[]) => readonly string[]
10
+ readonly defaultIndexName: (tableName: string, columns: readonly string[], unique: boolean) => string
11
+ }
12
+
13
+ export const makeDslTransactionDdlRuntime = (ctx: DslTransactionDdlRuntimeContext) => {
14
+ const transaction = (options: { readonly isolationLevel?: any; readonly readOnly?: boolean } = {}) =>
15
+ ctx.makePlan({
16
+ selection: {},
17
+ required: [],
18
+ available: {},
19
+ dialect: ctx.profile.dialect
20
+ }, {
21
+ kind: "transaction",
22
+ select: {},
23
+ transaction: {
24
+ kind: "transaction",
25
+ isolationLevel: options.isolationLevel,
26
+ readOnly: options.readOnly
27
+ },
28
+ where: [],
29
+ having: [],
30
+ joins: [],
31
+ groupBy: [],
32
+ orderBy: []
33
+ }, undefined, "transaction", "transaction")
34
+
35
+ const commit = () =>
36
+ ctx.makePlan({
37
+ selection: {},
38
+ required: [],
39
+ available: {},
40
+ dialect: ctx.profile.dialect
41
+ }, {
42
+ kind: "commit",
43
+ select: {},
44
+ transaction: {
45
+ kind: "commit"
46
+ },
47
+ where: [],
48
+ having: [],
49
+ joins: [],
50
+ groupBy: [],
51
+ orderBy: []
52
+ }, undefined, "transaction", "commit")
53
+
54
+ const rollback = () =>
55
+ ctx.makePlan({
56
+ selection: {},
57
+ required: [],
58
+ available: {},
59
+ dialect: ctx.profile.dialect
60
+ }, {
61
+ kind: "rollback",
62
+ select: {},
63
+ transaction: {
64
+ kind: "rollback"
65
+ },
66
+ where: [],
67
+ having: [],
68
+ joins: [],
69
+ groupBy: [],
70
+ orderBy: []
71
+ }, undefined, "transaction", "rollback")
72
+
73
+ const savepoint = (name: string) =>
74
+ ctx.makePlan({
75
+ selection: {},
76
+ required: [],
77
+ available: {},
78
+ dialect: ctx.profile.dialect
79
+ }, {
80
+ kind: "savepoint",
81
+ select: {},
82
+ transaction: {
83
+ kind: "savepoint",
84
+ name
85
+ },
86
+ where: [],
87
+ having: [],
88
+ joins: [],
89
+ groupBy: [],
90
+ orderBy: []
91
+ }, undefined, "transaction", "savepoint")
92
+
93
+ const rollbackTo = (name: string) =>
94
+ ctx.makePlan({
95
+ selection: {},
96
+ required: [],
97
+ available: {},
98
+ dialect: ctx.profile.dialect
99
+ }, {
100
+ kind: "rollbackTo",
101
+ select: {},
102
+ transaction: {
103
+ kind: "rollbackTo",
104
+ name
105
+ },
106
+ where: [],
107
+ having: [],
108
+ joins: [],
109
+ groupBy: [],
110
+ orderBy: []
111
+ }, undefined, "transaction", "rollbackTo")
112
+
113
+ const releaseSavepoint = (name: string) =>
114
+ ctx.makePlan({
115
+ selection: {},
116
+ required: [],
117
+ available: {},
118
+ dialect: ctx.profile.dialect
119
+ }, {
120
+ kind: "releaseSavepoint",
121
+ select: {},
122
+ transaction: {
123
+ kind: "releaseSavepoint",
124
+ name
125
+ },
126
+ where: [],
127
+ having: [],
128
+ joins: [],
129
+ groupBy: [],
130
+ orderBy: []
131
+ }, undefined, "transaction", "releaseSavepoint")
132
+
133
+ const createTable = (target: any, options: { readonly ifNotExists?: boolean } = {}) => {
134
+ const { sourceName, sourceBaseName } = ctx.targetSourceDetails(target)
135
+ return ctx.makePlan({
136
+ selection: {},
137
+ required: [],
138
+ available: {},
139
+ dialect: target[Plan.TypeId].dialect
140
+ }, {
141
+ kind: "createTable",
142
+ select: {},
143
+ target: {
144
+ kind: "from",
145
+ tableName: sourceName,
146
+ baseTableName: sourceBaseName,
147
+ source: target
148
+ },
149
+ ddl: {
150
+ kind: "createTable",
151
+ ifNotExists: options.ifNotExists ?? false
152
+ },
153
+ where: [],
154
+ having: [],
155
+ joins: [],
156
+ groupBy: [],
157
+ orderBy: []
158
+ }, undefined, "ddl", "createTable")
159
+ }
160
+
161
+ const dropTable = (target: any, options: { readonly ifExists?: boolean } = {}) => {
162
+ const { sourceName, sourceBaseName } = ctx.targetSourceDetails(target)
163
+ return ctx.makePlan({
164
+ selection: {},
165
+ required: [],
166
+ available: {},
167
+ dialect: target[Plan.TypeId].dialect
168
+ }, {
169
+ kind: "dropTable",
170
+ select: {},
171
+ target: {
172
+ kind: "from",
173
+ tableName: sourceName,
174
+ baseTableName: sourceBaseName,
175
+ source: target
176
+ },
177
+ ddl: {
178
+ kind: "dropTable",
179
+ ifExists: options.ifExists ?? false
180
+ },
181
+ where: [],
182
+ having: [],
183
+ joins: [],
184
+ groupBy: [],
185
+ orderBy: []
186
+ }, undefined, "ddl", "dropTable")
187
+ }
188
+
189
+ const createIndex = (target: any, columns: string | readonly string[], options: { readonly name?: string; readonly unique?: boolean; readonly ifNotExists?: boolean } = {}) => {
190
+ const normalizedColumns = ctx.normalizeColumnList(columns)
191
+ const { sourceName, sourceBaseName } = ctx.targetSourceDetails(target)
192
+ return ctx.makePlan({
193
+ selection: {},
194
+ required: [],
195
+ available: {},
196
+ dialect: target[Plan.TypeId].dialect
197
+ }, {
198
+ kind: "createIndex",
199
+ select: {},
200
+ target: {
201
+ kind: "from",
202
+ tableName: sourceName,
203
+ baseTableName: sourceBaseName,
204
+ source: target
205
+ },
206
+ ddl: {
207
+ kind: "createIndex",
208
+ name: options.name ?? ctx.defaultIndexName(sourceBaseName, normalizedColumns, options.unique ?? false),
209
+ columns: normalizedColumns,
210
+ unique: options.unique ?? false,
211
+ ifNotExists: options.ifNotExists ?? false
212
+ },
213
+ where: [],
214
+ having: [],
215
+ joins: [],
216
+ groupBy: [],
217
+ orderBy: []
218
+ }, undefined, "ddl", "createIndex")
219
+ }
220
+
221
+ const dropIndex = (target: any, columns: string | readonly string[], options: { readonly name?: string; readonly ifExists?: boolean } = {}) => {
222
+ const normalizedColumns = ctx.normalizeColumnList(columns)
223
+ const { sourceName, sourceBaseName } = ctx.targetSourceDetails(target)
224
+ return ctx.makePlan({
225
+ selection: {},
226
+ required: [],
227
+ available: {},
228
+ dialect: target[Plan.TypeId].dialect
229
+ }, {
230
+ kind: "dropIndex",
231
+ select: {},
232
+ target: {
233
+ kind: "from",
234
+ tableName: sourceName,
235
+ baseTableName: sourceBaseName,
236
+ source: target
237
+ },
238
+ ddl: {
239
+ kind: "dropIndex",
240
+ name: options.name ?? ctx.defaultIndexName(sourceBaseName, normalizedColumns, false),
241
+ ifExists: options.ifExists ?? false
242
+ },
243
+ where: [],
244
+ having: [],
245
+ joins: [],
246
+ groupBy: [],
247
+ orderBy: []
248
+ }, undefined, "ddl", "dropIndex")
249
+ }
250
+
251
+ return {
252
+ transaction,
253
+ commit,
254
+ rollback,
255
+ savepoint,
256
+ rollbackTo,
257
+ releaseSavepoint,
258
+ createTable,
259
+ dropTable,
260
+ createIndex,
261
+ dropIndex
262
+ }
263
+ }
@@ -1,18 +1,21 @@
1
+ import * as Chunk from "effect/Chunk"
1
2
  import * as Effect from "effect/Effect"
3
+ import * as Option from "effect/Option"
2
4
  import * as Schema from "effect/Schema"
3
5
  import * as SqlClient from "@effect/sql/SqlClient"
4
6
  import * as SqlError from "@effect/sql/SqlError"
7
+ import * as Stream from "effect/Stream"
5
8
 
6
- import * as Expression from "./expression.js"
9
+ import * as Expression from "./scalar.js"
7
10
  import * as ExpressionAst from "./expression-ast.js"
8
11
  import { resolveImplicationScope, type ImplicationScope } from "./implication-runtime.js"
9
- import { normalizeDbValue } from "./runtime-normalize.js"
10
- import { expressionRuntimeSchema } from "./runtime-schema.js"
12
+ import { normalizeDbValue } from "./runtime/normalize.js"
13
+ import { expressionRuntimeSchema } from "./runtime/schema.js"
11
14
  import { flattenSelection } from "./projections.js"
12
15
  import * as Query from "./query.js"
13
16
  import * as QueryAst from "./query-ast.js"
14
17
  import * as Renderer from "./renderer.js"
15
- import * as Plan from "./plan.js"
18
+ import * as Plan from "./row-set.js"
16
19
 
17
20
  /** Flat database row keyed by rendered projection aliases. */
18
21
  export type FlatRow = Readonly<Record<string, unknown>>
@@ -58,6 +61,9 @@ export interface Driver<
58
61
  execute<Row>(
59
62
  query: Renderer.RenderedQuery<Row, Dialect>
60
63
  ): Effect.Effect<ReadonlyArray<FlatRow>, Error, Context>
64
+ stream<Row>(
65
+ query: Renderer.RenderedQuery<Row, Dialect>
66
+ ): Stream.Stream<FlatRow, Error, Context>
61
67
  }
62
68
 
63
69
  /**
@@ -73,9 +79,12 @@ export interface Executor<
73
79
  Context = never
74
80
  > {
75
81
  readonly dialect: Dialect
76
- execute<PlanValue extends Query.QueryPlan<any, any, any, any, any, any, any, any, any, any>>(
82
+ execute<PlanValue extends Query.Plan.Any>(
77
83
  plan: Query.DialectCompatiblePlan<PlanValue, Dialect>
78
84
  ): Effect.Effect<Query.ResultRows<PlanValue>, Error, Context>
85
+ stream<PlanValue extends Query.Plan.Any>(
86
+ plan: Query.DialectCompatiblePlan<PlanValue, Dialect>
87
+ ): Stream.Stream<Query.ResultRow<PlanValue>, Error, Context>
79
88
  }
80
89
 
81
90
  const setPath = (
@@ -117,21 +126,21 @@ const hasWriteStatement = (statement: QueryAst.QueryStatement): boolean =>
117
126
 
118
127
  const hasWriteCapabilityInSource = (source: unknown): boolean =>
119
128
  typeof source === "object" && source !== null && "plan" in source
120
- ? hasWriteCapability((source as { readonly plan: Query.QueryPlan<any, any, any, any, any, any, any, any, any, any> }).plan)
129
+ ? hasWriteCapability((source as { readonly plan: Query.Plan.Any }).plan)
121
130
  : false
122
131
 
123
132
  export const hasWriteCapability = (
124
- plan: Query.QueryPlan<any, any, any, any, any, any, any, any, any, any>
133
+ plan: Query.Plan.Any
125
134
  ): boolean => {
126
135
  const ast = Query.getAst(plan)
127
136
  if (hasWriteStatement(ast.kind)) {
128
137
  return true
129
138
  }
130
139
  if (ast.kind === "set") {
131
- if (ast.setBase && hasWriteCapability((ast.setBase as Query.QueryPlan<any, any, any, any, any, any, any, any, any, any>))) {
140
+ if (ast.setBase && hasWriteCapability((ast.setBase as Query.Plan.Any))) {
132
141
  return true
133
142
  }
134
- if ((ast.setOperations ?? []).some((entry) => hasWriteCapability(entry.query as Query.QueryPlan<any, any, any, any, any, any, any, any, any, any>))) {
143
+ if ((ast.setOperations ?? []).some((entry) => hasWriteCapability(entry.query as Query.Plan.Any))) {
135
144
  return true
136
145
  }
137
146
  }
@@ -198,9 +207,6 @@ const hasOptionalSourceDependency = (
198
207
  scope: ImplicationScope
199
208
  ): boolean => {
200
209
  const state = expression[Expression.TypeId]
201
- if (state.sourceNullability === "resolved") {
202
- return false
203
- }
204
210
  return Object.keys(state.dependencies).some((sourceName) =>
205
211
  !scope.absentSourceNames.has(sourceName) && scope.sourceModes.get(sourceName) === "optional")
206
212
  }
@@ -223,8 +229,7 @@ const effectiveRuntimeNullability = (
223
229
  return "never"
224
230
  }
225
231
  }
226
- if (expression[Expression.TypeId].sourceNullability !== "resolved" &&
227
- Object.keys(expression[Expression.TypeId].dependencies).some((sourceName) => scope.absentSourceNames.has(sourceName))) {
232
+ if (Object.keys(expression[Expression.TypeId].dependencies).some((sourceName) => scope.absentSourceNames.has(sourceName))) {
228
233
  return "always"
229
234
  }
230
235
  return hasOptionalSourceDependency(expression, scope)
@@ -293,14 +298,13 @@ const decodeProjectionValue = (
293
298
  }
294
299
  }
295
300
 
296
- export const decodeRows = (
301
+ export const makeRowDecoder = (
297
302
  rendered: Renderer.RenderedQuery<any, any>,
298
- plan: Query.QueryPlan<any, any, any, any, any, any, any, any, any, any>,
299
- rows: ReadonlyArray<FlatRow>,
303
+ plan: Query.Plan.Any,
300
304
  options: {
301
305
  readonly driverMode?: DriverMode
302
306
  } = {}
303
- ): ReadonlyArray<any> => {
307
+ ): ((row: FlatRow) => any) => {
304
308
  const projections = flattenSelection(
305
309
  Query.getAst(plan).select as Record<string, unknown>
306
310
  )
@@ -309,7 +313,7 @@ export const decodeRows = (
309
313
  )
310
314
  const driverMode = options.driverMode ?? "raw"
311
315
  const scope = resolveImplicationScope(plan[Plan.TypeId].available, Query.getQueryState(plan).assumptions)
312
- return rows.map((row) => {
316
+ return (row) => {
313
317
  const decoded: Record<string, unknown> = {}
314
318
  for (const projection of rendered.projections) {
315
319
  if (!(projection.alias in row)) {
@@ -326,7 +330,31 @@ export const decodeRows = (
326
330
  )
327
331
  }
328
332
  return decoded
329
- })
333
+ }
334
+ }
335
+
336
+ export const decodeChunk = (
337
+ rendered: Renderer.RenderedQuery<any, any>,
338
+ plan: Query.Plan.Any,
339
+ rows: Chunk.Chunk<FlatRow>,
340
+ options: {
341
+ readonly driverMode?: DriverMode
342
+ } = {}
343
+ ): Chunk.Chunk<any> => {
344
+ const decodeRow = makeRowDecoder(rendered, plan, options)
345
+ return Chunk.unsafeFromArray(Chunk.toReadonlyArray(rows).map((row) => decodeRow(row)))
346
+ }
347
+
348
+ export const decodeRows = (
349
+ rendered: Renderer.RenderedQuery<any, any>,
350
+ plan: Query.Plan.Any,
351
+ rows: ReadonlyArray<FlatRow>,
352
+ options: {
353
+ readonly driverMode?: DriverMode
354
+ } = {}
355
+ ): ReadonlyArray<any> => {
356
+ const decodeRow = makeRowDecoder(rendered, plan, options)
357
+ return rows.map((row) => decodeRow(row))
330
358
  }
331
359
 
332
360
  /**
@@ -338,20 +366,23 @@ export const make = <
338
366
  Context = never
339
367
  >(
340
368
  dialect: Dialect,
341
- execute: <PlanValue extends Query.QueryPlan<any, any, any, any, any, any, any, any, any, any>>(
369
+ execute: <PlanValue extends Query.Plan.Any>(
342
370
  plan: Query.DialectCompatiblePlan<PlanValue, Dialect>
343
371
  ) => Effect.Effect<Query.ResultRows<PlanValue>, Error, Context>
344
372
  ): Executor<Dialect, Error, Context> => ({
345
373
  dialect,
346
374
  execute(plan) {
347
375
  return (execute as any)(plan)
376
+ },
377
+ stream(plan) {
378
+ return Stream.unwrap(Effect.map((execute as any)(plan), (rows: ReadonlyArray<any>) => Stream.fromIterable(rows)))
348
379
  }
349
380
  }) as Executor<Dialect, Error, Context>
350
381
 
351
382
  /**
352
383
  * Constructs a driver from a dialect and execution callback.
353
384
  */
354
- export const driver = <
385
+ export function driver<
355
386
  Dialect extends string,
356
387
  Error = never,
357
388
  Context = never
@@ -360,12 +391,58 @@ export const driver = <
360
391
  execute: <Row>(
361
392
  query: Renderer.RenderedQuery<Row, Dialect>
362
393
  ) => Effect.Effect<ReadonlyArray<FlatRow>, Error, Context>
363
- ): Driver<Dialect, Error, Context> => ({
394
+ ): Driver<Dialect, Error, Context>
395
+ export function driver<
396
+ Dialect extends string,
397
+ Error = never,
398
+ Context = never
399
+ >(
400
+ dialect: Dialect,
401
+ handlers: {
402
+ readonly execute: <Row>(
403
+ query: Renderer.RenderedQuery<Row, Dialect>
404
+ ) => Effect.Effect<ReadonlyArray<FlatRow>, Error, Context>
405
+ readonly stream: <Row>(
406
+ query: Renderer.RenderedQuery<Row, Dialect>
407
+ ) => Stream.Stream<FlatRow, Error, Context>
408
+ }
409
+ ): Driver<Dialect, Error, Context>
410
+ export function driver<
411
+ Dialect extends string,
412
+ Error = never,
413
+ Context = never
414
+ >(
415
+ dialect: Dialect,
416
+ executeOrHandlers:
417
+ | (<Row>(
418
+ query: Renderer.RenderedQuery<Row, Dialect>
419
+ ) => Effect.Effect<ReadonlyArray<FlatRow>, Error, Context>)
420
+ | {
421
+ readonly execute: <Row>(
422
+ query: Renderer.RenderedQuery<Row, Dialect>
423
+ ) => Effect.Effect<ReadonlyArray<FlatRow>, Error, Context>
424
+ readonly stream: <Row>(
425
+ query: Renderer.RenderedQuery<Row, Dialect>
426
+ ) => Stream.Stream<FlatRow, Error, Context>
427
+ }
428
+ ): Driver<Dialect, Error, Context> {
429
+ return {
364
430
  dialect,
365
431
  execute(query) {
366
- return execute(query)
432
+ return typeof executeOrHandlers === "function"
433
+ ? executeOrHandlers(query)
434
+ : executeOrHandlers.execute(query)
435
+ },
436
+ stream(query) {
437
+ if (typeof executeOrHandlers === "function") {
438
+ return Stream.unwrap(
439
+ Effect.map(executeOrHandlers(query), (rows) => Stream.fromIterable(rows))
440
+ )
441
+ }
442
+ return executeOrHandlers.stream(query)
367
443
  }
368
- })
444
+ }
445
+ }
369
446
 
370
447
  /**
371
448
  * Creates an executor by composing a renderer with a rendered-query driver.
@@ -391,20 +468,44 @@ export const fromDriver = <
391
468
  sqlDriver.execute(rendered),
392
469
  (rows) => remapRows<any>(rendered, rows)
393
470
  )
471
+ },
472
+ stream(plan: any) {
473
+ const rendered = renderer.render(plan) as Renderer.RenderedQuery<any, Dialect>
474
+ return Stream.mapChunks(
475
+ sqlDriver.stream(rendered),
476
+ (rows) => Chunk.unsafeFromArray(remapRows<any>(rendered, Chunk.toReadonlyArray(rows)))
477
+ )
394
478
  }
395
479
  }
396
480
  return executor as unknown as Executor<Dialect, Error, Context>
397
481
  }
398
482
 
399
- /**
400
- * Creates an executor backed by `@effect/sql`'s `SqlClient`.
401
- */
483
+ export const streamFromSqlClient = <Dialect extends string>(
484
+ query: Renderer.RenderedQuery<any, Dialect>
485
+ ): Stream.Stream<FlatRow, SqlError.SqlError, SqlClient.SqlClient> =>
486
+ Stream.unwrapScoped(
487
+ Effect.flatMap(SqlClient.SqlClient, (sql) =>
488
+ Effect.flatMap(
489
+ Effect.serviceOption(SqlClient.TransactionConnection),
490
+ Option.match({
491
+ onNone: () => sql.reserve,
492
+ onSome: ([connection]) => Effect.succeed(connection)
493
+ })
494
+ ).pipe(
495
+ Effect.map((connection) => connection.executeStream(query.sql, [...query.params], undefined))
496
+ )
497
+ )
498
+ )
499
+
402
500
  export const fromSqlClient = <Dialect extends string>(
403
501
  renderer: Renderer.Renderer<Dialect>
404
502
  ): Executor<Dialect, unknown, SqlClient.SqlClient> =>
405
- fromDriver(renderer, driver(renderer.dialect, (query) =>
406
- Effect.flatMap(SqlClient.SqlClient, (sql) =>
407
- sql.unsafe<FlatRow>(query.sql, [...query.params]))))
503
+ fromDriver(renderer, driver(renderer.dialect, {
504
+ execute: (query) =>
505
+ Effect.flatMap(SqlClient.SqlClient, (sql) =>
506
+ sql.unsafe<FlatRow>(query.sql, [...query.params])),
507
+ stream: (query) => streamFromSqlClient(query)
508
+ }))
408
509
 
409
510
  /** Runs an effect within the ambient `@effect/sql` transaction service. */
410
511
  export const withTransaction = <A, E, R>(
@@ -1,4 +1,4 @@
1
- import type * as Expression from "./expression.js"
1
+ import type * as Expression from "./scalar.js"
2
2
  import type * as Query from "./query.js"
3
3
  import type * as JsonPath from "./json/path.js"
4
4
  import type { JsonNode } from "./json/ast.js"
@@ -34,6 +34,15 @@ export interface CastNode<
34
34
  readonly target: Target
35
35
  }
36
36
 
37
+ /** Explicit collation captured by the internal expression AST. */
38
+ export interface CollateNode<
39
+ Value extends Expression.Any = Expression.Any
40
+ > {
41
+ readonly kind: "collate"
42
+ readonly value: Value
43
+ readonly collation: readonly [string, ...string[]]
44
+ }
45
+
37
46
  /** General SQL function call captured by the internal expression AST. */
38
47
  export interface FunctionCallNode<
39
48
  Name extends string = string,
@@ -136,7 +145,7 @@ export interface CaseNode<
136
145
 
137
146
  /** `exists (<subquery>)` expression node. */
138
147
  export interface ExistsNode<
139
- PlanValue extends Query.QueryPlan<any, any, any, any, any, any, any, any, any, any> = Query.QueryPlan<any, any, any, any, any, any, any, any, any, any>
148
+ PlanValue extends Query.Plan.Any = Query.Plan.Any
140
149
  > {
141
150
  readonly kind: "exists"
142
151
  readonly plan: PlanValue
@@ -144,7 +153,7 @@ export interface ExistsNode<
144
153
 
145
154
  /** Scalar subquery expression node. */
146
155
  export interface ScalarSubqueryNode<
147
- PlanValue extends Query.QueryPlan<any, any, any, any, any, any, any, any, any, any> = Query.QueryPlan<any, any, any, any, any, any, any, any, any, any>
156
+ PlanValue extends Query.Plan.Any = Query.Plan.Any
148
157
  > {
149
158
  readonly kind: "scalarSubquery"
150
159
  readonly plan: PlanValue
@@ -153,7 +162,7 @@ export interface ScalarSubqueryNode<
153
162
  /** `value in (<subquery>)` expression node. */
154
163
  export interface InSubqueryNode<
155
164
  Left extends Expression.Any = Expression.Any,
156
- PlanValue extends Query.QueryPlan<any, any, any, any, any, any, any, any, any, any> = Query.QueryPlan<any, any, any, any, any, any, any, any, any, any>
165
+ PlanValue extends Query.Plan.Any = Query.Plan.Any
157
166
  > {
158
167
  readonly kind: "inSubquery"
159
168
  readonly left: Left
@@ -165,7 +174,7 @@ export interface QuantifiedComparisonNode<
165
174
  Kind extends "comparisonAny" | "comparisonAll" = "comparisonAny" | "comparisonAll",
166
175
  Operator extends "eq" | "neq" | "lt" | "lte" | "gt" | "gte" = "eq" | "neq" | "lt" | "lte" | "gt" | "gte",
167
176
  Left extends Expression.Any = Expression.Any,
168
- PlanValue extends Query.QueryPlan<any, any, any, any, any, any, any, any, any, any> = Query.QueryPlan<any, any, any, any, any, any, any, any, any, any>
177
+ PlanValue extends Query.Plan.Any = Query.Plan.Any
169
178
  > {
170
179
  readonly kind: Kind
171
180
  readonly operator: Operator
@@ -339,6 +348,7 @@ export type Any =
339
348
  | ColumnNode
340
349
  | LiteralNode
341
350
  | CastNode
351
+ | CollateNode
342
352
  | FunctionCallNode
343
353
  | ExcludedNode
344
354
  | UnaryNode
@@ -0,0 +1,3 @@
1
+ import * as Expression from "./scalar.js";
2
+ export declare const groupingKeyOfExpression: (expression: Expression.Any) => string;
3
+ export declare const dedupeGroupedExpressions: <Values extends readonly Expression.Any[]>(values: Values) => Values;
@@ -1,4 +1,4 @@
1
- import * as Expression from "./expression.js"
1
+ import * as Expression from "./scalar.js"
2
2
  import * as ExpressionAst from "./expression-ast.js"
3
3
 
4
4
  const literalGroupingKey = (value: unknown): string => {
@@ -0,0 +1,15 @@
1
+ import * as Plan from "./row-set.js";
2
+ import type { PredicateFormula } from "./predicate/formula.js";
3
+ import type { SourceLike } from "./query.js";
4
+ export interface ImplicationScope {
5
+ readonly assumptions: PredicateFormula;
6
+ readonly nonNullKeys: ReadonlySet<string>;
7
+ readonly nullKeys: ReadonlySet<string>;
8
+ readonly requiredSourceNames: ReadonlySet<string>;
9
+ readonly absentSourceNames: ReadonlySet<string>;
10
+ readonly sourceModes: ReadonlyMap<string, Plan.SourceMode>;
11
+ }
12
+ export declare const presentFormulaOfSource: (source: Plan.Source<string, Plan.SourceMode, PredicateFormula, never>) => PredicateFormula;
13
+ export declare const presenceWitnessesOfSource: (source: Plan.Source<string, Plan.SourceMode, PredicateFormula, never>) => ReadonlySet<string>;
14
+ export declare const presenceWitnessesOfSourceLike: (source: SourceLike) => readonly string[];
15
+ export declare const resolveImplicationScope: (available: Readonly<Record<string, Plan.Source<string, Plan.SourceMode, PredicateFormula, never>>>, initialAssumptions: PredicateFormula) => ImplicationScope;
@@ -1,8 +1,8 @@
1
- import * as Expression from "./expression.js"
1
+ import * as Expression from "./scalar.js"
2
2
  import * as ExpressionAst from "./expression-ast.js"
3
- import * as Plan from "./plan.js"
3
+ import * as Plan from "./row-set.js"
4
4
  import * as Table from "./table.js"
5
- import type { PredicateFormula } from "./predicate-formula.js"
5
+ import type { PredicateFormula } from "./predicate/formula.js"
6
6
  import {
7
7
  assumeFormulaTrue,
8
8
  contradictsFormula,
@@ -10,7 +10,7 @@ import {
10
10
  guaranteedNullKeys,
11
11
  guaranteedSourceNames,
12
12
  trueFormula
13
- } from "./predicate-runtime.js"
13
+ } from "./predicate/runtime.js"
14
14
  import type { SourceLike } from "./query.js"
15
15
 
16
16
  export interface ImplicationScope {