effect-qb 4.0.0-beta.66 → 4.0.0-beta.98

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.
Files changed (129) hide show
  1. package/README.md +5 -2
  2. package/dist/index.js +9376 -0
  3. package/dist/mysql.js +3921 -2573
  4. package/dist/postgres/metadata.js +2491 -1373
  5. package/dist/postgres.js +5453 -5155
  6. package/dist/sqlite.js +6895 -5529
  7. package/dist/standard.js +9330 -0
  8. package/package.json +9 -2
  9. package/src/casing.ts +71 -0
  10. package/src/index.ts +2 -0
  11. package/src/internal/casing.ts +89 -0
  12. package/src/internal/coercion/rules.ts +13 -1
  13. package/src/internal/column-state.ts +21 -15
  14. package/src/internal/column.ts +44 -7
  15. package/src/internal/datatypes/define.ts +7 -1
  16. package/src/internal/datatypes/enrich.ts +23 -0
  17. package/src/internal/datatypes/lookup.ts +81 -25
  18. package/src/internal/datatypes/matrix.ts +903 -0
  19. package/src/internal/datatypes/shape.ts +2 -0
  20. package/src/internal/derived-table.ts +4 -36
  21. package/src/{mysql/internal/sql-expression-renderer.ts → internal/dialect-renderers/mysql.ts} +552 -361
  22. package/src/{postgres/internal/sql-expression-renderer.ts → internal/dialect-renderers/postgres.ts} +657 -400
  23. package/src/{sqlite/internal/sql-expression-renderer.ts → internal/dialect-renderers/sqlite.ts} +505 -347
  24. package/src/internal/dialect.ts +35 -0
  25. package/src/internal/dsl-mutation-runtime.ts +12 -162
  26. package/src/internal/dsl-plan-runtime.ts +10 -138
  27. package/src/internal/dsl-query-runtime.ts +5 -79
  28. package/src/internal/dsl-transaction-ddl-runtime.ts +41 -65
  29. package/src/internal/executor.ts +14 -16
  30. package/src/internal/grouping-key.ts +87 -20
  31. package/src/internal/implication-runtime.ts +1 -1
  32. package/src/internal/json/path-access.ts +351 -0
  33. package/src/internal/predicate/runtime.ts +3 -0
  34. package/src/internal/query.d.ts +38 -11
  35. package/src/internal/query.ts +64 -25
  36. package/src/internal/renderer.ts +26 -14
  37. package/src/internal/runtime/normalize.ts +12 -5
  38. package/src/internal/scalar.ts +7 -1
  39. package/src/internal/schema-derivation.d.ts +7 -7
  40. package/src/internal/schema-derivation.ts +9 -9
  41. package/src/internal/schema-expression.ts +2 -2
  42. package/src/internal/sql-expression-renderer.ts +19 -0
  43. package/src/internal/standard-dsl.ts +6978 -0
  44. package/src/internal/table-options.ts +126 -66
  45. package/src/internal/table.ts +652 -219
  46. package/src/mysql/column-extension.ts +3 -0
  47. package/src/mysql/column.ts +8 -9
  48. package/src/mysql/datatypes/index.ts +4 -2
  49. package/src/mysql/datatypes/spec.ts +6 -176
  50. package/src/mysql/errors/normalize.ts +0 -1
  51. package/src/mysql/executor.ts +7 -7
  52. package/src/mysql/internal/dialect.ts +9 -4
  53. package/src/mysql/internal/dsl.ts +312 -154
  54. package/src/mysql/internal/renderer.ts +6 -2
  55. package/src/mysql/json.ts +7 -2
  56. package/src/mysql/query-extension.ts +16 -0
  57. package/src/mysql/renderer.ts +37 -3
  58. package/src/mysql/type.ts +60 -0
  59. package/src/mysql.ts +7 -13
  60. package/src/postgres/check.ts +1 -0
  61. package/src/postgres/column-extension.ts +28 -0
  62. package/src/postgres/column.ts +2 -8
  63. package/src/postgres/datatypes/index.d.ts +2 -1
  64. package/src/postgres/datatypes/index.ts +4 -2
  65. package/src/postgres/datatypes/spec.ts +6 -260
  66. package/src/postgres/errors/normalize.ts +0 -1
  67. package/src/postgres/executor.ts +7 -7
  68. package/src/postgres/foreign-key.ts +24 -0
  69. package/src/postgres/function/core.ts +1 -3
  70. package/src/postgres/function/index.ts +1 -17
  71. package/src/postgres/index.ts +1 -0
  72. package/src/postgres/internal/dialect.ts +9 -4
  73. package/src/postgres/internal/dsl.ts +306 -163
  74. package/src/postgres/internal/renderer.ts +6 -2
  75. package/src/postgres/internal/schema-ddl.ts +22 -10
  76. package/src/postgres/internal/schema-model.ts +238 -7
  77. package/src/postgres/json-extension.ts +7 -0
  78. package/src/postgres/json.ts +762 -173
  79. package/src/postgres/jsonb.ts +37 -0
  80. package/src/postgres/primary-key.ts +24 -0
  81. package/src/postgres/query-extension.ts +2 -0
  82. package/src/postgres/renderer.ts +37 -3
  83. package/src/postgres/schema-management.ts +12 -11
  84. package/src/postgres/schema.ts +106 -15
  85. package/src/postgres/table.ts +205 -530
  86. package/src/postgres/type.ts +93 -10
  87. package/src/postgres/unique.ts +32 -0
  88. package/src/postgres.ts +20 -16
  89. package/src/sqlite/column-extension.ts +3 -0
  90. package/src/sqlite/column.ts +8 -9
  91. package/src/sqlite/datatypes/index.ts +4 -2
  92. package/src/sqlite/datatypes/spec.ts +6 -94
  93. package/src/sqlite/errors/normalize.ts +0 -1
  94. package/src/sqlite/executor.ts +7 -7
  95. package/src/sqlite/internal/dialect.ts +9 -4
  96. package/src/sqlite/internal/dsl.ts +301 -154
  97. package/src/sqlite/internal/renderer.ts +6 -2
  98. package/src/sqlite/json.ts +8 -2
  99. package/src/sqlite/query-extension.ts +2 -0
  100. package/src/sqlite/renderer.ts +37 -3
  101. package/src/sqlite/type.ts +40 -0
  102. package/src/sqlite.ts +7 -13
  103. package/src/standard/cast.ts +113 -0
  104. package/src/standard/check.ts +17 -0
  105. package/src/standard/column.ts +163 -0
  106. package/src/standard/datatypes/index.ts +83 -0
  107. package/src/standard/datatypes/spec.ts +12 -0
  108. package/src/standard/dialect.ts +40 -0
  109. package/src/standard/foreign-key.ts +37 -0
  110. package/src/standard/function/aggregate.ts +2 -0
  111. package/src/standard/function/core.ts +2 -0
  112. package/src/standard/function/index.ts +18 -0
  113. package/src/standard/function/string.ts +2 -0
  114. package/src/standard/function/temporal.ts +78 -0
  115. package/src/standard/function/window.ts +2 -0
  116. package/src/standard/index.ts +17 -0
  117. package/src/standard/internal/renderer.ts +45 -0
  118. package/src/standard/json.ts +883 -0
  119. package/src/standard/primary-key.ts +17 -0
  120. package/src/standard/query.ts +152 -0
  121. package/src/standard/renderer.ts +49 -0
  122. package/src/standard/table.ts +151 -0
  123. package/src/standard/unique.ts +17 -0
  124. package/src/standard.ts +32 -0
  125. package/src/internal/aggregation-validation.ts +0 -57
  126. package/src/internal/table.d.ts +0 -180
  127. package/src/mysql/table.ts +0 -186
  128. package/src/postgres/cast.ts +0 -45
  129. package/src/sqlite/table.ts +0 -175
