effect-qb 0.19.0 → 0.21.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 +3 -6
  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
@@ -5,18 +5,15 @@ import * as Plan from "./row-set.js"
5
5
  import type { Any as AnyExpression } from "./scalar.js"
6
6
  import type { TrueFormula } from "./predicate/formula.js"
7
7
  import type { BoundColumnFrom } from "./column-state.js"
8
- import { bindColumn, type AnyColumnDefinition } from "./column-state.js"
8
+ import { bindColumn, BoundColumnTypeId, type AnyBoundColumn, type AnyColumnDefinition } from "./column-state.js"
9
9
  import {
10
10
  collectInlineOptions,
11
- normalizeColumnList,
12
11
  resolvePrimaryKeyColumns,
12
+ type ColumnList,
13
13
  type DdlExpressionLike,
14
14
  type IndexKeySpec,
15
15
  type LiteralStringInput,
16
- type MatchingColumnArityInput,
17
- type NonEmptyColumnInput,
18
16
  type NonEmptyStringInput,
19
- type NormalizeColumns,
20
17
  type ReferentialAction,
21
18
  type TableOptionSpec,
22
19
  type ValidateForeignKeyOptionColumns,
@@ -47,6 +44,7 @@ export const options: unique symbol = Symbol.for("effect-qb/Table/declaredOption
47
44
  const CacheSymbol: unique symbol = Symbol.for("effect-qb/Table/cache")
48
45
  const SchemaCacheSymbol: unique symbol = Symbol.for("effect-qb/Table/schemaCache")
49
46
  const DeclaredOptionsSymbol: unique symbol = Symbol.for("effect-qb/Table/factoryDeclaredOptions")
47
+ const ResolveOptionSymbol: unique symbol = Symbol.for("effect-qb/Table/resolveOption")
50
48
 
51
49
  type InlinePrimaryKeyKeys<Fields extends TableFieldMap> = Extract<{
52
50
  [K in keyof Fields]: Fields[K]["metadata"]["primaryKey"] extends true ? K : never
@@ -63,6 +61,43 @@ type NonEmptyFieldMap<Fields extends TableFieldMap> =
63
61
  string extends keyof Fields ? Fields : "" extends keyof Fields ? never : Fields
64
62
  type FieldColumnName<Fields extends TableFieldMap> = Extract<keyof Fields, string>
65
63
  type FieldColumnList<Fields extends TableFieldMap> = readonly [FieldColumnName<Fields>, ...FieldColumnName<Fields>[]]
64
+ export type SchemaTableDefinition = TableDefinition<any, any, any, "schema", any, any>
65
+ type LooseTableSelection = any
66
+ type ConcreteSelector<
67
+ Table extends SchemaTableDefinition,
68
+ Selection extends AnyColumnSelection
69
+ > = SchemaTableDefinition extends Table ? never : (table: Table) => Selection
70
+ type ColumnNameOfBound<Column> = Column extends {
71
+ readonly [BoundColumnTypeId]: {
72
+ readonly columnName: infer ColumnName extends string
73
+ }
74
+ } ? ColumnName : never
75
+ type BoundColumnTupleNames<Columns extends readonly AnyBoundColumn[]> =
76
+ Columns extends readonly [infer Head extends AnyBoundColumn, ...infer Tail extends AnyBoundColumn[]]
77
+ ? readonly [ColumnNameOfBound<Head>, ...BoundColumnTupleNames<Tail>]
78
+ : readonly []
79
+ type ColumnSelectionNames<Selection> =
80
+ Selection extends AnyBoundColumn
81
+ ? readonly [ColumnNameOfBound<Selection>]
82
+ : Selection extends readonly [infer Head extends AnyBoundColumn, ...infer Tail extends AnyBoundColumn[]]
83
+ ? readonly [ColumnNameOfBound<Head>, ...BoundColumnTupleNames<Tail>]
84
+ : never
85
+ export type TableColumnSelection<Table extends SchemaTableDefinition> =
86
+ TableColumn<Table> | readonly [TableColumn<Table>, ...TableColumn<Table>[]]
87
+ export type TableColumn<Table extends SchemaTableDefinition> =
88
+ SchemaTableDefinition extends Table ? AnyBoundColumn : Table extends TableDefinition<infer Name, infer Fields, any, "schema", any>
89
+ ? BoundColumns<Name, Fields>[Extract<keyof Fields, string>]
90
+ : never
91
+ export type AnyColumnSelection = AnyBoundColumn | readonly [AnyBoundColumn, ...AnyBoundColumn[]]
92
+ export type SelectedColumns<Selection extends AnyColumnSelection> = ColumnSelectionNames<Selection>
93
+ type MatchingSelectionArityInput<
94
+ Left extends AnyColumnSelection,
95
+ Right extends AnyColumnSelection
96
+ > = SelectedColumns<Left>["length"] extends SelectedColumns<Right>["length"]
97
+ ? SelectedColumns<Right>["length"] extends SelectedColumns<Left>["length"]
98
+ ? unknown
99
+ : never
100
+ : never
66
101
  type FieldIndexKeySpec<Fields extends TableFieldMap> =
67
102
  | (Extract<IndexKeySpec, { readonly kind: "column" }> & { readonly column: FieldColumnName<Fields> })
68
103
  | Extract<IndexKeySpec, { readonly kind: "expression" }>
@@ -80,12 +115,16 @@ type ClassOptionSpec<Fields extends TableFieldMap = TableFieldMap> =
80
115
  })
81
116
  | Extract<TableOptionSpec, { readonly kind: "check" }>
82
117
  interface TableOptionBuilderLike<
83
- Spec extends TableOptionSpec = TableOptionSpec
118
+ Spec extends TableOptionSpec = TableOptionSpec,
119
+ TableContext extends SchemaTableDefinition = SchemaTableDefinition
84
120
  > {
85
121
  readonly option: Spec
86
122
  }
87
123
 
88
- type ClassTableOption<Fields extends TableFieldMap> = TableOptionBuilderLike<ClassOptionSpec<Fields>>
124
+ type ClassTableOption<Fields extends TableFieldMap> = TableOption<
125
+ ClassOptionSpec<Fields>,
126
+ TableDefinition<string, Fields, keyof Fields & string, "schema", any>
127
+ >
89
128
  type ClassDeclaredTableOptions<Fields extends TableFieldMap> = readonly ClassTableOption<Fields>[]
90
129
  type TableNameOf<Table extends TableDefinition<any, any, any, "schema", any>> =
91
130
  Table extends TableDefinition<infer Name, any, any, "schema", any> ? Name : never
@@ -95,39 +134,101 @@ type TablePrimaryKeyOf<Table extends TableDefinition<any, any, any, "schema", an
95
134
  Table extends TableDefinition<any, any, infer PrimaryKeyColumns, "schema", any> ? PrimaryKeyColumns : never
96
135
  type TableSchemaNameOf<Table extends TableDefinition<any, any, any, "schema", any>> =
97
136
  Table extends TableDefinition<any, any, any, "schema", infer SchemaName> ? SchemaName : never
137
+ type HasBroadColumns<Columns extends readonly string[]> = string extends Columns[number] ? true : false
138
+
139
+ export type ConflictArbiterScope = "unconditional" | "partial"
140
+ export type ConflictArbiter<
141
+ Columns extends ColumnList = ColumnList,
142
+ Scope extends ConflictArbiterScope = ConflictArbiterScope,
143
+ Name extends string | undefined = string | undefined,
144
+ Constraint extends boolean = boolean
145
+ > = {
146
+ readonly columns: Columns
147
+ readonly scope: Scope
148
+ readonly name?: Name
149
+ readonly constraint: Constraint
150
+ }
151
+
152
+ type InlineConflictArbiters<Fields extends TableFieldMap> = Extract<{
153
+ [K in keyof Fields]: Fields[K] extends AnyColumnDefinition
154
+ ? Fields[K]["metadata"]["primaryKey"] extends true
155
+ ? ConflictArbiter<readonly [Extract<K, string>], "unconditional", undefined, true>
156
+ : Fields[K]["metadata"]["unique"] extends true
157
+ ? ConflictArbiter<
158
+ readonly [Extract<K, string>],
159
+ "unconditional",
160
+ Fields[K]["metadata"]["uniqueConstraint"] extends { readonly name?: infer Name extends string } ? Name : undefined,
161
+ true
162
+ >
163
+ : never
164
+ : never
165
+ }[keyof Fields], ConflictArbiter>
166
+
167
+ type TableConflictArbitersOf<Table extends TableDefinition<any, any, any, any, any, any>> =
168
+ Table extends TableDefinition<any, any, any, any, any, infer ConflictArbiters> ? ConflictArbiters : never
169
+
170
+ type NormalizeArbiterColumns<Columns> =
171
+ Columns extends readonly [infer Head extends string, ...infer Tail extends string[]]
172
+ ? readonly [Head, ...Tail]
173
+ : Columns extends string
174
+ ? readonly [Columns]
175
+ : never
176
+
177
+ type OptionColumns<Spec extends TableOptionSpec> =
178
+ Spec extends { readonly columns?: infer Columns } ? NormalizeArbiterColumns<Columns> : never
179
+
180
+ type OptionName<Spec extends TableOptionSpec> =
181
+ Spec extends { readonly name: infer Name extends string } ? Name : undefined
182
+
183
+ type ConflictArbiterFromOption<Spec extends TableOptionSpec> =
184
+ OptionColumns<Spec> extends infer Columns extends ColumnList
185
+ ? HasBroadColumns<Columns> extends true
186
+ ? never
187
+ : Spec extends { readonly kind: "primaryKey" | "unique" }
188
+ ? ConflictArbiter<Columns, "unconditional", OptionName<Spec>, true>
189
+ : Spec extends { readonly kind: "index"; readonly unique: true }
190
+ ? ConflictArbiter<Columns, Spec extends { readonly predicate: DdlExpressionLike } ? "partial" : "unconditional", OptionName<Spec>, false>
191
+ : never
192
+ : never
98
193
 
99
194
  type BuildPrimaryKey<
100
- Table extends TableDefinition<any, any, any, "schema", any>,
195
+ Table extends TableDefinition<any, any, any, "schema", any, any>,
101
196
  Spec extends TableOptionSpec
102
197
  > = Spec extends { readonly kind: "primaryKey"; readonly columns: infer Columns extends readonly string[] }
103
- ? Columns[number] & keyof TableFieldsOf<Table> & string
198
+ ? HasBroadColumns<Columns> extends true
199
+ ? TablePrimaryKeyOf<Table>
200
+ : Columns[number] & keyof TableFieldsOf<Table> & string
104
201
  : TablePrimaryKeyOf<Table>
105
202
 
106
203
  type OptionInputConstraint<
107
- Table extends TableDefinition<any, any, any, "schema", any>,
204
+ Table extends TableDefinition<any, any, any, "schema", any, any>,
108
205
  Spec extends TableOptionSpec
109
206
  > = Spec extends { readonly kind: "primaryKey"; readonly columns: infer Columns extends readonly string[] }
110
- ? ValidatePrimaryKeyColumns<Table[typeof TypeId]["fields"], Columns> extends never ? never : unknown
207
+ ? HasBroadColumns<Columns> extends true ? unknown : ValidatePrimaryKeyColumns<Table[typeof TypeId]["fields"], Columns> extends never ? never : unknown
111
208
  : Spec extends { readonly kind: "index" }
112
- ? ValidateIndexOptionColumns<Table[typeof TypeId]["fields"], Spec> extends never ? never : unknown
209
+ ? Spec extends { readonly columns: infer Columns extends readonly string[] }
210
+ ? HasBroadColumns<Columns> extends true ? unknown : ValidateIndexOptionColumns<Table[typeof TypeId]["fields"], Spec> extends never ? never : unknown
211
+ : ValidateIndexOptionColumns<Table[typeof TypeId]["fields"], Spec> extends never ? never : unknown
113
212
  : Spec extends { readonly kind: "foreignKey" }
114
- ? ValidateForeignKeyOptionColumns<Table[typeof TypeId]["fields"], Spec> extends never ? never : unknown
213
+ ? Spec extends { readonly columns: infer Columns extends readonly string[] }
214
+ ? HasBroadColumns<Columns> extends true ? unknown : ValidateForeignKeyOptionColumns<Table[typeof TypeId]["fields"], Spec> extends never ? never : unknown
215
+ : ValidateForeignKeyOptionColumns<Table[typeof TypeId]["fields"], Spec> extends never ? never : unknown
115
216
  : Spec extends { readonly columns: infer Columns extends readonly string[] }
116
- ? ValidateKnownColumns<Table[typeof TypeId]["fields"], Columns> extends never ? never : unknown
217
+ ? HasBroadColumns<Columns> extends true ? unknown : ValidateKnownColumns<Table[typeof TypeId]["fields"], Columns> extends never ? never : unknown
117
218
  : unknown
118
219
 
119
220
  type OptionInputTable<
120
- Table extends TableDefinition<any, any, any, "schema", any>,
221
+ Table extends TableDefinition<any, any, any, "schema", any, any>,
121
222
  Spec extends TableOptionSpec
122
223
  > = Table & OptionInputConstraint<Table, Spec>
123
224
 
124
225
  type OptionValidationArgs<
125
- Table extends TableDefinition<any, any, any, "schema", any>,
226
+ Table extends TableDefinition<any, any, any, "schema", any, any>,
126
227
  Spec extends TableOptionSpec
127
228
  > = OptionInputConstraint<Table, Spec> extends never ? [never] : []
128
229
 
129
230
  type ApplyOption<
130
- Table extends TableDefinition<any, any, any, "schema", any>,
231
+ Table extends TableDefinition<any, any, any, "schema", any, any>,
131
232
  Spec extends TableOptionSpec
132
233
  > = Spec extends { readonly kind: "primaryKey" }
133
234
  ? TableDefinition<
@@ -135,34 +236,41 @@ type ApplyOption<
135
236
  TableFieldsOf<Table>,
136
237
  BuildPrimaryKey<Table, Spec>,
137
238
  "schema",
138
- TableSchemaNameOf<Table>
239
+ TableSchemaNameOf<Table>,
240
+ TableConflictArbitersOf<Table> | ConflictArbiterFromOption<Spec>
241
+ >
242
+ : TableDefinition<
243
+ TableNameOf<Table>,
244
+ TableFieldsOf<Table>,
245
+ TablePrimaryKeyOf<Table>,
246
+ "schema",
247
+ TableSchemaNameOf<Table>,
248
+ TableConflictArbitersOf<Table> | ConflictArbiterFromOption<Spec>
139
249
  >
140
- : Table
141
250
 
142
251
  type ApplyTableOption<
143
- Table extends TableDefinition<any, any, any, "schema", any>,
252
+ Table extends TableDefinition<any, any, any, "schema", any, any>,
144
253
  Spec extends TableOptionSpec
145
- > = Spec extends { readonly kind: "primaryKey" }
146
- ? ApplyOption<Table, Spec>
147
- : Table
254
+ > = ApplyOption<Table, Spec>
148
255
 
149
256
  type TableOptionPipe<
150
257
  Name extends string,
151
258
  Fields extends TableFieldMap,
152
259
  PrimaryKeyColumns extends keyof Fields & string,
153
260
  Kind extends TableKind,
154
- SchemaName extends string | undefined
261
+ SchemaName extends string | undefined,
262
+ ConflictArbiters extends ConflictArbiter
155
263
  > = Kind extends "schema"
156
264
  ? {
157
265
  pipe<Spec extends TableOptionSpec>(
158
- option: TableOption<Spec>,
159
- ...validation: OptionValidationArgs<TableDefinition<Name, Fields, PrimaryKeyColumns, "schema", SchemaName>, Spec>
160
- ): ApplyTableOption<TableDefinition<Name, Fields, PrimaryKeyColumns, "schema", SchemaName>, Spec>
266
+ option: TableOption<Spec, TableDefinition<Name, Fields, PrimaryKeyColumns, "schema", SchemaName, ConflictArbiters>>,
267
+ ...validation: OptionValidationArgs<TableDefinition<Name, Fields, PrimaryKeyColumns, "schema", SchemaName, ConflictArbiters>, Spec>
268
+ ): ApplyTableOption<TableDefinition<Name, Fields, PrimaryKeyColumns, "schema", SchemaName, ConflictArbiters>, Spec>
161
269
  }
