effect-qb 0.14.0 → 0.16.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/mysql.js +61555 -4252
- package/dist/postgres/metadata.js +728 -104
- package/dist/postgres.js +6906 -4023
- package/package.json +15 -2
- package/src/internal/aggregation-validation.ts +3 -3
- package/src/internal/case-analysis.d.ts +18 -0
- package/src/internal/case-analysis.ts +4 -4
- package/src/internal/coercion/analysis.d.ts +7 -0
- package/src/internal/{coercion-analysis.ts → coercion/analysis.ts} +3 -3
- package/src/internal/coercion/errors.d.ts +17 -0
- package/src/internal/{coercion-errors.ts → coercion/errors.ts} +1 -1
- package/src/internal/coercion/kind.d.ts +4 -0
- package/src/internal/{coercion-kind.ts → coercion/kind.ts} +2 -2
- package/src/internal/{coercion-normalize.ts → coercion/normalize.ts} +1 -1
- package/src/internal/coercion/rules.d.ts +6 -0
- package/src/internal/{coercion-rules.ts → coercion/rules.ts} +2 -2
- package/src/internal/column-state.d.ts +190 -0
- package/src/internal/column-state.ts +43 -47
- package/src/internal/column.ts +43 -305
- package/src/internal/datatypes/define.d.ts +17 -0
- package/src/internal/datatypes/define.ts +18 -4
- package/src/internal/datatypes/lookup.d.ts +44 -0
- package/src/internal/datatypes/lookup.ts +61 -152
- package/src/internal/datatypes/shape.d.ts +16 -0
- package/src/internal/datatypes/shape.ts +1 -1
- package/src/internal/derived-table.d.ts +4 -0
- package/src/internal/derived-table.ts +21 -16
- package/src/internal/dialect.ts +12 -1
- package/src/internal/dsl-mutation-runtime.ts +378 -0
- package/src/internal/dsl-plan-runtime.ts +387 -0
- package/src/internal/dsl-query-runtime.ts +160 -0
- package/src/internal/dsl-transaction-ddl-runtime.ts +263 -0
- package/src/internal/executor.ts +146 -34
- package/src/internal/expression-ast.ts +15 -5
- package/src/internal/grouping-key.d.ts +3 -0
- package/src/internal/grouping-key.ts +1 -1
- package/src/internal/implication-runtime.d.ts +15 -0
- package/src/internal/implication-runtime.ts +4 -4
- package/src/internal/json/ast.d.ts +30 -0
- package/src/internal/json/ast.ts +1 -1
- package/src/internal/json/errors.d.ts +8 -0
- package/src/internal/json/path.d.ts +75 -0
- package/src/internal/json/path.ts +1 -1
- package/src/internal/json/types.d.ts +62 -0
- package/src/internal/predicate/analysis.d.ts +20 -0
- package/src/internal/predicate/analysis.ts +183 -0
- package/src/internal/predicate/atom.d.ts +28 -0
- package/src/internal/{predicate-atom.ts → predicate/atom.ts} +7 -0
- package/src/internal/{predicate-branches.ts → predicate/branches.ts} +2 -2
- package/src/internal/predicate/context.d.ts +67 -0
- package/src/internal/{predicate-context.ts → predicate/context.ts} +163 -20
- package/src/internal/predicate/formula.d.ts +35 -0
- package/src/internal/{predicate-formula.ts → predicate/formula.ts} +1 -1
- package/src/internal/predicate/key.d.ts +11 -0
- package/src/internal/predicate/key.ts +73 -0
- package/src/internal/{predicate-nnf.ts → predicate/nnf.ts} +2 -2
- package/src/internal/predicate/normalize.d.ts +53 -0
- package/src/internal/{predicate-normalize.ts → predicate/normalize.ts} +130 -49
- package/src/internal/predicate/runtime.d.ts +31 -0
- package/src/internal/{predicate-runtime.ts → predicate/runtime.ts} +127 -17
- package/src/internal/projection-alias.d.ts +13 -0
- package/src/internal/projections.d.ts +31 -0
- package/src/internal/projections.ts +1 -1
- package/src/internal/query-ast.d.ts +217 -0
- package/src/internal/query-ast.ts +1 -1
- package/src/internal/query-requirements.d.ts +20 -0
- package/src/internal/query.d.ts +775 -0
- package/src/internal/query.ts +683 -369
- package/src/internal/renderer.ts +11 -21
- package/src/internal/row-set.d.ts +53 -0
- package/src/internal/{plan.ts → row-set.ts} +11 -9
- package/src/internal/runtime/driver-value-mapping.ts +186 -0
- package/src/internal/{runtime-normalize.ts → runtime/normalize.ts} +9 -31
- package/src/internal/{runtime-schema.ts → runtime/schema.ts} +13 -38
- package/src/internal/runtime/value.d.ts +22 -0
- package/src/internal/{runtime-value.ts → runtime/value.ts} +2 -2
- package/src/internal/scalar.d.ts +107 -0
- package/src/internal/scalar.ts +202 -0
- package/src/internal/schema-derivation.d.ts +105 -0
- package/src/internal/schema-expression.d.ts +18 -0
- package/src/internal/schema-expression.ts +38 -7
- package/src/internal/table-options.d.ts +94 -0
- package/src/internal/table-options.ts +8 -2
- package/src/internal/table.d.ts +173 -0
- package/src/internal/table.ts +32 -14
- package/src/mysql/column.ts +95 -18
- package/src/mysql/datatypes/index.ts +47 -7
- package/src/mysql/errors/generated.ts +57336 -0
- package/src/mysql/errors/index.ts +1 -0
- package/src/mysql/errors/normalize.ts +55 -53
- package/src/mysql/errors/types.ts +74 -0
- package/src/mysql/executor.ts +88 -11
- package/src/mysql/function/aggregate.ts +1 -5
- package/src/mysql/function/core.ts +1 -4
- package/src/mysql/function/index.ts +0 -1
- package/src/mysql/function/string.ts +1 -5
- package/src/mysql/function/temporal.ts +12 -15
- package/src/mysql/function/window.ts +1 -6
- package/src/{internal/mysql-dialect.ts → mysql/internal/dialect.ts} +12 -6
- package/src/{internal/mysql-query.ts → mysql/internal/dsl.ts} +1299 -2143
- package/src/mysql/internal/renderer.ts +46 -0
- package/src/mysql/internal/sql-expression-renderer.ts +1501 -0
- package/src/mysql/json.ts +2 -0
- package/src/mysql/query.ts +111 -91
- package/src/mysql/renderer.ts +8 -3
- package/src/mysql/table.ts +1 -1
- package/src/mysql.ts +6 -4
- package/src/postgres/cast.ts +30 -16
- package/src/postgres/column.ts +179 -46
- package/src/postgres/datatypes/index.d.ts +515 -0
- package/src/postgres/datatypes/index.ts +22 -13
- package/src/postgres/datatypes/spec.d.ts +412 -0
- package/src/postgres/errors/generated.ts +2636 -0
- package/src/postgres/errors/index.ts +1 -0
- package/src/postgres/errors/normalize.ts +47 -62
- package/src/postgres/errors/types.ts +92 -34
- package/src/postgres/executor.ts +54 -7
- package/src/postgres/function/aggregate.ts +1 -5
- package/src/postgres/function/core.ts +12 -6
- package/src/postgres/function/index.ts +0 -1
- package/src/postgres/function/string.ts +1 -5
- package/src/postgres/function/temporal.ts +12 -15
- package/src/postgres/function/window.ts +1 -6
- package/src/{internal/postgres-dialect.ts → postgres/internal/dialect.ts} +12 -6
- package/src/{internal/postgres-query.ts → postgres/internal/dsl.ts} +1356 -2133
- package/src/{internal/postgres-renderer.ts → postgres/internal/renderer.ts} +17 -8
- package/src/postgres/internal/schema-ddl.ts +108 -0
- package/src/{internal/postgres-schema-model.ts → postgres/internal/schema-model.ts} +12 -6
- package/src/{internal → postgres/internal}/sql-expression-renderer.ts +79 -25
- package/src/postgres/{function/json.ts → json.ts} +77 -85
- package/src/postgres/metadata.ts +2 -2
- package/src/postgres/query.ts +113 -89
- package/src/postgres/renderer.ts +8 -13
- package/src/postgres/schema-expression.ts +2 -1
- package/src/postgres/schema-management.ts +1 -1
- package/src/postgres/table.ts +12 -4
- package/src/postgres/type.ts +33 -2
- package/src/postgres.ts +6 -4
- package/src/internal/expression.ts +0 -327
- package/src/internal/mysql-renderer.ts +0 -37
- package/src/internal/predicate-analysis.ts +0 -81
- package/src/internal/predicate-key.ts +0 -28
- package/src/internal/schema-ddl.ts +0 -55
- package/src/mysql/function/json.ts +0 -4
- package/src/mysql/private/query.ts +0 -1
- package/src/postgres/private/query.ts +0 -1
|
@@ -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
|
+
}
|
package/src/internal/executor.ts
CHANGED
|
@@ -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 "./
|
|
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 {
|
|
10
|
-
import { expressionRuntimeSchema } from "./runtime
|
|
12
|
+
import { fromDriverValue } from "./runtime/driver-value-mapping.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 "./
|
|
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.
|
|
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.
|
|
129
|
+
? hasWriteCapability((source as { readonly plan: Query.Plan.Any }).plan)
|
|
121
130
|
: false
|
|
122
131
|
|
|
123
132
|
export const hasWriteCapability = (
|
|
124
|
-
plan: Query.
|
|
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.
|
|
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.
|
|
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].
|
|
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)
|
|
@@ -238,12 +243,19 @@ const decodeProjectionValue = (
|
|
|
238
243
|
expression: Expression.Any,
|
|
239
244
|
raw: unknown,
|
|
240
245
|
scope: ImplicationScope,
|
|
241
|
-
driverMode: DriverMode
|
|
246
|
+
driverMode: DriverMode,
|
|
247
|
+
valueMappings?: Expression.DriverValueMappings
|
|
242
248
|
): unknown => {
|
|
243
249
|
let normalized = raw
|
|
244
250
|
if (driverMode === "raw") {
|
|
245
251
|
try {
|
|
246
|
-
normalized =
|
|
252
|
+
normalized = fromDriverValue(raw, {
|
|
253
|
+
dialect: rendered.dialect,
|
|
254
|
+
dbType: expression[Expression.TypeId].dbType,
|
|
255
|
+
runtimeSchema: expression[Expression.TypeId].runtimeSchema,
|
|
256
|
+
driverValueMapping: expression[Expression.TypeId].driverValueMapping,
|
|
257
|
+
valueMappings
|
|
258
|
+
})
|
|
247
259
|
} catch (cause) {
|
|
248
260
|
throw makeRowDecodeError(rendered, projection, expression, raw, "normalize", cause)
|
|
249
261
|
}
|
|
@@ -293,14 +305,14 @@ const decodeProjectionValue = (
|
|
|
293
305
|
}
|
|
294
306
|
}
|
|
295
307
|
|
|
296
|
-
export const
|
|
308
|
+
export const makeRowDecoder = (
|
|
297
309
|
rendered: Renderer.RenderedQuery<any, any>,
|
|
298
|
-
plan: Query.
|
|
299
|
-
rows: ReadonlyArray<FlatRow>,
|
|
310
|
+
plan: Query.Plan.Any,
|
|
300
311
|
options: {
|
|
301
312
|
readonly driverMode?: DriverMode
|
|
313
|
+
readonly valueMappings?: Expression.DriverValueMappings
|
|
302
314
|
} = {}
|
|
303
|
-
):
|
|
315
|
+
): ((row: FlatRow) => any) => {
|
|
304
316
|
const projections = flattenSelection(
|
|
305
317
|
Query.getAst(plan).select as Record<string, unknown>
|
|
306
318
|
)
|
|
@@ -308,8 +320,9 @@ export const decodeRows = (
|
|
|
308
320
|
projections.map((projection) => [projection.alias, projection.expression] as const)
|
|
309
321
|
)
|
|
310
322
|
const driverMode = options.driverMode ?? "raw"
|
|
323
|
+
const valueMappings = options.valueMappings ?? rendered.valueMappings
|
|
311
324
|
const scope = resolveImplicationScope(plan[Plan.TypeId].available, Query.getQueryState(plan).assumptions)
|
|
312
|
-
return
|
|
325
|
+
return (row) => {
|
|
313
326
|
const decoded: Record<string, unknown> = {}
|
|
314
327
|
for (const projection of rendered.projections) {
|
|
315
328
|
if (!(projection.alias in row)) {
|
|
@@ -322,11 +335,37 @@ export const decodeRows = (
|
|
|
322
335
|
setPath(
|
|
323
336
|
decoded,
|
|
324
337
|
projection.path,
|
|
325
|
-
decodeProjectionValue(rendered, projection, expression, row[projection.alias], scope, driverMode)
|
|
338
|
+
decodeProjectionValue(rendered, projection, expression, row[projection.alias], scope, driverMode, valueMappings)
|
|
326
339
|
)
|
|
327
340
|
}
|
|
328
341
|
return decoded
|
|
329
|
-
}
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
export const decodeChunk = (
|
|
346
|
+
rendered: Renderer.RenderedQuery<any, any>,
|
|
347
|
+
plan: Query.Plan.Any,
|
|
348
|
+
rows: Chunk.Chunk<FlatRow>,
|
|
349
|
+
options: {
|
|
350
|
+
readonly driverMode?: DriverMode
|
|
351
|
+
readonly valueMappings?: Expression.DriverValueMappings
|
|
352
|
+
} = {}
|
|
353
|
+
): Chunk.Chunk<any> => {
|
|
354
|
+
const decodeRow = makeRowDecoder(rendered, plan, options)
|
|
355
|
+
return Chunk.unsafeFromArray(Chunk.toReadonlyArray(rows).map((row) => decodeRow(row)))
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
export const decodeRows = (
|
|
359
|
+
rendered: Renderer.RenderedQuery<any, any>,
|
|
360
|
+
plan: Query.Plan.Any,
|
|
361
|
+
rows: ReadonlyArray<FlatRow>,
|
|
362
|
+
options: {
|
|
363
|
+
readonly driverMode?: DriverMode
|
|
364
|
+
readonly valueMappings?: Expression.DriverValueMappings
|
|
365
|
+
} = {}
|
|
366
|
+
): ReadonlyArray<any> => {
|
|
367
|
+
const decodeRow = makeRowDecoder(rendered, plan, options)
|
|
368
|
+
return rows.map((row) => decodeRow(row))
|
|
330
369
|
}
|
|
331
370
|
|
|
332
371
|
/**
|
|
@@ -338,20 +377,23 @@ export const make = <
|
|
|
338
377
|
Context = never
|
|
339
378
|
>(
|
|
340
379
|
dialect: Dialect,
|
|
341
|
-
execute: <PlanValue extends Query.
|
|
380
|
+
execute: <PlanValue extends Query.Plan.Any>(
|
|
342
381
|
plan: Query.DialectCompatiblePlan<PlanValue, Dialect>
|
|
343
382
|
) => Effect.Effect<Query.ResultRows<PlanValue>, Error, Context>
|
|
344
383
|
): Executor<Dialect, Error, Context> => ({
|
|
345
384
|
dialect,
|
|
346
385
|
execute(plan) {
|
|
347
386
|
return (execute as any)(plan)
|
|
387
|
+
},
|
|
388
|
+
stream(plan) {
|
|
389
|
+
return Stream.unwrap(Effect.map((execute as any)(plan), (rows: ReadonlyArray<any>) => Stream.fromIterable(rows)))
|
|
348
390
|
}
|
|
349
391
|
}) as Executor<Dialect, Error, Context>
|
|
350
392
|
|
|
351
393
|
/**
|
|
352
394
|
* Constructs a driver from a dialect and execution callback.
|
|
353
395
|
*/
|
|
354
|
-
export
|
|
396
|
+
export function driver<
|
|
355
397
|
Dialect extends string,
|
|
356
398
|
Error = never,
|
|
357
399
|
Context = never
|
|
@@ -360,12 +402,58 @@ export const driver = <
|
|
|
360
402
|
execute: <Row>(
|
|
361
403
|
query: Renderer.RenderedQuery<Row, Dialect>
|
|
362
404
|
) => Effect.Effect<ReadonlyArray<FlatRow>, Error, Context>
|
|
363
|
-
): Driver<Dialect, Error, Context>
|
|
405
|
+
): Driver<Dialect, Error, Context>
|
|
406
|
+
export function driver<
|
|
407
|
+
Dialect extends string,
|
|
408
|
+
Error = never,
|
|
409
|
+
Context = never
|
|
410
|
+
>(
|
|
411
|
+
dialect: Dialect,
|
|
412
|
+
handlers: {
|
|
413
|
+
readonly execute: <Row>(
|
|
414
|
+
query: Renderer.RenderedQuery<Row, Dialect>
|
|
415
|
+
) => Effect.Effect<ReadonlyArray<FlatRow>, Error, Context>
|
|
416
|
+
readonly stream: <Row>(
|
|
417
|
+
query: Renderer.RenderedQuery<Row, Dialect>
|
|
418
|
+
) => Stream.Stream<FlatRow, Error, Context>
|
|
419
|
+
}
|
|
420
|
+
): Driver<Dialect, Error, Context>
|
|
421
|
+
export function driver<
|
|
422
|
+
Dialect extends string,
|
|
423
|
+
Error = never,
|
|
424
|
+
Context = never
|
|
425
|
+
>(
|
|
426
|
+
dialect: Dialect,
|
|
427
|
+
executeOrHandlers:
|
|
428
|
+
| (<Row>(
|
|
429
|
+
query: Renderer.RenderedQuery<Row, Dialect>
|
|
430
|
+
) => Effect.Effect<ReadonlyArray<FlatRow>, Error, Context>)
|
|
431
|
+
| {
|
|
432
|
+
readonly execute: <Row>(
|
|
433
|
+
query: Renderer.RenderedQuery<Row, Dialect>
|
|
434
|
+
) => Effect.Effect<ReadonlyArray<FlatRow>, Error, Context>
|
|
435
|
+
readonly stream: <Row>(
|
|
436
|
+
query: Renderer.RenderedQuery<Row, Dialect>
|
|
437
|
+
) => Stream.Stream<FlatRow, Error, Context>
|
|
438
|
+
}
|
|
439
|
+
): Driver<Dialect, Error, Context> {
|
|
440
|
+
return {
|
|
364
441
|
dialect,
|
|
365
442
|
execute(query) {
|
|
366
|
-
return
|
|
443
|
+
return typeof executeOrHandlers === "function"
|
|
444
|
+
? executeOrHandlers(query)
|
|
445
|
+
: executeOrHandlers.execute(query)
|
|
446
|
+
},
|
|
447
|
+
stream(query) {
|
|
448
|
+
if (typeof executeOrHandlers === "function") {
|
|
449
|
+
return Stream.unwrap(
|
|
450
|
+
Effect.map(executeOrHandlers(query), (rows) => Stream.fromIterable(rows))
|
|
451
|
+
)
|
|
452
|
+
}
|
|
453
|
+
return executeOrHandlers.stream(query)
|
|
367
454
|
}
|
|
368
|
-
}
|
|
455
|
+
}
|
|
456
|
+
}
|
|
369
457
|
|
|
370
458
|
/**
|
|
371
459
|
* Creates an executor by composing a renderer with a rendered-query driver.
|
|
@@ -391,20 +479,44 @@ export const fromDriver = <
|
|
|
391
479
|
sqlDriver.execute(rendered),
|
|
392
480
|
(rows) => remapRows<any>(rendered, rows)
|
|
393
481
|
)
|
|
482
|
+
},
|
|
483
|
+
stream(plan: any) {
|
|
484
|
+
const rendered = renderer.render(plan) as Renderer.RenderedQuery<any, Dialect>
|
|
485
|
+
return Stream.mapChunks(
|
|
486
|
+
sqlDriver.stream(rendered),
|
|
487
|
+
(rows) => Chunk.unsafeFromArray(remapRows<any>(rendered, Chunk.toReadonlyArray(rows)))
|
|
488
|
+
)
|
|
394
489
|
}
|
|
395
490
|
}
|
|
396
491
|
return executor as unknown as Executor<Dialect, Error, Context>
|
|
397
492
|
}
|
|
398
493
|
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
494
|
+
export const streamFromSqlClient = <Dialect extends string>(
|
|
495
|
+
query: Renderer.RenderedQuery<any, Dialect>
|
|
496
|
+
): Stream.Stream<FlatRow, SqlError.SqlError, SqlClient.SqlClient> =>
|
|
497
|
+
Stream.unwrapScoped(
|
|
498
|
+
Effect.flatMap(SqlClient.SqlClient, (sql) =>
|
|
499
|
+
Effect.flatMap(
|
|
500
|
+
Effect.serviceOption(SqlClient.TransactionConnection),
|
|
501
|
+
Option.match({
|
|
502
|
+
onNone: () => sql.reserve,
|
|
503
|
+
onSome: ([connection]) => Effect.succeed(connection)
|
|
504
|
+
})
|
|
505
|
+
).pipe(
|
|
506
|
+
Effect.map((connection) => connection.executeStream(query.sql, [...query.params], undefined))
|
|
507
|
+
)
|
|
508
|
+
)
|
|
509
|
+
)
|
|
510
|
+
|
|
402
511
|
export const fromSqlClient = <Dialect extends string>(
|
|
403
512
|
renderer: Renderer.Renderer<Dialect>
|
|
404
513
|
): Executor<Dialect, unknown, SqlClient.SqlClient> =>
|
|
405
|
-
fromDriver(renderer, driver(renderer.dialect,
|
|
406
|
-
|
|
407
|
-
|
|
514
|
+
fromDriver(renderer, driver(renderer.dialect, {
|
|
515
|
+
execute: (query) =>
|
|
516
|
+
Effect.flatMap(SqlClient.SqlClient, (sql) =>
|
|
517
|
+
sql.unsafe<FlatRow>(query.sql, [...query.params])),
|
|
518
|
+
stream: (query) => streamFromSqlClient(query)
|
|
519
|
+
}))
|
|
408
520
|
|
|
409
521
|
/** Runs an effect within the ambient `@effect/sql` transaction service. */
|
|
410
522
|
export const withTransaction = <A, E, R>(
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type * as Expression from "./
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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,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;
|