@@ -1,9 +1,10 @@
1
1
  import * as Query from "../../internal/query.js"
2
2
  import type * as Expression from "../../internal/scalar.js"
3
+ import type * as Casing from "../../internal/casing.js"
3
4
  import { type RenderState } from "../../internal/dialect.js"
4
5
  import { postgresDialect } from "./dialect.js"
5
6
  import { type Projection } from "../../internal/projections.js"
6
- import { renderQueryAst } from "./sql-expression-renderer.js"
7
+ import { renderQueryAst } from "../../internal/sql-expression-renderer.js"
7
8
 
8
9
  /**
9
10
  * Minimal rendered-query payload produced by the built-in Postgres renderer.
@@ -20,6 +21,7 @@ export interface PostgresRenderResult {
20
21
 
21
22
  export interface PostgresRenderOptions {
22
23
  readonly valueMappings?: Expression.DriverValueMappings
24
+ readonly casing?: Casing.Options
23
25
  }
24
26
 
25
27
  /**
@@ -32,9 +34,11 @@ export const renderPostgresPlan = <PlanValue extends Query.Plan.Any>(
32
34
  const state: RenderState = {
33
35
  params: [],
34
36
  valueMappings: options.valueMappings,
37
+ casing: options.casing,
35
38
  ctes: [],
36
39
  cteNames: new Set<string>(),
37
- cteSources: new Map<string, unknown>()
40
+ cteSources: new Map<string, unknown>(),
41
+ sourceNames: new Map()
38
42
  }
39
43
  const rendered = renderQueryAst(
40
44
  Query.getAst(plan as Query.Plan.Any) as any,
@@ -1,7 +1,7 @@
1
1
  import type * as Expression from "../../internal/scalar.js"
2
2
  import type { RenderState, SqlDialect } from "../../internal/dialect.js"
3
3
  import * as SchemaExpression from "../../internal/schema-expression.js"
4
- import { renderExpression } from "./sql-expression-renderer.js"
4
+ import { renderExpression } from "../../internal/sql-expression-renderer.js"
5
5
  import type { DdlExpressionLike } from "../../internal/table-options.js"
6
6
  import { parse, toSql } from "pgsql-ast-parser"
7
7
  import { postgresDialect } from "./dialect.js"
@@ -30,21 +30,30 @@ const inlineLiteralDialect: SqlDialect<"postgres"> = {
30
30
  return String(value)
31
31
  }
32
32
  if (value instanceof Date) {
33
+ if (Number.isNaN(value.getTime())) {
34
+ throw new Error("Expected a valid Date value")
35
+ }
33
36
  return escapeString(value.toISOString())
34
37
  }
35
38
  return escapeString(String(value))
36
39
  }
37
40
  }
38
41
 
39
- export const renderDdlExpressionSql = (expression: DdlExpressionLike): string =>
42
+ const makeExpressionState = (state: Partial<RenderState> = {}): RenderState => ({
43
+ ...state,
44
+ params: [],
45
+ ctes: [],
46
+ cteNames: new Set(),
47
+ cteSources: new Map()
48
+ })
49
+
50
+ export const renderDdlExpressionSql = (
51
+ expression: DdlExpressionLike,
52
+ state?: Partial<RenderState>
53
+ ): string =>
40
54
  SchemaExpression.isSchemaExpression(expression)
41
55
  ? SchemaExpression.render(expression)
42
- : renderExpression(expression as Expression.Any, {
43
- params: [],
44
- ctes: [],
45
- cteNames: new Set(),
46
- cteSources: new Map()
47
- }, inlineLiteralDialect)
56
+ : renderExpression(expression as Expression.Any, makeExpressionState(state), inlineLiteralDialect)
48
57
 
49
58
  const stripRedundantOuterParens = (value: string): string => {
50
59
  let current = value.trim()
@@ -99,8 +108,11 @@ const canonicalizeDdlExpressionSql = (value: string): string =>
99
108
  )
100
109
  )
101
110
 
102
- export const normalizeDdlExpressionSql = (expression: DdlExpressionLike): string => {
103
- const rendered = renderDdlExpressionSql(expression)
111
+ export const normalizeDdlExpressionSql = (
112
+ expression: DdlExpressionLike,
113
+ state?: Partial<RenderState>
114
+ ): string => {
115
+ const rendered = renderDdlExpressionSql(expression, state)
104
116
  try {
105
117
  return canonicalizeDdlExpressionSql(toSql.expr(parse(rendered, "expr")))
106
118
  } catch {
@@ -1,7 +1,11 @@
1
1
  import * as Table from "../../internal/table.js"
2
2
  import type { AnyColumnDefinition } from "../../internal/column-state.js"
3
+ import type { RenderState } from "../../internal/dialect.js"
4
+ import * as Casing from "../../internal/casing.js"
5
+ import * as Expression from "../../internal/scalar.js"
6
+ import * as SchemaExpression from "../../internal/schema-expression.js"
3
7
  import { normalizeDdlExpressionSql } from "./schema-ddl.js"
4
- import type { TableOptionSpec } from "../../internal/table-options.js"
8
+ import { validateOptions, type ColumnList, type DdlExpressionLike, type IndexKeySpec, type TableOptionSpec } from "../../internal/table-options.js"
5
9
  import type { EnumDefinition } from "../schema-management.js"
6
10
  import { EnumTypeId } from "../schema-management.js"
7
11
 
@@ -52,15 +56,238 @@ export const isTableDefinition = (value: unknown): value is Table.AnyTable =>
52
56
  export const isEnumDefinition = (value: unknown): value is EnumDefinition =>
53
57
  typeof value === "object" && value !== null && EnumTypeId in value
54
58
 
59
+ const applyCasing = (
60
+ casing: Casing.Options | undefined,
61
+ category: Casing.Category,
62
+ name: string
63
+ ): string =>
64
+ Casing.applyCategory(casing, category, name)
65
+
66
+ const mapColumnList = (
67
+ columns: ColumnList,
68
+ casing: Casing.Options | undefined
69
+ ): ColumnList =>
70
+ !Array.isArray(columns)
71
+ ? columns
72
+ : columns.length === 0
73
+ ? columns
74
+ : [
75
+ mapCasedValue(columns[0], casing, "columns"),
76
+ ...columns.slice(1).map((column) => mapCasedValue(column, casing, "columns"))
77
+ ] as ColumnList
78
+
79
+ const expressionStateForTable = (
80
+ state: Table.AnyTable[typeof Table.TypeId],
81
+ tableName: string,
82
+ columns: ReadonlyMap<string, string>,
83
+ casing: Casing.Options | undefined
84
+ ): Partial<RenderState> => ({
85
+ casing,
86
+ rowLocalColumns: true,
87
+ sourceNames: new Map([
88
+ [state.name, { tableName, columns }],
89
+ [state.baseName, { tableName, columns }]
90
+ ])
91
+ })
92
+
93
+ const mapDdlExpression = (
94
+ expression: DdlExpressionLike,
95
+ state: Partial<RenderState>
96
+ ): SchemaExpression.SchemaExpression =>
97
+ SchemaExpression.fromSql(normalizeDdlExpressionSql(expression, state))
98
+
99
+ function mapOptionName(
100
+ name: string,
101
+ casing: Casing.Options | undefined,
102
+ category: "indexes" | "constraints"
103
+ ): string
104
+ function mapOptionName(
105
+ name: unknown,
106
+ casing: Casing.Options | undefined,
107
+ category: "indexes" | "constraints"
108
+ ): unknown
109
+ function mapOptionName(
110
+ name: unknown,
111
+ casing: Casing.Options | undefined,
112
+ category: "indexes" | "constraints"
113
+ ): unknown {
114
+ return typeof name === "string"
115
+ ? applyCasing(casing, category, name)
116
+ : name
117
+ }
118
+
119
+ function mapCasedValue(
120
+ value: string,
121
+ casing: Casing.Options | undefined,
122
+ category: Casing.Category
123
+ ): string
124
+ function mapCasedValue(
125
+ value: unknown,
126
+ casing: Casing.Options | undefined,
127
+ category: Casing.Category
128
+ ): unknown
129
+ function mapCasedValue(
130
+ value: unknown,
131
+ casing: Casing.Options | undefined,
132
+ category: Casing.Category
133
+ ): unknown {
134
+ return typeof value === "string"
135
+ ? applyCasing(casing, category, value)
136
+ : value
137
+ }
138
+
139
+ const isDdlExpressionLike = (value: unknown): value is DdlExpressionLike =>
140
+ typeof value === "object" &&
141
+ value !== null &&
142
+ (Expression.TypeId in value || SchemaExpression.TypeId in value)
143
+
144
+ function mapIndexKey(
145
+ key: IndexKeySpec,
146
+ casing: Casing.Options | undefined,
147
+ expressionState: Partial<RenderState>
148
+ ): IndexKeySpec
149
+ function mapIndexKey(
150
+ key: unknown,
151
+ casing: Casing.Options | undefined,
152
+ expressionState: Partial<RenderState>
153
+ ): unknown
154
+ function mapIndexKey(
155
+ key: unknown,
156
+ casing: Casing.Options | undefined,
157
+ expressionState: Partial<RenderState>
158
+ ): unknown {
159
+ if (typeof key !== "object" || key === null || !("kind" in key)) {
160
+ return key
161
+ }
162
+ const kind = (key as { readonly kind?: unknown }).kind
163
+ if (kind === "column") {
164
+ const column = (key as { readonly column?: unknown }).column
165
+ return typeof column === "string"
166
+ ? {
167
+ ...key,
168
+ column: applyCasing(casing, "columns", column)
169
+ }
170
+ : key
171
+ }
172
+ if (kind === "expression") {
173
+ const expression = (key as { readonly expression?: unknown }).expression
174
+ return isDdlExpressionLike(expression)
175
+ ? {
176
+ ...key,
177
+ expression: mapDdlExpression(expression, expressionState)
178
+ }
179
+ : key
180
+ }
181
+ return key
182
+ }
183
+
184
+ const mapOption = (
185
+ option: TableOptionSpec,
186
+ casing: Casing.Options | undefined,
187
+ expressionState: Partial<RenderState>
188
+ ): TableOptionSpec => {
189
+ switch (option.kind) {
190
+ case "index":
191
+ return {
192
+ ...option,
193
+ columns: option.columns === undefined ? undefined : mapColumnList(option.columns, casing),
194
+ name: option.name === undefined ? undefined : mapOptionName(option.name, casing, "indexes"),
195
+ include: option.include === undefined
196
+ ? undefined
197
+ : Array.isArray(option.include)
198
+ ? option.include.map((column) => mapCasedValue(column, casing, "columns")) as unknown as readonly string[]
199
+ : option.include,
200
+ predicate: option.predicate === undefined
201
+ ? undefined
202
+ : isDdlExpressionLike(option.predicate)
203
+ ? mapDdlExpression(option.predicate, expressionState)
204
+ : option.predicate,
205
+ keys: option.keys === undefined
206
+ ? undefined
207
+ : Array.isArray(option.keys)
208
+ ? option.keys.length === 0
209
+ ? option.keys
210
+ : [
211
+ mapIndexKey(option.keys[0], casing, expressionState),
212
+ ...option.keys.slice(1).map((key) => mapIndexKey(key, casing, expressionState))
213
+ ] as unknown as readonly [IndexKeySpec, ...IndexKeySpec[]]
214
+ : option.keys
215
+ }
216
+ case "primaryKey":
217
+ return {
218
+ ...option,
219
+ columns: mapColumnList(option.columns, casing),
220
+ name: option.name === undefined ? undefined : mapOptionName(option.name, casing, "constraints")
221
+ }
222
+ case "unique":
223
+ return {
224
+ ...option,
225
+ columns: mapColumnList(option.columns, casing),
226
+ name: option.name === undefined ? undefined : mapOptionName(option.name, casing, "constraints")
227
+ }
228
+ case "foreignKey":
229
+ return {
230
+ ...option,
231
+ columns: mapColumnList(option.columns, casing),
232
+ name: option.name === undefined ? undefined : mapOptionName(option.name, casing, "constraints"),
233
+ references: () => {
234
+ const reference = typeof option.references === "function"
235
+ ? option.references()
236
+ : option.references
237
+ if (typeof reference !== "object" || reference === null) {
238
+ return reference
239
+ }
240
+ const referenceCasing = reference.casing
241
+ return {
242
+ ...reference,
243
+ tableName: mapCasedValue(reference.tableName, referenceCasing, "tables"),
244
+ schemaName: reference.schemaName === undefined
245
+ ? undefined
246
+ : mapCasedValue(reference.schemaName, referenceCasing, "schemas"),
247
+ columns: mapColumnList(reference.columns, referenceCasing),
248
+ knownColumns: reference.knownColumns === undefined
249
+ ? undefined
250
+ : Array.isArray(reference.knownColumns)
251
+ ? reference.knownColumns.map((column) =>
252
+ mapCasedValue(column, referenceCasing, "columns")) as unknown as readonly string[]
253
+ : reference.knownColumns
254
+ }
255
+ }
256
+ }
257
+ case "check":
258
+ return {
259
+ ...option,
260
+ name: mapOptionName(option.name, casing, "constraints"),
261
+ predicate: isDdlExpressionLike(option.predicate)
262
+ ? mapDdlExpression(option.predicate, expressionState)
263
+ : option.predicate
264
+ }
265
+ default:
266
+ return option
267
+ }
268
+ }
269
+
55
270
  export const toTableModel = (table: Table.AnyTable): TableModel => {
56
271
  const state = table[Table.TypeId]
272
+ const casing = state.casing
273
+ const tableName = applyCasing(casing, "tables", state.baseName)
274
+ const schemaName = state.schemaName === undefined
275
+ ? undefined
276
+ : applyCasing(casing, "schemas", state.schemaName)
57
277
  const fields = state.fields as Record<string, AnyColumnDefinition>
278
+ const options = table[Table.OptionsSymbol] as unknown
279
+ const normalizedOptions = (Array.isArray(options) ? options : [options]) as readonly TableOptionSpec[]
280
+ validateOptions(state.name, fields, normalizedOptions)
281
+ const columnNames = new Map(
282
+ Object.keys(fields).map((name) => [name, applyCasing(casing, "columns", name)] as const)
283
+ )
284
+ const expressionState = expressionStateForTable(state, tableName, columnNames, casing)
58
285
  const columns = Object.entries(fields).map(([name, column]) => {
59
286
  const metadata = column.metadata
60
287
  const enumDefinition = metadata.enum
61
288
  const ddlType = metadata.ddlType ?? metadata.dbType.kind
62
289
  return {
63
- name,
290
+ name: columnNames.get(name) ?? name,
64
291
  ddlType,
65
292
  dbTypeKind: enumDefinition?.name ?? column.metadata.dbType.kind,
66
293
  typeKind: enumDefinition === undefined ? undefined : "e",
@@ -70,20 +297,24 @@ export const toTableModel = (table: Table.AnyTable): TableModel => {
70
297
  generated: column.metadata.generated,
71
298
  defaultSql: column.metadata.defaultValue === undefined
72
299
  ? undefined
73
- : normalizeDdlExpressionSql(column.metadata.defaultValue),
300
+ : normalizeDdlExpressionSql(column.metadata.defaultValue, expressionState),
74
301
  generatedSql: column.metadata.generatedValue === undefined
75
302
  ? undefined
76
- : normalizeDdlExpressionSql(column.metadata.generatedValue),
303
+ : normalizeDdlExpressionSql(column.metadata.generatedValue, expressionState),
77
304
  identity: column.metadata.identity,
78
305
  column
79
306
  }
80
307
  }) satisfies ReadonlyArray<ColumnModel>
81
308
  return {
82
309
  kind: "table",
83
- schemaName: state.schemaName,
84
- name: state.baseName,
310
+ schemaName,
311
+ name: tableName,
85
312
  columns,
86
- options: table[Table.OptionsSymbol],
313
+ options: normalizedOptions.map((option) =>
314
+ typeof option === "object" && option !== null && "kind" in option
315
+ ? mapOption(option, casing, expressionState)
316
+ : option as TableOptionSpec
317
+ ),
87
318
  table
88
319
  }
89
320
  }
@@ -0,0 +1,7 @@
1
+ import { json } from "./json.js"
2
+
3
+ /** Removes null object fields using Postgres json/jsonb strip-null functions. */
4
+ export const stripNulls = json.stripNulls
5
+
6
+ /** Evaluates a Postgres SQL/JSON path predicate with the @@ operator. */
7
+ export const pathMatch = json.pathMatch