effect-qb 0.13.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/README.md +6 -1431
- package/dist/mysql.js +61945 -3611
- package/dist/postgres/metadata.js +2818 -0
- package/dist/postgres.js +9942 -5591
- package/package.json +21 -10
- 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 +119 -56
- package/src/internal/column.ts +387 -149
- package/src/internal/datatypes/define.d.ts +17 -0
- package/src/internal/datatypes/define.ts +18 -34
- 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 +173 -38
- package/src/internal/expression-ast.ts +19 -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 +171 -0
- 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} +13 -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} +111 -32
- package/src/internal/predicate/formula.d.ts +35 -0
- package/src/internal/{predicate-formula.ts → predicate/formula.ts} +32 -20
- 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 +273 -0
- package/src/internal/predicate/runtime.d.ts +31 -0
- package/src/internal/predicate/runtime.ts +679 -0
- 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 +767 -275
- package/src/internal/renderer.ts +7 -21
- package/src/internal/row-set.d.ts +53 -0
- package/src/internal/{plan.ts → row-set.ts} +23 -11
- package/src/internal/{runtime-normalize.ts → runtime/normalize.ts} +9 -31
- package/src/internal/{runtime-schema.ts → runtime/schema.ts} +84 -55
- 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-derivation.ts +93 -21
- package/src/internal/schema-expression.d.ts +18 -0
- package/src/internal/schema-expression.ts +75 -0
- package/src/internal/table-options.d.ts +94 -0
- package/src/internal/table-options.ts +94 -8
- package/src/internal/table.d.ts +173 -0
- package/src/internal/table.ts +135 -54
- package/src/mysql/column.ts +95 -18
- package/src/mysql/datatypes/index.ts +58 -3
- 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 -3
- package/src/mysql/function/index.ts +1 -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/mysql/internal/dsl.ts +6115 -0
- 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 -86
- 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 +30 -0
- package/src/postgres/column.ts +178 -20
- package/src/postgres/datatypes/index.d.ts +515 -0
- package/src/postgres/datatypes/index.ts +49 -5
- 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 +20 -2
- package/src/postgres/function/index.ts +1 -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/query-factory.ts → postgres/internal/dsl.ts} +1568 -2120
- package/src/{internal/postgres-renderer.ts → postgres/internal/renderer.ts} +6 -6
- package/src/postgres/internal/schema-ddl.ts +108 -0
- package/src/postgres/internal/schema-model.ts +150 -0
- package/src/{internal → postgres/internal}/sql-expression-renderer.ts +112 -46
- package/src/postgres/json.ts +493 -0
- package/src/postgres/metadata.ts +31 -0
- package/src/postgres/query.ts +113 -86
- package/src/postgres/renderer.ts +3 -13
- package/src/postgres/schema-expression.ts +17 -0
- package/src/postgres/schema-management.ts +204 -0
- package/src/postgres/schema.ts +35 -0
- package/src/postgres/table.ts +316 -42
- package/src/postgres/type.ts +31 -0
- package/src/postgres.ts +20 -4
- package/CHANGELOG.md +0 -134
- package/src/internal/expression.ts +0 -327
- package/src/internal/predicate-normalize.ts +0 -202
- package/src/mysql/function/json.ts +0 -4
- package/src/mysql/private/query.ts +0 -13
- package/src/postgres/function/json.ts +0 -4
- package/src/postgres/private/query.ts +0 -13
- /package/src/internal/{predicate-atom.ts → predicate/atom.ts} +0 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import * as Query from "
|
|
2
|
-
import { type RenderState } from "
|
|
3
|
-
import { postgresDialect } from "./
|
|
4
|
-
import { type Projection } from "
|
|
1
|
+
import * as Query from "../../internal/query.js"
|
|
2
|
+
import { type RenderState } from "../../internal/dialect.js"
|
|
3
|
+
import { postgresDialect } from "./dialect.js"
|
|
4
|
+
import { type Projection } from "../../internal/projections.js"
|
|
5
5
|
import { renderQueryAst } from "./sql-expression-renderer.js"
|
|
6
6
|
|
|
7
7
|
/**
|
|
@@ -19,7 +19,7 @@ export interface PostgresRenderResult {
|
|
|
19
19
|
/**
|
|
20
20
|
* Renders the current query AST into Postgres SQL plus bind parameters.
|
|
21
21
|
*/
|
|
22
|
-
export const renderPostgresPlan = <PlanValue extends Query.
|
|
22
|
+
export const renderPostgresPlan = <PlanValue extends Query.Plan.Any>(
|
|
23
23
|
plan: Query.DialectCompatiblePlan<PlanValue, "postgres">
|
|
24
24
|
): PostgresRenderResult => {
|
|
25
25
|
const state: RenderState = {
|
|
@@ -28,7 +28,7 @@ export const renderPostgresPlan = <PlanValue extends Query.QueryPlan<any, any, a
|
|
|
28
28
|
cteNames: new Set<string>()
|
|
29
29
|
}
|
|
30
30
|
const rendered = renderQueryAst(
|
|
31
|
-
Query.getAst(plan as Query.
|
|
31
|
+
Query.getAst(plan as Query.Plan.Any) as any,
|
|
32
32
|
state,
|
|
33
33
|
postgresDialect
|
|
34
34
|
)
|
|
@@ -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
|
+
}
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
import * as Table from "../../internal/table.js"
|
|
2
|
+
import type { AnyColumnDefinition } from "../../internal/column-state.js"
|
|
3
|
+
import { normalizeDdlExpressionSql } from "./schema-ddl.js"
|
|
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
|
+
|
|
8
|
+
export interface EnumModel {
|
|
9
|
+
readonly kind: "enum"
|
|
10
|
+
readonly schemaName?: string
|
|
11
|
+
readonly name: string
|
|
12
|
+
readonly values: readonly string[]
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export interface ColumnModel {
|
|
16
|
+
readonly name: string
|
|
17
|
+
readonly ddlType: string
|
|
18
|
+
readonly dbTypeKind: string
|
|
19
|
+
readonly typeKind?: string
|
|
20
|
+
readonly typeSchema?: string
|
|
21
|
+
readonly nullable: boolean
|
|
22
|
+
readonly hasDefault: boolean
|
|
23
|
+
readonly generated: boolean
|
|
24
|
+
readonly defaultSql?: string
|
|
25
|
+
readonly generatedSql?: string
|
|
26
|
+
readonly identity?: {
|
|
27
|
+
readonly generation: "always" | "byDefault"
|
|
28
|
+
}
|
|
29
|
+
readonly column?: AnyColumnDefinition
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export interface TableModel {
|
|
33
|
+
readonly kind: "table"
|
|
34
|
+
readonly schemaName?: string
|
|
35
|
+
readonly name: string
|
|
36
|
+
readonly columns: readonly ColumnModel[]
|
|
37
|
+
readonly options: readonly TableOptionSpec[]
|
|
38
|
+
readonly table?: Table.AnyTable
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export interface SchemaModel {
|
|
42
|
+
readonly dialect: "postgres"
|
|
43
|
+
readonly enums: readonly EnumModel[]
|
|
44
|
+
readonly tables: readonly TableModel[]
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export const isTableDefinition = (value: unknown): value is Table.AnyTable =>
|
|
48
|
+
value !== null &&
|
|
49
|
+
(typeof value === "object" || typeof value === "function") &&
|
|
50
|
+
Table.TypeId in value
|
|
51
|
+
|
|
52
|
+
export const isEnumDefinition = (value: unknown): value is EnumDefinition =>
|
|
53
|
+
typeof value === "object" && value !== null && EnumTypeId in value
|
|
54
|
+
|
|
55
|
+
export const toTableModel = (table: Table.AnyTable): TableModel => {
|
|
56
|
+
const state = table[Table.TypeId]
|
|
57
|
+
const fields = state.fields as Record<string, AnyColumnDefinition>
|
|
58
|
+
const columns = Object.entries(fields).map(([name, column]) => {
|
|
59
|
+
const metadata = column.metadata
|
|
60
|
+
const enumDefinition = metadata.enum
|
|
61
|
+
const ddlType = metadata.ddlType ?? metadata.dbType.kind
|
|
62
|
+
return {
|
|
63
|
+
name,
|
|
64
|
+
ddlType,
|
|
65
|
+
dbTypeKind: enumDefinition?.name ?? column.metadata.dbType.kind,
|
|
66
|
+
typeKind: enumDefinition === undefined ? undefined : "e",
|
|
67
|
+
typeSchema: enumDefinition?.schemaName,
|
|
68
|
+
nullable: column.metadata.nullable,
|
|
69
|
+
hasDefault: column.metadata.hasDefault,
|
|
70
|
+
generated: column.metadata.generated,
|
|
71
|
+
defaultSql: column.metadata.defaultValue === undefined
|
|
72
|
+
? undefined
|
|
73
|
+
: normalizeDdlExpressionSql(column.metadata.defaultValue),
|
|
74
|
+
generatedSql: column.metadata.generatedValue === undefined
|
|
75
|
+
? undefined
|
|
76
|
+
: normalizeDdlExpressionSql(column.metadata.generatedValue),
|
|
77
|
+
identity: column.metadata.identity,
|
|
78
|
+
column
|
|
79
|
+
}
|
|
80
|
+
}) satisfies ReadonlyArray<ColumnModel>
|
|
81
|
+
return {
|
|
82
|
+
kind: "table",
|
|
83
|
+
schemaName: state.schemaName,
|
|
84
|
+
name: state.baseName,
|
|
85
|
+
columns,
|
|
86
|
+
options: table[Table.OptionsSymbol],
|
|
87
|
+
table
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
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 => ({
|
|
98
|
+
kind: "enum",
|
|
99
|
+
schemaName: definition.schemaName,
|
|
100
|
+
name: definition.name,
|
|
101
|
+
values: [...definition.values]
|
|
102
|
+
})
|
|
103
|
+
|
|
104
|
+
const enumModelsOfTable = (table: Table.AnyTable): readonly EnumModel[] => {
|
|
105
|
+
const state = table[Table.TypeId]
|
|
106
|
+
const fields = state.fields as Record<string, AnyColumnDefinition>
|
|
107
|
+
return Object.values(fields)
|
|
108
|
+
.flatMap((column) => column.metadata.enum === undefined
|
|
109
|
+
? []
|
|
110
|
+
: [{
|
|
111
|
+
kind: "enum" as const,
|
|
112
|
+
schemaName: column.metadata.enum.schemaName,
|
|
113
|
+
name: column.metadata.enum.name,
|
|
114
|
+
values: [...column.metadata.enum.values]
|
|
115
|
+
} satisfies EnumModel
|
|
116
|
+
])
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
export const fromDiscoveredValues = (values: ReadonlyArray<unknown>): SchemaModel => {
|
|
120
|
+
const tables = values.filter(isTableDefinition).map(toTableModel)
|
|
121
|
+
const enums = new Map<string, EnumModel>()
|
|
122
|
+
for (const value of values) {
|
|
123
|
+
if (isEnumDefinition(value)) {
|
|
124
|
+
enums.set(enumKey(value.schemaName, value.name), toEnumModel(value))
|
|
125
|
+
} else if (isTableDefinition(value)) {
|
|
126
|
+
for (const enumModel of enumModelsOfTable(value)) {
|
|
127
|
+
const key = enumKey(enumModel.schemaName, enumModel.name)
|
|
128
|
+
const existing = enums.get(key)
|
|
129
|
+
if (existing === undefined) {
|
|
130
|
+
enums.set(key, enumModel)
|
|
131
|
+
continue
|
|
132
|
+
}
|
|
133
|
+
if (JSON.stringify(existing.values) !== JSON.stringify(enumModel.values)) {
|
|
134
|
+
throw new Error(`Conflicting enum definitions discovered for '${key}'`)
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
return {
|
|
140
|
+
dialect: "postgres",
|
|
141
|
+
enums: [...enums.values()],
|
|
142
|
+
tables
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
export const tableKey = (schemaName: string | undefined, name: string): string =>
|
|
147
|
+
`${schemaName ?? "public"}.${name}`
|
|
148
|
+
|
|
149
|
+
export const enumKey = (schemaName: string | undefined, name: string): string =>
|
|
150
|
+
`${schemaName ?? "public"}.${name}`
|
|
@@ -1,12 +1,14 @@
|
|
|
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 { flattenSelection, type Projection } from "
|
|
9
|
-
import { type SelectionValue, validateAggregationSelection } from "
|
|
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 { flattenSelection, type Projection } from "../../internal/projections.js"
|
|
9
|
+
import { type SelectionValue, validateAggregationSelection } from "../../internal/aggregation-validation.js"
|
|
10
|
+
import * as SchemaExpression from "../../internal/schema-expression.js"
|
|
11
|
+
import type { DdlExpressionLike } from "../../internal/table-options.js"
|
|
10
12
|
|
|
11
13
|
const renderDbType = (
|
|
12
14
|
dialect: SqlDialect,
|
|
@@ -44,6 +46,15 @@ const renderCastType = (
|
|
|
44
46
|
}
|
|
45
47
|
}
|
|
46
48
|
|
|
49
|
+
const renderDdlExpression = (
|
|
50
|
+
expression: DdlExpressionLike,
|
|
51
|
+
state: RenderState,
|
|
52
|
+
dialect: SqlDialect
|
|
53
|
+
): string =>
|
|
54
|
+
SchemaExpression.isSchemaExpression(expression)
|
|
55
|
+
? SchemaExpression.render(expression)
|
|
56
|
+
: renderExpression(expression, state, dialect)
|
|
57
|
+
|
|
47
58
|
const renderColumnDefinition = (
|
|
48
59
|
dialect: SqlDialect,
|
|
49
60
|
state: RenderState,
|
|
@@ -52,12 +63,14 @@ const renderColumnDefinition = (
|
|
|
52
63
|
): string => {
|
|
53
64
|
const clauses = [
|
|
54
65
|
dialect.quoteIdentifier(columnName),
|
|
55
|
-
renderDbType(dialect, column.metadata.dbType)
|
|
66
|
+
column.metadata.ddlType ?? renderDbType(dialect, column.metadata.dbType)
|
|
56
67
|
]
|
|
57
|
-
if (column.metadata.
|
|
58
|
-
clauses.push(`generated
|
|
68
|
+
if (column.metadata.identity) {
|
|
69
|
+
clauses.push(`generated ${column.metadata.identity.generation === "byDefault" ? "by default" : "always"} as identity`)
|
|
70
|
+
} else if (column.metadata.generatedValue) {
|
|
71
|
+
clauses.push(`generated always as (${renderDdlExpression(column.metadata.generatedValue, state, dialect)}) stored`)
|
|
59
72
|
} else if (column.metadata.defaultValue) {
|
|
60
|
-
clauses.push(`default ${
|
|
73
|
+
clauses.push(`default ${renderDdlExpression(column.metadata.defaultValue, state, dialect)}`)
|
|
61
74
|
}
|
|
62
75
|
if (!column.metadata.nullable) {
|
|
63
76
|
clauses.push("not null")
|
|
@@ -65,14 +78,6 @@ const renderColumnDefinition = (
|
|
|
65
78
|
return clauses.join(" ")
|
|
66
79
|
}
|
|
67
80
|
|
|
68
|
-
const renderCheckPredicate = (
|
|
69
|
-
predicate: Expression.Any,
|
|
70
|
-
state: RenderState,
|
|
71
|
-
dialect: SqlDialect
|
|
72
|
-
): string => {
|
|
73
|
-
return renderExpression(predicate, state, dialect)
|
|
74
|
-
}
|
|
75
|
-
|
|
76
81
|
const renderCreateTableSql = (
|
|
77
82
|
targetSource: QueryAst.FromClause,
|
|
78
83
|
state: RenderState,
|
|
@@ -87,21 +92,21 @@ const renderCreateTableSql = (
|
|
|
87
92
|
for (const option of table[Table.OptionsSymbol]) {
|
|
88
93
|
switch (option.kind) {
|
|
89
94
|
case "primaryKey":
|
|
90
|
-
definitions.push(`primary key (${option.columns.map((column) => dialect.quoteIdentifier(column)).join(", ")})`)
|
|
95
|
+
definitions.push(`${option.name ? `constraint ${dialect.quoteIdentifier(option.name)} ` : ""}primary key (${option.columns.map((column) => dialect.quoteIdentifier(column)).join(", ")})${option.deferrable ? ` deferrable${option.initiallyDeferred ? " initially deferred" : ""}` : ""}`)
|
|
91
96
|
break
|
|
92
97
|
case "unique":
|
|
93
|
-
definitions.push(`unique (${option.columns.map((column) => dialect.quoteIdentifier(column)).join(", ")})`)
|
|
98
|
+
definitions.push(`${option.name ? `constraint ${dialect.quoteIdentifier(option.name)} ` : ""}unique${option.nullsNotDistinct ? " nulls not distinct" : ""} (${option.columns.map((column) => dialect.quoteIdentifier(column)).join(", ")})${option.deferrable ? ` deferrable${option.initiallyDeferred ? " initially deferred" : ""}` : ""}`)
|
|
94
99
|
break
|
|
95
100
|
case "foreignKey": {
|
|
96
101
|
const reference = option.references()
|
|
97
102
|
definitions.push(
|
|
98
|
-
`foreign key (${option.columns.map((column) => dialect.quoteIdentifier(column)).join(", ")}) references ${dialect.renderTableReference(reference.tableName, reference.tableName, reference.schemaName)} (${reference.columns.map((column) => dialect.quoteIdentifier(column)).join(", ")})`
|
|
103
|
+
`${option.name ? `constraint ${dialect.quoteIdentifier(option.name)} ` : ""}foreign key (${option.columns.map((column) => dialect.quoteIdentifier(column)).join(", ")}) references ${dialect.renderTableReference(reference.tableName, reference.tableName, reference.schemaName)} (${reference.columns.map((column) => dialect.quoteIdentifier(column)).join(", ")})${option.onDelete ? ` on delete ${option.onDelete.replace(/[A-Z]/g, (value) => ` ${value.toLowerCase()}`).trim()}` : ""}${option.onUpdate ? ` on update ${option.onUpdate.replace(/[A-Z]/g, (value) => ` ${value.toLowerCase()}`).trim()}` : ""}${option.deferrable ? ` deferrable${option.initiallyDeferred ? " initially deferred" : ""}` : ""}`
|
|
99
104
|
)
|
|
100
105
|
break
|
|
101
106
|
}
|
|
102
107
|
case "check":
|
|
103
108
|
definitions.push(
|
|
104
|
-
`constraint ${dialect.quoteIdentifier(option.name)} check (${
|
|
109
|
+
`constraint ${dialect.quoteIdentifier(option.name)} check (${renderDdlExpression(option.predicate, state, dialect)})${option.noInherit ? " no inherit" : ""}`
|
|
105
110
|
)
|
|
106
111
|
break
|
|
107
112
|
case "index":
|
|
@@ -258,6 +263,12 @@ const renderPostgresJsonPathArray = (
|
|
|
258
263
|
}
|
|
259
264
|
}).join(", ")}]`
|
|
260
265
|
|
|
266
|
+
const renderPostgresTextLiteral = (
|
|
267
|
+
value: string,
|
|
268
|
+
state: RenderState,
|
|
269
|
+
dialect: SqlDialect
|
|
270
|
+
): string => `cast(${dialect.renderLiteral(value, state)} as text)`
|
|
271
|
+
|
|
261
272
|
const renderPostgresJsonAccessStep = (
|
|
262
273
|
segment: JsonPath.AnySegment,
|
|
263
274
|
textMode: boolean,
|
|
@@ -288,6 +299,10 @@ const renderPostgresJsonValue = (
|
|
|
288
299
|
: `cast(${rendered} as jsonb)`
|
|
289
300
|
}
|
|
290
301
|
|
|
302
|
+
const renderPostgresJsonKind = (
|
|
303
|
+
value: Expression.Any
|
|
304
|
+
): "json" | "jsonb" => value[Expression.TypeId].dbType.kind === "jsonb" ? "jsonb" : "json"
|
|
305
|
+
|
|
291
306
|
const renderJsonOpaquePath = (
|
|
292
307
|
value: unknown,
|
|
293
308
|
state: RenderState,
|
|
@@ -311,6 +326,24 @@ const renderFunctionCall = (
|
|
|
311
326
|
state: RenderState,
|
|
312
327
|
dialect: SqlDialect
|
|
313
328
|
): string => {
|
|
329
|
+
if (name === "array") {
|
|
330
|
+
return `ARRAY[${args.map((arg) => renderExpression(arg, state, dialect)).join(", ")}]`
|
|
331
|
+
}
|
|
332
|
+
if (name === "extract" && args.length === 2) {
|
|
333
|
+
const field = args[0]
|
|
334
|
+
const source = args[1]
|
|
335
|
+
if (field === undefined) {
|
|
336
|
+
throw new Error("Unsupported SQL extract expression")
|
|
337
|
+
}
|
|
338
|
+
if (source === undefined) {
|
|
339
|
+
throw new Error("Unsupported SQL extract expression")
|
|
340
|
+
}
|
|
341
|
+
const fieldRuntime = isExpression(field) && field[Expression.TypeId].dbType.kind === "text" && typeof field[Expression.TypeId].runtime === "string"
|
|
342
|
+
? field[Expression.TypeId].runtime
|
|
343
|
+
: undefined
|
|
344
|
+
const renderedField = fieldRuntime ?? renderExpression(field, state, dialect)
|
|
345
|
+
return `extract(${renderedField} from ${renderExpression(source, state, dialect)})`
|
|
346
|
+
}
|
|
314
347
|
const renderedArgs = args.map((arg) => renderExpression(arg, state, dialect)).join(", ")
|
|
315
348
|
if (args.length === 0) {
|
|
316
349
|
switch (name) {
|
|
@@ -328,6 +361,7 @@ const renderFunctionCall = (
|
|
|
328
361
|
}
|
|
329
362
|
|
|
330
363
|
const renderJsonExpression = (
|
|
364
|
+
expression: Expression.Any,
|
|
331
365
|
ast: Record<string, unknown>,
|
|
332
366
|
state: RenderState,
|
|
333
367
|
dialect: SqlDialect
|
|
@@ -340,6 +374,12 @@ const renderJsonExpression = (
|
|
|
340
374
|
const base = extractJsonBase(ast)
|
|
341
375
|
const segments = extractJsonPathSegments(ast)
|
|
342
376
|
const exact = segments.every((segment) => segment.kind === "key" || segment.kind === "index")
|
|
377
|
+
const postgresExpressionKind = dialect.name === "postgres" && isJsonExpression(expression)
|
|
378
|
+
? renderPostgresJsonKind(expression)
|
|
379
|
+
: undefined
|
|
380
|
+
const postgresBaseKind = dialect.name === "postgres" && isJsonExpression(base)
|
|
381
|
+
? renderPostgresJsonKind(base)
|
|
382
|
+
: undefined
|
|
343
383
|
|
|
344
384
|
switch (kind) {
|
|
345
385
|
case "jsonGet":
|
|
@@ -363,7 +403,7 @@ const renderJsonExpression = (
|
|
|
363
403
|
}
|
|
364
404
|
const jsonPathLiteral = dialect.renderLiteral(renderJsonPathStringLiteral(segments), state)
|
|
365
405
|
const queried = `jsonb_path_query_first(${renderPostgresJsonValue(base, state, dialect)}, ${jsonPathLiteral})`
|
|
366
|
-
return textMode ? `
|
|
406
|
+
return textMode ? `(${queried} #>> '{}')` : queried
|
|
367
407
|
}
|
|
368
408
|
if (dialect.name === "mysql") {
|
|
369
409
|
const extracted = `json_extract(${baseSql}, ${renderMySqlJsonPath(segments, state, dialect)})`
|
|
@@ -387,12 +427,12 @@ const renderJsonExpression = (
|
|
|
387
427
|
}
|
|
388
428
|
if (dialect.name === "postgres") {
|
|
389
429
|
if (kind === "jsonHasAnyKeys") {
|
|
390
|
-
return `(${baseSql} ?| ${
|
|
430
|
+
return `(${baseSql} ?| array[${keys.map((key) => renderPostgresTextLiteral(String(key), state, dialect)).join(", ")}])`
|
|
391
431
|
}
|
|
392
432
|
if (kind === "jsonHasAllKeys") {
|
|
393
|
-
return `(${baseSql} ?& ${
|
|
433
|
+
return `(${baseSql} ?& array[${keys.map((key) => renderPostgresTextLiteral(String(key), state, dialect)).join(", ")}])`
|
|
394
434
|
}
|
|
395
|
-
return `(${baseSql} ? ${
|
|
435
|
+
return `(${baseSql} ? ${renderPostgresTextLiteral(String(keys[0]!), state, dialect)})`
|
|
396
436
|
}
|
|
397
437
|
if (dialect.name === "mysql") {
|
|
398
438
|
const mode = kind === "jsonHasAllKeys" ? "all" : "one"
|
|
@@ -423,7 +463,7 @@ const renderJsonExpression = (
|
|
|
423
463
|
renderExpression(entry.value, state, dialect)
|
|
424
464
|
])
|
|
425
465
|
if (dialect.name === "postgres") {
|
|
426
|
-
return
|
|
466
|
+
return `${postgresExpressionKind === "jsonb" ? "jsonb" : "json"}_build_object(${renderedEntries.join(", ")})`
|
|
427
467
|
}
|
|
428
468
|
if (dialect.name === "mysql") {
|
|
429
469
|
return `json_object(${renderedEntries.join(", ")})`
|
|
@@ -436,7 +476,7 @@ const renderJsonExpression = (
|
|
|
436
476
|
: []
|
|
437
477
|
const renderedValues = values.map((value) => renderExpression(value, state, dialect)).join(", ")
|
|
438
478
|
if (dialect.name === "postgres") {
|
|
439
|
-
return
|
|
479
|
+
return `${postgresExpressionKind === "jsonb" ? "jsonb" : "json"}_build_array(${renderedValues})`
|
|
440
480
|
}
|
|
441
481
|
if (dialect.name === "mysql") {
|
|
442
482
|
return `json_array(${renderedValues})`
|
|
@@ -470,7 +510,8 @@ const renderJsonExpression = (
|
|
|
470
510
|
return undefined
|
|
471
511
|
}
|
|
472
512
|
if (dialect.name === "postgres") {
|
|
473
|
-
|
|
513
|
+
const baseSql = renderExpression(base, state, dialect)
|
|
514
|
+
return `${postgresBaseKind === "jsonb" ? "jsonb" : "json"}_typeof(${baseSql})`
|
|
474
515
|
}
|
|
475
516
|
if (dialect.name === "mysql") {
|
|
476
517
|
return `json_type(${renderExpression(base, state, dialect)})`
|
|
@@ -481,8 +522,11 @@ const renderJsonExpression = (
|
|
|
481
522
|
return undefined
|
|
482
523
|
}
|
|
483
524
|
if (dialect.name === "postgres") {
|
|
484
|
-
const
|
|
485
|
-
|
|
525
|
+
const baseSql = renderExpression(base, state, dialect)
|
|
526
|
+
const typeOf = `${postgresBaseKind === "jsonb" ? "jsonb" : "json"}_typeof`
|
|
527
|
+
const arrayLength = `${postgresBaseKind === "jsonb" ? "jsonb" : "json"}_array_length`
|
|
528
|
+
const objectKeys = `${postgresBaseKind === "jsonb" ? "jsonb" : "json"}_object_keys`
|
|
529
|
+
return `(case when ${typeOf}(${baseSql}) = 'array' then ${arrayLength}(${baseSql}) when ${typeOf}(${baseSql}) = 'object' then (select count(*)::int from ${objectKeys}(${baseSql})) else null end)`
|
|
486
530
|
}
|
|
487
531
|
if (dialect.name === "mysql") {
|
|
488
532
|
return `json_length(${renderExpression(base, state, dialect)})`
|
|
@@ -493,8 +537,10 @@ const renderJsonExpression = (
|
|
|
493
537
|
return undefined
|
|
494
538
|
}
|
|
495
539
|
if (dialect.name === "postgres") {
|
|
496
|
-
const
|
|
497
|
-
|
|
540
|
+
const baseSql = renderExpression(base, state, dialect)
|
|
541
|
+
const typeOf = `${postgresBaseKind === "jsonb" ? "jsonb" : "json"}_typeof`
|
|
542
|
+
const objectKeys = `${postgresBaseKind === "jsonb" ? "jsonb" : "json"}_object_keys`
|
|
543
|
+
return `(case when ${typeOf}(${baseSql}) = 'object' then array(select ${objectKeys}(${baseSql})) else null end)`
|
|
498
544
|
}
|
|
499
545
|
if (dialect.name === "mysql") {
|
|
500
546
|
return `json_keys(${renderExpression(base, state, dialect)})`
|
|
@@ -505,7 +551,7 @@ const renderJsonExpression = (
|
|
|
505
551
|
return undefined
|
|
506
552
|
}
|
|
507
553
|
if (dialect.name === "postgres") {
|
|
508
|
-
return
|
|
554
|
+
return `${postgresBaseKind === "jsonb" ? "jsonb" : "json"}_strip_nulls(${renderExpression(base, state, dialect)})`
|
|
509
555
|
}
|
|
510
556
|
unsupportedJsonFeature(dialect, "jsonStripNulls")
|
|
511
557
|
return undefined
|
|
@@ -772,7 +818,7 @@ export const renderQueryAst = (
|
|
|
772
818
|
case "set": {
|
|
773
819
|
const setAst = ast as QueryAst.Ast<Record<string, unknown>, any, "set">
|
|
774
820
|
const base = renderQueryAst(
|
|
775
|
-
Query.getAst(setAst.setBase as Query.
|
|
821
|
+
Query.getAst(setAst.setBase as Query.Plan.Any) as QueryAst.Ast<
|
|
776
822
|
Record<string, unknown>,
|
|
777
823
|
any,
|
|
778
824
|
QueryAst.QueryStatement
|
|
@@ -785,7 +831,7 @@ export const renderQueryAst = (
|
|
|
785
831
|
`(${base.sql})`,
|
|
786
832
|
...(setAst.setOperations ?? []).map((entry) => {
|
|
787
833
|
const rendered = renderQueryAst(
|
|
788
|
-
Query.getAst(entry.query as Query.
|
|
834
|
+
Query.getAst(entry.query as Query.Plan.Any) as QueryAst.Ast<
|
|
789
835
|
Record<string, unknown>,
|
|
790
836
|
any,
|
|
791
837
|
QueryAst.QueryStatement
|
|
@@ -812,7 +858,7 @@ export const renderQueryAst = (
|
|
|
812
858
|
} else if (insertAst.insertSource?.kind === "query") {
|
|
813
859
|
const columns = insertAst.insertSource.columns.map((column) => dialect.quoteIdentifier(column)).join(", ")
|
|
814
860
|
const renderedQuery = renderQueryAst(
|
|
815
|
-
Query.getAst(insertAst.insertSource.query as Query.
|
|
861
|
+
Query.getAst(insertAst.insertSource.query as Query.Plan.Any) as QueryAst.Ast<
|
|
816
862
|
Record<string, unknown>,
|
|
817
863
|
any,
|
|
818
864
|
QueryAst.QueryStatement
|
|
@@ -1105,7 +1151,7 @@ const renderSourceReference = (
|
|
|
1105
1151
|
if (typeof source === "object" && source !== null && "kind" in source && (source as { readonly kind?: string }).kind === "cte") {
|
|
1106
1152
|
const cte = source as unknown as {
|
|
1107
1153
|
readonly name: string
|
|
1108
|
-
readonly plan: Query.
|
|
1154
|
+
readonly plan: Query.Plan.Any
|
|
1109
1155
|
readonly recursive?: boolean
|
|
1110
1156
|
}
|
|
1111
1157
|
if (!state.cteNames.has(cte.name)) {
|
|
@@ -1122,7 +1168,7 @@ const renderSourceReference = (
|
|
|
1122
1168
|
if (typeof source === "object" && source !== null && "kind" in source && (source as { readonly kind?: string }).kind === "derived") {
|
|
1123
1169
|
const derived = source as unknown as {
|
|
1124
1170
|
readonly name: string
|
|
1125
|
-
readonly plan: Query.
|
|
1171
|
+
readonly plan: Query.Plan.Any
|
|
1126
1172
|
}
|
|
1127
1173
|
if (!state.cteNames.has(derived.name)) {
|
|
1128
1174
|
// derived tables are inlined, so no CTE registration is needed
|
|
@@ -1132,7 +1178,7 @@ const renderSourceReference = (
|
|
|
1132
1178
|
if (typeof source === "object" && source !== null && "kind" in source && (source as { readonly kind?: string }).kind === "lateral") {
|
|
1133
1179
|
const lateral = source as unknown as {
|
|
1134
1180
|
readonly name: string
|
|
1135
|
-
readonly plan: Query.
|
|
1181
|
+
readonly plan: Query.Plan.Any
|
|
1136
1182
|
}
|
|
1137
1183
|
return `lateral (${renderQueryAst(Query.getAst(lateral.plan) as QueryAst.Ast<Record<string, unknown>, any, QueryAst.QueryStatement>, state, dialect).sql}) as ${dialect.quoteIdentifier(lateral.name)}`
|
|
1138
1184
|
}
|
|
@@ -1184,7 +1230,7 @@ export const renderExpression = (
|
|
|
1184
1230
|
const rawAst = (expression as Expression.Any & {
|
|
1185
1231
|
readonly [ExpressionAst.TypeId]: ExpressionAst.Any
|
|
1186
1232
|
})[ExpressionAst.TypeId] as ExpressionAst.Any | Record<string, unknown>
|
|
1187
|
-
const jsonSql = renderJsonExpression(rawAst as Record<string, unknown>, state, dialect)
|
|
1233
|
+
const jsonSql = renderJsonExpression(expression, rawAst as Record<string, unknown>, state, dialect)
|
|
1188
1234
|
if (jsonSql !== undefined) {
|
|
1189
1235
|
return jsonSql
|
|
1190
1236
|
}
|
|
@@ -1201,9 +1247,11 @@ export const renderExpression = (
|
|
|
1201
1247
|
: operator === "gt"
|
|
1202
1248
|
? ">"
|
|
1203
1249
|
: ">="
|
|
1204
|
-
|
|
1250
|
+
switch (ast.kind) {
|
|
1205
1251
|
case "column":
|
|
1206
|
-
return
|
|
1252
|
+
return ast.tableName.length === 0
|
|
1253
|
+
? dialect.quoteIdentifier(ast.columnName)
|
|
1254
|
+
: `${dialect.quoteIdentifier(ast.tableName)}.${dialect.quoteIdentifier(ast.columnName)}`
|
|
1207
1255
|
case "literal":
|
|
1208
1256
|
return dialect.renderLiteral(ast.value, state)
|
|
1209
1257
|
case "excluded":
|
|
@@ -1212,6 +1260,8 @@ export const renderExpression = (
|
|
|
1212
1260
|
: `excluded.${dialect.quoteIdentifier(ast.columnName)}`
|
|
1213
1261
|
case "cast":
|
|
1214
1262
|
return `cast(${renderExpression(ast.value, state, dialect)} as ${renderCastType(dialect, ast.target)})`
|
|
1263
|
+
case "collate":
|
|
1264
|
+
return `(${renderExpression(ast.value, state, dialect)} collate ${ast.collation.map((segment) => dialect.quoteIdentifier(segment)).join(".")})`
|
|
1215
1265
|
case "function":
|
|
1216
1266
|
return renderFunctionCall(ast.name, Array.isArray(ast.args) ? ast.args : [], state, dialect)
|
|
1217
1267
|
case "eq":
|
|
@@ -1232,6 +1282,22 @@ export const renderExpression = (
|
|
|
1232
1282
|
return dialect.name === "postgres"
|
|
1233
1283
|
? `(${renderExpression(ast.left, state, dialect)} ilike ${renderExpression(ast.right, state, dialect)})`
|
|
1234
1284
|
: `(lower(${renderExpression(ast.left, state, dialect)}) like lower(${renderExpression(ast.right, state, dialect)}))`
|
|
1285
|
+
case "regexMatch":
|
|
1286
|
+
return dialect.name === "postgres"
|
|
1287
|
+
? `(${renderExpression(ast.left, state, dialect)} ~ ${renderExpression(ast.right, state, dialect)})`
|
|
1288
|
+
: `(${renderExpression(ast.left, state, dialect)} regexp ${renderExpression(ast.right, state, dialect)})`
|
|
1289
|
+
case "regexIMatch":
|
|
1290
|
+
return dialect.name === "postgres"
|
|
1291
|
+
? `(${renderExpression(ast.left, state, dialect)} ~* ${renderExpression(ast.right, state, dialect)})`
|
|
1292
|
+
: `(${renderExpression(ast.left, state, dialect)} regexp ${renderExpression(ast.right, state, dialect)})`
|
|
1293
|
+
case "regexNotMatch":
|
|
1294
|
+
return dialect.name === "postgres"
|
|
1295
|
+
? `(${renderExpression(ast.left, state, dialect)} !~ ${renderExpression(ast.right, state, dialect)})`
|
|
1296
|
+
: `(${renderExpression(ast.left, state, dialect)} not regexp ${renderExpression(ast.right, state, dialect)})`
|
|
1297
|
+
case "regexNotIMatch":
|
|
1298
|
+
return dialect.name === "postgres"
|
|
1299
|
+
? `(${renderExpression(ast.left, state, dialect)} !~* ${renderExpression(ast.right, state, dialect)})`
|
|
1300
|
+
: `(${renderExpression(ast.left, state, dialect)} not regexp ${renderExpression(ast.right, state, dialect)})`
|
|
1235
1301
|
case "isDistinctFrom":
|
|
1236
1302
|
return dialect.name === "mysql"
|
|
1237
1303
|
? `(not (${renderExpression(ast.left, state, dialect)} <=> ${renderExpression(ast.right, state, dialect)}))`
|