162
270
  : {}
163
271
 
164
272
  export type ValidateDeclaredOptions<
165
- Table extends TableDefinition<any, any, any, "schema", any>,
273
+ Table extends TableDefinition<any, any, any, "schema", any, any>,
166
274
  Options extends DeclaredTableOptions
167
275
  > = {
168
276
  readonly [K in keyof Options]: Options[K] extends TableOptionBuilderLike<infer Spec>
@@ -171,7 +279,7 @@ export type ValidateDeclaredOptions<
171
279
  }
172
280
 
173
281
  export type ApplyDeclaredOptions<
174
- Table extends TableDefinition<any, any, any, "schema", any>,
282
+ Table extends TableDefinition<any, any, any, "schema", any, any>,
175
283
  Options extends DeclaredTableOptions
176
284
  > = Options extends readonly [infer Head, ...infer Tail]
177
285
  ? Head extends TableOptionBuilderLike<infer Spec>
@@ -197,9 +305,9 @@ export interface TableSchemas<
197
305
  Fields extends TableFieldMap,
198
306
  PrimaryKeyColumns extends keyof Fields & string
199
307
  > {
200
- readonly select: Schema.Schema<SelectRow<Name, Fields>>
201
- readonly insert: Schema.Schema<InsertRow<Name, Fields>>
202
- readonly update: Schema.Schema<UpdateRow<Name, Fields, PrimaryKeyColumns>>
308
+ readonly select: Schema.ConstraintDecoder<SelectRow<Name, Fields>, never>
309
+ readonly insert: Schema.ConstraintDecoder<InsertRow<Name, Fields>, never>
310
+ readonly update: Schema.ConstraintDecoder<UpdateRow<Name, Fields, PrimaryKeyColumns>, never>
203
311
  }
