effect-qb 0.19.0 → 0.20.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 (92) hide show
  1. package/README.md +7 -1
  2. package/dist/index.js +1990 -679
  3. package/dist/mysql.js +1490 -617
  4. package/dist/postgres/metadata.js +1334 -263
  5. package/dist/postgres.js +3376 -2307
  6. package/dist/sqlite.js +1573 -628
  7. package/dist/standard.js +1984 -673
  8. package/package.json +2 -4
  9. package/src/internal/coercion/rules.ts +13 -1
  10. package/src/internal/column-state.d.ts +3 -3
  11. package/src/internal/column-state.ts +13 -12
  12. package/src/internal/column.ts +8 -8
  13. package/src/internal/datatypes/define.ts +5 -0
  14. package/src/internal/datatypes/lookup.ts +67 -18
  15. package/src/internal/datatypes/matrix.ts +903 -0
  16. package/src/internal/datatypes/shape.ts +2 -0
  17. package/src/internal/dialect-renderers/mysql.ts +6 -4
  18. package/src/internal/dialect-renderers/postgres.ts +6 -4
  19. package/src/internal/dialect-renderers/sqlite.ts +6 -4
  20. package/src/internal/dialect.ts +1 -1
  21. package/src/internal/executor.ts +56 -43
  22. package/src/internal/json/path-access.ts +351 -0
  23. package/src/internal/query.d.ts +1 -1
  24. package/src/internal/query.ts +1 -1
  25. package/src/internal/runtime/driver-value-mapping.ts +3 -3
  26. package/src/internal/runtime/schema.ts +28 -38
  27. package/src/internal/runtime/value.ts +20 -23
  28. package/src/internal/scalar.d.ts +1 -1
  29. package/src/internal/scalar.ts +2 -1
  30. package/src/internal/schema-derivation.d.ts +7 -7
  31. package/src/internal/schema-derivation.ts +11 -11
  32. package/src/internal/standard-dsl.ts +121 -28
  33. package/src/internal/table.ts +451 -120
  34. package/src/mysql/column.ts +6 -6
  35. package/src/mysql/datatypes/index.ts +1 -0
  36. package/src/mysql/datatypes/spec.ts +6 -176
  37. package/src/mysql/errors/normalize.ts +0 -1
  38. package/src/mysql/executor.ts +4 -6
  39. package/src/mysql/function/temporal.ts +1 -1
  40. package/src/mysql/internal/dsl.ts +116 -16
  41. package/src/mysql/json.ts +1 -33
  42. package/src/mysql/renderer.ts +13 -6
  43. package/src/mysql/type.ts +60 -0
  44. package/src/mysql.ts +3 -1
  45. package/src/postgres/check.ts +1 -0
  46. package/src/postgres/column.ts +11 -11
  47. package/src/postgres/datatypes/index.ts +1 -0
  48. package/src/postgres/datatypes/spec.ts +6 -260
  49. package/src/postgres/errors/normalize.ts +0 -1
  50. package/src/postgres/executor.ts +4 -6
  51. package/src/postgres/foreign-key.ts +24 -0
  52. package/src/postgres/function/temporal.ts +1 -1
  53. package/src/postgres/index.ts +1 -0
  54. package/src/postgres/internal/dsl.ts +122 -21
  55. package/src/postgres/json-extension.ts +7 -0
  56. package/src/postgres/json.ts +726 -173
  57. package/src/postgres/jsonb.ts +0 -1
  58. package/src/postgres/primary-key.ts +24 -0
  59. package/src/postgres/renderer.ts +13 -6
  60. package/src/postgres/schema-management.ts +1 -6
  61. package/src/postgres/schema.ts +16 -8
  62. package/src/postgres/table.ts +111 -113
  63. package/src/postgres/type.ts +86 -4
  64. package/src/postgres/unique.ts +32 -0
  65. package/src/postgres.ts +12 -6
  66. package/src/sqlite/column.ts +6 -6
  67. package/src/sqlite/datatypes/index.ts +1 -0
  68. package/src/sqlite/datatypes/spec.ts +6 -94
  69. package/src/sqlite/errors/normalize.ts +0 -1
  70. package/src/sqlite/executor.ts +4 -6
  71. package/src/sqlite/function/temporal.ts +1 -1
  72. package/src/sqlite/internal/dsl.ts +100 -5
  73. package/src/sqlite/json.ts +1 -32
  74. package/src/sqlite/renderer.ts +13 -6
  75. package/src/sqlite/type.ts +40 -0
  76. package/src/sqlite.ts +3 -1
  77. package/src/standard/cast.ts +113 -0
  78. package/src/standard/check.ts +17 -0
  79. package/src/standard/column.ts +10 -10
  80. package/src/standard/datatypes/index.ts +2 -2
  81. package/src/standard/datatypes/spec.ts +10 -96
  82. package/src/standard/foreign-key.ts +37 -0
  83. package/src/standard/function/temporal.ts +1 -1
  84. package/src/standard/index.ts +17 -0
  85. package/src/standard/json.ts +883 -0
  86. package/src/standard/primary-key.ts +17 -0
  87. package/src/standard/renderer.ts +31 -3
  88. package/src/standard/table.ts +25 -21
  89. package/src/standard/unique.ts +17 -0
  90. package/src/standard.ts +14 -0
  91. package/src/internal/table.d.ts +0 -174
  92. package/src/postgres/cast.ts +0 -45
