effect-qb 0.12.3 → 0.14.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 (65) hide show
  1. package/README.md +6 -1283
  2. package/dist/mysql.js +6376 -4978
  3. package/dist/postgres/metadata.js +2724 -0
  4. package/dist/postgres.js +5475 -3636
  5. package/package.json +13 -8
  6. package/src/internal/column-state.ts +88 -6
  7. package/src/internal/column.ts +569 -34
  8. package/src/internal/datatypes/define.ts +0 -30
  9. package/src/internal/executor.ts +45 -11
  10. package/src/internal/expression-ast.ts +15 -0
  11. package/src/internal/expression.ts +3 -1
  12. package/src/internal/implication-runtime.ts +171 -0
  13. package/src/internal/mysql-query.ts +7173 -0
  14. package/src/internal/mysql-renderer.ts +2 -2
  15. package/src/internal/plan.ts +14 -4
  16. package/src/internal/{query-factory.ts → postgres-query.ts} +669 -230
  17. package/src/internal/postgres-renderer.ts +2 -2
  18. package/src/internal/postgres-schema-model.ts +144 -0
  19. package/src/internal/predicate-analysis.ts +10 -0
  20. package/src/internal/predicate-context.ts +112 -36
  21. package/src/internal/predicate-formula.ts +31 -19
  22. package/src/internal/predicate-normalize.ts +177 -106
  23. package/src/internal/predicate-runtime.ts +676 -0
  24. package/src/internal/query.ts +471 -41
  25. package/src/internal/renderer.ts +2 -2
  26. package/src/internal/runtime-schema.ts +74 -20
  27. package/src/internal/schema-ddl.ts +55 -0
  28. package/src/internal/schema-derivation.ts +93 -21
  29. package/src/internal/schema-expression.ts +44 -0
  30. package/src/internal/sql-expression-renderer.ts +123 -35
  31. package/src/internal/table-options.ts +88 -7
  32. package/src/internal/table.ts +106 -42
  33. package/src/mysql/column.ts +3 -1
  34. package/src/mysql/datatypes/index.ts +17 -2
  35. package/src/mysql/executor.ts +20 -17
  36. package/src/mysql/function/aggregate.ts +6 -0
  37. package/src/mysql/function/core.ts +5 -0
  38. package/src/mysql/function/index.ts +20 -0
  39. package/src/mysql/function/json.ts +4 -0
  40. package/src/mysql/function/string.ts +6 -0
  41. package/src/mysql/function/temporal.ts +103 -0
  42. package/src/mysql/function/window.ts +7 -0
  43. package/src/mysql/private/query.ts +1 -0
  44. package/src/mysql/query.ts +6 -26
  45. package/src/mysql.ts +2 -0
  46. package/src/postgres/cast.ts +31 -0
  47. package/src/postgres/column.ts +27 -1
  48. package/src/postgres/datatypes/index.ts +40 -5
  49. package/src/postgres/executor.ts +19 -17
  50. package/src/postgres/function/aggregate.ts +6 -0
  51. package/src/postgres/function/core.ts +16 -0
  52. package/src/postgres/function/index.ts +20 -0
  53. package/src/postgres/function/json.ts +501 -0
  54. package/src/postgres/function/string.ts +6 -0
  55. package/src/postgres/function/temporal.ts +107 -0
  56. package/src/postgres/function/window.ts +7 -0
  57. package/src/postgres/metadata.ts +31 -0
  58. package/src/postgres/private/query.ts +1 -0
  59. package/src/postgres/query.ts +6 -28
  60. package/src/postgres/schema-expression.ts +16 -0
  61. package/src/postgres/schema-management.ts +204 -0
  62. package/src/postgres/schema.ts +35 -0
  63. package/src/postgres/table.ts +307 -41
  64. package/src/postgres/type.ts +4 -0
  65. package/src/postgres.ts +16 -0
@@ -1,22 +1,36 @@
1
+ import type * as Brand from "effect/Brand"
1
2
  import * as Schema from "effect/Schema"
2
3
 
3
4
  import * as Expression from "./expression.js"
5
+ import type { CanCastDbType } from "./datatypes/lookup.js"
4
6
  import {
7
+ BigIntStringSchema,
8
+ InstantStringSchema,
5
9
  LocalDateStringSchema,
6
10
  DecimalStringSchema,
7
11
  LocalDateTimeStringSchema,
12
+ LocalTimeStringSchema,
13
+ OffsetTimeStringSchema,
8
14
  type LocalDateString,
15
+ type LocalTimeString,
16
+ type OffsetTimeString,
17
+ type InstantString,
9
18
  type DecimalString,
10
- type LocalDateTimeString
19
+ type LocalDateTimeString,
20
+ type BigIntString
11
21
  } from "./runtime-value.js"
