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
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import * as Query from "
|
|
2
|
-
import
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
1
|
+
import * as Query from "../../internal/query.js"
|
|
2
|
+
import type * as Expression from "../../internal/scalar.js"
|
|
3
|
+
import { type RenderState } from "../../internal/dialect.js"
|
|
4
|
+
import { postgresDialect } from "./dialect.js"
|
|
5
|
+
import { type Projection } from "../../internal/projections.js"
|
|
5
6
|
import { renderQueryAst } from "./sql-expression-renderer.js"
|
|
6
7
|
|
|
7
8
|
/**
|
|
@@ -14,27 +15,35 @@ export interface PostgresRenderResult {
|
|
|
14
15
|
readonly sql: string
|
|
15
16
|
readonly params: readonly unknown[]
|
|
16
17
|
readonly projections: readonly Projection[]
|
|
18
|
+
readonly valueMappings?: Expression.DriverValueMappings
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export interface PostgresRenderOptions {
|
|
22
|
+
readonly valueMappings?: Expression.DriverValueMappings
|
|
17
23
|
}
|
|
18
24
|
|
|
19
25
|
/**
|
|
20
26
|
* Renders the current query AST into Postgres SQL plus bind parameters.
|
|
21
27
|
*/
|
|
22
|
-
export const renderPostgresPlan = <PlanValue extends Query.
|
|
23
|
-
plan: Query.DialectCompatiblePlan<PlanValue, "postgres"
|
|
28
|
+
export const renderPostgresPlan = <PlanValue extends Query.Plan.Any>(
|
|
29
|
+
plan: Query.DialectCompatiblePlan<PlanValue, "postgres">,
|
|
30
|
+
options: PostgresRenderOptions = {}
|
|
24
31
|
): PostgresRenderResult => {
|
|
25
32
|
const state: RenderState = {
|
|
26
33
|
params: [],
|
|
34
|
+
valueMappings: options.valueMappings,
|
|
27
35
|
ctes: [],
|
|
28
36
|
cteNames: new Set<string>()
|
|
29
37
|
}
|
|
30
38
|
const rendered = renderQueryAst(
|
|
31
|
-
Query.getAst(plan as Query.
|
|
39
|
+
Query.getAst(plan as Query.Plan.Any) as any,
|
|
32
40
|
state,
|
|
33
41
|
postgresDialect
|
|
34
42
|
)
|
|
35
43
|
return {
|
|
36
44
|
sql: rendered.sql,
|
|
37
45
|
params: state.params,
|
|
38
|
-
projections: rendered.projections
|
|
46
|
+
projections: rendered.projections,
|
|
47
|
+
valueMappings: state.valueMappings
|
|
39
48
|
}
|
|
40
49
|
}
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import type * as Expression from "../../internal/scalar.js"
|
|
2
|
+
import type { RenderState, SqlDialect } from "../../internal/dialect.js"
|
|
3
|
+
import * as SchemaExpression from "../../internal/schema-expression.js"
|
|
4
|
+
import { renderExpression } from "./sql-expression-renderer.js"
|
|
5
|
+
import type { DdlExpressionLike } from "../../internal/table-options.js"
|
|
6
|
+
import { parse, toSql } from "pgsql-ast-parser"
|
|
7
|
+
import { postgresDialect } from "./dialect.js"
|
|
8
|
+
|
|
9
|
+
export const renderDdlExpression = (
|
|
10
|
+
expression: DdlExpressionLike,
|
|
11
|
+
state: RenderState,
|
|
12
|
+
dialect: SqlDialect
|
|
13
|
+
): string =>
|
|
14
|
+
SchemaExpression.isSchemaExpression(expression)
|
|
15
|
+
? SchemaExpression.render(expression)
|
|
16
|
+
: renderExpression(expression as Expression.Any, state, dialect)
|
|
17
|
+
|
|
18
|
+
const escapeString = (value: string): string => `'${value.replaceAll("'", "''")}'`
|
|
19
|
+
|
|
20
|
+
const inlineLiteralDialect: SqlDialect<"postgres"> = {
|
|
21
|
+
...postgresDialect,
|
|
22
|
+
renderLiteral(value) {
|
|
23
|
+
if (value === null) {
|
|
24
|
+
return "null"
|
|
25
|
+
}
|
|
26
|
+
if (typeof value === "boolean") {
|
|
27
|
+
return value ? "true" : "false"
|
|
28
|
+
}
|
|
29
|
+
if (typeof value === "number" || typeof value === "bigint") {
|
|
30
|
+
return String(value)
|
|
31
|
+
}
|
|
32
|
+
if (value instanceof Date) {
|
|
33
|
+
return escapeString(value.toISOString())
|
|
34
|
+
}
|
|
35
|
+
return escapeString(String(value))
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export const renderDdlExpressionSql = (expression: DdlExpressionLike): string =>
|
|
40
|
+
SchemaExpression.isSchemaExpression(expression)
|
|
41
|
+
? SchemaExpression.render(expression)
|
|
42
|
+
: renderExpression(expression as Expression.Any, {
|
|
43
|
+
params: [],
|
|
44
|
+
ctes: [],
|
|
45
|
+
cteNames: new Set()
|
|
46
|
+
}, inlineLiteralDialect)
|
|
47
|
+
|
|
48
|
+
const stripRedundantOuterParens = (value: string): string => {
|
|
49
|
+
let current = value.trim()
|
|
50
|
+
while (current.startsWith("(") && current.endsWith(")")) {
|
|
51
|
+
let depth = 0
|
|
52
|
+
let wrapsWholeExpression = true
|
|
53
|
+
let inSingleQuote = false
|
|
54
|
+
let inDoubleQuote = false
|
|
55
|
+
for (let index = 0; index < current.length; index++) {
|
|
56
|
+
const char = current[index]!
|
|
57
|
+
const previous = index > 0 ? current[index - 1] : undefined
|
|
58
|
+
if (char === "'" && !inDoubleQuote && previous !== "\\") {
|
|
59
|
+
inSingleQuote = !inSingleQuote
|
|
60
|
+
continue
|
|
61
|
+
}
|
|
62
|
+
if (char === "\"" && !inSingleQuote && previous !== "\\") {
|
|
63
|
+
inDoubleQuote = !inDoubleQuote
|
|
64
|
+
continue
|
|
65
|
+
}
|
|
66
|
+
if (inSingleQuote || inDoubleQuote) {
|
|
67
|
+
continue
|
|
68
|
+
}
|
|
69
|
+
if (char === "(") {
|
|
70
|
+
depth += 1
|
|
71
|
+
} else if (char === ")") {
|
|
72
|
+
depth -= 1
|
|
73
|
+
if (depth === 0 && index < current.length - 1) {
|
|
74
|
+
wrapsWholeExpression = false
|
|
75
|
+
break
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
if (!wrapsWholeExpression) {
|
|
80
|
+
break
|
|
81
|
+
}
|
|
82
|
+
current = current.slice(1, -1).trim()
|
|
83
|
+
}
|
|
84
|
+
return current
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
const canonicalizeDdlExpressionSql = (value: string): string =>
|
|
88
|
+
stripRedundantOuterParens(
|
|
89
|
+
value
|
|
90
|
+
.trim()
|
|
91
|
+
.replace(/\s+/g, " ")
|
|
92
|
+
.replace(/"[^"]+"\./g, "")
|
|
93
|
+
.replace(/"([A-Za-z_][A-Za-z0-9_]*)"/g, "$1")
|
|
94
|
+
.replace(/\bCOLLATE\b/g, "collate")
|
|
95
|
+
.replace(
|
|
96
|
+
/cast\(((?:'(?:[^']|'')*'|"[^"]+"|[a-zA-Z_][a-zA-Z0-9_]*|\([^()]+\))) as ([^)]+)\)/gi,
|
|
97
|
+
(_, expression: string, target: string) => `${expression}::${target.trim()}`
|
|
98
|
+
)
|
|
99
|
+
)
|
|
100
|
+
|
|
101
|
+
export const normalizeDdlExpressionSql = (expression: DdlExpressionLike): string => {
|
|
102
|
+
const rendered = renderDdlExpressionSql(expression)
|
|
103
|
+
try {
|
|
104
|
+
return canonicalizeDdlExpressionSql(toSql.expr(parse(rendered, "expr")))
|
|
105
|
+
} catch {
|
|
106
|
+
return canonicalizeDdlExpressionSql(rendered)
|
|
107
|
+
}
|
|
108
|
+
}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import * as Table from "
|
|
2
|
-
import type { AnyColumnDefinition } from "
|
|
1
|
+
import * as Table from "../../internal/table.js"
|
|
2
|
+
import type { AnyColumnDefinition } from "../../internal/column-state.js"
|
|
3
3
|
import { normalizeDdlExpressionSql } from "./schema-ddl.js"
|
|
4
|
-
import type { TableOptionSpec } from "
|
|
5
|
-
import type { EnumDefinition } from "../
|
|
6
|
-
import { EnumTypeId } from "../
|
|
4
|
+
import type { TableOptionSpec } from "../../internal/table-options.js"
|
|
5
|
+
import type { EnumDefinition } from "../schema-management.js"
|
|
6
|
+
import { EnumTypeId } from "../schema-management.js"
|
|
7
7
|
|
|
8
8
|
export interface EnumModel {
|
|
9
9
|
readonly kind: "enum"
|
|
@@ -88,7 +88,13 @@ export const toTableModel = (table: Table.AnyTable): TableModel => {
|
|
|
88
88
|
}
|
|
89
89
|
}
|
|
90
90
|
|
|
91
|
-
export const toEnumModel =
|
|
91
|
+
export const toEnumModel = <
|
|
92
|
+
Name extends string,
|
|
93
|
+
Values extends readonly [string, ...string[]],
|
|
94
|
+
SchemaName extends string | undefined
|
|
95
|
+
>(
|
|
96
|
+
definition: EnumDefinition<Name, Values, SchemaName>
|
|
97
|
+
): EnumModel => ({
|
|
92
98
|
kind: "enum",
|
|
93
99
|
schemaName: definition.schemaName,
|
|
94
100
|
name: definition.name,
|
|
@@ -1,14 +1,19 @@
|
|
|
1
|
-
import * as Query from "
|
|
2
|
-
import * as Expression from "
|
|
3
|
-
import * as Table from "
|
|
4
|
-
import * as QueryAst from "
|
|
5
|
-
import type { RenderState, SqlDialect } from "
|
|
6
|
-
import * as ExpressionAst from "
|
|
7
|
-
import * as JsonPath from "
|
|
8
|
-
import {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
1
|
+
import * as Query from "../../internal/query.js"
|
|
2
|
+
import * as Expression from "../../internal/scalar.js"
|
|
3
|
+
import * as Table from "../../internal/table.js"
|
|
4
|
+
import * as QueryAst from "../../internal/query-ast.js"
|
|
5
|
+
import type { RenderState, SqlDialect } from "../../internal/dialect.js"
|
|
6
|
+
import * as ExpressionAst from "../../internal/expression-ast.js"
|
|
7
|
+
import * as JsonPath from "../../internal/json/path.js"
|
|
8
|
+
import {
|
|
9
|
+
renderJsonSelectSql,
|
|
10
|
+
renderSelectSql,
|
|
11
|
+
toDriverValue
|
|
12
|
+
} from "../../internal/runtime/driver-value-mapping.js"
|
|
13
|
+
import { flattenSelection, type Projection } from "../../internal/projections.js"
|
|
14
|
+
import { type SelectionValue, validateAggregationSelection } from "../../internal/aggregation-validation.js"
|
|
15
|
+
import * as SchemaExpression from "../../internal/schema-expression.js"
|
|
16
|
+
import type { DdlExpressionLike } from "../../internal/table-options.js"
|
|
12
17
|
|
|
13
18
|
const renderDbType = (
|
|
14
19
|
dialect: SqlDialect,
|
|
@@ -294,11 +299,54 @@ const renderPostgresJsonValue = (
|
|
|
294
299
|
throw new Error("Expected a JSON expression")
|
|
295
300
|
}
|
|
296
301
|
const rendered = renderExpression(value, state, dialect)
|
|
302
|
+
const ast = (value as Expression.Any & {
|
|
303
|
+
readonly [ExpressionAst.TypeId]: ExpressionAst.Any
|
|
304
|
+
})[ExpressionAst.TypeId]
|
|
305
|
+
if (ast.kind === "literal") {
|
|
306
|
+
return `cast(${rendered} as jsonb)`
|
|
307
|
+
}
|
|
297
308
|
return value[Expression.TypeId].dbType.kind === "jsonb"
|
|
298
309
|
? rendered
|
|
299
310
|
: `cast(${rendered} as jsonb)`
|
|
300
311
|
}
|
|
301
312
|
|
|
313
|
+
const expressionDriverContext = (
|
|
314
|
+
expression: Expression.Any,
|
|
315
|
+
state: RenderState,
|
|
316
|
+
dialect: SqlDialect
|
|
317
|
+
) => ({
|
|
318
|
+
dialect: dialect.name,
|
|
319
|
+
valueMappings: state.valueMappings,
|
|
320
|
+
dbType: expression[Expression.TypeId].dbType,
|
|
321
|
+
runtimeSchema: expression[Expression.TypeId].runtimeSchema,
|
|
322
|
+
driverValueMapping: expression[Expression.TypeId].driverValueMapping
|
|
323
|
+
})
|
|
324
|
+
|
|
325
|
+
const renderJsonInputExpression = (
|
|
326
|
+
expression: Expression.Any,
|
|
327
|
+
state: RenderState,
|
|
328
|
+
dialect: SqlDialect
|
|
329
|
+
): string =>
|
|
330
|
+
renderJsonSelectSql(
|
|
331
|
+
renderExpression(expression, state, dialect),
|
|
332
|
+
expressionDriverContext(expression, state, dialect)
|
|
333
|
+
)
|
|
334
|
+
|
|
335
|
+
const encodeArrayValues = (
|
|
336
|
+
values: readonly unknown[],
|
|
337
|
+
column: Table.AnyTable[typeof Table.TypeId]["fields"][string],
|
|
338
|
+
state: RenderState,
|
|
339
|
+
dialect: SqlDialect
|
|
340
|
+
): readonly unknown[] =>
|
|
341
|
+
values.map((value) =>
|
|
342
|
+
toDriverValue(value, {
|
|
343
|
+
dialect: dialect.name,
|
|
344
|
+
valueMappings: state.valueMappings,
|
|
345
|
+
dbType: column.metadata.dbType,
|
|
346
|
+
runtimeSchema: column.schema,
|
|
347
|
+
driverValueMapping: column.metadata.driverValueMapping
|
|
348
|
+
}))
|
|
349
|
+
|
|
302
350
|
const renderPostgresJsonKind = (
|
|
303
351
|
value: Expression.Any
|
|
304
352
|
): "json" | "jsonb" => value[Expression.TypeId].dbType.kind === "jsonb" ? "jsonb" : "json"
|
|
@@ -460,7 +508,7 @@ const renderJsonExpression = (
|
|
|
460
508
|
: []
|
|
461
509
|
const renderedEntries = entries.flatMap((entry) => [
|
|
462
510
|
dialect.renderLiteral(entry.key, state),
|
|
463
|
-
|
|
511
|
+
renderJsonInputExpression(entry.value, state, dialect)
|
|
464
512
|
])
|
|
465
513
|
if (dialect.name === "postgres") {
|
|
466
514
|
return `${postgresExpressionKind === "jsonb" ? "jsonb" : "json"}_build_object(${renderedEntries.join(", ")})`
|
|
@@ -474,7 +522,7 @@ const renderJsonExpression = (
|
|
|
474
522
|
const values = Array.isArray((ast as { readonly values?: readonly Expression.Any[] }).values)
|
|
475
523
|
? (ast as { readonly values: readonly Expression.Any[] }).values
|
|
476
524
|
: []
|
|
477
|
-
const renderedValues = values.map((value) =>
|
|
525
|
+
const renderedValues = values.map((value) => renderJsonInputExpression(value, state, dialect)).join(", ")
|
|
478
526
|
if (dialect.name === "postgres") {
|
|
479
527
|
return `${postgresExpressionKind === "jsonb" ? "jsonb" : "json"}_build_array(${renderedValues})`
|
|
480
528
|
}
|
|
@@ -488,7 +536,7 @@ const renderJsonExpression = (
|
|
|
488
536
|
return undefined
|
|
489
537
|
}
|
|
490
538
|
if (dialect.name === "postgres") {
|
|
491
|
-
return `to_json(${
|
|
539
|
+
return `to_json(${renderJsonInputExpression(base, state, dialect)})`
|
|
492
540
|
}
|
|
493
541
|
if (dialect.name === "mysql") {
|
|
494
542
|
return `cast(${renderExpression(base, state, dialect)} as json)`
|
|
@@ -499,7 +547,7 @@ const renderJsonExpression = (
|
|
|
499
547
|
return undefined
|
|
500
548
|
}
|
|
501
549
|
if (dialect.name === "postgres") {
|
|
502
|
-
return `to_jsonb(${
|
|
550
|
+
return `to_jsonb(${renderJsonInputExpression(base, state, dialect)})`
|
|
503
551
|
}
|
|
504
552
|
if (dialect.name === "mysql") {
|
|
505
553
|
return `cast(${renderExpression(base, state, dialect)} as json)`
|
|
@@ -753,7 +801,7 @@ const renderSelectionList = (
|
|
|
753
801
|
const flattened = flattenSelection(selection)
|
|
754
802
|
const projections = selectionProjections(selection)
|
|
755
803
|
const sql = flattened.map(({ expression, alias }) =>
|
|
756
|
-
`${renderExpression(expression, state, dialect)} as ${dialect.quoteIdentifier(alias)}`).join(", ")
|
|
804
|
+
`${renderSelectSql(renderExpression(expression, state, dialect), expressionDriverContext(expression, state, dialect))} as ${dialect.quoteIdentifier(alias)}`).join(", ")
|
|
757
805
|
return {
|
|
758
806
|
sql,
|
|
759
807
|
projections
|
|
@@ -818,7 +866,7 @@ export const renderQueryAst = (
|
|
|
818
866
|
case "set": {
|
|
819
867
|
const setAst = ast as QueryAst.Ast<Record<string, unknown>, any, "set">
|
|
820
868
|
const base = renderQueryAst(
|
|
821
|
-
Query.getAst(setAst.setBase as Query.
|
|
869
|
+
Query.getAst(setAst.setBase as Query.Plan.Any) as QueryAst.Ast<
|
|
822
870
|
Record<string, unknown>,
|
|
823
871
|
any,
|
|
824
872
|
QueryAst.QueryStatement
|
|
@@ -831,7 +879,7 @@ export const renderQueryAst = (
|
|
|
831
879
|
`(${base.sql})`,
|
|
832
880
|
...(setAst.setOperations ?? []).map((entry) => {
|
|
833
881
|
const rendered = renderQueryAst(
|
|
834
|
-
Query.getAst(entry.query as Query.
|
|
882
|
+
Query.getAst(entry.query as Query.Plan.Any) as QueryAst.Ast<
|
|
835
883
|
Record<string, unknown>,
|
|
836
884
|
any,
|
|
837
885
|
QueryAst.QueryStatement
|
|
@@ -858,7 +906,7 @@ export const renderQueryAst = (
|
|
|
858
906
|
} else if (insertAst.insertSource?.kind === "query") {
|
|
859
907
|
const columns = insertAst.insertSource.columns.map((column) => dialect.quoteIdentifier(column)).join(", ")
|
|
860
908
|
const renderedQuery = renderQueryAst(
|
|
861
|
-
Query.getAst(insertAst.insertSource.query as Query.
|
|
909
|
+
Query.getAst(insertAst.insertSource.query as Query.Plan.Any) as QueryAst.Ast<
|
|
862
910
|
Record<string, unknown>,
|
|
863
911
|
any,
|
|
864
912
|
QueryAst.QueryStatement
|
|
@@ -874,14 +922,18 @@ export const renderQueryAst = (
|
|
|
874
922
|
const table = targetSource.source as Table.AnyTable
|
|
875
923
|
const fields = table[Table.TypeId].fields
|
|
876
924
|
const rendered = unnestSource.values.map((entry) =>
|
|
877
|
-
`cast(${dialect.renderLiteral(entry.values, state)} as ${renderCastType(dialect, fields[entry.columnName]!.metadata.dbType)}[])`
|
|
925
|
+
`cast(${dialect.renderLiteral(encodeArrayValues(entry.values, fields[entry.columnName]!, state, dialect), state)} as ${renderCastType(dialect, fields[entry.columnName]!.metadata.dbType)}[])`
|
|
878
926
|
).join(", ")
|
|
879
927
|
sql += ` (${columns}) select * from unnest(${rendered})`
|
|
880
928
|
} else {
|
|
881
929
|
const rowCount = unnestSource.values[0]?.values.length ?? 0
|
|
882
930
|
const rows = Array.from({ length: rowCount }, (_, index) =>
|
|
883
931
|
`(${unnestSource.values.map((entry) =>
|
|
884
|
-
dialect.renderLiteral(
|
|
932
|
+
dialect.renderLiteral(
|
|
933
|
+
entry.values[index],
|
|
934
|
+
state,
|
|
935
|
+
(targetSource.source as Table.AnyTable)[Table.TypeId].fields[entry.columnName]![Expression.TypeId]
|
|
936
|
+
)
|
|
885
937
|
).join(", ")})`
|
|
886
938
|
).join(", ")
|
|
887
939
|
sql += ` (${columns}) values ${rows}`
|
|
@@ -1151,7 +1203,7 @@ const renderSourceReference = (
|
|
|
1151
1203
|
if (typeof source === "object" && source !== null && "kind" in source && (source as { readonly kind?: string }).kind === "cte") {
|
|
1152
1204
|
const cte = source as unknown as {
|
|
1153
1205
|
readonly name: string
|
|
1154
|
-
readonly plan: Query.
|
|
1206
|
+
readonly plan: Query.Plan.Any
|
|
1155
1207
|
readonly recursive?: boolean
|
|
1156
1208
|
}
|
|
1157
1209
|
if (!state.cteNames.has(cte.name)) {
|
|
@@ -1168,7 +1220,7 @@ const renderSourceReference = (
|
|
|
1168
1220
|
if (typeof source === "object" && source !== null && "kind" in source && (source as { readonly kind?: string }).kind === "derived") {
|
|
1169
1221
|
const derived = source as unknown as {
|
|
1170
1222
|
readonly name: string
|
|
1171
|
-
readonly plan: Query.
|
|
1223
|
+
readonly plan: Query.Plan.Any
|
|
1172
1224
|
}
|
|
1173
1225
|
if (!state.cteNames.has(derived.name)) {
|
|
1174
1226
|
// derived tables are inlined, so no CTE registration is needed
|
|
@@ -1178,7 +1230,7 @@ const renderSourceReference = (
|
|
|
1178
1230
|
if (typeof source === "object" && source !== null && "kind" in source && (source as { readonly kind?: string }).kind === "lateral") {
|
|
1179
1231
|
const lateral = source as unknown as {
|
|
1180
1232
|
readonly name: string
|
|
1181
|
-
readonly plan: Query.
|
|
1233
|
+
readonly plan: Query.Plan.Any
|
|
1182
1234
|
}
|
|
1183
1235
|
return `lateral (${renderQueryAst(Query.getAst(lateral.plan) as QueryAst.Ast<Record<string, unknown>, any, QueryAst.QueryStatement>, state, dialect).sql}) as ${dialect.quoteIdentifier(lateral.name)}`
|
|
1184
1236
|
}
|
|
@@ -1253,13 +1305,15 @@ export const renderExpression = (
|
|
|
1253
1305
|
? dialect.quoteIdentifier(ast.columnName)
|
|
1254
1306
|
: `${dialect.quoteIdentifier(ast.tableName)}.${dialect.quoteIdentifier(ast.columnName)}`
|
|
1255
1307
|
case "literal":
|
|
1256
|
-
return dialect.renderLiteral(ast.value, state)
|
|
1308
|
+
return dialect.renderLiteral(ast.value, state, expression[Expression.TypeId])
|
|
1257
1309
|
case "excluded":
|
|
1258
1310
|
return dialect.name === "mysql"
|
|
1259
1311
|
? `values(${dialect.quoteIdentifier(ast.columnName)})`
|
|
1260
1312
|
: `excluded.${dialect.quoteIdentifier(ast.columnName)}`
|
|
1261
1313
|
case "cast":
|
|
1262
1314
|
return `cast(${renderExpression(ast.value, state, dialect)} as ${renderCastType(dialect, ast.target)})`
|
|
1315
|
+
case "collate":
|
|
1316
|
+
return `(${renderExpression(ast.value, state, dialect)} collate ${ast.collation.map((segment) => dialect.quoteIdentifier(segment)).join(".")})`
|
|
1263
1317
|
case "function":
|
|
1264
1318
|
return renderFunctionCall(ast.name, Array.isArray(ast.args) ? ast.args : [], state, dialect)
|
|
1265
1319
|
case "eq":
|