@@ -16,7 +16,7 @@ import {
16
16
  import { mysqlDatatypes } from "./datatypes/index.js"
17
17
 
18
18
  const primitive = <Type, Db extends Expression.DbType.Any>(
19
- schema: Schema.Schema<Type, any, any>,
19
+ schema: Schema.Schema<Type>,
20
20
  dbType: Db
21
21
  ): ColumnDefinition<Type, Type, Type, Db, false, false, false, false, false, undefined> =>
22
22
  makeColumnDefinition(schema as Schema.Schema<NonNullable<Type>>, {
@@ -41,11 +41,11 @@ const renderNumericDdlType = (
41
41
  : `${kind}(${options.precision},${options.scale})`
42
42
  }
43
43
 
44
- export const custom = <SchemaType extends Schema.Schema.Any, Db extends Expression.DbType.Any>(
44
+ export const custom = <SchemaType extends Schema.Top, Db extends Expression.DbType.Any>(
45
45
  schema: SchemaType,
46
46
  dbType: Db
47
47
  ) =>
48
- makeColumnDefinition(schema as Schema.Schema<NonNullable<Schema.Schema.Type<SchemaType>>, any, any>, {
48
+ makeColumnDefinition(schema as unknown as Schema.Schema<NonNullable<Schema.Schema.Type<SchemaType>>>, {
49
49
  dbType: enrichDbType(mysqlDatatypes, dbType),
50
50
  nullable: false,
51
51
  hasDefault: false,
@@ -57,7 +57,7 @@ export const custom = <SchemaType extends Schema.Schema.Any, Db extends Expressi
57
57
  identity: undefined
58
58
  })
59
59
 
60
- export const uuid = () => primitive(Schema.UUID, mysqlDatatypes.uuid())
60
+ export const uuid = () => primitive(Schema.String.check(Schema.isUUID()), mysqlDatatypes.uuid())
61
61
  export const text = () => primitive(Schema.String, mysqlDatatypes.text())
62
62
  export const int = () => primitive(Schema.Int, mysqlDatatypes.int())
63
63
  export const number = (options?: BaseColumn.NumericOptions) =>
@@ -76,8 +76,8 @@ export const boolean = () => primitive(Schema.Boolean, mysqlDatatypes.boolean())
76
76
  export const date = () => primitive(LocalDateStringSchema, mysqlDatatypes.date())
77
77
  export const datetime = () => primitive(LocalDateTimeStringSchema, mysqlDatatypes.datetime())
78
78
  export const timestamp = () => primitive(LocalDateTimeStringSchema, mysqlDatatypes.timestamp())
79
- export const json = <SchemaType extends Schema.Schema.Any>(schema: SchemaType) =>
80
- makeColumnDefinition(schema as Schema.Schema<NonNullable<Schema.Schema.Type<SchemaType>>, any, any>, {
79
+ export const json = <SchemaType extends Schema.Top>(schema: SchemaType) =>
80
+ makeColumnDefinition(schema as unknown as Schema.Schema<NonNullable<Schema.Schema.Type<SchemaType>>>, {
81
81
  dbType: { ...mysqlDatatypes.json(), variant: "json" } as Expression.DbType.Json<"mysql", "json">,
82
82
  nullable: false,
83
83
  hasDefault: false,
@@ -15,6 +15,7 @@ const withMetadata = <Kind extends keyof typeof mysqlDatatypeKinds & string>(
15
15
  runtime: kindSpec.runtime,
16
16
  compareGroup: familySpec?.compareGroup,
17
17
  castTargets: familySpec?.castTargets,
18
+ implicitTargets: (familySpec as { readonly implicitTargets?: readonly string[] }).implicitTargets,
18
19
  traits: familySpec?.traits
19
20
  }
20
21
  }
@@ -1,180 +1,10 @@
1
- import type { DatatypeFamilySpec, DatatypeKindSpec } from "../../internal/datatypes/shape.js"
1
+ import {
2
+ mysqlDatatypeFamilies as matrixMysqlDatatypeFamilies,
3
+ mysqlDatatypeKinds as matrixMysqlDatatypeKinds
4
+ } from "../../internal/datatypes/matrix.js"
2
5
 
3
- export const mysqlDatatypeFamilies = {
4
- text: {
5
- compareGroup: "text",
6
- castTargets: [
7
- "text",
8
- "numeric",
9
- "boolean",
10
- "date",
11
- "time",
12
- "datetime",
13
- "timestamp",
14
- "year",
15
- "binary",
16
- "json",
17
- "bit",
18
- "enum",
19
- "set",
20
- "null"
21
- ],
22
- traits: {
23
- textual: true,
24
- ordered: true
25
- }
26
- },
27
- numeric: {
28
- compareGroup: "numeric",
29
- castTargets: ["numeric", "text", "boolean", "date", "time", "datetime", "timestamp", "year", "bit"],
30
- traits: {
31
- ordered: true
32
- }
33
- },
34
- boolean: {
35
- compareGroup: "boolean",
36
- castTargets: ["boolean", "text", "numeric"],
37
- traits: {}
38
- },
39
- bit: {
40
- compareGroup: "bit",
41
- castTargets: ["bit", "text", "numeric"],
42
- traits: {}
43
- },
44
- date: {
45
- compareGroup: "date",
46
- castTargets: ["date", "datetime", "timestamp", "text"],
47
- traits: {
48
- ordered: true
49
- }
50
- },
51
- time: {
52
- compareGroup: "time",
53
- castTargets: ["time", "datetime", "timestamp", "text"],
54
- traits: {
55
- ordered: true
56
- }
57
- },
58
- datetime: {
59
- compareGroup: "datetime",
60
- castTargets: ["datetime", "timestamp", "date", "text"],
61
- traits: {
62
- ordered: true
63
- }
64
- },
65
- timestamp: {
66
- compareGroup: "timestamp",
67
- castTargets: ["timestamp", "datetime", "date", "text"],
68
- traits: {
69
- ordered: true
70
- }
71
- },
72
- year: {
73
- compareGroup: "year",
74
- castTargets: ["year", "text", "numeric"],
75
- traits: {
76
- ordered: true
77
- }
78
- },
79
- binary: {
80
- compareGroup: "binary",
81
- castTargets: ["binary", "text"],
82
- traits: {}
83
- },
84
- json: {
85
- compareGroup: "json",
86
- castTargets: ["json", "text"],
87
- traits: {}
88
- },
89
- spatial: {
90
- compareGroup: "spatial",
91
- castTargets: ["spatial", "text"],
92
- traits: {}
93
- },
94
- enum: {
95
- compareGroup: "enum",
96
- castTargets: ["enum", "text"],
97
- traits: {
98
- textual: true,
99
- ordered: true
100
- }
101
- },
102
- set: {
103
- compareGroup: "set",
104
- castTargets: ["set", "text"],
105
- traits: {
106
- textual: true
107
- }
108
- },
109
- null: {
110
- compareGroup: "null",
111
- castTargets: [
112
- "text",
113
- "numeric",
114
- "boolean",
115
- "bit",
116
- "date",
117
- "time",
118
- "datetime",
119
- "timestamp",
120
- "year",
121
- "binary",
122
- "json",
123
- "spatial",
124
- "enum",
125
- "set",
126
- "null"
127
- ],
128
- traits: {}
129
- }
130
- } as const satisfies Record<string, DatatypeFamilySpec>
131
-
132
- export const mysqlDatatypeKinds = {
133
- char: { family: "text", runtime: "string" },
134
- varchar: { family: "text", runtime: "string" },
135
- tinytext: { family: "text", runtime: "string" },
136
- text: { family: "text", runtime: "string" },
137
- mediumtext: { family: "text", runtime: "string" },
138
- longtext: { family: "text", runtime: "string" },
139
- tinyint: { family: "numeric", runtime: "number" },
140
- smallint: { family: "numeric", runtime: "number" },
141
- mediumint: { family: "numeric", runtime: "number" },
142
- int: { family: "numeric", runtime: "number" },
143
- integer: { family: "numeric", runtime: "number" },
144
- bigint: { family: "numeric", runtime: "bigintString" },
145
- decimal: { family: "numeric", runtime: "decimalString" },
146
- dec: { family: "numeric", runtime: "decimalString" },
147
- numeric: { family: "numeric", runtime: "decimalString" },
148
- fixed: { family: "numeric", runtime: "decimalString" },
149
- float: { family: "numeric", runtime: "number" },
150
- double: { family: "numeric", runtime: "number" },
151
- real: { family: "numeric", runtime: "number" },
152
- bool: { family: "boolean", runtime: "boolean" },
153
- boolean: { family: "boolean", runtime: "boolean" },
154
- bit: { family: "bit", runtime: "string" },
155
- date: { family: "date", runtime: "localDate" },
156
- time: { family: "time", runtime: "localTime" },
157
- datetime: { family: "datetime", runtime: "localDateTime" },
158
- timestamp: { family: "timestamp", runtime: "localDateTime" },
159
- year: { family: "year", runtime: "year" },
160
- binary: { family: "binary", runtime: "bytes" },
161
- varbinary: { family: "binary", runtime: "bytes" },
162
- tinyblob: { family: "binary", runtime: "bytes" },
163
- blob: { family: "binary", runtime: "bytes" },
164
- mediumblob: { family: "binary", runtime: "bytes" },
165
- longblob: { family: "binary", runtime: "bytes" },
166
- json: { family: "json", runtime: "json" },
167
- geometry: { family: "spatial", runtime: "unknown" },
168
- point: { family: "spatial", runtime: "unknown" },
169
- linestring: { family: "spatial", runtime: "unknown" },
170
- polygon: { family: "spatial", runtime: "unknown" },
171
- multipoint: { family: "spatial", runtime: "unknown" },
172
- multilinestring: { family: "spatial", runtime: "unknown" },
173
- multipolygon: { family: "spatial", runtime: "unknown" },
174
- geometrycollection: { family: "spatial", runtime: "unknown" },
175
- enum: { family: "enum", runtime: "string" },
176
- set: { family: "set", runtime: "string" }
177
- } as const satisfies Record<string, DatatypeKindSpec>
6
+ export const mysqlDatatypeFamilies = matrixMysqlDatatypeFamilies
7
+ export const mysqlDatatypeKinds = matrixMysqlDatatypeKinds
178
8
 
179
9
  export type MysqlDatatypeFamily = keyof typeof mysqlDatatypeFamilies
180
10
  export type MysqlDatatypeKind = keyof typeof mysqlDatatypeKinds
@@ -30,7 +30,6 @@ const unwrapMysqlDriverCause = (cause: unknown): unknown => {
30
30
  while (
31
31
  isRecord(current) &&
32
32
  "_tag" in current &&
33
- current._tag === "SqlError" &&
34
33
  "cause" in current
35
34
  ) {
36
35
  current = current.cause
@@ -1,5 +1,5 @@
1
1
  import * as Effect from "effect/Effect"
2
- import * as SqlClient from "@effect/sql/SqlClient"
2
+ import * as SqlClient from "effect/unstable/sql/SqlClient"
3
3
  import * as Stream from "effect/Stream"
4
4
 
5
5
  import * as CoreExecutor from "../internal/executor.js"
@@ -41,8 +41,6 @@ export type MysqlQueryError<PlanValue extends CoreQuery.QueryPlan<any, any, any,
41
41
 
42
42
  /** Runs an effect within the ambient MySQL SQL transaction service. */
43
43
  export const withTransaction = CoreExecutor.withTransaction
44
- /** Runs an effect in a nested MySQL SQL transaction scope. */
45
- export const withSavepoint = CoreExecutor.withSavepoint
46
44
 
47
45
  /** MySQL executor whose error channel narrows based on the query plan. */
48
46
  export interface QueryExecutor<Context = never> {
@@ -133,10 +131,10 @@ const fromDriver = <
133
131
  stream(plan) {
134
132
  const rendered = renderer.render(plan)
135
133
  return Stream.mapError(
136
- Stream.mapChunksEffect(
134
+ Stream.mapArrayEffect(
137
135
  sqlDriver.stream(rendered),
138
136
  (rows) => Effect.try({
139
- try: () => CoreExecutor.decodeChunk(rendered, plan, rows, { driverMode, valueMappings }),
137
+ try: () => CoreExecutor.decodeRows(rendered, plan, rows, { driverMode, valueMappings }) as never,
140
138
  catch: (error) => error as RowDecodeError
141
139
  })
142
140
  ),
@@ -166,7 +164,7 @@ const sqlClientDriver = (): Driver<any, SqlClient.SqlClient> =>
166
164
  * Creates the standard MySQL executor pipeline.
167
165
  *
168
166
  * By default this uses the built-in MySQL renderer plus the ambient
169
- * `@effect/sql` `SqlClient`. Advanced callers can override the renderer,
167
+ * `effect/unstable/sql` `SqlClient`. Advanced callers can override the renderer,
170
168
  * driver, or both.
171
169
  */
172
170
  export function make(): QueryExecutor<SqlClient.SqlClient>
@@ -35,7 +35,7 @@ const makeTemporal = <
35
35
  >(
36
36
  name: Name,
37
37
  dbType: Db,
38
- runtimeSchema: Schema.Schema<Runtime, any, any>
38
+ runtimeSchema: Schema.Schema<Runtime>
39
39
  ): TemporalExpression<Runtime, Db, Name> =>
40
40
  makeExpression({
41
41
  runtime: undefined as unknown as Runtime,
@@ -1573,11 +1573,14 @@ const profile: QueryDialectProfile<Dialect, TextDb, NumericDb, BoolDb, Timestamp
1573
1573
 
1574
1574
  const literalSchemaOf = <Value extends LiteralValue>(
1575
1575
  value: Value
1576
- ): Schema.Schema.Any | undefined => {
1576
+ ): Schema.Top | undefined => {
1577
1577
  if (value === null || value instanceof Date) {
1578
1578
  return undefined
1579
1579
  }
1580
- return Schema.Literal(value) as Schema.Schema.Any
1580
+ if (typeof value === "number" && !Number.isFinite(value)) {
1581
+ return undefined
1582
+ }
1583
+ return Schema.Literal(value) as unknown as Schema.Top
1581
1584
  }
1582
1585
 
1583
1586
  const literal = <const Value extends LiteralValue>(
@@ -4504,6 +4507,83 @@ type ValidateTargetColumnInput<
4504
4507
  Columns extends DdlColumnInput
4505
4508
  > = ValidateTargetColumns<Target, NormalizeDdlColumns<Columns>> extends never ? never : Columns
4506
4509
 
4510
+ type SameColumnSet<
4511
+ Left extends readonly string[],
4512
+ Right extends readonly string[]
4513
+ > = string extends Left[number] | Right[number]
4514
+ ? false
4515
+ : Exclude<Left[number], Right[number]> extends never
4516
+ ? Exclude<Right[number], Left[number]> extends never
4517
+ ? true
4518
+ : false
4519
+ : false
4520
+
4521
+ type ConflictArbitersOf<Target extends MutationTargetLike> =
4522
+ Target[typeof Table.TypeId]["conflictArbiters"][number]
4523
+
4524
+ type MatchingConflictArbiter<
4525
+ Target extends MutationTargetLike,
4526
+ Columns extends readonly string[],
4527
+ AllowPartial extends boolean
4528
+ > = ConflictArbitersOf<Target> extends infer Arbiter extends Table.ConflictArbiter
4529
+ ? Arbiter extends Table.ConflictArbiter
4530
+ ? SameColumnSet<Arbiter["columns"], Columns> extends true
4531
+ ? Arbiter["scope"] extends "unconditional"
4532
+ ? true
4533
+ : AllowPartial extends true ? true : never
4534
+ : never
4535
+ : never
4536
+ : never
4537
+
4538
+ type HasInlineConflictArbiter<
4539
+ Target extends MutationTargetLike,
4540
+ Columns extends readonly string[]
4541
+ > = Columns extends readonly [infer Column extends Extract<keyof Target[typeof Table.TypeId]["fields"], string>]
4542
+ ? Target[typeof Table.TypeId]["fields"][Column] extends { readonly metadata: { readonly primaryKey: true } | { readonly unique: true } }
4543
+ ? true
4544
+ : false
4545
+ : false
4546
+
4547
+ type HasConflictArbiter<
4548
+ Target extends MutationTargetLike,
4549
+ Columns extends readonly string[],
4550
+ AllowPartial extends boolean
4551
+ > = string extends Extract<keyof Target[typeof Table.TypeId]["fields"], string>
4552
+ ? true
4553
+ : HasInlineConflictArbiter<Target, Columns> extends true
4554
+ ? true
4555
+ : true extends MatchingConflictArbiter<Target, Columns, AllowPartial> ? true : false
4556
+
4557
+ type ConflictTargetArbiterError<
4558
+ Columns,
4559
+ AllowPartial extends boolean
4560
+ > = {
4561
+ readonly __effect_qb_error__: "effect-qb: conflict target columns must match a primary key, unique constraint, or unique index"
4562
+ readonly __effect_qb_conflict_columns__: Columns
4563
+ readonly __effect_qb_partial_target__: AllowPartial
4564
+ readonly __effect_qb_hint__: "Declare the target columns as primaryKey/unique, add a table-level Unique.make(...), or use a simple Pg.Index.uniqueIndex(...)"
4565
+ }
4566
+
4567
+ type ValidateConflictColumnInput<
4568
+ Target extends MutationTargetLike,
4569
+ Columns extends DdlColumnInput,
4570
+ AllowPartial extends boolean
4571
+ > = ValidateTargetColumnInput<Target, Columns> extends never
4572
+ ? never
4573
+ : HasConflictArbiter<Target, NormalizeDdlColumns<Columns>, AllowPartial> extends true
4574
+ ? Columns
4575
+ : ConflictTargetArbiterError<NormalizeDdlColumns<Columns>, AllowPartial>
4576
+
4577
+ type ConflictColumnPlanConstraint<
4578
+ Target extends MutationTargetLike,
4579
+ Columns extends DdlColumnInput,
4580
+ AllowPartial extends boolean
4581
+ > = ValidateTargetColumnInput<Target, Columns> extends never
4582
+ ? never
4583
+ : HasConflictArbiter<Target, NormalizeDdlColumns<Columns>, AllowPartial> extends true
4584
+ ? unknown
4585
+ : ConflictTargetArbiterError<NormalizeDdlColumns<Columns>, AllowPartial>
4586
+
4507
4587
  type CreateIndexOptions<Name extends string = string> = {
4508
4588
  readonly name?: NonEmptyStringInput<Name>
4509
4589
  readonly unique?: boolean
@@ -4947,6 +5027,21 @@ type ConflictConstraintNameConstraint<Target> =
4947
5027
  ? { readonly constraint: NonEmptyStringInput<Constraint> }
4948
5028
  : unknown
4949
5029
 
5030
+ type ConflictTargetHasPredicate<Target> =
5031
+ Target extends { readonly where: PredicateInput } ? true : false
5032
+
5033
+ type ConflictTargetPlanConstraint<
5034
+ Target extends MutationTargetLike,
5035
+ ConflictTarget
5036
+ > =
5037
+ ConflictTarget extends { readonly constraint: string }
5038
+ ? unknown
5039
+ : ConflictTarget extends { readonly columns: infer Columns extends DdlColumnInput }
5040
+ ? ConflictColumnPlanConstraint<Target, Columns, ConflictTargetHasPredicate<ConflictTarget>>
5041
+ : ConflictTarget extends DdlColumnInput
5042
+ ? ConflictColumnPlanConstraint<Target, ConflictTarget, false>
5043
+ : unknown
5044
+
4950
5045
  type ConflictActionInput<
4951
5046
  Target extends MutationTargetLike,
4952
5047
  Dialect extends string,
@@ -5095,6 +5190,11 @@ type MutationTargetTupleDialectConstraint<
5095
5190
  Dialect extends string
5096
5191
  > = Exclude<TableDialectOf<Targets[number]>, Dialect | "standard"> extends never ? unknown : never
5097
5192
 
5193
+ type TableDialectConstraint<
5194
+ Target extends TableLike,
5195
+ Dialect extends string
5196
+ > = Exclude<TableDialectOf<Target>, Dialect> extends never ? unknown : never
5197
+
5098
5198
  type DuplicateMutationTargetSourceName<
5099
5199
  Targets extends readonly MutationTargetLike[],
5100
5200
  Seen extends string = never
@@ -6212,7 +6312,7 @@ type AsCurriedResult<
6212
6312
 
6213
6313
  export interface InsertApi {
6214
6314
  <Target extends MutationTargetLike>(
6215
- target: Target
6315
+ target: Target & TableDialectConstraint<Target, Dialect>
6216
6316
  ): QueryPlan<
6217
6317
  {},
6218
6318
  never,
@@ -6229,7 +6329,7 @@ type AsCurriedResult<
6229
6329
  EmptyFacts
6230
6330
  >
6231
6331
  <Target extends MutationTargetLike, Values extends Record<string, unknown>>(
6232
- target: Target,
6332
+ target: Target & TableDialectConstraint<Target, Dialect>,
6233
6333
  values: MutationValuesInput<"insert", Target, Values> & MutationValuesDialectConstraint<Values, Dialect, TextDb, NumericDb, BoolDb, TimestampDb, NullDb>
6234
6334
  ): QueryPlan<
6235
6335
  {},
@@ -6262,9 +6362,9 @@ type AsCurriedResult<
6262
6362
  >(
6263
6363
  target: ConflictTarget & ConflictConstraintNameConstraint<ConflictTarget>,
6264
6364
  options?: Options & ConflictActionUpdateNonEmptyConstraint<Options>
6265
- ) =>
6365
+ ) =>
6266
6366
  <PlanValue extends QueryPlan<any, any, any, any, any, any, any, any, any, any>>(
6267
- plan: PlanValue & RequireInsertStatement<PlanValue>
6367
+ plan: PlanValue & RequireInsertStatement<PlanValue> & ConflictTargetPlanConstraint<MutationTargetOfPlan<PlanValue>, ConflictTarget>
6268
6368
  ) => QueryPlan<
6269
6369
  SelectionOfPlan<PlanValue>,
6270
6370
  Exclude<RequiredOfPlan<PlanValue> | ConflictRequired<UpdateValues, Options, ConflictTarget>, AvailableNames<AvailableOfPlan<PlanValue>>>,
@@ -6301,7 +6401,7 @@ type AsCurriedResult<
6301
6401
  EmptyFacts
6302
6402
  >
6303
6403
  <Target extends MutationTargetLike, Values extends Record<string, unknown>>(
6304
- target: Target,
6404
+ target: Target & TableDialectConstraint<Target, Dialect>,
6305
6405
  values: MutationValuesInput<"update", Target, Values> & UpdateValuesNonEmptyConstraint<Values> & MutationValuesDialectConstraint<Values, Dialect, TextDb, NumericDb, BoolDb, TimestampDb, NullDb>
6306
6406
  ): QueryPlan<
6307
6407
  {},
@@ -6326,9 +6426,9 @@ type AsCurriedResult<
6326
6426
  const Columns extends DdlColumnInput,
6327
6427
  UpdateValues extends MutationInputOf<Table.UpdateOf<Target>> | undefined = undefined
6328
6428
  >(
6329
- target: Target,
6429
+ target: Target & TableDialectConstraint<Target, Dialect>,
6330
6430
  values: Values & MutationValuesDialectConstraint<Values, Dialect, TextDb, NumericDb, BoolDb, TimestampDb, NullDb>,
6331
- conflictColumns: ValidateTargetColumnInput<Target, Columns>,
6431
+ conflictColumns: ValidateConflictColumnInput<Target, Columns, false>,
6332
6432
  updateValues?: UpdateValues & UpdateValuesNonEmptyConstraint<Exclude<UpdateValues, undefined>> & MutationValuesDialectConstraint<Exclude<UpdateValues, undefined>, Dialect, TextDb, NumericDb, BoolDb, TimestampDb, NullDb>
6333
6433
  ) => QueryPlan<
6334
6434
  {},
@@ -6350,7 +6450,7 @@ type AsCurriedResult<
6350
6450
 
6351
6451
  interface DeleteApi {
6352
6452
  <Target extends MutationTargetLike>(
6353
- target: Target
6453
+ target: Target & TableDialectConstraint<Target, Dialect>
6354
6454
  ): QueryPlan<
6355
6455
  {},
6356
6456
  never,
@@ -6386,7 +6486,7 @@ type AsCurriedResult<
6386
6486
  }
6387
6487
 
6388
6488
  type TruncateApi = <Target extends MutationTargetLike>(
6389
- target: Target,
6489
+ target: Target & TableDialectConstraint<Target, Dialect>,
6390
6490
  options?: TruncateOptions
6391
6491
  ) => QueryPlan<
6392
6492
  {},
@@ -6419,7 +6519,7 @@ type AsCurriedResult<
6419
6519
  MatchedPredicate extends PredicateInput | undefined = undefined,
6420
6520
  NotMatchedPredicate extends PredicateInput | undefined = undefined
6421
6521
  >(
6422
- target: Target,
6522
+ target: Target & TableDialectConstraint<Target, Dialect>,
6423
6523
  source: Source & (
6424
6524
  SourceRequiredOf<Source> extends never ? unknown : SourceRequirementError<Source>
6425
6525
  ) & SourceDialectConstraint<Source, Dialect>,
@@ -6676,7 +6776,7 @@ type AsCurriedResult<
6676
6776
  >
6677
6777
 
6678
6778
  type CreateTableApi = <Target extends SchemaTableLike>(
6679
- target: Target,
6779
+ target: Target & TableDialectConstraint<Target, Dialect>,
6680
6780
  options?: CreateTableOptions
6681
6781
  ) => QueryPlan<
6682
6782
  {},
@@ -6692,7 +6792,7 @@ type AsCurriedResult<
6692
6792
  >
6693
6793
 
6694
6794
  type DropTableApi = <Target extends SchemaTableLike>(
6695
- target: Target,
6795
+ target: Target & TableDialectConstraint<Target, Dialect>,
6696
6796
  options?: DropTableOptions
6697
6797
  ) => QueryPlan<
6698
6798
  {},
@@ -6708,7 +6808,7 @@ type AsCurriedResult<
6708
6808
  >
6709
6809
 
6710
6810
  type CreateIndexApi = <Target extends SchemaTableLike, const Columns extends DdlColumnInput, Name extends string = string>(
6711
- target: Target,
6811
+ target: Target & TableDialectConstraint<Target, Dialect>,
6712
6812
  columns: Columns & ValidateDdlColumnInput<Target, Columns>,
6713
6813
  options?: CreateIndexOptions<Name>
6714
6814
  ) => QueryPlan<
@@ -6725,7 +6825,7 @@ type AsCurriedResult<
6725
6825
  >
6726
6826
 
6727
6827
  type DropIndexApi = <Target extends SchemaTableLike, const Columns extends DdlColumnInput, Name extends string = string>(
6728
- target: Target,
6828
+ target: Target & TableDialectConstraint<Target, Dialect>,
6729
6829
  columns: Columns & ValidateDdlColumnInput<Target, Columns>,
6730
6830
  options?: DropIndexOptions<Name>
6731
6831
  ) => QueryPlan<
package/src/mysql/json.ts CHANGED
@@ -1,39 +1,7 @@
1
- /** MySQL JSON expression helpers. */
2
- export { json } from "./internal/dsl.js"
1
+ /** MySQL-specific JSON expression helpers. Portable JSON helpers are exported from `effect-qb`. */
3
2
  import { json } from "./internal/dsl.js"
4
3
 
5
- export const key = json.key
6
- export const index = json.index
7
- export const wildcard = json.wildcard
8
- export const slice = json.slice
9
- export const descend = json.descend
10
- export const path = json.path
11
- export const get = json.get
12
- export const access = json.access
13
- export const traverse = json.traverse
14
- export const text = json.text
15
- export const accessText = json.accessText
16
- export const traverseText = json.traverseText
17
- export const contains = json.contains
18
- export const containedBy = json.containedBy
19
- export const hasKey = json.hasKey
20
- export const keyExists = json.keyExists
21
- export const hasAnyKeys = json.hasAnyKeys
22
- export const hasAllKeys = json.hasAllKeys
23
- export const delete_ = json.delete
24
- export { delete_ as delete }
25
- export const remove = json.remove
26
- export const set = json.set
27
- export const insert = json.insert
28
- export const concat = json.concat
29
- export const merge = json.merge
30
- export const buildObject = json.buildObject
31
- export const buildArray = json.buildArray
32
- export const toJson = json.toJson
33
- export const toJsonb = json.toJsonb
34
4
  export const typeOf = json.typeOf
35
5
  export const length = json.length
36
- export const keys = json.keys
37
6
  export const stripNulls = json.stripNulls
38
- export const pathExists = json.pathExists
39
7
  export const pathMatch = json.pathMatch
@@ -20,6 +20,9 @@ export type ValueMappings = Expression.DriverValueMappingsFor<MysqlDatatypeKind
20
20
 
21
21
  export interface MakeOptions {
22
22
  readonly valueMappings?: ValueMappings
23
+ }
24
+
25
+ interface RendererState extends MakeOptions {
23
26
  readonly casing?: Casing.Options
24
27
  }
25
28
 
@@ -33,19 +36,23 @@ const RendererProto = {
33
36
  }
34
37
 
35
38
  /** Creates the built-in MySQL renderer. */
36
- export const make = (options: MakeOptions = {}): Renderer => {
37
- const renderer = CoreRenderer.makeTrusted("mysql", (plan) => renderMysqlPlan(plan, options))
39
+ const makeWithState = (state: RendererState = {}): Renderer => {
40
+ const renderer = CoreRenderer.makeTrusted("mysql", (plan) => renderMysqlPlan(plan, state))
38
41
  return Object.assign(Object.create(RendererProto), renderer, {
39
42
  [Casing.TypeId]: {
40
- casing: options.casing
43
+ casing: state.casing
41
44
  },
42
45
  withCasing: (override: Casing.Options) =>
43
- make({
44
- ...options,
45
- casing: Casing.merge(options.casing, override)
46
+ makeWithState({
47
+ ...state,
48
+ casing: Casing.merge(state.casing, override)
46
49
  })
47
50
  }) as Renderer
48
51
  }
49
52
 
53
+ /** Creates the built-in MySQL renderer. */
54
+ export const make = (options: MakeOptions = {}): Renderer =>
55
+ makeWithState({ valueMappings: options.valueMappings })
56
+
50
57
  /** Shared built-in MySQL renderer instance. */
51
58
  export const mysql = make()
@@ -0,0 +1,60 @@
1
+ import type * as Expression from "../internal/scalar.js"
2
+ import type { NonEmptyStringInput } from "../internal/table-options.js"
3
+ import {
4
+ mysqlSpecificDatatypeKeys,
5
+ pickDatatypeConstructors,
6
+ type MysqlSpecificDatatypeKey
7
+ } from "../internal/datatypes/matrix.js"
8
+ import { mysqlDatatypes } from "./datatypes/index.js"
9
+
10
+ type MysqlSpecificDatatypes = Pick<typeof mysqlDatatypes, MysqlSpecificDatatypeKey>
11
+
12
+ type MysqlTypeNamespace = MysqlSpecificDatatypes & {
13
+ readonly enum: <Kind extends string>(kind: NonEmptyStringInput<Kind>) => Expression.DbType.Enum<"mysql", Kind>
14
+ readonly set: <Kind extends string>(kind: NonEmptyStringInput<Kind>) => Expression.DbType.Set<"mysql", Kind>
15
+ readonly custom: <Kind extends string>(kind: NonEmptyStringInput<Kind>) => Expression.DbType.Base<"mysql", Kind>
16
+ readonly driverValueMapping: <Db extends Expression.DbType.Any>(
17
+ dbType: Db,
18
+ mapping: Expression.DriverValueMapping
19
+ ) => Db
20
+ }
21
+
22
+ const enum_ = <Kind extends string>(
23
+ kind: NonEmptyStringInput<Kind>
24
+ ): Expression.DbType.Enum<"mysql", Kind> => ({
25
+ dialect: "mysql",
26
+ kind: kind as Kind,
27
+ variant: "enum"
28
+ })
29
+
30
+ const set = <Kind extends string>(
31
+ kind: NonEmptyStringInput<Kind>
32
+ ): Expression.DbType.Set<"mysql", Kind> => ({
33
+ dialect: "mysql",
34
+ kind: kind as Kind,
35
+ variant: "set"
36
+ })
37
+
38
+ const custom = <Kind extends string>(
39
+ kind: NonEmptyStringInput<Kind>
40
+ ): Expression.DbType.Base<"mysql", Kind> => ({
41
+ dialect: "mysql",
42
+ kind: kind as Kind
43
+ })
44
+
45
+ const driverValueMapping = <Db extends Expression.DbType.Any>(
46
+ dbType: Db,
47
+ mapping: Expression.DriverValueMapping
48
+ ): Db => ({
49
+ ...dbType,
50
+ driverValueMapping: mapping
51
+ })
52
+
53
+ /** MySQL-only database-type constructors for casts and typed column references. */
54
+ export const type: MysqlTypeNamespace = {
55
+ ...pickDatatypeConstructors(mysqlDatatypes, mysqlSpecificDatatypeKeys),
56
+ enum: enum_,
57
+ set,
58
+ custom,
59
+ driverValueMapping
60
+ }