effect-qb 0.15.0 → 0.17.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.
Files changed (88) hide show
  1. package/dist/mysql.js +1957 -595
  2. package/dist/postgres/metadata.js +2507 -182
  3. package/dist/postgres.js +9587 -8201
  4. package/dist/sqlite.js +8360 -0
  5. package/package.json +7 -2
  6. package/src/internal/column-state.ts +7 -0
  7. package/src/internal/column.ts +22 -0
  8. package/src/internal/derived-table.ts +29 -3
  9. package/src/internal/dialect.ts +14 -1
  10. package/src/internal/dsl-mutation-runtime.ts +173 -4
  11. package/src/internal/dsl-plan-runtime.ts +165 -20
  12. package/src/internal/dsl-query-runtime.ts +60 -6
  13. package/src/internal/dsl-transaction-ddl-runtime.ts +72 -2
  14. package/src/internal/executor.ts +62 -13
  15. package/src/internal/expression-ast.ts +3 -2
  16. package/src/internal/grouping-key.ts +141 -1
  17. package/src/internal/implication-runtime.ts +2 -1
  18. package/src/internal/json/types.ts +155 -40
  19. package/src/internal/predicate/analysis.ts +103 -1
  20. package/src/internal/predicate/atom.ts +7 -0
  21. package/src/internal/predicate/context.ts +170 -17
  22. package/src/internal/predicate/key.ts +64 -2
  23. package/src/internal/predicate/normalize.ts +115 -34
  24. package/src/internal/predicate/runtime.ts +144 -13
  25. package/src/internal/query.ts +563 -103
  26. package/src/internal/renderer.ts +39 -2
  27. package/src/internal/runtime/driver-value-mapping.ts +244 -0
  28. package/src/internal/runtime/normalize.ts +62 -38
  29. package/src/internal/runtime/schema.ts +5 -3
  30. package/src/internal/runtime/value.ts +153 -30
  31. package/src/internal/scalar.ts +11 -0
  32. package/src/internal/table-options.ts +108 -1
  33. package/src/internal/table.ts +87 -29
  34. package/src/mysql/column.ts +19 -2
  35. package/src/mysql/datatypes/index.ts +21 -0
  36. package/src/mysql/errors/catalog.ts +5 -5
  37. package/src/mysql/errors/normalize.ts +2 -2
  38. package/src/mysql/executor.ts +20 -5
  39. package/src/mysql/internal/dialect.ts +12 -6
  40. package/src/mysql/internal/dsl.ts +995 -263
  41. package/src/mysql/internal/renderer.ts +13 -3
  42. package/src/mysql/internal/sql-expression-renderer.ts +530 -128
  43. package/src/mysql/query.ts +9 -2
  44. package/src/mysql/renderer.ts +7 -2
  45. package/src/mysql/table.ts +38 -12
  46. package/src/postgres/cast.ts +22 -7
  47. package/src/postgres/column.ts +5 -2
  48. package/src/postgres/errors/normalize.ts +2 -2
  49. package/src/postgres/executor.ts +68 -10
  50. package/src/postgres/function/core.ts +19 -1
  51. package/src/postgres/internal/dialect.ts +12 -6
  52. package/src/postgres/internal/dsl.ts +958 -288
  53. package/src/postgres/internal/renderer.ts +13 -3
  54. package/src/postgres/internal/schema-ddl.ts +2 -1
  55. package/src/postgres/internal/schema-model.ts +6 -3
  56. package/src/postgres/internal/sql-expression-renderer.ts +477 -96
  57. package/src/postgres/json.ts +57 -17
  58. package/src/postgres/query.ts +9 -2
  59. package/src/postgres/renderer.ts +7 -2
  60. package/src/postgres/schema-management.ts +91 -4
  61. package/src/postgres/schema.ts +1 -1
  62. package/src/postgres/table.ts +189 -53
  63. package/src/postgres/type.ts +4 -0
  64. package/src/sqlite/column.ts +128 -0
  65. package/src/sqlite/datatypes/index.ts +79 -0
  66. package/src/sqlite/datatypes/spec.ts +98 -0
  67. package/src/sqlite/errors/catalog.ts +103 -0
  68. package/src/sqlite/errors/fields.ts +19 -0
  69. package/src/sqlite/errors/index.ts +19 -0
  70. package/src/sqlite/errors/normalize.ts +229 -0
  71. package/src/sqlite/errors/requirements.ts +71 -0
  72. package/src/sqlite/errors/types.ts +29 -0
  73. package/src/sqlite/executor.ts +227 -0
  74. package/src/sqlite/function/aggregate.ts +2 -0
  75. package/src/sqlite/function/core.ts +2 -0
  76. package/src/sqlite/function/index.ts +19 -0
  77. package/src/sqlite/function/string.ts +2 -0
  78. package/src/sqlite/function/temporal.ts +100 -0
  79. package/src/sqlite/function/window.ts +2 -0
  80. package/src/sqlite/internal/dialect.ts +37 -0
  81. package/src/sqlite/internal/dsl.ts +6926 -0
  82. package/src/sqlite/internal/renderer.ts +47 -0
  83. package/src/sqlite/internal/sql-expression-renderer.ts +1821 -0
  84. package/src/sqlite/json.ts +2 -0
  85. package/src/sqlite/query.ts +196 -0
  86. package/src/sqlite/renderer.ts +24 -0
  87. package/src/sqlite/table.ts +183 -0
  88. package/src/sqlite.ts +22 -0
