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.
- package/dist/mysql.js +61270 -4259
- package/dist/postgres/metadata.js +176 -82
- package/dist/postgres.js +5903 -3316
- package/package.json +14 -1
- 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 +36 -47
- package/src/internal/column.ts +21 -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/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 +132 -31
- 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 → predicate/analysis.ts} +3 -3
- package/src/internal/predicate/atom.d.ts +28 -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} +8 -5
- 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 → predicate/key.ts} +2 -2
- 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} +19 -19
- package/src/internal/predicate/runtime.d.ts +31 -0
- package/src/internal/{predicate-runtime.ts → predicate/runtime.ts} +9 -6
- 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 +389 -313
- package/src/internal/renderer.ts +7 -21
- package/src/internal/row-set.d.ts +53 -0
- package/src/internal/{plan.ts → row-set.ts} +11 -9
- 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 +191 -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 +94 -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 +69 -7
- 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} +1 -1
- package/src/{internal/mysql-query.ts → mysql/internal/dsl.ts} +1024 -2082
- package/src/{internal/mysql-renderer.ts → mysql/internal/renderer.ts} +6 -6
- package/src/mysql/internal/sql-expression-renderer.ts +1455 -0
- package/src/mysql/json.ts +2 -0
- package/src/mysql/query.ts +111 -91
- package/src/mysql/renderer.ts +1 -1
- package/src/mysql/table.ts +1 -1
- package/src/mysql.ts +6 -4
- package/src/postgres/cast.ts +11 -12
- package/src/postgres/column.ts +178 -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 +37 -5
- 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} +1 -1
- package/src/{internal/postgres-query.ts → postgres/internal/dsl.ts} +1085 -2089
- package/src/{internal/postgres-renderer.ts → postgres/internal/renderer.ts} +6 -6
- 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 +19 -17
- 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 +3 -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 +29 -2
- package/src/postgres.ts +6 -4
- package/src/internal/expression.ts +0 -327
- 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
- /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
|
+
}
|
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 { normalizeDbValue } from "./runtime
|
|
10
|
-
import { expressionRuntimeSchema } from "./runtime
|
|
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 "./
|
|
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)
|
|
@@ -293,14 +298,13 @@ const decodeProjectionValue = (
|
|
|
293
298
|
}
|
|
294
299
|
}
|
|
295
300
|
|
|
296
|
-
export const
|
|
301
|
+
export const makeRowDecoder = (
|
|
297
302
|
rendered: Renderer.RenderedQuery<any, any>,
|
|
298
|
-
plan: Query.
|
|
299
|
-
rows: ReadonlyArray<FlatRow>,
|
|
303
|
+
plan: Query.Plan.Any,
|
|
300
304
|
options: {
|
|
301
305
|
readonly driverMode?: DriverMode
|
|
302
306
|
} = {}
|
|
303
|
-
):
|
|
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
|
|
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.
|
|
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
|
|
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
|
|
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
|
-
|
|
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,
|
|
406
|
-
|
|
407
|
-
|
|
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 "./
|
|
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;
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import * as Expression from "./
|
|
1
|
+
import * as Expression from "./scalar.js"
|
|
2
2
|
import * as ExpressionAst from "./expression-ast.js"
|
|
3
|
-
import * as Plan from "./
|
|
3
|
+
import * as Plan from "./row-set.js"
|
|
4
4
|
import * as Table from "./table.js"
|
|
5
|
-
import type { PredicateFormula } from "./predicate
|
|
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
|
|
13
|
+
} from "./predicate/runtime.js"
|
|
14
14
|
import type { SourceLike } from "./query.js"
|
|
15
15
|
|
|
16
16
|
export interface ImplicationScope {
|