12
22
  import {
13
23
  type AnyBoundColumn,
14
24
  type AnyColumnDefinition,
15
25
  type BaseSelectType,
16
26
  type BoundColumn,
27
+ BoundColumnTypeId,
17
28
  ColumnTypeId,
29
+ type DdlExpression,
18
30
  type ColumnDefinition,
31
+ type ColumnUniqueOptions,
19
32
  type ColumnReference,
33
+ type ColumnIndexOptions,
20
34
  type HasDefault,
21
35
  type InsertType,
22
36
  type IsGenerated,
@@ -29,6 +43,8 @@ import {
29
43
  type UpdateType
30
44
  } from "./column-state.js"
31
45
 
46
+ type ReferentialAction = "noAction" | "restrict" | "cascade" | "setNull" | "setDefault"
47
+
32
48
  type CompatibleReference<
33
49
  Self extends AnyColumnDefinition,
34
50
  Target extends AnyBoundColumn
@@ -51,7 +67,7 @@ type NullableColumn<Column extends AnyColumnDefinition> = ColumnDefinition<
51
67
  IsPrimaryKey<Column>,
52
68
  Column[typeof ColumnTypeId]["unique"],
53
69
  ReferencesOf<Column>
54
- >
70
+ > & PreserveBrand<Column>
55
71
 
56
72
  type PrimaryKeyColumn<Column extends AnyColumnDefinition> = ColumnDefinition<
57
73
  SelectType<Column>,
@@ -64,7 +80,7 @@ type PrimaryKeyColumn<Column extends AnyColumnDefinition> = ColumnDefinition<
64
80
  true,
65
81
  true,
66
82
  ReferencesOf<Column>
67
- >
83
+ > & PreserveBrand<Column>
68
84
 
69
85
  type UniqueColumn<Column extends AnyColumnDefinition> = ColumnDefinition<
70
86
  SelectType<Column>,
@@ -77,7 +93,9 @@ type UniqueColumn<Column extends AnyColumnDefinition> = ColumnDefinition<
77
93
  IsPrimaryKey<Column>,
78
94
  true,
79
95
  ReferencesOf<Column>
80
- >
96
+ > & PreserveBrand<Column>
97
+
98
+ type IndexedColumn<Column extends AnyColumnDefinition> = Column
81
99
 
82
100
  type HasDefaultColumn<Column extends AnyColumnDefinition> = ColumnDefinition<
83
101
  SelectType<Column>,
@@ -90,7 +108,20 @@ type HasDefaultColumn<Column extends AnyColumnDefinition> = ColumnDefinition<
90
108
  IsPrimaryKey<Column>,
91
109
  Column[typeof ColumnTypeId]["unique"],
92
110
  ReferencesOf<Column>
93
- >
111
+ > & PreserveBrand<Column>
112
+
113
+ type DdlTypedColumn<Column extends AnyColumnDefinition> = ColumnDefinition<
114
+ SelectType<Column>,
115
+ InsertType<Column>,
116
+ UpdateType<Column>,
117
+ Column[typeof ColumnTypeId]["dbType"],
118
+ IsNullable<Column>,
119
+ HasDefault<Column>,
120
+ IsGenerated<Column>,
121
+ IsPrimaryKey<Column>,
122
+ Column[typeof ColumnTypeId]["unique"],
123
+ ReferencesOf<Column>
124
+ > & PreserveBrand<Column>
94
125
 
95
126
  type GeneratedColumn<Column extends AnyColumnDefinition> = ColumnDefinition<
96
127
  SelectType<Column>,
@@ -103,7 +134,55 @@ type GeneratedColumn<Column extends AnyColumnDefinition> = ColumnDefinition<
103
134
  IsPrimaryKey<Column>,
104
135
  Column[typeof ColumnTypeId]["unique"],
105
136
  ReferencesOf<Column>
106
- >
137
+ > & PreserveBrand<Column>
138
+
139
+ type ByDefaultIdentityColumn<Column extends AnyColumnDefinition> = ColumnDefinition<
140
+ SelectType<Column>,
141
+ InsertType<Column>,
142
+ UpdateType<Column>,
143
+ Column[typeof ColumnTypeId]["dbType"],
144
+ IsNullable<Column>,
145
+ true,
146
+ false,
147
+ IsPrimaryKey<Column>,
148
+ Column[typeof ColumnTypeId]["unique"],
149
+ ReferencesOf<Column>
150
+ > & PreserveBrand<Column>
151
+
152
+ type AlwaysIdentityColumn<Column extends AnyColumnDefinition> = ColumnDefinition<
153
+ SelectType<Column>,
154
+ InsertType<Column>,
155
+ UpdateType<Column>,
156
+ Column[typeof ColumnTypeId]["dbType"],
157
+ IsNullable<Column>,
158
+ false,
159
+ true,
160
+ IsPrimaryKey<Column>,
161
+ Column[typeof ColumnTypeId]["unique"],
162
+ ReferencesOf<Column>
163
+ > & PreserveBrand<Column>
164
+
165
+ type CompatibleColumnExpression<
166
+ Column extends AnyColumnDefinition,
167
+ Value extends Expression.Any
168
+ > = [Expression.RuntimeOf<Value>] extends [SelectType<Column>]
169
+ ? Column
170
+ : CanCastDbType<
171
+ Expression.DbTypeOf<Value>,
172
+ Column[typeof ColumnTypeId]["dbType"],
173
+ Column[typeof ColumnTypeId]["dbType"]["dialect"]
174
+ > extends true
175
+ ? Column
176
+ : never
177
+
178
+ type CompatibleDdlExpression<
179
+ Column extends AnyColumnDefinition,
180
+ Value extends DdlExpression
181
+ > = Value extends Expression.Any ? CompatibleColumnExpression<Column, Value> : Column
182
+
183
+ type BaseInsertType<Column extends AnyColumnDefinition> = NonNullable<InsertType<Column>>
184
+
185
+ type BaseUpdateType<Column extends AnyColumnDefinition> = NonNullable<UpdateType<Column>>
107
186
 
108
187
  type ReferencingColumn<
109
188
  Column extends AnyColumnDefinition,
@@ -119,7 +198,16 @@ type ReferencingColumn<
119
198
  IsPrimaryKey<Column>,
120
199
  Column[typeof ColumnTypeId]["unique"],
121
200
  ColumnReference<Target>
122
- >
201
+ > & PreserveBrand<Column>
202
+
203
+ type ForeignKeyOptions<Target extends AnyBoundColumn> = {
204
+ readonly target: () => Target
205
+ readonly name?: string
206
+ readonly onUpdate?: ReferentialAction
207
+ readonly onDelete?: ReferentialAction
208
+ readonly deferrable?: boolean
209
+ readonly initiallyDeferred?: boolean
210
+ }
123
211
 
124
212
  type SchemaCompatibleColumn<
125
213
  Column extends AnyColumnDefinition,
@@ -151,18 +239,130 @@ type ColumnWithSchema<
151
239
  ReferencesOf<Column>,
152
240
  Column[typeof ColumnTypeId]["source"],
153
241
  Column[typeof ColumnTypeId]["dependencies"]
154
- >
242
+ > & PreserveBrand<Column>
243
+
244
+ type BrandNameOf<Column extends AnyBoundColumn> =
245
+ `${Column[typeof BoundColumnTypeId]["tableName"]}.${Column[typeof BoundColumnTypeId]["columnName"]}`
246
+
247
+ type BrandedValue<
248
+ Value,
249
+ BrandName extends string
250
+ > = [Extract<Value, null | undefined>] extends [never]
251
+ ? Value & Brand.Brand<BrandName>
252
+ : Exclude<Value, null | undefined> & Brand.Brand<BrandName> | Extract<Value, null | undefined>
253
+
254
+ type BrandMetadata<Column extends AnyColumnDefinition> = {
255
+ readonly metadata: Column["metadata"] & { readonly brand: true }
256
+ }
257
+
258
+ type PreserveBrand<Column extends AnyColumnDefinition> = Column["metadata"]["brand"] extends true
259
+ ? BrandMetadata<Column>
260
+ : {}
261
+
262
+ type BrandedColumn<
263
+ Column extends AnyBoundColumn
264
+ > = ColumnDefinition<
265
+ BrandedValue<SelectType<Column>, BrandNameOf<Column>>,
266
+ BrandedValue<InsertType<Column>, BrandNameOf<Column>>,
267
+ BrandedValue<UpdateType<Column>, BrandNameOf<Column>>,
268
+ Column[typeof ColumnTypeId]["dbType"],
269
+ IsNullable<Column>,
270
+ HasDefault<Column>,
271
+ IsGenerated<Column>,
272
+ IsPrimaryKey<Column>,
273
+ Column[typeof ColumnTypeId]["unique"],
274
+ ReferencesOf<Column>,
275
+ Column[typeof ColumnTypeId]["source"],
276
+ Column[typeof ColumnTypeId]["dependencies"]
277
+ > & BrandMetadata<Column>
278
+
279
+ type BrandMarkedColumn<
280
+ Column extends AnyColumnDefinition
281
+ > = ColumnDefinition<
282
+ SelectType<Column>,
283
+ InsertType<Column>,
284
+ UpdateType<Column>,
285
+ Column[typeof ColumnTypeId]["dbType"],
286
+ IsNullable<Column>,
287
+ HasDefault<Column>,
288
+ IsGenerated<Column>,
289
+ IsPrimaryKey<Column>,
290
+ Column[typeof ColumnTypeId]["unique"],
291
+ ReferencesOf<Column>,
292
+ Column[typeof ColumnTypeId]["source"],
293
+ Column[typeof ColumnTypeId]["dependencies"]
294
+ > & BrandMetadata<Column>
295
+
296
+ export interface ArrayOptions {
297
+ readonly nullableElements?: boolean
298
+ }
299
+
300
+ export type NumericOptions =
301
+ | {
302
+ readonly precision?: undefined
303
+ readonly scale?: undefined
304
+ }
305
+ | {
306
+ readonly precision: number
307
+ readonly scale?: number
308
+ }
309
+
310
+ type ArrayElementSelect<
311
+ Column extends AnyColumnDefinition,
312
+ Options extends ArrayOptions | undefined
313
+ > = Options extends { readonly nullableElements: true }
314
+ ? NullableSelect<BaseSelectType<Column>>
315
+ : BaseSelectType<Column>
316
+
317
+ type ArrayElementInsert<
318
+ Column extends AnyColumnDefinition,
319
+ Options extends ArrayOptions | undefined
320
+ > = Options extends { readonly nullableElements: true }
321
+ ? NullableSelect<BaseInsertType<Column>>
322
+ : BaseInsertType<Column>
323
+
324
+ type ArrayElementUpdate<
325
+ Column extends AnyColumnDefinition,
326
+ Options extends ArrayOptions | undefined
327
+ > = Options extends { readonly nullableElements: true }
328
+ ? NullableSelect<BaseUpdateType<Column>>
329
+ : BaseUpdateType<Column>
330
+
331
+ type ArrayColumn<
332
+ Column extends AnyColumnDefinition,
333
+ Options extends ArrayOptions | undefined = undefined
334
+ > = ColumnDefinition<
335
+ ReadonlyArray<ArrayElementSelect<Column, Options>>,
336
+ ReadonlyArray<ArrayElementInsert<Column, Options>>,
337
+ ReadonlyArray<ArrayElementUpdate<Column, Options>>,
338
+ Expression.DbType.Array<
339
+ Column[typeof ColumnTypeId]["dbType"]["dialect"],
340
+ Column[typeof ColumnTypeId]["dbType"],
341
+ `${Column[typeof ColumnTypeId]["dbType"]["kind"]}[]`
342
+ >,
343
+ IsNullable<Column>,
344
+ HasDefault<Column>,
345
+ IsGenerated<Column>,
346
+ IsPrimaryKey<Column>,
347
+ Column[typeof ColumnTypeId]["unique"],
348
+ ReferencesOf<Column>,
349
+ Column[typeof ColumnTypeId]["source"],
350
+ Column[typeof ColumnTypeId]["dependencies"]
351
+ > & PreserveBrand<Column>
155
352
 
156
353
  const mapColumn = <
157
354
  Column extends AnyColumnDefinition,
158
355
  Next extends AnyColumnDefinition
159
356
  >(
160
357
  column: Column,
161
- metadata: Next["metadata"]
358
+ metadata: AnyColumnDefinition["metadata"]
162
359
  ): Next => remapColumnDefinition(column as any, {
163
360
  metadata
164
361
  }) as Next
165
362
 
363
+ const isColumnDefinitionValue = (value: unknown): value is AnyColumnDefinition =>
364
+ typeof value === "object" && value !== null && ColumnTypeId in value
365
+
166
366
  const primitive = <Type, Db extends Expression.DbType.Any>(
167
367
  schema: Schema.Schema<Type, any, any>,
168
368
  dbType: Db
@@ -209,7 +409,7 @@ type ColumnModule<
209
409
  readonly uuid: () => ColumnDefinition<string, string, string, Expression.DbType.Base<Dialect, UuidKind>, false, false, false, false, false, undefined>
210
410
  readonly text: () => ColumnDefinition<string, string, string, Expression.DbType.Base<Dialect, TextKind>, false, false, false, false, false, undefined>
211
411
  readonly int: () => ColumnDefinition<number, number, number, Expression.DbType.Base<Dialect, IntKind>, false, false, false, false, false, undefined>
212
- readonly number: () => ColumnDefinition<DecimalString, DecimalString, DecimalString, Expression.DbType.Base<Dialect, NumberKind>, false, false, false, false, false, undefined>
412
+ readonly number: (options?: NumericOptions) => ColumnDefinition<DecimalString, DecimalString, DecimalString, Expression.DbType.Base<Dialect, NumberKind>, false, false, false, false, false, undefined>
213
413
  readonly boolean: () => ColumnDefinition<boolean, boolean, boolean, Expression.DbType.Base<Dialect, BooleanKind>, false, false, false, false, false, undefined>
214
414
  readonly date: () => ColumnDefinition<LocalDateString, LocalDateString, LocalDateString, Expression.DbType.Base<Dialect, DateKind>, false, false, false, false, false, undefined>
215
415
  readonly timestamp: () => ColumnDefinition<LocalDateTimeString, LocalDateTimeString, LocalDateTimeString, Expression.DbType.Base<Dialect, TimestampKind>, false, false, false, false, false, undefined>
@@ -229,12 +429,71 @@ type ColumnModule<
229
429
  >
230
430
  }
231
431
 
432
+ type PostgresColumnModule = ColumnModule<
433
+ "postgres",
434
+ "uuid",
435
+ "text",
436
+ "int4",
437
+ "numeric",
438
+ "bool",
439
+ "date",
440
+ "timestamp",
441
+ "json"
442
+ > & {
443
+ readonly int2: () => ColumnDefinition<number, number, number, Expression.DbType.Base<"postgres", "int2">, false, false, false, false, false, undefined>
444
+ readonly int8: () => ColumnDefinition<BigIntString, BigIntString, BigIntString, Expression.DbType.Base<"postgres", "int8">, false, false, false, false, false, undefined>
445
+ readonly float4: () => ColumnDefinition<number, number, number, Expression.DbType.Base<"postgres", "float4">, false, false, false, false, false, undefined>
446
+ readonly float8: () => ColumnDefinition<number, number, number, Expression.DbType.Base<"postgres", "float8">, false, false, false, false, false, undefined>
447
+ readonly char: (length?: number) => ColumnDefinition<string, string, string, Expression.DbType.Base<"postgres", "char">, false, false, false, false, false, undefined>
448
+ readonly varchar: (length?: number) => ColumnDefinition<string, string, string, Expression.DbType.Base<"postgres", "varchar">, false, false, false, false, false, undefined>
449
+ readonly time: () => ColumnDefinition<LocalTimeString, LocalTimeString, LocalTimeString, Expression.DbType.Base<"postgres", "time">, false, false, false, false, false, undefined>
450
+ readonly timetz: () => ColumnDefinition<OffsetTimeString, OffsetTimeString, OffsetTimeString, Expression.DbType.Base<"postgres", "timetz">, false, false, false, false, false, undefined>
451
+ readonly timestamptz: () => ColumnDefinition<InstantString, InstantString, InstantString, Expression.DbType.Base<"postgres", "timestamptz">, false, false, false, false, false, undefined>
452
+ readonly interval: () => ColumnDefinition<string, string, string, Expression.DbType.Base<"postgres", "interval">, false, false, false, false, false, undefined>
453
+ readonly bytea: () => ColumnDefinition<Uint8Array, Uint8Array, Uint8Array, Expression.DbType.Base<"postgres", "bytea">, false, false, false, false, false, undefined>
454
+ readonly name: () => ColumnDefinition<string, string, string, Expression.DbType.Base<"postgres", "name">, false, false, false, false, false, undefined>
455
+ readonly oid: () => ColumnDefinition<number, number, number, Expression.DbType.Base<"postgres", "oid">, false, false, false, false, false, undefined>
456
+ readonly regclass: () => ColumnDefinition<string, string, string, Expression.DbType.Base<"postgres", "regclass">, false, false, false, false, false, undefined>
457
+ readonly bit: () => ColumnDefinition<string, string, string, Expression.DbType.Base<"postgres", "bit">, false, false, false, false, false, undefined>
458
+ readonly varbit: () => ColumnDefinition<string, string, string, Expression.DbType.Base<"postgres", "varbit">, false, false, false, false, false, undefined>
459
+ readonly xml: () => ColumnDefinition<string, string, string, Expression.DbType.Base<"postgres", "xml">, false, false, false, false, false, undefined>
460
+ readonly pg_lsn: () => ColumnDefinition<string, string, string, Expression.DbType.Base<"postgres", "pg_lsn">, false, false, false, false, false, undefined>
461
+ readonly jsonb: <SchemaType extends Schema.Schema.Any>(
462
+ schema: SchemaType
463
+ ) => ColumnDefinition<
464
+ Schema.Schema.Type<SchemaType>,
465
+ Schema.Schema.Type<SchemaType>,
466
+ Schema.Schema.Type<SchemaType>,
467
+ Expression.DbType.Json<"postgres", "jsonb">,
468
+ false,
469
+ false,
470
+ false,
471
+ false,
472
+ false,
473
+ undefined
474
+ >
475
+ }
476
+
232
477
  const typeFactory = <Dialect extends string>(dialect: Dialect) =>
233
478
  <Kind extends string>(kind: Kind): Expression.DbType.Base<Dialect, Kind> => ({
234
479
  dialect,
235
480
  kind
236
481
  })
237
482
 
483
+ const postgresType = typeFactory("postgres")
484
+
485
+ const renderNumericDdlType = (
486
+ kind: string,
487
+ options?: NumericOptions
488
+ ): string | undefined => {
489
+ if (options === undefined || options.precision === undefined) {
490
+ return undefined
491
+ }
492
+ return options.scale === undefined
493
+ ? `${kind}(${options.precision})`
494
+ : `${kind}(${options.precision},${options.scale})`
495
+ }
496
+
238
497
  const makeColumnModule = <
239
498
  Dialect extends string,
240
499
  UuidKind extends string,
@@ -271,12 +530,25 @@ const makeColumnModule = <
271
530
  generated: false,
272
531
  primaryKey: false,
273
532
  unique: false,
274
- references: undefined
533
+ references: undefined,
534
+ ddlType: undefined,
535
+ identity: undefined
275
536
  }),