@@ -50,12 +50,33 @@ type MysqlUuidWitness = Expression.DbType.Base<"mysql", "uuid"> & {
50
50
  }
51
51
  }
52
52
 
53
+ type MysqlJsonWitness = Expression.DbType.Base<"mysql", "json"> & {
54
+ readonly family: "json"
55
+ readonly runtime: "json"
56
+ readonly compareGroup: "json"
57
+ readonly castTargets: readonly ["json", "text"]
58
+ readonly driverValueMapping: {
59
+ readonly toDriver: (value: unknown) => unknown
60
+ }
61
+ }
62
+
63
+ mysqlDatatypeModule.json = () => ({
64
+ ...withMetadata("json"),
65
+ driverValueMapping: {
66
+ toDriver: (value: unknown) =>
67
+ value !== null && typeof value === "object"
68
+ ? JSON.stringify(value)
69
+ : value
70
+ }
71
+ }) as MysqlJsonWitness
72
+
53
73
  export const mysqlDatatypes = mysqlDatatypeModule as DatatypeModule<
54
74
  "mysql",
55
75
  typeof mysqlDatatypeKinds,
56
76
  typeof mysqlDatatypeFamilies
57
77
  > & {
58
78
  readonly uuid: () => MysqlUuidWitness
79
+ readonly json: () => MysqlJsonWitness
59
80
  }
60
81
 
61
82
  export type MysqlDatatypeModule = typeof mysqlDatatypes
@@ -51636,17 +51636,17 @@ export const mysqlErrorCatalogByNumber = {
51636
51636
  "MY-015153": [mysqlErrorCatalogBySymbol["ER_WARN_AUDIT_LOG_FILTER_RECOVERY_LOGGING_DISABLED_LOG"]!],
51637
51637
  } as const
51638
51638
 
51639
- const mysqlSymbolPattern = /^(?:[A-Z][A-Z0-9_]*|MY-\d+)$/
51640
- const mysqlNumberPattern = /^(?:\d+|MY-\d+)$/
51641
-
51642
51639
  export type MysqlErrorSymbol = keyof typeof mysqlErrorCatalogBySymbol
51643
51640
  export type MysqlErrorDescriptor<Symbol extends MysqlErrorSymbol = MysqlErrorSymbol> = (typeof mysqlErrorCatalogBySymbol)[Symbol]
