effect-qb 0.16.0 → 0.19.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/README.md +4 -0
- package/dist/index.js +8065 -0
- package/dist/mysql.js +4036 -2418
- package/dist/postgres/metadata.js +2536 -625
- package/dist/postgres.js +8248 -7857
- package/dist/sqlite.js +8854 -0
- package/dist/standard.js +8019 -0
- package/package.json +15 -3
- package/src/casing.ts +71 -0
- package/src/index.ts +2 -0
- package/src/internal/casing.ts +89 -0
- package/src/internal/column-state.ts +11 -6
- package/src/internal/column.ts +44 -7
- package/src/internal/datatypes/define.ts +2 -1
- package/src/internal/datatypes/enrich.ts +23 -0
- package/src/internal/datatypes/lookup.ts +14 -7
- package/src/internal/derived-table.ts +7 -13
- package/src/internal/dialect-renderers/mysql.ts +2046 -0
- package/src/{postgres/internal/sql-expression-renderer.ts → internal/dialect-renderers/postgres.ts} +867 -283
- package/src/{mysql/internal/sql-expression-renderer.ts → internal/dialect-renderers/sqlite.ts} +834 -358
- package/src/internal/dialect.ts +37 -0
- package/src/internal/dsl-mutation-runtime.ts +29 -10
- package/src/internal/dsl-plan-runtime.ts +41 -24
- package/src/internal/dsl-query-runtime.ts +11 -31
- package/src/internal/dsl-transaction-ddl-runtime.ts +61 -15
- package/src/internal/executor.ts +57 -15
- package/src/internal/expression-ast.ts +3 -2
- package/src/internal/grouping-key.ts +216 -9
- package/src/internal/implication-runtime.ts +3 -2
- package/src/internal/json/types.ts +155 -40
- package/src/internal/predicate/context.ts +14 -1
- package/src/internal/predicate/key.ts +19 -2
- package/src/internal/predicate/runtime.ts +30 -3
- package/src/internal/query.d.ts +38 -11
- package/src/internal/query.ts +315 -54
- package/src/internal/renderer.ts +51 -6
- package/src/internal/runtime/driver-value-mapping.ts +58 -0
- package/src/internal/runtime/normalize.ts +74 -43
- package/src/internal/runtime/schema.ts +5 -3
- package/src/internal/runtime/value.ts +153 -30
- package/src/internal/scalar.ts +6 -1
- package/src/internal/schema-derivation.d.ts +12 -61
- package/src/internal/schema-derivation.ts +90 -38
- package/src/internal/schema-expression.ts +2 -2
- package/src/internal/sql-expression-renderer.ts +19 -0
- package/src/internal/standard-dsl.ts +6885 -0
- package/src/internal/table-options.ts +229 -62
- package/src/internal/table.d.ts +33 -32
- package/src/internal/table.ts +469 -160
- package/src/mysql/column-extension.ts +3 -0
- package/src/mysql/column.ts +27 -12
- package/src/mysql/datatypes/index.ts +24 -2
- package/src/mysql/errors/catalog.ts +5 -5
- package/src/mysql/errors/normalize.ts +2 -2
- package/src/mysql/executor.ts +7 -5
- package/src/mysql/internal/dialect.ts +9 -4
- package/src/mysql/internal/dsl.ts +906 -324
- package/src/mysql/internal/renderer.ts +7 -2
- package/src/mysql/json.ts +37 -0
- package/src/mysql/query-extension.ts +16 -0
- package/src/mysql/query.ts +9 -2
- package/src/mysql/renderer.ts +31 -4
- package/src/mysql.ts +4 -12
- package/src/postgres/column-extension.ts +28 -0
- package/src/postgres/column.ts +9 -13
- package/src/postgres/datatypes/index.d.ts +2 -1
- package/src/postgres/datatypes/index.ts +3 -2
- package/src/postgres/errors/normalize.ts +2 -2
- package/src/postgres/executor.ts +55 -10
- package/src/postgres/function/core.ts +20 -4
- package/src/postgres/function/index.ts +1 -17
- package/src/postgres/internal/dialect.ts +9 -4
- package/src/postgres/internal/dsl.ts +850 -359
- package/src/postgres/internal/renderer.ts +7 -2
- package/src/postgres/internal/schema-ddl.ts +22 -9
- package/src/postgres/internal/schema-model.ts +244 -10
- package/src/postgres/json.ts +100 -24
- package/src/postgres/jsonb.ts +38 -0
- package/src/postgres/query-extension.ts +2 -0
- package/src/postgres/query.ts +9 -2
- package/src/postgres/renderer.ts +31 -4
- package/src/postgres/schema-management.ts +108 -16
- package/src/postgres/schema.ts +98 -15
- package/src/postgres/table.ts +203 -398
- package/src/postgres/type.ts +8 -7
- package/src/postgres.ts +9 -11
- package/src/sqlite/column-extension.ts +3 -0
- package/src/sqlite/column.ts +127 -0
- package/src/sqlite/datatypes/index.ts +80 -0
- package/src/sqlite/datatypes/spec.ts +98 -0
- package/src/sqlite/errors/catalog.ts +103 -0
- package/src/sqlite/errors/fields.ts +19 -0
- package/src/sqlite/errors/index.ts +19 -0
- package/src/sqlite/errors/normalize.ts +229 -0
- package/src/sqlite/errors/requirements.ts +71 -0
- package/src/sqlite/errors/types.ts +29 -0
- package/src/sqlite/executor.ts +229 -0
- package/src/sqlite/function/aggregate.ts +2 -0
- package/src/sqlite/function/core.ts +2 -0
- package/src/sqlite/function/index.ts +19 -0
- package/src/sqlite/function/string.ts +2 -0
- package/src/sqlite/function/temporal.ts +100 -0
- package/src/sqlite/function/window.ts +2 -0
- package/src/sqlite/internal/dialect.ts +42 -0
- package/src/sqlite/internal/dsl.ts +6979 -0
- package/src/sqlite/internal/renderer.ts +51 -0
- package/src/sqlite/json.ts +39 -0
- package/src/sqlite/query-extension.ts +2 -0
- package/src/sqlite/query.ts +196 -0
- package/src/sqlite/renderer.ts +51 -0
- package/src/sqlite.ts +14 -0
- package/src/standard/column.ts +163 -0
- package/src/standard/datatypes/index.ts +83 -0
- package/src/standard/datatypes/spec.ts +98 -0
- package/src/standard/dialect.ts +40 -0
- package/src/standard/function/aggregate.ts +2 -0
- package/src/standard/function/core.ts +2 -0
- package/src/standard/function/index.ts +18 -0
- package/src/standard/function/string.ts +2 -0
- package/src/standard/function/temporal.ts +78 -0
- package/src/standard/function/window.ts +2 -0
- package/src/standard/internal/renderer.ts +45 -0
- package/src/standard/query.ts +152 -0
- package/src/standard/renderer.ts +21 -0
- package/src/standard/table.ts +147 -0
- package/src/standard.ts +18 -0
- package/src/internal/aggregation-validation.ts +0 -57
- package/src/mysql/table.ts +0 -157
package/src/internal/dialect.ts
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import type * as Schema from "effect/Schema"
|
|
2
2
|
|
|
3
|
+
import type * as QueryAst from "./query-ast.js"
|
|
4
|
+
import type { Projection } from "./projections.js"
|
|
3
5
|
import type * as Expression from "./scalar.js"
|
|
6
|
+
import type * as Casing from "./casing.js"
|
|
4
7
|
|
|
5
8
|
/**
|
|
6
9
|
* Mutable rendering state shared while serializing SQL for a concrete dialect.
|
|
@@ -11,12 +14,20 @@ import type * as Expression from "./scalar.js"
|
|
|
11
14
|
export interface RenderState {
|
|
12
15
|
readonly params: unknown[]
|
|
13
16
|
readonly valueMappings?: Expression.DriverValueMappings
|
|
17
|
+
readonly casing?: Casing.Options
|
|
14
18
|
readonly ctes: {
|
|
15
19
|
readonly name: string
|
|
16
20
|
readonly sql: string
|
|
17
21
|
readonly recursive?: boolean
|
|
18
22
|
}[]
|
|
19
23
|
readonly cteNames: Set<string>
|
|
24
|
+
readonly cteSources: Map<string, unknown>
|
|
25
|
+
readonly sourceNames?: Map<string, {
|
|
26
|
+
readonly tableName: string
|
|
27
|
+
readonly columns: ReadonlyMap<string, string>
|
|
28
|
+
}>
|
|
29
|
+
readonly rowLocalColumns?: boolean
|
|
30
|
+
readonly allowExcluded?: boolean
|
|
20
31
|
}
|
|
21
32
|
|
|
22
33
|
export interface RenderValueContext {
|
|
@@ -25,6 +36,22 @@ export interface RenderValueContext {
|
|
|
25
36
|
readonly driverValueMapping?: Expression.DriverValueMapping
|
|
26
37
|
}
|
|
27
38
|
|
|
39
|
+
export const quoteDoubleQuotedIdentifier = (value: string): string => {
|
|
40
|
+
return `"${value.replaceAll("\"", "\"\"")}"`
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export const quoteBacktickIdentifier = (value: string): string => {
|
|
44
|
+
return `\`${value.replaceAll("`", "``")}\``
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export const renderDbTypeName = (value: string): string =>
|
|
48
|
+
value
|
|
49
|
+
|
|
50
|
+
export interface RenderedAst {
|
|
51
|
+
readonly sql: string
|
|
52
|
+
readonly projections: readonly Projection[]
|
|
53
|
+
}
|
|
54
|
+
|
|
28
55
|
/**
|
|
29
56
|
* Minimal runtime contract for a SQL dialect.
|
|
30
57
|
*
|
|
@@ -38,4 +65,14 @@ export interface SqlDialect<Name extends string = string> {
|
|
|
38
65
|
renderLiteral(value: unknown, state: RenderState, context?: RenderValueContext): string
|
|
39
66
|
renderTableReference(tableName: string, baseTableName: string, schemaName?: string): string
|
|
40
67
|
renderConcat(values: readonly string[]): string
|
|
68
|
+
renderQueryAst(
|
|
69
|
+
ast: QueryAst.Ast<Record<string, unknown>, any, QueryAst.QueryStatement>,
|
|
70
|
+
state: RenderState,
|
|
71
|
+
dialect: SqlDialect<Name>
|
|
72
|
+
): RenderedAst
|
|
73
|
+
renderExpression(
|
|
74
|
+
expression: Expression.Any,
|
|
75
|
+
state: RenderState,
|
|
76
|
+
dialect: SqlDialect<Name>
|
|
77
|
+
): string
|
|
41
78
|
}
|
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
import * as Expression from "./scalar.js"
|
|
2
2
|
import * as Plan from "./row-set.js"
|
|
3
|
+
import { normalizeStatementFlag } from "./dsl-transaction-ddl-runtime.js"
|
|
3
4
|
|
|
4
5
|
type DslMutationRuntimeContext = {
|
|
6
|
+
readonly profile: {
|
|
7
|
+
readonly dialect: string
|
|
8
|
+
}
|
|
5
9
|
readonly makePlan: (...args: readonly any[]) => any
|
|
6
10
|
readonly getAst: (plan: any) => any
|
|
7
11
|
readonly getQueryState: (plan: any) => any
|
|
@@ -14,11 +18,21 @@ type DslMutationRuntimeContext = {
|
|
|
14
18
|
readonly buildConflictTarget: (target: any, input: any) => any
|
|
15
19
|
readonly mutationTargetClauses: (target: any) => readonly any[]
|
|
16
20
|
readonly mutationAvailableSources: (target: any) => Record<string, any>
|
|
17
|
-
readonly
|
|
21
|
+
readonly normalizeConflictColumns: (target: any, columns: string | readonly string[]) => readonly string[]
|
|
18
22
|
readonly targetSourceDetails: (target: any) => { readonly sourceName: string; readonly sourceBaseName: string }
|
|
19
23
|
readonly sourceDetails: (source: any) => { readonly sourceName: string; readonly sourceBaseName: string }
|
|
20
24
|
}
|
|
21
25
|
|
|
26
|
+
export const expectConflictClause = <
|
|
27
|
+
Conflict extends {
|
|
28
|
+
readonly kind: string
|
|
29
|
+
readonly action: string
|
|
30
|
+
readonly target?: { readonly kind: string; readonly name?: string }
|
|
31
|
+
} | undefined
|
|
32
|
+
>(
|
|
33
|
+
conflict: Conflict
|
|
34
|
+
): Conflict => conflict
|
|
35
|
+
|
|
22
36
|
export const makeDslMutationRuntime = (ctx: DslMutationRuntimeContext) => {
|
|
23
37
|
const insert = (target: any, values?: Record<string, unknown>) => {
|
|
24
38
|
const { sourceName, sourceBaseName } = ctx.targetSourceDetails(target)
|
|
@@ -105,7 +119,7 @@ export const makeDslMutationRuntime = (ctx: DslMutationRuntimeContext) => {
|
|
|
105
119
|
const columns = ctx.normalizeInsertSelectColumns(selection)
|
|
106
120
|
return ctx.makePlan({
|
|
107
121
|
selection: current.selection,
|
|
108
|
-
required: ctx.currentRequiredList(sourcePlan[Plan.TypeId].required)
|
|
122
|
+
required: ctx.currentRequiredList(sourcePlan[Plan.TypeId].required),
|
|
109
123
|
available: current.available,
|
|
110
124
|
dialect: current.dialect
|
|
111
125
|
}, {
|
|
@@ -125,17 +139,23 @@ export const makeDslMutationRuntime = (ctx: DslMutationRuntimeContext) => {
|
|
|
125
139
|
const currentAst = ctx.getAst(plan)
|
|
126
140
|
const currentQuery = ctx.getQueryState(plan)
|
|
127
141
|
const insertTarget = currentAst.into!.source
|
|
128
|
-
const conflictTarget =
|
|
142
|
+
const conflictTarget = expectConflictClause({
|
|
143
|
+
kind: "conflict",
|
|
144
|
+
action: "doNothing",
|
|
145
|
+
target: ctx.buildConflictTarget(insertTarget, target)
|
|
146
|
+
}).target
|
|
129
147
|
const updateAssignments = options.update
|
|
130
148
|
? ctx.buildMutationAssignments(insertTarget, options.update)
|
|
131
149
|
: []
|
|
132
150
|
const updateWhere = options.where === undefined
|
|
133
151
|
? undefined
|
|
134
152
|
: ctx.toDialectExpression(options.where)
|
|
153
|
+
const targetWhere = conflictTarget.kind === "columns" ? conflictTarget.where : undefined
|
|
135
154
|
const required = [
|
|
136
155
|
...ctx.currentRequiredList(current.required),
|
|
137
156
|
...updateAssignments.flatMap((entry) => Object.keys(entry.value[Expression.TypeId].dependencies)),
|
|
138
|
-
...(updateWhere ? Object.keys(updateWhere[Expression.TypeId].dependencies) : [])
|
|
157
|
+
...(updateWhere ? Object.keys(updateWhere[Expression.TypeId].dependencies) : []),
|
|
158
|
+
...(targetWhere ? Object.keys(targetWhere[Expression.TypeId].dependencies) : [])
|
|
139
159
|
].filter((name, index, list) =>
|
|
140
160
|
!(name in current.available) && list.indexOf(name) === index)
|
|
141
161
|
return ctx.makePlan({
|
|
@@ -215,7 +235,7 @@ export const makeDslMutationRuntime = (ctx: DslMutationRuntimeContext) => {
|
|
|
215
235
|
kind: "conflict",
|
|
216
236
|
target: {
|
|
217
237
|
kind: "columns",
|
|
218
|
-
columns: ctx.
|
|
238
|
+
columns: ctx.normalizeConflictColumns(target, conflictColumns) as readonly [string, ...string[]]
|
|
219
239
|
},
|
|
220
240
|
action: updateAssignments.length > 0 ? "doUpdate" : "doNothing",
|
|
221
241
|
values: updateAssignments.length > 0 ? updateAssignments : undefined
|
|
@@ -250,6 +270,8 @@ export const makeDslMutationRuntime = (ctx: DslMutationRuntimeContext) => {
|
|
|
250
270
|
}
|
|
251
271
|
|
|
252
272
|
const truncate = (target: any, options: { readonly restartIdentity?: boolean; readonly cascade?: boolean } = {}) => {
|
|
273
|
+
const restartIdentity = normalizeStatementFlag(options.restartIdentity)
|
|
274
|
+
const cascade = normalizeStatementFlag(options.cascade)
|
|
253
275
|
const { sourceName, sourceBaseName } = ctx.targetSourceDetails(target)
|
|
254
276
|
return ctx.makePlan({
|
|
255
277
|
selection: {},
|
|
@@ -267,8 +289,8 @@ export const makeDslMutationRuntime = (ctx: DslMutationRuntimeContext) => {
|
|
|
267
289
|
},
|
|
268
290
|
truncate: {
|
|
269
291
|
kind: "truncate",
|
|
270
|
-
restartIdentity
|
|
271
|
-
cascade
|
|
292
|
+
restartIdentity,
|
|
293
|
+
cascade
|
|
272
294
|
},
|
|
273
295
|
where: [],
|
|
274
296
|
having: [],
|
|
@@ -284,9 +306,6 @@ export const makeDslMutationRuntime = (ctx: DslMutationRuntimeContext) => {
|
|
|
284
306
|
const onExpression = ctx.toDialectExpression(on)
|
|
285
307
|
const matched = options.whenMatched
|
|
286
308
|
const notMatched = options.whenNotMatched
|
|
287
|
-
if (matched && "delete" in matched && "update" in matched) {
|
|
288
|
-
throw new Error("merge whenMatched cannot specify both update and delete")
|
|
289
|
-
}
|
|
290
309
|
const matchedPredicate = matched?.predicate ? ctx.toDialectExpression(matched.predicate) : undefined
|
|
291
310
|
const matchedAssignments = matched && "update" in matched && matched.update
|
|
292
311
|
? ctx.buildMutationAssignments(target, matched.update)
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import * as Expression from "./scalar.js"
|
|
2
2
|
import * as Plan from "./row-set.js"
|
|
3
|
-
import * as Table from "./table.js"
|
|
4
3
|
|
|
5
4
|
type DslPlanRuntimeContext = {
|
|
6
5
|
readonly profile: {
|
|
@@ -22,7 +21,27 @@ type DslPlanRuntimeContext = {
|
|
|
22
21
|
readonly attachInsertSource: (plan: any, source: any) => any
|
|
23
22
|
}
|
|
24
23
|
|
|
24
|
+
type LockMode = "update" | "share" | "lowPriority" | "ignore" | "quick"
|
|
25
|
+
|
|
26
|
+
export const renderSelectLockMode = (mode: LockMode): string =>
|
|
27
|
+
mode === "update" ? "for update" : "for share"
|
|
28
|
+
|
|
29
|
+
export const renderMysqlMutationLockMode = (
|
|
30
|
+
mode: LockMode,
|
|
31
|
+
_statement: "update" | "delete"
|
|
32
|
+
): string => {
|
|
33
|
+
if (mode === "lowPriority") {
|
|
34
|
+
return " low_priority"
|
|
35
|
+
}
|
|
36
|
+
return mode === "ignore" ? " ignore" : " quick"
|
|
37
|
+
}
|
|
38
|
+
|
|
25
39
|
export const makeDslPlanRuntime = (ctx: DslPlanRuntimeContext) => {
|
|
40
|
+
const sourceRequiredList = (source: any): readonly string[] =>
|
|
41
|
+
typeof source === "object" && source !== null && "required" in source
|
|
42
|
+
? ctx.currentRequiredList(source.required)
|
|
43
|
+
: []
|
|
44
|
+
|
|
26
45
|
const buildSetOperation = (kind: string, all: boolean, left: any, right: any) => {
|
|
27
46
|
const leftState = left[Plan.TypeId]
|
|
28
47
|
const leftAst = ctx.getAst(left)
|
|
@@ -92,32 +111,26 @@ export const makeDslPlanRuntime = (ctx: DslPlanRuntimeContext) => {
|
|
|
92
111
|
return ctx.attachInsertSource(plan, source)
|
|
93
112
|
}
|
|
94
113
|
|
|
95
|
-
if (
|
|
96
|
-
typeof source !== "object" ||
|
|
97
|
-
source === null ||
|
|
98
|
-
("kind" in source && source.kind === "values" && !("name" in source)) ||
|
|
99
|
-
(!(Table.TypeId in source) && !("name" in source && "baseName" in source))
|
|
100
|
-
) {
|
|
101
|
-
throw new Error("from(...) requires an aliased source in select/update statements")
|
|
102
|
-
}
|
|
103
|
-
|
|
104
114
|
const sourceLike = source
|
|
105
115
|
const { sourceName, sourceBaseName } = ctx.sourceDetails(sourceLike)
|
|
106
116
|
const presenceWitnesses = ctx.presenceWitnessesOfSourceLike(sourceLike)
|
|
117
|
+
const sourceRequired = sourceRequiredList(sourceLike)
|
|
107
118
|
|
|
108
119
|
if (currentQuery.statement === "select") {
|
|
120
|
+
const nextAvailable = {
|
|
121
|
+
[sourceName]: {
|
|
122
|
+
name: sourceName,
|
|
123
|
+
mode: "required",
|
|
124
|
+
baseName: sourceBaseName,
|
|
125
|
+
_presentFormula: ctx.trueFormula(),
|
|
126
|
+
_presenceWitnesses: presenceWitnesses
|
|
127
|
+
}
|
|
128
|
+
}
|
|
109
129
|
return ctx.makePlan({
|
|
110
130
|
selection: current.selection,
|
|
111
|
-
required: ctx.currentRequiredList(current.required).filter((name) =>
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
name: sourceName,
|
|
115
|
-
mode: "required",
|
|
116
|
-
baseName: sourceBaseName,
|
|
117
|
-
_presentFormula: ctx.trueFormula(),
|
|
118
|
-
_presenceWitnesses: presenceWitnesses
|
|
119
|
-
}
|
|
120
|
-
},
|
|
131
|
+
required: [...ctx.currentRequiredList(current.required), ...sourceRequired].filter((name, index, values) =>
|
|
132
|
+
!(name in nextAvailable) && values.indexOf(name) === index),
|
|
133
|
+
available: nextAvailable,
|
|
121
134
|
dialect: current.dialect
|
|
122
135
|
}, {
|
|
123
136
|
...currentAst,
|
|
@@ -143,7 +156,8 @@ export const makeDslPlanRuntime = (ctx: DslPlanRuntimeContext) => {
|
|
|
143
156
|
}
|
|
144
157
|
return ctx.makePlan({
|
|
145
158
|
selection: current.selection,
|
|
146
|
-
required: ctx.currentRequiredList(current.required).filter((name) =>
|
|
159
|
+
required: [...ctx.currentRequiredList(current.required), ...sourceRequired].filter((name, index, values) =>
|
|
160
|
+
!(name in nextAvailable) && values.indexOf(name) === index),
|
|
147
161
|
available: nextAvailable,
|
|
148
162
|
dialect: current.dialect
|
|
149
163
|
}, {
|
|
@@ -160,7 +174,7 @@ export const makeDslPlanRuntime = (ctx: DslPlanRuntimeContext) => {
|
|
|
160
174
|
}, currentQuery.assumptions, currentQuery.capabilities, currentQuery.statement)
|
|
161
175
|
}
|
|
162
176
|
|
|
163
|
-
|
|
177
|
+
return plan
|
|
164
178
|
}
|
|
165
179
|
|
|
166
180
|
const having = (predicate: any) =>
|
|
@@ -195,6 +209,7 @@ export const makeDslPlanRuntime = (ctx: DslPlanRuntimeContext) => {
|
|
|
195
209
|
const currentQuery = ctx.getQueryState(plan)
|
|
196
210
|
const { sourceName, sourceBaseName } = ctx.sourceDetails(table)
|
|
197
211
|
const presenceWitnesses = ctx.presenceWitnessesOfSourceLike(table)
|
|
212
|
+
const sourceRequired = sourceRequiredList(table)
|
|
198
213
|
const nextAvailable = {
|
|
199
214
|
...current.available,
|
|
200
215
|
[sourceName]: {
|
|
@@ -207,7 +222,8 @@ export const makeDslPlanRuntime = (ctx: DslPlanRuntimeContext) => {
|
|
|
207
222
|
}
|
|
208
223
|
return ctx.makePlan({
|
|
209
224
|
selection: current.selection,
|
|
210
|
-
required: ctx.currentRequiredList(current.required).filter((name) =>
|
|
225
|
+
required: [...ctx.currentRequiredList(current.required), ...sourceRequired].filter((name, index, values) =>
|
|
226
|
+
!(name in nextAvailable) && values.indexOf(name) === index),
|
|
211
227
|
available: nextAvailable,
|
|
212
228
|
dialect: current.dialect ?? table[Plan.TypeId]?.dialect ?? table.dialect
|
|
213
229
|
}, {
|
|
@@ -230,6 +246,7 @@ export const makeDslPlanRuntime = (ctx: DslPlanRuntimeContext) => {
|
|
|
230
246
|
const onFormula = ctx.formulaOfExpressionRuntime(onExpression)
|
|
231
247
|
const { sourceName, sourceBaseName } = ctx.sourceDetails(table)
|
|
232
248
|
const presenceWitnesses = ctx.presenceWitnessesOfSourceLike(table)
|
|
249
|
+
const sourceRequired = sourceRequiredList(table)
|
|
233
250
|
const baseAvailable = (kind === "right" || kind === "full"
|
|
234
251
|
? Object.fromEntries(
|
|
235
252
|
Object.entries(current.available as Record<string, any>).map(([name, source]) => [name, {
|
|
@@ -253,7 +270,7 @@ export const makeDslPlanRuntime = (ctx: DslPlanRuntimeContext) => {
|
|
|
253
270
|
}
|
|
254
271
|
return ctx.makePlan({
|
|
255
272
|
selection: current.selection,
|
|
256
|
-
required: [...ctx.currentRequiredList(current.required), ...ctx.extractRequiredFromDialectInputRuntime(on)].filter((name, index, values) =>
|
|
273
|
+
required: [...ctx.currentRequiredList(current.required), ...sourceRequired, ...ctx.extractRequiredFromDialectInputRuntime(on)].filter((name, index, values) =>
|
|
257
274
|
!(name in nextAvailable) && values.indexOf(name) === index),
|
|
258
275
|
available: nextAvailable,
|
|
259
276
|
dialect: current.dialect ?? table.dialect ?? onExpression[Expression.TypeId].dialect
|
|
@@ -20,20 +20,12 @@ type DslQueryRuntimeContext = {
|
|
|
20
20
|
|
|
21
21
|
export const makeDslQueryRuntime = (ctx: DslQueryRuntimeContext) => {
|
|
22
22
|
const values = (rows: readonly [Record<string, any>, ...Record<string, any>[]]) => {
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
...Record<string, Expression.Any>[]
|
|
29
|
-
]
|
|
23
|
+
const [first, ...rest] = rows
|
|
24
|
+
const normalizedRows = [
|
|
25
|
+
ctx.normalizeValuesRow(first),
|
|
26
|
+
...rest.map((row) => ctx.normalizeValuesRow(row))
|
|
27
|
+
] satisfies readonly [Record<string, Expression.Any>, ...Record<string, Expression.Any>[]]
|
|
30
28
|
const columnNames = Object.keys(normalizedRows[0]!)
|
|
31
|
-
for (const row of normalizedRows) {
|
|
32
|
-
const rowKeys = Object.keys(row)
|
|
33
|
-
if (rowKeys.length !== columnNames.length || !rowKeys.every((key, index) => key === columnNames[index])) {
|
|
34
|
-
throw new Error("values(...) rows must project the same columns in the same order")
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
29
|
return Object.assign(Object.create(ctx.ValuesInputProto), {
|
|
38
30
|
kind: "values",
|
|
39
31
|
dialect: ctx.profile.dialect,
|
|
@@ -45,20 +37,6 @@ export const makeDslQueryRuntime = (ctx: DslQueryRuntimeContext) => {
|
|
|
45
37
|
const unnest = (columns: Record<string, readonly any[]>, alias: string) => {
|
|
46
38
|
const normalizedColumns = ctx.normalizeUnnestColumns(columns)
|
|
47
39
|
const columnNames = Object.keys(normalizedColumns)
|
|
48
|
-
if (columnNames.length === 0) {
|
|
49
|
-
throw new Error("unnest(...) requires at least one column array")
|
|
50
|
-
}
|
|
51
|
-
const firstColumn = normalizedColumns[columnNames[0] as keyof typeof normalizedColumns]
|
|
52
|
-
const rowCount = firstColumn?.length ?? 0
|
|
53
|
-
if (rowCount === 0) {
|
|
54
|
-
throw new Error("unnest(...) requires at least one row")
|
|
55
|
-
}
|
|
56
|
-
for (const columnName of columnNames) {
|
|
57
|
-
const values = normalizedColumns[columnName]!
|
|
58
|
-
if (values.length !== rowCount) {
|
|
59
|
-
throw new Error("unnest(...) column arrays must have the same length")
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
40
|
const firstRow = Object.fromEntries(
|
|
63
41
|
columnNames.map((columnName) => [columnName, normalizedColumns[columnName]![0]!])
|
|
64
42
|
) as Record<string, Expression.Any>
|
|
@@ -97,8 +75,8 @@ export const makeDslQueryRuntime = (ctx: DslQueryRuntimeContext) => {
|
|
|
97
75
|
return Object.assign(source, columns)
|
|
98
76
|
}
|
|
99
77
|
|
|
100
|
-
const select = (selection: any) =>
|
|
101
|
-
ctx.makePlan({
|
|
78
|
+
const select = (selection: any = {}) => {
|
|
79
|
+
return ctx.makePlan({
|
|
102
80
|
selection,
|
|
103
81
|
required: ctx.extractRequiredRuntime(selection),
|
|
104
82
|
available: {},
|
|
@@ -112,6 +90,7 @@ export const makeDslQueryRuntime = (ctx: DslQueryRuntimeContext) => {
|
|
|
112
90
|
groupBy: [],
|
|
113
91
|
orderBy: []
|
|
114
92
|
}, undefined, "read", "select")
|
|
93
|
+
}
|
|
115
94
|
|
|
116
95
|
const groupBy = (...values: readonly Expression.Any[]) =>
|
|
117
96
|
(plan: any) => {
|
|
@@ -132,8 +111,8 @@ export const makeDslQueryRuntime = (ctx: DslQueryRuntimeContext) => {
|
|
|
132
111
|
}, currentQuery.assumptions, currentQuery.capabilities, currentQuery.statement)
|
|
133
112
|
}
|
|
134
113
|
|
|
135
|
-
const returning = (selection: any) =>
|
|
136
|
-
(plan: any) => {
|
|
114
|
+
const returning = (selection: any) => {
|
|
115
|
+
return (plan: any) => {
|
|
137
116
|
const current = plan[Plan.TypeId]
|
|
138
117
|
const currentAst = ctx.getAst(plan)
|
|
139
118
|
const currentQuery = ctx.getQueryState(plan)
|
|
@@ -148,6 +127,7 @@ export const makeDslQueryRuntime = (ctx: DslQueryRuntimeContext) => {
|
|
|
148
127
|
select: selection
|
|
149
128
|
}, currentQuery.assumptions, currentQuery.capabilities, currentQuery.statement, currentQuery.target, currentQuery.insertSource)
|
|
150
129
|
}
|
|
130
|
+
}
|
|
151
131
|
|
|
152
132
|
return {
|
|
153
133
|
values,
|
|
@@ -10,9 +10,44 @@ type DslTransactionDdlRuntimeContext = {
|
|
|
10
10
|
readonly defaultIndexName: (tableName: string, columns: readonly string[], unique: boolean) => string
|
|
11
11
|
}
|
|
12
12
|
|
|
13
|
+
export const renderTransactionIsolationLevel = (
|
|
14
|
+
isolationLevel: unknown
|
|
15
|
+
): string => {
|
|
16
|
+
if (isolationLevel === undefined) {
|
|
17
|
+
return ""
|
|
18
|
+
}
|
|
19
|
+
return `isolation level ${isolationLevel as string}`
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export const expectDdlClauseKind = <
|
|
23
|
+
Ddl extends { readonly kind: string },
|
|
24
|
+
Kind extends Ddl["kind"]
|
|
25
|
+
>(
|
|
26
|
+
ddl: Ddl | undefined,
|
|
27
|
+
_kind: Kind
|
|
28
|
+
): Extract<Ddl, { readonly kind: Kind }> =>
|
|
29
|
+
ddl as Extract<Ddl, { readonly kind: Kind }>
|
|
30
|
+
|
|
31
|
+
export const expectTruncateClause = <
|
|
32
|
+
Truncate extends { readonly kind: string }
|
|
33
|
+
>(
|
|
34
|
+
truncate: Truncate | undefined
|
|
35
|
+
): Extract<Truncate, { readonly kind: "truncate" }> =>
|
|
36
|
+
truncate as Extract<Truncate, { readonly kind: "truncate" }>
|
|
37
|
+
|
|
38
|
+
export const normalizeStatementFlag = (value: unknown): boolean =>
|
|
39
|
+
(value as boolean | undefined) ?? false
|
|
40
|
+
|
|
41
|
+
export const normalizeStatementIdentifier = (
|
|
42
|
+
_apiName: string,
|
|
43
|
+
_identifierName: string,
|
|
44
|
+
value: unknown
|
|
45
|
+
): string =>
|
|
46
|
+
value as string
|
|
47
|
+
|
|
13
48
|
export const makeDslTransactionDdlRuntime = (ctx: DslTransactionDdlRuntimeContext) => {
|
|
14
|
-
const transaction = (options: { readonly isolationLevel?: any; readonly readOnly?: boolean } = {}) =>
|
|
15
|
-
ctx.makePlan({
|
|
49
|
+
const transaction = (options: { readonly isolationLevel?: any; readonly readOnly?: boolean } = {}) => {
|
|
50
|
+
return ctx.makePlan({
|
|
16
51
|
selection: {},
|
|
17
52
|
required: [],
|
|
18
53
|
available: {},
|
|
@@ -31,6 +66,7 @@ export const makeDslTransactionDdlRuntime = (ctx: DslTransactionDdlRuntimeContex
|
|
|
31
66
|
groupBy: [],
|
|
32
67
|
orderBy: []
|
|
33
68
|
}, undefined, "transaction", "transaction")
|
|
69
|
+
}
|
|
34
70
|
|
|
35
71
|
const commit = () =>
|
|
36
72
|
ctx.makePlan({
|
|
@@ -70,8 +106,8 @@ export const makeDslTransactionDdlRuntime = (ctx: DslTransactionDdlRuntimeContex
|
|
|
70
106
|
orderBy: []
|
|
71
107
|
}, undefined, "transaction", "rollback")
|
|
72
108
|
|
|
73
|
-
const savepoint = (name: string) =>
|
|
74
|
-
ctx.makePlan({
|
|
109
|
+
const savepoint = (name: string) => {
|
|
110
|
+
return ctx.makePlan({
|
|
75
111
|
selection: {},
|
|
76
112
|
required: [],
|
|
77
113
|
available: {},
|
|
@@ -89,9 +125,10 @@ export const makeDslTransactionDdlRuntime = (ctx: DslTransactionDdlRuntimeContex
|
|
|
89
125
|
groupBy: [],
|
|
90
126
|
orderBy: []
|
|
91
127
|
}, undefined, "transaction", "savepoint")
|
|
128
|
+
}
|
|
92
129
|
|
|
93
|
-
const rollbackTo = (name: string) =>
|
|
94
|
-
ctx.makePlan({
|
|
130
|
+
const rollbackTo = (name: string) => {
|
|
131
|
+
return ctx.makePlan({
|
|
95
132
|
selection: {},
|
|
96
133
|
required: [],
|
|
97
134
|
available: {},
|
|
@@ -109,9 +146,10 @@ export const makeDslTransactionDdlRuntime = (ctx: DslTransactionDdlRuntimeContex
|
|
|
109
146
|
groupBy: [],
|
|
110
147
|
orderBy: []
|
|
111
148
|
}, undefined, "transaction", "rollbackTo")
|
|
149
|
+
}
|
|
112
150
|
|
|
113
|
-
const releaseSavepoint = (name: string) =>
|
|
114
|
-
ctx.makePlan({
|
|
151
|
+
const releaseSavepoint = (name: string) => {
|
|
152
|
+
return ctx.makePlan({
|
|
115
153
|
selection: {},
|
|
116
154
|
required: [],
|
|
117
155
|
available: {},
|
|
@@ -129,8 +167,10 @@ export const makeDslTransactionDdlRuntime = (ctx: DslTransactionDdlRuntimeContex
|
|
|
129
167
|
groupBy: [],
|
|
130
168
|
orderBy: []
|
|
131
169
|
}, undefined, "transaction", "releaseSavepoint")
|
|
170
|
+
}
|
|
132
171
|
|
|
133
172
|
const createTable = (target: any, options: { readonly ifNotExists?: boolean } = {}) => {
|
|
173
|
+
const ifNotExists = normalizeStatementFlag(options.ifNotExists)
|
|
134
174
|
const { sourceName, sourceBaseName } = ctx.targetSourceDetails(target)
|
|
135
175
|
return ctx.makePlan({
|
|
136
176
|
selection: {},
|
|
@@ -148,7 +188,7 @@ export const makeDslTransactionDdlRuntime = (ctx: DslTransactionDdlRuntimeContex
|
|
|
148
188
|
},
|
|
149
189
|
ddl: {
|
|
150
190
|
kind: "createTable",
|
|
151
|
-
ifNotExists
|
|
191
|
+
ifNotExists
|
|
152
192
|
},
|
|
153
193
|
where: [],
|
|
154
194
|
having: [],
|
|
@@ -159,6 +199,7 @@ export const makeDslTransactionDdlRuntime = (ctx: DslTransactionDdlRuntimeContex
|
|
|
159
199
|
}
|
|
160
200
|
|
|
161
201
|
const dropTable = (target: any, options: { readonly ifExists?: boolean } = {}) => {
|
|
202
|
+
const ifExists = normalizeStatementFlag(options.ifExists)
|
|
162
203
|
const { sourceName, sourceBaseName } = ctx.targetSourceDetails(target)
|
|
163
204
|
return ctx.makePlan({
|
|
164
205
|
selection: {},
|
|
@@ -176,7 +217,7 @@ export const makeDslTransactionDdlRuntime = (ctx: DslTransactionDdlRuntimeContex
|
|
|
176
217
|
},
|
|
177
218
|
ddl: {
|
|
178
219
|
kind: "dropTable",
|
|
179
|
-
ifExists
|
|
220
|
+
ifExists
|
|
180
221
|
},
|
|
181
222
|
where: [],
|
|
182
223
|
having: [],
|
|
@@ -188,6 +229,9 @@ export const makeDslTransactionDdlRuntime = (ctx: DslTransactionDdlRuntimeContex
|
|
|
188
229
|
|
|
189
230
|
const createIndex = (target: any, columns: string | readonly string[], options: { readonly name?: string; readonly unique?: boolean; readonly ifNotExists?: boolean } = {}) => {
|
|
190
231
|
const normalizedColumns = ctx.normalizeColumnList(columns)
|
|
232
|
+
const unique = normalizeStatementFlag(options.unique)
|
|
233
|
+
const ifNotExists = normalizeStatementFlag(options.ifNotExists)
|
|
234
|
+
const name = options.name
|
|
191
235
|
const { sourceName, sourceBaseName } = ctx.targetSourceDetails(target)
|
|
192
236
|
return ctx.makePlan({
|
|
193
237
|
selection: {},
|
|
@@ -205,10 +249,10 @@ export const makeDslTransactionDdlRuntime = (ctx: DslTransactionDdlRuntimeContex
|
|
|
205
249
|
},
|
|
206
250
|
ddl: {
|
|
207
251
|
kind: "createIndex",
|
|
208
|
-
name:
|
|
252
|
+
name: name ?? ctx.defaultIndexName(sourceBaseName, normalizedColumns, unique),
|
|
209
253
|
columns: normalizedColumns,
|
|
210
|
-
unique
|
|
211
|
-
ifNotExists
|
|
254
|
+
unique,
|
|
255
|
+
ifNotExists
|
|
212
256
|
},
|
|
213
257
|
where: [],
|
|
214
258
|
having: [],
|
|
@@ -220,6 +264,8 @@ export const makeDslTransactionDdlRuntime = (ctx: DslTransactionDdlRuntimeContex
|
|
|
220
264
|
|
|
221
265
|
const dropIndex = (target: any, columns: string | readonly string[], options: { readonly name?: string; readonly ifExists?: boolean } = {}) => {
|
|
222
266
|
const normalizedColumns = ctx.normalizeColumnList(columns)
|
|
267
|
+
const ifExists = normalizeStatementFlag(options.ifExists)
|
|
268
|
+
const name = options.name
|
|
223
269
|
const { sourceName, sourceBaseName } = ctx.targetSourceDetails(target)
|
|
224
270
|
return ctx.makePlan({
|
|
225
271
|
selection: {},
|
|
@@ -237,8 +283,8 @@ export const makeDslTransactionDdlRuntime = (ctx: DslTransactionDdlRuntimeContex
|
|
|
237
283
|
},
|
|
238
284
|
ddl: {
|
|
239
285
|
kind: "dropIndex",
|
|
240
|
-
name:
|
|
241
|
-
ifExists
|
|
286
|
+
name: name ?? ctx.defaultIndexName(sourceBaseName, normalizedColumns, false),
|
|
287
|
+
ifExists
|
|
242
288
|
},
|
|
243
289
|
where: [],
|
|
244
290
|
having: [],
|