276
537
  uuid: () => primitive(Schema.UUID, dialectType(kinds.uuid)),
277
538
  text: () => primitive(Schema.String, dialectType(kinds.text)),
278
539
  int: () => primitive(Schema.Int, dialectType(kinds.int)),
279
- number: () => primitive(DecimalStringSchema, dialectType(kinds.number)),
540
+ number: (options?: NumericOptions) =>
541
+ makeColumnDefinition(DecimalStringSchema, {
542
+ dbType: dialectType(kinds.number),
543
+ nullable: false,
544
+ hasDefault: false,
545
+ generated: false,
546
+ primaryKey: false,
547
+ unique: false,
548
+ references: undefined,
549
+ ddlType: renderNumericDdlType(kinds.number, options),
550
+ identity: undefined
551
+ }),
280
552
  boolean: () => primitive(Schema.Boolean, dialectType(kinds.boolean)),
281
553
  date: () => primitive(LocalDateStringSchema, dialectType(kinds.date)),
282
554
  timestamp: () => primitive(LocalDateTimeStringSchema, dialectType(kinds.timestamp)),
@@ -291,13 +563,14 @@ const makeColumnModule = <
291
563
  generated: false,
292
564
  primaryKey: false,
293
565
  unique: false,
294
- references: undefined
566
+ references: undefined,
567
+ ddlType: undefined,
568
+ identity: undefined
295
569
  })