51644
51641
  export type MysqlErrorNumber = keyof typeof mysqlErrorCatalogByNumber
51645
51642
  export type MysqlErrorTag<Symbol extends MysqlErrorSymbol = MysqlErrorSymbol> = MysqlErrorDescriptor<Symbol>["tag"]
51646
51643
  export type MysqlErrorDescriptorsByNumber<Number extends MysqlErrorNumber = MysqlErrorNumber> = (typeof mysqlErrorCatalogByNumber)[Number]
51647
51644
 
51648
- export const isMysqlErrorSymbol = (value: string): value is MysqlErrorSymbol => mysqlSymbolPattern.test(value)
51649
- export const isMysqlErrorNumber = (value: string): value is MysqlErrorNumber => mysqlNumberPattern.test(value)
51645
+ export const isMysqlErrorSymbol = (value: string): value is MysqlErrorSymbol =>
51646
+ value in mysqlErrorCatalogBySymbol
51647
+
51648
+ export const isMysqlErrorNumber = (value: string): value is MysqlErrorNumber =>
51649
+ value in mysqlErrorCatalogByNumber
51650
51650
 
51651
51651
  export const getMysqlErrorDescriptor = <Symbol extends MysqlErrorSymbol>(symbol: Symbol): MysqlErrorDescriptor<Symbol> =>
51652
51652
  mysqlErrorCatalogBySymbol[symbol]