204
312
 
205
313
  type AnyTableSchemas = {
@@ -221,13 +329,15 @@ interface TableState<
221
329
  Fields extends TableFieldMap,
222
330
  PrimaryKeyColumns extends keyof Fields & string,
223
331
  Kind extends TableKind = "schema",
224
- SchemaName extends string | undefined = DefaultSchemaName
332
+ SchemaName extends string | undefined = DefaultSchemaName,
333
+ ConflictArbiters extends ConflictArbiter = InlineConflictArbiters<Fields>
225
334
  > {
226
335
  readonly name: Name
227
336
  readonly baseName: string
228
337
  readonly schemaName: SchemaName
229
338
  readonly fields: Fields
230
339
  readonly primaryKey: readonly PrimaryKeyColumns[]
340
+ readonly conflictArbiters: readonly ConflictArbiters[]
231
341
  readonly kind: Kind
232
342
  readonly casing?: Casing.Options
233
343
  }
@@ -243,12 +353,13 @@ export type TableDefinition<
243
353
  Fields extends TableFieldMap,
244
354
  PrimaryKeyColumns extends keyof Fields & string = InlinePrimaryKeyKeys<Fields>,
245
355
  Kind extends TableKind = "schema",
246
- SchemaName extends string | undefined = DefaultSchemaName
247
- > = TableOptionPipe<Name, Fields, PrimaryKeyColumns, Kind, SchemaName> & Pipeable & {
356
+ SchemaName extends string | undefined = DefaultSchemaName,
357
+ ConflictArbiters extends ConflictArbiter = InlineConflictArbiters<Fields>
358
+ > = Pipeable & TableOptionPipe<Name, Fields, PrimaryKeyColumns, Kind, SchemaName, ConflictArbiters> & {
248
359
  readonly name: Name
249
360
  readonly columns: BoundColumns<Name, Fields>
250
361
  readonly schemas: TableSchemas<Name, Fields, PrimaryKeyColumns> & AnyTableSchemas
251
- readonly [TypeId]: TableState<Name, Fields, PrimaryKeyColumns, Kind, SchemaName>
362
+ readonly [TypeId]: TableState<Name, Fields, PrimaryKeyColumns, Kind, SchemaName, ConflictArbiters>
252
363
  readonly [Plan.TypeId]: Plan.State<
253
364
  BoundColumns<Name, Fields>,
254
365
  never,
@@ -274,11 +385,12 @@ export type TableClassStatic<
274
385
  Name extends string,
275
386
  Fields extends TableFieldMap,
276
387
  PrimaryKeyColumns extends keyof Fields & string = InlinePrimaryKeyKeys<Fields>,
277
- SchemaName extends string | undefined = DefaultSchemaName
388
+ SchemaName extends string | undefined = DefaultSchemaName,
389
+ ConflictArbiters extends ConflictArbiter = InlineConflictArbiters<Fields>
278
390
  > = (abstract new (...args: any[]) => any) & Pipeable & {
279
391
  readonly columns: BoundColumns<Name, Fields>
280
392
  readonly schemas: TableSchemas<Name, Fields, PrimaryKeyColumns>
281
- readonly [TypeId]: TableState<Name, Fields, PrimaryKeyColumns, "schema", SchemaName>
393
+ readonly [TypeId]: TableState<Name, Fields, PrimaryKeyColumns, "schema", SchemaName, ConflictArbiters>
282
394
  readonly [Plan.TypeId]: Plan.State<
283
395
  BoundColumns<Name, Fields>,
284
396
  never,
@@ -298,32 +410,33 @@ export type TableClassStatic<
298
410
 
299
411
  /** Minimal structural table-like contract used across helper APIs. */
300
412
  export type AnyTable<Dialect extends string = string> = {
301
- readonly [TypeId]: TableState<string, TableFieldMap, string, TableKind, string | undefined>
413
+ readonly [TypeId]: TableState<string, TableFieldMap, string, TableKind, string | undefined, ConflictArbiter>
302
414
  readonly [OptionsSymbol]: readonly TableOptionSpec[]
303
415
  } & Plan.RowSet<any, any, Record<string, Plan.AnySource>, Dialect>
304
416
 
305
- type FieldsOfAnyTable<Table extends AnyTable> = Table[typeof TypeId]["fields"]
306
-
307
- type ColumnNamesOfAnyTable<Table extends AnyTable> = Extract<keyof FieldsOfAnyTable<Table>, string>
417
+ type CheckPredicateTable = any
418
+ type CheckPredicate = (table: CheckPredicateTable) => DdlExpressionLike
308
419
 
309
420
  /** Public table-option builder type used by `Table.index`, `Table.primaryKey`, and friends. */
310
421
  export type TableOption<
311
- Spec extends TableOptionSpec = TableOptionSpec
422
+ Spec extends TableOptionSpec = TableOptionSpec,
423
+ TableContext extends SchemaTableDefinition = SchemaTableDefinition
312
424
  > = Pipeable & {
313
425
  readonly pipe: Pipeable["pipe"]
314
426
  readonly option: Spec
427
+ readonly [ResolveOptionSymbol]?: (table: TableDefinition<any, any, any, "schema", any>) => Spec
315
428
  } & (Spec extends { readonly kind: "primaryKey" }
316
429
  ? {
317
- <Table extends TableDefinition<any, any, any, "schema", any>>(
430
+ <Table extends TableContext>(
318
431
  table: Table,
319
432
  ...validation: OptionValidationArgs<Table, Spec>
320
433
  ): ApplyOption<Table, Spec>
321
434
  }
322
435
  : {
323
- <Table extends TableDefinition<any, any, any, "schema", any>>(
436
+ <Table extends TableContext>(
324
437
  table: Table,
325
438
  ...validation: OptionValidationArgs<Table, Spec>
326
- ): Table
439
+ ): ApplyOption<Table, Spec>
327
440
  })
328
441
 
329
442
  const TableProto = {
@@ -351,8 +464,42 @@ type BuildArtifacts<
351
464
  readonly columns: BoundColumns<Name, Fields>
352
465
  readonly normalizedOptions: readonly TableOptionSpec[]
353
466
  readonly primaryKey: readonly PrimaryKeyColumns[]
467
+ readonly conflictArbiters: readonly ConflictArbiter[]
354
468
  }
355
469
 
470
+ const conflictArbitersFromOptions = (
471
+ options: readonly TableOptionSpec[]
472
+ ): readonly ConflictArbiter[] =>
473
+ options.flatMap((option): readonly ConflictArbiter[] => {
474
+ if (typeof option !== "object" || option === null) {
475
+ return []
476
+ }
477
+ if (!("columns" in option) || !Array.isArray(option.columns) || option.columns.length === 0) {
478
+ return []
479
+ }
480
+ switch (option.kind) {
481
+ case "primaryKey":
482
+ case "unique":
483
+ return [{
484
+ columns: option.columns as ColumnList,
485
+ scope: "unconditional",
486
+ name: option.name,
487
+ constraint: true
488
+ }]
489
+ case "index":
490
+ return option.unique === true
491
+ ? [{
492
+ columns: option.columns as ColumnList,
493
+ scope: option.predicate === undefined ? "unconditional" : "partial",
494
+ name: option.name,
495
+ constraint: false
496
+ }]
497
+ : []
498
+ default:
499
+ return []
500
+ }
501
+ })
502
+
356
503
  const buildArtifacts = <
357
504
  Name extends string,
358
505
  Fields extends TableFieldMap,
@@ -368,13 +515,15 @@ const buildArtifacts = <
368
515
  validateFieldDialects(name, fields)
369
516
  validateOptions(name, fields, declaredOptions)
370
517
  const primaryKey = resolvePrimaryKeyColumns(fields, declaredOptions) as readonly (keyof Fields & string)[]
518
+ const conflictArbiters = conflictArbitersFromOptions(normalizedOptions)
371
519
  const columns = Object.fromEntries(
372
520
  Object.entries(fields).map(([key, column]) => [key, bindColumn(name, key, column, name, schemaName, casing)])
373
521
  ) as BoundColumns<Name, Fields>
374
522
  return {
375
523
  columns,
376
524
  normalizedOptions,
377
- primaryKey
525
+ primaryKey,
526
+ conflictArbiters
378
527
  }
379
528
  }
380
529
 
@@ -444,8 +593,8 @@ export function selectSchema<
444
593
  PrimaryKeyColumns extends keyof Fields & string
445
594
  >(
446
595
  table: TableDefinition<Name, Fields, PrimaryKeyColumns, any, any> | TableClassStatic<Name, Fields, PrimaryKeyColumns, any>
447
- ): Schema.Schema<SelectRow<Name, Fields>> {
448
- return schemaFor(table, "select") as Schema.Schema<SelectRow<Name, Fields>>
596
+ ): Schema.ConstraintDecoder<SelectRow<Name, Fields>, never> {
597
+ return schemaFor(table, "select") as Schema.ConstraintDecoder<SelectRow<Name, Fields>, never>
449
598
  }
450
599
 
451
600
  export function insertSchema<
@@ -454,8 +603,8 @@ export function insertSchema<
454
603
  PrimaryKeyColumns extends keyof Fields & string
455
604
  >(
456
605
  table: TableDefinition<Name, Fields, PrimaryKeyColumns, any, any> | TableClassStatic<Name, Fields, PrimaryKeyColumns, any>
457
- ): Schema.Schema<InsertRow<Name, Fields>> {
458
- return schemaFor(table, "insert") as Schema.Schema<InsertRow<Name, Fields>>
606
+ ): Schema.ConstraintDecoder<InsertRow<Name, Fields>, never> {
607
+ return schemaFor(table, "insert") as Schema.ConstraintDecoder<InsertRow<Name, Fields>, never>
459
608
  }
460
609
 
461
610
  export function updateSchema<
@@ -464,8 +613,8 @@ export function updateSchema<
464
613
  PrimaryKeyColumns extends keyof Fields & string
465
614
  >(
466
615
  table: TableDefinition<Name, Fields, PrimaryKeyColumns, any, any> | TableClassStatic<Name, Fields, PrimaryKeyColumns, any>
467
- ): Schema.Schema<UpdateRow<Name, Fields, PrimaryKeyColumns>> {
468
- return schemaFor(table, "update") as Schema.Schema<UpdateRow<Name, Fields, PrimaryKeyColumns>>
616
+ ): Schema.ConstraintDecoder<UpdateRow<Name, Fields, PrimaryKeyColumns>, never> {
617
+ return schemaFor(table, "update") as Schema.ConstraintDecoder<UpdateRow<Name, Fields, PrimaryKeyColumns>, never>
469
618
  }
470
619
 
471
620
  const schemasFor = <
@@ -519,7 +668,8 @@ const makeTable = <
519
668
  Fields extends TableFieldMap,
520
669
  PrimaryKeyColumns extends keyof Fields & string,
521
670
  Kind extends TableKind = "schema",
522
- SchemaName extends string | undefined = DefaultSchemaName
671
+ SchemaName extends string | undefined = DefaultSchemaName,
672
+ ConflictArbiters extends ConflictArbiter = InlineConflictArbiters<Fields>
523
673
  >(
524
674
  name: Name,
525
675
  fields: Fields,
@@ -529,7 +679,7 @@ const makeTable = <
529
679
  schemaName?: SchemaName,
530
680
  schemaMode: "default" | "explicit" = "default",
531
681
  casing?: Casing.Options
532
- ): TableDefinition<Name, Fields, PrimaryKeyColumns, Kind, SchemaName> => {
682
+ ): TableDefinition<Name, Fields, PrimaryKeyColumns, Kind, SchemaName, ConflictArbiters> => {
533
683
  const resolvedSchemaName = schemaMode === "explicit"
534
684
  ? schemaName
535
685
  : ("public" as SchemaName)
@@ -545,6 +695,7 @@ const makeTable = <
545
695
  schemaName: resolvedSchemaName,
546
696
  fields,
547
697
  primaryKey: artifacts.primaryKey,
698
+ conflictArbiters: artifacts.conflictArbiters as readonly ConflictArbiters[],
548
699
  kind,
549
700
  casing
550
701
  }
@@ -645,7 +796,8 @@ const ensureClassArtifacts = <
645
796
  const artifacts = {
646
797
  columns: table.columns,
647
798
  normalizedOptions: table[OptionsSymbol],
648
- primaryKey: table[TypeId].primaryKey as readonly PrimaryKeyColumns[]
799
+ primaryKey: table[TypeId].primaryKey as readonly PrimaryKeyColumns[],
800
+ conflictArbiters: table[TypeId].conflictArbiters
649
801
  } satisfies BuildArtifacts<Name, Fields, PrimaryKeyColumns>
650
802
  Object.defineProperty(self, CacheSymbol, {
651
803
  configurable: true,
@@ -674,7 +826,10 @@ const appendOption = <
674
826
  ) as unknown as ApplyOption<Table, Spec>
675
827
  }
676
828
 
677
- const makeOption = <Spec extends TableOptionSpec>(option: Spec): TableOption<Spec> => {
829
+ const makeOption = <
830
+ Spec extends TableOptionSpec,
831
+ TableContext extends SchemaTableDefinition = SchemaTableDefinition
832
+ >(option: Spec): TableOption<Spec, TableContext> => {
678
833
  return attachPipe(Object.assign(
679
834
  <Table extends TableDefinition<any, any, any, "schema", any>>(
680
835
  table: Table,
@@ -682,13 +837,16 @@ const makeOption = <Spec extends TableOptionSpec>(option: Spec): TableOption<Spe
682
837
  ): ApplyTableOption<Table, Spec> =>
683
838
  appendOption(table, option) as unknown as ApplyTableOption<Table, Spec>,
684
839
  { option }
685
- )) as TableOption<Spec>
840
+ )) as unknown as TableOption<Spec, TableContext>
686
841
  }
687
842
 
688
- const makeResolvedOption = <Spec extends TableOptionSpec>(
843
+ const makeResolvedOption = <
844
+ Spec extends TableOptionSpec,
845
+ TableContext extends SchemaTableDefinition = SchemaTableDefinition
846
+ >(
689
847
  option: Spec,
690
848
  resolve: (table: TableDefinition<any, any, any, "schema", any>) => Spec
691
- ): TableOption<Spec> => {
849
+ ): TableOption<Spec, TableContext> => {
692
850
  return attachPipe(Object.assign(
693
851
  <Table extends TableDefinition<any, any, any, "schema", any>>(
694
852
  table: Table,
@@ -698,19 +856,53 @@ const makeResolvedOption = <Spec extends TableOptionSpec>(
698
856
  table,
699
857
  resolve(table)
700
858
  ) as unknown as ApplyTableOption<Table, Spec>,
701
- { option }
702
- )) as TableOption<Spec>
859
+ {
860
+ option,
861
+ [ResolveOptionSymbol]: resolve
862
+ }
863
+ )) as unknown as TableOption<Spec, TableContext>
703
864
  }
704
865
 
705
866
  export const option = <Spec extends TableOptionSpec>(spec: Spec): TableOption<Spec> =>
706
867
  makeOption(spec)
707
868
 
708
- export const optionFromTable = <Spec extends TableOptionSpec>(
869
+ export const optionFromTable = <
870
+ Spec extends TableOptionSpec,
871
+ TableContext extends SchemaTableDefinition = SchemaTableDefinition
872
+ >(
709
873
  spec: Spec,
710
874
  resolve: (table: TableDefinition<any, any, any, "schema", any>) => Spec
711
- ): TableOption<Spec> =>
875
+ ): TableOption<Spec, TableContext> =>
712
876
  makeResolvedOption(spec, resolve)
713
877
 
878
+ export const resolveOption = <
879
+ Spec extends TableOptionSpec,
880
+ TableContext extends SchemaTableDefinition
881
+ >(
882
+ option: TableOption<Spec, TableContext>,
883
+ table: TableContext
884
+ ): Spec => {
885
+ const resolve = option[ResolveOptionSymbol]
886
+ return resolve === undefined ? option.option : resolve(table)
887
+ }
888
+
889
+ export const mapOption = <
890
+ Spec extends TableOptionSpec,
891
+ Next extends TableOptionSpec,
892
+ TableContext extends SchemaTableDefinition
893
+ >(
894
+ option: TableOption<Spec, TableContext>,
895
+ map: (spec: Spec) => Next
896
+ ): TableOption<Next, TableContext> => {
897
+ const resolve = option[ResolveOptionSymbol]
898
+ return resolve === undefined
899
+ ? makeOption<Next, TableContext>(map(option.option))
900
+ : makeResolvedOption<Next, TableContext>(
901
+ map(option.option),
902
+ (table) => map(resolve(table))
903
+ )
904
+ }
905
+
714
906
  /** Creates a table definition from a name and field map. */
715
907
  export function make<
716
908
  Name extends string,
@@ -732,7 +924,7 @@ export function make(
732
924
  name: string,
733
925
  fields: TableFieldMap,
734
926
  schemaName?: string
735
- ): TableDefinition<string, TableFieldMap, string, "schema", string | undefined> {
927
+ ): any {
736
928
  const resolvedSchemaName = arguments.length >= 3
737
929
  ? schemaName
738
930
  : "public"
@@ -778,7 +970,8 @@ export const withSchema = <
778
970
  Table[typeof TypeId]["fields"],
779
971
  Table[typeof TypeId]["primaryKey"][number],
780
972
  Table[typeof TypeId]["kind"],
781
- SchemaName
973
+ SchemaName,
974
+ Table[typeof TypeId]["conflictArbiters"][number]
782
975
  > => {
783
976
  const state = table[TypeId]
784
977
  return makeTable(
@@ -795,7 +988,8 @@ export const withSchema = <
795
988
  Table[typeof TypeId]["fields"],
796
989
  Table[typeof TypeId]["primaryKey"][number],
797
990
  Table[typeof TypeId]["kind"],
798
- SchemaName
991
+ SchemaName,
992
+ Table[typeof TypeId]["conflictArbiters"][number]
799
993
  >
800
994
  }
801
995
 
@@ -811,16 +1005,18 @@ export const alias = <
811
1005
  Fields extends TableFieldMap,
812
1006
  PrimaryKeyColumns extends keyof Fields & string,
813
1007
  SchemaName extends string,
1008
+ ConflictArbiters extends ConflictArbiter,
814
1009
  AliasName extends string
815
1010
  >(
816
- table: TableDefinition<Name, Fields, PrimaryKeyColumns, any, SchemaName> | TableClassStatic<Name, Fields, PrimaryKeyColumns, SchemaName>,
1011
+ table: TableDefinition<Name, Fields, PrimaryKeyColumns, any, SchemaName, ConflictArbiters> | TableClassStatic<Name, Fields, PrimaryKeyColumns, SchemaName, ConflictArbiters>,
817
1012
  aliasName: LiteralStringInput<AliasName>
818
1013
  ): TableDefinition<
819
1014
  AliasName,
820
1015
  Fields,
821
1016
  PrimaryKeyColumns,
822
1017
  "alias",
823
- SchemaName
1018
+ SchemaName,
1019
+ ConflictArbiters
824
1020
  > => {
825
1021
  const state = table[TypeId]
826
1022
  const columns = Object.fromEntries(
@@ -836,6 +1032,7 @@ export const alias = <
836
1032
  schemaName: state.schemaName,
837
1033
  fields: state.fields,
838
1034
  primaryKey: state.primaryKey,
1035
+ conflictArbiters: state.conflictArbiters,
839
1036
  kind: "alias",
840
1037
  casing: state.casing
841
1038
  }
@@ -913,12 +1110,14 @@ export function Class<
913
1110
 
914
1111
  static get [TypeId]() {
915
1112
  const declaredOptions = extractDeclaredOptions((this as unknown as TableClassStatic<Name, Fields>)[options])
1113
+ const normalizedOptions = [...collectInlineOptions(fields), ...declaredOptions]
916
1114
  return {
917
1115
  name,
918
1116
  baseName: name,
919
1117
  schemaName: resolvedSchemaName,
920
1118
  fields,
921
1119
  primaryKey: resolvePrimaryKeyColumns(fields, collectInlineOptions(fields)),
1120
+ conflictArbiters: conflictArbitersFromOptions(normalizedOptions),
922
1121
  kind: "schema"
923
1122
  }
924
1123
  }
@@ -962,88 +1161,220 @@ export function Class<
962
1161
  }
963
1162
  }
964
1163
 
1164
+ const selectionArray = (selection: AnyColumnSelection): readonly AnyBoundColumn[] =>
1165
+ (Array.isArray(selection) ? selection : [selection]) as readonly AnyBoundColumn[]
1166
+
1167
+ export const selectedColumnList = <Selection extends AnyColumnSelection>(
1168
+ selection: Selection
1169
+ ): SelectedColumns<Selection> =>
1170
+ selectionArray(selection).map((column) => column[BoundColumnTypeId].columnName) as unknown as SelectedColumns<Selection>
1171
+
1172
+ const referenceFromSelection = <Selection extends AnyColumnSelection>(selection: Selection) => {
1173
+ const columns = selectionArray(selection)
1174
+ const first = columns[0]!
1175
+ const bound = first[BoundColumnTypeId]
1176
+ return {
1177
+ tableName: bound.baseTableName,
1178
+ schemaName: bound.schemaName,
1179
+ casing: bound.casing,
1180
+ columns: columns.map((column) => column[BoundColumnTypeId].columnName) as unknown as SelectedColumns<Selection>
1181
+ }
1182
+ }
1183
+
965
1184
  /** Declares a table-level primary key. */
966
- export const primaryKey = <
967
- const Columns extends string | readonly string[]
1185
+ export function primaryKey<
1186
+ Table extends SchemaTableDefinition,
1187
+ Selection extends TableColumnSelection<Table> = TableColumnSelection<Table>
1188
+ >(
1189
+ columns: ConcreteSelector<Table, Selection>
1190
+ ): TableOption<{
1191
+ readonly kind: "primaryKey"
1192
+ readonly columns: SelectedColumns<Selection>
1193
+ }, Table>
1194
+ export function primaryKey<
1195
+ Selection extends AnyColumnSelection
968
1196
  >(
969
- columns: Columns & NonEmptyColumnInput<Columns>
1197
+ columns: (table: LooseTableSelection) => Selection
1198
+ ): TableOption<{
1199
+ readonly kind: "primaryKey"
1200
+ readonly columns: SelectedColumns<Selection>
1201
+ }>
1202
+ export function primaryKey(
1203
+ columns: (table: any) => AnyColumnSelection
970
1204
  ): TableOption<{
971
1205
  readonly kind: "primaryKey"
972
- readonly columns: NormalizeColumns<Columns>
973
- }> => makeOption({
974
- kind: "primaryKey",
975
- columns: normalizeColumnList(columns) as NormalizeColumns<Columns>
976
- })
1206
+ readonly columns: readonly [string, ...string[]]
1207
+ }> {
1208
+ return makeResolvedOption({
1209
+ kind: "primaryKey",
1210
+ columns: [] as unknown as readonly [string, ...string[]]
1211
+ }, (table) => ({
1212
+ kind: "primaryKey",
1213
+ columns: selectedColumnList(columns(table))
1214
+ }))
1215
+ }
977
1216
 
978
1217
  /** Declares a table-level unique constraint. */
979
- export const unique = <
980
- const Columns extends string | readonly string[]
1218
+ export function unique<
1219
+ Table extends SchemaTableDefinition,
1220
+ Selection extends TableColumnSelection<Table> = TableColumnSelection<Table>
1221
+ >(
1222
+ columns: ConcreteSelector<Table, Selection>
1223
+ ): TableOption<{
1224
+ readonly kind: "unique"
1225
+ readonly columns: SelectedColumns<Selection>
1226
+ }, Table>
1227
+ export function unique<
1228
+ Selection extends AnyColumnSelection
981
1229
  >(
982
- columns: Columns & NonEmptyColumnInput<Columns>
1230
+ columns: (table: LooseTableSelection) => Selection
1231
+ ): TableOption<{
1232
+ readonly kind: "unique"
1233
+ readonly columns: SelectedColumns<Selection>
1234
+ }>
1235
+ export function unique(
1236
+ columns: (table: any) => AnyColumnSelection
983
1237
  ): TableOption<{
984
1238
  readonly kind: "unique"
985
- readonly columns: NormalizeColumns<Columns>
986
- }> => makeOption({
987
- kind: "unique",
988
- columns: normalizeColumnList(columns) as NormalizeColumns<Columns>
989
- })
1239
+ readonly columns: readonly [string, ...string[]]
1240
+ }> {
1241
+ return makeResolvedOption({
1242
+ kind: "unique",
1243
+ columns: [] as unknown as readonly [string, ...string[]]
1244
+ }, (table) => ({
1245
+ kind: "unique",
1246
+ columns: selectedColumnList(columns(table))
1247
+ }))
1248
+ }
990
1249
 
991
1250
  /** Declares a table-level index. */
992
- export const index = <
993
- const Columns extends string | readonly string[]
1251
+ export function index<
1252
+ Table extends SchemaTableDefinition,
1253
+ Selection extends TableColumnSelection<Table> = TableColumnSelection<Table>
1254
+ >(
1255
+ columns: ConcreteSelector<Table, Selection>
1256
+ ): TableOption<{
1257
+ readonly kind: "index"
1258
+ readonly columns: SelectedColumns<Selection>
1259
+ }, Table>
1260
+ export function index<
1261
+ Selection extends AnyColumnSelection
994
1262
  >(
995
- columns: Columns & NonEmptyColumnInput<Columns>
1263
+ columns: (table: LooseTableSelection) => Selection
1264
+ ): TableOption<{
1265
+ readonly kind: "index"
1266
+ readonly columns: SelectedColumns<Selection>
1267
+ }>
1268
+ export function index(
1269
+ columns: (table: any) => AnyColumnSelection
996
1270
  ): TableOption<{
997
1271
  readonly kind: "index"
998
- readonly columns: NormalizeColumns<Columns>
999
- }> => makeOption({
1000
- kind: "index",
1001
- columns: normalizeColumnList(columns) as NormalizeColumns<Columns>
1002
- })
1272
+ readonly columns: readonly [string, ...string[]]
1273
+ }> {
1274
+ return makeResolvedOption({
1275
+ kind: "index",
1276
+ columns: [] as unknown as readonly [string, ...string[]]
1277
+ }, (table) => ({
1278
+ kind: "index",
1279
+ columns: selectedColumnList(columns(table))
1280
+ }))
1281
+ }
1003
1282
 
1004
1283
  /** Declares a table-level foreign key. */
1005
- export const foreignKey = <
1006
- const LocalColumns extends string | readonly string[],
1007
- TargetTable extends AnyTable,
1008
- const TargetColumns extends string | readonly string[]
1284
+ export function foreignKey<
1285
+ Table extends SchemaTableDefinition,
1286
+ LocalSelection extends TableColumnSelection<Table> = TableColumnSelection<Table>,
1287
+ TargetSelection extends AnyColumnSelection = AnyColumnSelection
1009
1288
  >(
1010
- columns: LocalColumns & NonEmptyColumnInput<LocalColumns>,
1011
- target: () => TargetTable,
1012
- referencedColumns: TargetColumns & NonEmptyColumnInput<TargetColumns> & MatchingColumnArityInput<LocalColumns, TargetColumns>
1289
+ columns: ConcreteSelector<Table, LocalSelection>,
1290
+ target: () => TargetSelection & MatchingSelectionArityInput<LocalSelection, TargetSelection>
1013
1291
  ): TableOption<{
1014
1292
  readonly kind: "foreignKey"
1015
- readonly columns: NormalizeColumns<LocalColumns>
1293
+ readonly columns: SelectedColumns<LocalSelection>
1016
1294
  readonly references: () => {
1017
1295
  readonly tableName: string
1018
1296
  readonly schemaName?: string
1019
- readonly columns: NormalizeColumns<TargetColumns>
1020
- readonly knownColumns: readonly ColumnNamesOfAnyTable<TargetTable>[]
1297
+ readonly casing?: Casing.Options
1298
+ readonly columns: SelectedColumns<TargetSelection>
1021
1299
  }
1022
- }> => makeOption({
1023
- kind: "foreignKey",
1024
- columns: normalizeColumnList(columns) as NormalizeColumns<LocalColumns>,
1025
- references: () => ({
1026
- tableName: target()[TypeId].baseName,
1027
- schemaName: target()[TypeId].schemaName,
1028
- casing: target()[TypeId].casing,
1029
- columns: normalizeColumnList(referencedColumns) as NormalizeColumns<TargetColumns>,
1030
- knownColumns: Object.keys(target()[TypeId].fields).map((key) => key as ColumnNamesOfAnyTable<TargetTable>)
1031
- })
1032
- })
1300
+ }, Table>
1301
+ export function foreignKey<
1302
+ LocalSelection extends AnyColumnSelection,
1303
+ TargetSelection extends AnyColumnSelection
1304
+ >(
1305
+ columns: (table: LooseTableSelection) => LocalSelection,
1306
+ target: () => TargetSelection
1307
+ ): TableOption<{
1308
+ readonly kind: "foreignKey"
1309
+ readonly columns: SelectedColumns<LocalSelection>
1310
+ readonly references: () => {
1311
+ readonly tableName: string
1312
+ readonly schemaName?: string
1313
+ readonly casing?: Casing.Options
1314
+ readonly columns: SelectedColumns<TargetSelection>
1315
+ }
1316
+ }>
1317
+ export function foreignKey(
1318
+ columns: (table: any) => AnyColumnSelection,
1319
+ target: () => AnyColumnSelection
1320
+ ): TableOption<{
1321
+ readonly kind: "foreignKey"
1322
+ readonly columns: readonly [string, ...string[]]
1323
+ readonly references: () => {
1324
+ readonly tableName: string
1325
+ readonly schemaName?: string
1326
+ readonly casing?: Casing.Options
1327
+ readonly columns: readonly [string, ...string[]]
1328
+ }
1329
+ }> {
1330
+ return makeResolvedOption({
1331
+ kind: "foreignKey",
1332
+ columns: [] as unknown as readonly [string, ...string[]],
1333
+ references: () => referenceFromSelection(target())
1334
+ }, (table) => ({
1335
+ kind: "foreignKey",
1336
+ columns: selectedColumnList(columns(table)),
1337
+ references: () => referenceFromSelection(target())
1338
+ }))
1339
+ }
1033
1340
 