296
570
  }
297
571
  }
298
572
 
299
- /** Postgres-specialized column constructors. */
300
- export const postgres = makeColumnModule("postgres", {
573
+ const postgresBase = makeColumnModule("postgres", {
301
574
  uuid: "uuid",
302
575
  text: "text",
303
576
  int: "int4",
@@ -308,6 +581,66 @@ export const postgres = makeColumnModule("postgres", {
308
581
  json: "json"
309
582
  })
310
583
 
584
+ /** Postgres-specialized column constructors. */
585
+ export const postgres: PostgresColumnModule = {
586
+ ...postgresBase,
587
+ int2: () => primitive(Schema.Int, postgresType("int2")),
588
+ int8: () => primitive(BigIntStringSchema, postgresType("int8")),
589
+ float4: () => primitive(Schema.Number, postgresType("float4")),
590
+ float8: () => primitive(Schema.Number, postgresType("float8")),
591
+ char: (length = 1) =>
592
+ makeColumnDefinition(Schema.String, {
593
+ dbType: postgresType("char"),
594
+ nullable: false,
595
+ hasDefault: false,
596
+ generated: false,
597
+ primaryKey: false,
598
+ unique: false,
599
+ references: undefined,
600
+ ddlType: `char(${length})`,
601
+ identity: undefined
602
+ }),
603
+ varchar: (length?: number) =>
604
+ makeColumnDefinition(Schema.String, {
605
+ dbType: postgresType("varchar"),
606
+ nullable: false,
607
+ hasDefault: false,
608
+ generated: false,
609
+ primaryKey: false,
610
+ unique: false,
611
+ references: undefined,
612
+ ddlType: length === undefined ? "varchar" : `varchar(${length})`,
613
+ identity: undefined
614
+ }),
615
+ time: () => primitive(LocalTimeStringSchema, postgresType("time")),
616
+ timetz: () => primitive(OffsetTimeStringSchema, postgresType("timetz")),
617
+ timestamptz: () => primitive(InstantStringSchema, postgresType("timestamptz")),
618
+ interval: () => primitive(Schema.String, postgresType("interval")),
619
+ bytea: () => primitive(Schema.Uint8ArrayFromSelf, postgresType("bytea")),
620
+ name: () => primitive(Schema.String, postgresType("name")),
621
+ oid: () => primitive(Schema.Int, postgresType("oid")),
622
+ regclass: () => primitive(Schema.String, postgresType("regclass")),
623
+ bit: () => primitive(Schema.String, postgresType("bit")),
624
+ varbit: () => primitive(Schema.String, postgresType("varbit")),
625
+ xml: () => primitive(Schema.String, postgresType("xml")),
626
+ pg_lsn: () => primitive(Schema.String, postgresType("pg_lsn")),
627
+ jsonb: <SchemaType extends Schema.Schema.Any>(schema: SchemaType) =>
628
+ makeColumnDefinition(schema as unknown as Schema.Schema<NonNullable<Schema.Schema.Type<SchemaType>>, any, any>, {
629
+ dbType: {
630
+ ...postgresType("jsonb"),
631
+ variant: "jsonb"
632
+ } as Expression.DbType.Json<"postgres", "jsonb">,
633
+ nullable: false,
634
+ hasDefault: false,
635
+ generated: false,
636
+ primaryKey: false,
637
+ unique: false,
638
+ references: undefined,
639
+ ddlType: undefined,
640
+ identity: undefined
641
+ })
642
+ }
643
+
311
644
  /** MySQL-specialized column constructors. */
312
645
  export const mysql = makeColumnModule("mysql", {
313
646
  uuid: "uuid",
@@ -326,17 +659,55 @@ export const uuid = postgres.uuid
326
659
  export const text = postgres.text
327
660
  /** Creates a Postgres `int4` column. */
328
661
  export const int = postgres.int
662
+ /** Creates a Postgres `int2` column. */
663
+ export const int2 = postgres.int2
664
+ /** Creates a Postgres `int8` column. */
665
+ export const int8 = postgres.int8
329
666
  /** Creates a Postgres `numeric` column decoded as `DecimalString`. */
330
667
  export const number = postgres.number
668
+ /** Creates a Postgres `float4` column. */
669
+ export const float4 = postgres.float4
670
+ /** Creates a Postgres `float8` column. */
671
+ export const float8 = postgres.float8
331
672
  /** Creates a Postgres `bool` column. */
332
673
  export const boolean = postgres.boolean
333
674
  /** Creates a Postgres `date` column decoded as `LocalDateString`. */
334
675
  export const date = postgres.date
335
676
  /** Creates a Postgres `timestamp` column decoded as `LocalDateTimeString`. */
336
677
  export const timestamp = postgres.timestamp
678
+ /** Creates a Postgres `time` column decoded as `LocalTimeString`. */
679
+ export const time = postgres.time
680
+ /** Creates a Postgres `timetz` column decoded as `OffsetTimeString`. */
681
+ export const timetz = postgres.timetz
682
+ /** Creates a Postgres `timestamptz` column decoded as `InstantString`. */
683
+ export const timestamptz = postgres.timestamptz
684
+ /** Creates a Postgres `char` column. */
685
+ export const char = postgres.char
686
+ /** Creates a Postgres `varchar` column. */
687
+ export const varchar = postgres.varchar
688
+ /** Creates a Postgres `interval` column. */
689
+ export const interval = postgres.interval
690
+ /** Creates a Postgres `bytea` column. */
691
+ export const bytea = postgres.bytea
692
+ /** Creates a Postgres `name` column. */
693
+ export const name = postgres.name
694
+ /** Creates a Postgres `oid` column. */
695
+ export const oid = postgres.oid
696
+ /** Creates a Postgres `regclass` column. */
697
+ export const regclass = postgres.regclass
698
+ /** Creates a Postgres `bit` column. */
699
+ export const bit = postgres.bit
700
+ /** Creates a Postgres `varbit` column. */
701
+ export const varbit = postgres.varbit
702
+ /** Creates a Postgres `xml` column. */
703
+ export const xml = postgres.xml
704
+ /** Creates a Postgres `pg_lsn` column. */
705
+ export const pg_lsn = postgres.pg_lsn
337
706
 
338
707
  /** Creates a Postgres `json` column backed by an arbitrary Effect schema. */
339
708
  export const json = postgres.json
709
+ /** Creates a Postgres `jsonb` column backed by an arbitrary Effect schema. */
710
+ export const jsonb = postgres.jsonb
340
711
  /** Creates a Postgres column backed by an arbitrary SQL type and Effect schema. */
341
712
  export const custom = postgres.custom
342
713
 
@@ -349,6 +720,33 @@ export const schema = <SchemaType extends Schema.Schema.Any>(nextSchema: SchemaT
349
720
  schema: nextSchema
350
721
  }) as ColumnWithSchema<Column, SchemaType>
351
722
 
723
+ type BrandResult<Column extends AnyColumnDefinition> = Column extends AnyBoundColumn
724
+ ? BrandedColumn<Column>
725
+ : BrandMarkedColumn<Column>
726
+
727
+ /** Brands a column with its `table.column` provenance. */
728
+ export const brand = <Column extends AnyColumnDefinition>(
729
+ column: Column
730
+ ): BrandResult<Column> => {
731
+ if (BoundColumnTypeId in column) {
732
+ const boundColumn = column as unknown as AnyBoundColumn
733
+ const brandName = `${boundColumn[BoundColumnTypeId].tableName}.${boundColumn[BoundColumnTypeId].columnName}`
734
+ return remapColumnDefinition(boundColumn, {
735
+ schema: Schema.brand(brandName)(boundColumn.schema),
736
+ metadata: {
737
+ ...boundColumn.metadata,
738
+ brand: true
739
+ }
740
+ }) as BrandResult<Column>
741
+ }
742
+ return remapColumnDefinition(column, {
743
+ metadata: {
744
+ ...column.metadata,
745
+ brand: true
746
+ }
747
+ }) as BrandResult<Column>
748
+ }
749
+
352
750
  /** Marks a column as nullable. Nullable columns decode as `T | null`. */
353
751
  export const nullable = <Column extends AnyColumnDefinition>(
354
752
  column: Column[typeof ColumnTypeId]["primaryKey"] extends true ? never : Column
@@ -369,32 +767,142 @@ export const primaryKey = <Column extends AnyColumnDefinition>(
369
767
  unique: true
370
768
  })
371
769
 
770
+ type UniqueModifier = {
771
+ <Column extends AnyColumnDefinition>(column: Column): UniqueColumn<Column>
772
+ readonly options: <const Options extends ColumnUniqueOptions>(
773
+ options: Options
774
+ ) => <Column extends AnyColumnDefinition>(column: Column) => UniqueColumn<Column>
775
+ }
776
+
372
777
  /** Marks a column as unique. */
373
- export const unique = <Column extends AnyColumnDefinition>(
778
+ export const unique: UniqueModifier = Object.assign(
779
+ <Column extends AnyColumnDefinition>(column: Column): UniqueColumn<Column> =>
780
+ mapColumn(column, {
781
+ ...column.metadata,
782
+ unique: true
783
+ }),
784
+ {
785
+ options: <const Options extends ColumnUniqueOptions>(options: Options) =>
786
+ <Column extends AnyColumnDefinition>(column: Column): UniqueColumn<Column> =>
787
+ mapColumn(column, {
788
+ ...column.metadata,
789
+ unique: true,
790
+ uniqueConstraint: options
791
+ })
792
+ }
793
+ )
794
+
795
+ /** Marks a column as having a database default expression and therefore optional on insert. */
796
+ export const default_ = <Value extends DdlExpression>(value: Value) =>
797
+ <Column extends AnyColumnDefinition>(
798
+ column: Column[typeof ColumnTypeId]["generated"] extends true ? never : CompatibleDdlExpression<Column, Value>
799
+ ): HasDefaultColumn<Column> =>
800
+ mapColumn(column, {
801
+ ...column.metadata,
802
+ hasDefault: true,
803
+ defaultValue: value,
804
+ generatedValue: undefined,
805
+ identity: undefined
806
+ })
807
+
808
+ /** Marks a column as generated by the database expression and omitted from insert/update. */
809
+ export const generated = <Value extends DdlExpression>(value: Value) =>
810
+ <Column extends AnyColumnDefinition>(
811
+ column: Column[typeof ColumnTypeId]["hasDefault"] extends true ? never : CompatibleDdlExpression<Column, Value>
812
+ ): GeneratedColumn<Column> =>
813
+ mapColumn(column, {
814
+ ...column.metadata,
815
+ generated: true,
816
+ hasDefault: false,
817
+ defaultValue: undefined,
818
+ generatedValue: value,
819
+ identity: undefined
820
+ })
821
+
822
+ /** Preserves the exact SQL type used for DDL rendering. */
823
+ export const ddlType = <SqlType extends string>(sqlType: SqlType) =>
824
+ <Column extends AnyColumnDefinition>(column: Column): DdlTypedColumn<Column> =>
825
+ mapColumn(column, {
826
+ ...column.metadata,
827
+ ddlType: sqlType
828
+ })
829
+
830
+ /** Marks a column as a Postgres array type. */
831
+ export const array = <Options extends ArrayOptions | undefined = undefined>(
832
+ options?: Options
833
+ ) =>
834
+ <Column extends AnyColumnDefinition>(
835
+ column: Column
836
+ ): ArrayColumn<Column, Options> =>
837
+ remapColumnDefinition(column as AnyColumnDefinition, {
838
+ schema: Schema.Array(options?.nullableElements ? Schema.NullOr(column.schema) : column.schema),
839
+ metadata: {
840
+ ...column.metadata,
841
+ dbType: {
842
+ dialect: column.metadata.dbType.dialect,
843
+ kind: `${column.metadata.dbType.kind}[]`,
844
+ element: column.metadata.dbType
845
+ } as Expression.DbType.Array<
846
+ Column[typeof ColumnTypeId]["dbType"]["dialect"],
847
+ Column[typeof ColumnTypeId]["dbType"],
848
+ `${Column[typeof ColumnTypeId]["dbType"]["kind"]}[]`
849
+ >,
850
+ ddlType: `${column.metadata.ddlType ?? column.metadata.dbType.kind}[]`
851
+ }
852
+ }) as ArrayColumn<Column, Options>
853
+
854
+ /** Marks a column as indexed. */
855
+ export function index<Column extends AnyColumnDefinition>(
374
856
  column: Column
375
- ): UniqueColumn<Column> =>
376
- mapColumn(column, {
377
- ...column.metadata,
378
- unique: true
379
- })
857
+ ): IndexedColumn<Column>
858
+ export function index<const Options extends ColumnIndexOptions>(
859
+ options: Options
860
+ ): <Column extends AnyColumnDefinition>(column: Column) => IndexedColumn<Column>
861
+ export function index(arg: unknown): unknown {
862
+ if (isColumnDefinitionValue(arg)) {
863
+ return mapColumn(arg, {
864
+ ...arg.metadata,
865
+ index: arg.metadata.index ?? {}
866
+ })
867
+ }
868
+ const options = (arg ?? {}) as ColumnIndexOptions
869
+ return <Column extends AnyColumnDefinition>(
870
+ column: Column
871
+ ): IndexedColumn<Column> =>
872
+ mapColumn(column, {
873
+ ...column.metadata,
874
+ index: options
875
+ })
876
+ }
380
877
 
381
- /** Marks a column as having a server-side default and therefore optional on insert. */
382
- export const hasDefault = <Column extends AnyColumnDefinition>(
878
+ /** Marks a column as `generated by default as identity`. */
879
+ export const identityByDefault = <Column extends AnyColumnDefinition>(
383
880
  column: Column[typeof ColumnTypeId]["generated"] extends true ? never : Column
384
- ): HasDefaultColumn<Column> =>
881
+ ): ByDefaultIdentityColumn<Column> =>
385
882
  mapColumn(column, {
386
883
  ...column.metadata,
387
- hasDefault: true
884
+ hasDefault: true,
885
+ generated: false,
886
+ defaultValue: undefined,
887
+ generatedValue: undefined,
888
+ identity: {
889
+ generation: "byDefault"
890
+ }
388
891
  })
389
892
 
390
- /** Marks a column as generated by the database and omitted from insert/update. */
391
- export const generated = <Column extends AnyColumnDefinition>(
893
+ /** Marks a column as `generated always as identity`. */
894
+ export const identityAlways = <Column extends AnyColumnDefinition>(
392
895
  column: Column[typeof ColumnTypeId]["hasDefault"] extends true ? never : Column
393
- ): GeneratedColumn<Column> =>
896
+ ): AlwaysIdentityColumn<Column> =>
394
897
  mapColumn(column, {
395
898
  ...column.metadata,
899
+ hasDefault: false,
396
900
  generated: true,
397
- hasDefault: false
901
+ defaultValue: undefined,
902
+ generatedValue: undefined,
903
+ identity: {
904
+ generation: "always"
905
+ }
398
906
  })
399
907
 
400
908
  /**
@@ -402,16 +910,43 @@ export const generated = <Column extends AnyColumnDefinition>(
402
910
  *
403
911
  * The base, non-null select types must match.
404
912
  */
405
- export const references = <Target extends AnyBoundColumn>(target: () => Target) =>
406
- <Column extends AnyColumnDefinition>(
407
- column: CompatibleReference<Column, Target>
408
- ): ReferencingColumn<Column, Target> =>
913
+ export function foreignKey<Target extends AnyBoundColumn>(
914
+ target: () => Target
915
+ ): <Column extends AnyColumnDefinition>(
916
+ column: CompatibleReference<Column, Target>
917
+ ) => ReferencingColumn<Column, Target>
918
+ export function foreignKey<const Options extends ForeignKeyOptions<AnyBoundColumn>>(
919
+ options: Options
920
+ ): <Column extends AnyColumnDefinition>(
921
+ column: CompatibleReference<Column, ReturnType<Options["target"]>>
922
+ ) => ReferencingColumn<Column, ReturnType<Options["target"]>>
923
+ export function foreignKey(arg: unknown): unknown {
924
+ if (typeof arg === "function") {
925
+ const target = arg as () => AnyBoundColumn
926
+ return <Column extends AnyColumnDefinition>(
927
+ column: CompatibleReference<Column, AnyBoundColumn>
928
+ ): ReferencingColumn<Column, AnyBoundColumn> =>
929
+ mapColumn(column, {
930
+ ...column.metadata,
931
+ references: { target }
932
+ })
933
+ }
934
+ const options = arg as ForeignKeyOptions<AnyBoundColumn>
935
+ return <Column extends AnyColumnDefinition>(
936
+ column: CompatibleReference<Column, ReturnType<typeof options.target>>
937
+ ): ReferencingColumn<Column, ReturnType<typeof options.target>> =>
409
938
  mapColumn(column, {
410
939
  ...column.metadata,
411
- references: { target }
940
+ references: options
412
941
  })
942
+ }
943
+
944
+ export const references = <Target extends AnyBoundColumn>(target: () => Target) =>
945
+ foreignKey(target)
413
946
 
414
947
  /** Convenience alias for any column definition. */
415
948
  export type Any = AnyColumnDefinition
416
949
  /** Convenience alias for any bound column. */
417
950
  export type AnyBound = BoundColumn<any, any, any, any, any, any, any, any, any, any, any, any>
951
+
952
+ export { default_ as default }