@@ -48,8 +48,8 @@ const asNumber = (value: unknown): number | undefined => {
48
48
  if (typeof value === "number" && Number.isFinite(value)) {
49
49
  return value
50
50
  }
51
- if (typeof value === "string" && value.trim() !== "") {
52
- const parsed = Number(value)
51
+ if (typeof value === "string" && /^[+-]?\d+$/.test(value.trim())) {
52
+ const parsed = Number(value.trim())
53
53
  return Number.isFinite(parsed) ? parsed : undefined
54
54
  }
55
55
  return undefined
@@ -5,6 +5,7 @@ import * as Stream from "effect/Stream"
5
5
  import * as CoreExecutor from "../internal/executor.js"
6
6
  import * as CoreQuery from "../internal/query.js"
7
7
  import * as CoreRenderer from "../internal/renderer.js"
8
+ import type * as Expression from "../internal/scalar.js"
8
9
  import { renderMysqlPlan } from "./internal/renderer.js"
9
10
  import {
10
11
  narrowMysqlDriverErrorForReadQuery,
@@ -28,6 +29,7 @@ export interface MakeOptions<Error = never, Context = never> {
28
29
  readonly renderer?: Renderer
29
30
  readonly driver?: Driver<Error, Context>
30
31
  readonly driverMode?: CoreExecutor.DriverMode
32
+ readonly valueMappings?: Expression.DriverValueMappings
31
33
  }
32
34
  /** Standard composed error shape for MySQL executors. */
33
35
  export type MysqlExecutorError = MysqlDriverError | RowDecodeError
@@ -101,7 +103,8 @@ const fromDriver = <
101
103
  >(
102
104
  renderer: Renderer,
103
105
  sqlDriver: Driver<Error, Context>,
104
- driverMode: CoreExecutor.DriverMode = "raw"
106
+ driverMode: CoreExecutor.DriverMode = "raw",
107
+ valueMappings?: Expression.DriverValueMappings
105
108
  ): QueryExecutor<Context> => ({
106
109
  dialect: "mysql",
107
110
  execute(plan) {
@@ -110,7 +113,7 @@ const fromDriver = <
110
113
  Effect.flatMap(
111
114
  sqlDriver.execute(rendered),
112
115
  (rows) => Effect.try({
113
- try: () => CoreExecutor.decodeRows(rendered, plan, rows, { driverMode }),
116
+ try: () => CoreExecutor.decodeRows(rendered, plan, rows, { driverMode, valueMappings }),
114
117
  catch: (error) => error as RowDecodeError
115
118
  })
116
119
  ),
@@ -131,7 +134,7 @@ const fromDriver = <
131
134
  Stream.mapChunksEffect(
132
135
  sqlDriver.stream(rendered),
133
136
  (rows) => Effect.try({
134
- try: () => CoreExecutor.decodeChunk(rendered, plan, rows, { driverMode }),
137
+ try: () => CoreExecutor.decodeChunk(rendered, plan, rows, { driverMode, valueMappings }),
135
138
  catch: (error) => error as RowDecodeError
136
139
  })
137
140
  ),
@@ -169,6 +172,7 @@ export function make(
169
172
  options: {
170
173
  readonly renderer?: Renderer
171
174
  readonly driverMode?: CoreExecutor.DriverMode
175
+ readonly valueMappings?: Expression.DriverValueMappings
172
176
  }
173
177
  ): QueryExecutor<SqlClient.SqlClient>
174
178
  export function make<Error = never, Context = never>(
@@ -176,15 +180,26 @@ export function make<Error = never, Context = never>(
176
180
  readonly renderer?: Renderer
177
181
  readonly driver: Driver<Error, Context>
178
182
  readonly driverMode?: CoreExecutor.DriverMode
183
+ readonly valueMappings?: Expression.DriverValueMappings
179
184
  }
180
185
  ): QueryExecutor<Context>
181
186
  export function make<Error = never, Context = never>(
182
187
  options: MakeOptions<Error, Context> = {}
183
188
  ): QueryExecutor<any> {
184
189
  if (options.driver) {
185
- return fromDriver(options.renderer ?? CoreRenderer.make("mysql", renderMysqlPlan), options.driver, options.driverMode)
190
+ return fromDriver(
191
+ options.renderer ?? CoreRenderer.make("mysql", (plan) => renderMysqlPlan(plan, { valueMappings: options.valueMappings })),
192
+ options.driver,
193
+ options.driverMode,
194
+ options.valueMappings
195
+ )
186
196
  }
187
- return fromDriver(options.renderer ?? CoreRenderer.make("mysql", renderMysqlPlan), sqlClientDriver(), options.driverMode)
197
+ return fromDriver(
198
+ options.renderer ?? CoreRenderer.make("mysql", (plan) => renderMysqlPlan(plan, { valueMappings: options.valueMappings })),
199
+ sqlClientDriver(),
200
+ options.driverMode,
201
+ options.valueMappings
202
+ )
188
203
  }
189
204
 
190
205
  /** Creates a MySQL-specialized executor from a typed implementation callback. */
@@ -1,15 +1,21 @@
1
- import type { RenderState, SqlDialect } from "../../internal/dialect.js"
1
+ import type { RenderState, RenderValueContext, SqlDialect } from "../../internal/dialect.js"
2
+ import { toDriverValue } from "../../internal/runtime/driver-value-mapping.js"
2
3
 
3
4
  const quoteIdentifier = (value: string): string => `\`${value.replaceAll("`", "``")}\``
4
5
 
5
- const renderLiteral = (value: unknown, state: RenderState): string => {
6
- if (value === null) {
6
+ const renderLiteral = (value: unknown, state: RenderState, context: RenderValueContext = {}): string => {
7
+ const driverValue = toDriverValue(value, {
8
+ dialect: "mysql",
9
+ valueMappings: state.valueMappings,
10
+ ...context
11
+ })
12
+ if (driverValue === null) {
7
13
  return "null"
8
14
  }
9
- if (typeof value === "boolean") {
10
- return value ? "true" : "false"
15
+ if (typeof driverValue === "boolean") {
16
+ return driverValue ? "true" : "false"
11
17
  }
12
- state.params.push(value)
18
+ state.params.push(driverValue)
13
19
  return "?"
14
20
  }
15
21