1034
1341
  /** Declares a check constraint expression. */
1035
- export const check = <const Name extends string>(
1342
+ export function check<const Name extends string>(
1036
1343
  name: NonEmptyStringInput<Name>,
1037
1344
  predicate: DdlExpressionLike
1038
1345
  ): TableOption<{
1039
1346
  readonly kind: "check"
1040
1347
  readonly name: Name
1041
1348
  readonly predicate: DdlExpressionLike
1042
- }> => makeOption({
1043
- kind: "check",
1044
- name,
1045
- predicate
1046
- })
1349
+ }>
1350
+ export function check<const Name extends string>(
1351
+ name: NonEmptyStringInput<Name>,
1352
+ predicate: CheckPredicate
1353
+ ): TableOption<{
1354
+ readonly kind: "check"
1355
+ readonly name: Name
1356
+ readonly predicate: DdlExpressionLike
1357
+ }>
1358
+ export function check(
1359
+ name: string,
1360
+ predicate: DdlExpressionLike | CheckPredicate
1361
+ ): TableOption<{
1362
+ readonly kind: "check"
1363
+ readonly name: string
1364
+ readonly predicate: DdlExpressionLike
1365
+ }> {
1366
+ const spec = {
1367
+ kind: "check",
1368
+ name,
1369
+ predicate: predicate as DdlExpressionLike
1370
+ } as const
1371
+ return typeof predicate === "function"
1372
+ ? makeResolvedOption(spec, (table) => ({
1373
+ ...spec,
1374
+ predicate: predicate(table as CheckPredicateTable)
1375
+ }))
1376
+ : makeOption(spec)
1377
+ }
1047
1378
 
1048
1379
  /** Extracts the row type produced by `selectSchema(table)`. */
1049
1380
  export type SelectOf<Table extends AnyTable> = Table[typeof TypeId] extends {