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
@@ -27,7 +27,7 @@ import {
27
27
  } from "./value.js"
28
28
  import type { RuntimeTag } from "../datatypes/shape.js"
29
29
 
30
- export type RuntimeSchema = Schema.Schema<any, any, any>
30
+ export type RuntimeSchema = Schema.Top
31
31
 
32
32
  type SchemaContext = {
33
33
  readonly assumptions: PredicateFormula
@@ -38,7 +38,7 @@ const schemaCache = new WeakMap<Expression.Any, RuntimeSchema | undefined>()
38
38
  const isRecord = (value: unknown): value is Record<string, unknown> =>
39
39
  typeof value === "object" && value !== null && !Array.isArray(value)
40
40
 
41
- const FiniteNumberSchema = Schema.Number.pipe(Schema.finite())
41
+ const FiniteNumberSchema = Schema.Number.check(Schema.isFinite())
42
42
 
43
43
  const runtimeSchemaForTag = (tag: RuntimeTag): RuntimeSchema | undefined => {
44
44
  switch (tag) {
@@ -67,14 +67,11 @@ const runtimeSchemaForTag = (tag: RuntimeTag): RuntimeSchema | undefined => {
67
67
  case "decimalString":
68
68
  return DecimalStringSchema
69
69
  case "bytes":
70
- return Schema.Uint8ArrayFromSelf
70
+ return Schema.Uint8Array
71
71
  case "array":
72
72
  return Schema.Array(Schema.Unknown)
73
73
  case "record":
74
- return Schema.Record({
75
- key: Schema.String,
76
- value: Schema.Unknown
77
- })
74
+ return Schema.Record(Schema.String, Schema.Unknown)
78
75
  case "null":
79
76
  return Schema.Null
80
77
  case "unknown":
@@ -114,7 +111,7 @@ export const runtimeSchemaForDbType = (
114
111
  }
115
112
 
116
113
  const makeSchemaFromAst = (ast: SchemaAST.AST): RuntimeSchema =>
117
- Schema.make(ast)
114
+ Schema.make<RuntimeSchema>(ast)
118
115
 
119
116
  const unionAst = (asts: ReadonlyArray<SchemaAST.AST>): SchemaAST.AST | undefined => {
120
117
  if (asts.length === 0) {
@@ -123,7 +120,7 @@ const unionAst = (asts: ReadonlyArray<SchemaAST.AST>): SchemaAST.AST | undefined
123
120
  if (asts.length === 1) {
124
121
  return asts[0]
125
122
  }
126
- return SchemaAST.Union.make(asts)
123
+ return new SchemaAST.Union(asts, "anyOf")
127
124
  }
128
125
 
129
126
  const propertyAstOf = (
@@ -131,18 +128,14 @@ const propertyAstOf = (
131
128
  key: string
132
129
  ): SchemaAST.AST | undefined => {
133
130
  switch (ast._tag) {
134
- case "Transformation":
135
- return propertyAstOf(SchemaAST.typeAST(ast), key)
136
- case "Refinement":
137
- return propertyAstOf(ast.from, key)
138
131
  case "Suspend":
139
- return propertyAstOf(ast.f(), key)
140
- case "TypeLiteral": {
132
+ return propertyAstOf(ast.thunk(), key)
133
+ case "Objects": {
141
134
  const property = ast.propertySignatures.find((entry) => entry.name === key)
142
135
  if (property !== undefined) {
143
136
  return property.type
144
137
  }
145
- const index = ast.indexSignatures.find((entry) => entry.parameter._tag === "StringKeyword")
138
+ const index = ast.indexSignatures.find((entry) => entry.parameter._tag === "String")
146
139
  return index?.type
147
140
  }
148
141
  case "Union": {
@@ -162,21 +155,17 @@ const numberAstOf = (
162
155
  index: number
163
156
  ): SchemaAST.AST | undefined => {
164
157
  switch (ast._tag) {
165
- case "Transformation":
166
- return numberAstOf(SchemaAST.typeAST(ast), index)
167
- case "Refinement":
168
- return numberAstOf(ast.from, index)
169
158
  case "Suspend":
170
- return numberAstOf(ast.f(), index)
171
- case "TupleType": {
159
+ return numberAstOf(ast.thunk(), index)
160
+ case "Arrays": {
172
161
  const element = ast.elements[index]
173
162
  if (element !== undefined) {
174
- return element.type
163
+ return element
175
164
  }
176
165
  if (ast.rest.length === 0) {
177
166
  return undefined
178
167
  }
179
- return unionAst(ast.rest.map((entry) => entry.type))
168
+ return unionAst(ast.rest)
180
169
  }
181
170
  case "Union": {
182
171
  const values = ast.types.flatMap((member) => {
@@ -199,7 +188,9 @@ const schemaAstAtExactJsonPath = (
199
188
  schema: RuntimeSchema,
200
189
  segments: readonly JsonPath.CanonicalSegment[]
201
190
  ): SchemaAST.AST | undefined => {
202
- let current: SchemaAST.AST = SchemaAST.typeAST(schema.ast)
191
+ // JSON path operators return encoded JSON subvalues, so preserve field-level
192
+ // encoding links instead of walking the type-side AST.
193
+ let current: SchemaAST.AST = schema.ast
203
194
  for (const segment of segments) {
204
195
  if (segment.kind === "key") {
205
196
  const property = propertyAstOf(current, segment.key)
@@ -230,7 +221,7 @@ const unionSchemas = (schemas: ReadonlyArray<RuntimeSchema | undefined>): Runtim
230
221
  if (resolved.length === 1) {
231
222
  return resolved[0]
232
223
  }
233
- return Schema.Union(...resolved)
224
+ return Schema.Union(resolved)
234
225
  }
235
226
 
236
227
  const firstSelectedExpression = (
@@ -241,24 +232,23 @@ const firstSelectedExpression = (
241
232
  }
242
233
 
243
234
  const isJsonCompatibleAst = (ast: SchemaAST.AST): boolean => {
235
+ ast = SchemaAST.toType(ast)
244
236
  switch (ast._tag) {
245
- case "StringKeyword":
246
- case "NumberKeyword":
247
- case "BooleanKeyword":
248
- case "TupleType":
249
- case "TypeLiteral":
237
+ case "String":
238
+ case "Number":
239
+ case "Boolean":
240
+ case "Null":
241
+ case "Arrays":
242
+ case "Objects":
250
243
  return true
251
244
  case "Literal":
252
- return ast.literal === null ||
253
- typeof ast.literal === "string" ||
245
+ return typeof ast.literal === "string" ||
254
246
  typeof ast.literal === "number" ||
255
247
  typeof ast.literal === "boolean"
256
248
  case "Union":
257
249
  return ast.types.every(isJsonCompatibleAst)
258
- case "Transformation":
259
- return isJsonCompatibleAst(SchemaAST.typeAST(ast))
260
250
  case "Suspend":
261
- return isJsonCompatibleAst(ast.f())
251
+ return isJsonCompatibleAst(ast.thunk())
262
252
  default:
263
253
  return false
264
254
  }
@@ -268,7 +258,7 @@ const jsonCompatibleSchema = (schema: RuntimeSchema | undefined): RuntimeSchema
268
258
  if (schema === undefined) {
269
259
  return undefined
270
260
  }
271
- const ast = SchemaAST.typeAST(schema.ast)
261
+ const ast = SchemaAST.toType(schema.ast)
272
262
  return isJsonCompatibleAst(ast) ? schema : JsonValueSchema
273
263
  }
274
264
 
@@ -283,7 +273,7 @@ const buildStructSchema = (
283
273
  }
284
274
 
285
275
  const buildTupleSchema = (values: readonly Expression.Any[], context?: SchemaContext): RuntimeSchema =>
286
- Schema.Tuple(...values.map((value) => expressionRuntimeSchema(value, context) ?? JsonValueSchema))
276
+ Schema.Tuple(values.map((value) => expressionRuntimeSchema(value, context) ?? JsonValueSchema))
287
277
 
288
278
  const deriveCaseSchema = (
289
279
  ast: ExpressionAst.CaseNode,
@@ -19,7 +19,7 @@ const brandString = <BrandName extends string>(
19
19
  brand: BrandName
20
20
  ): Schema.Schema<string & Brand.Brand<BrandName>> =>
21
21
  Schema.String.pipe(
22
- Schema.pattern(pattern),
22
+ Schema.check(Schema.isPattern(pattern)),
23
23
  Schema.brand(brand)
24
24
  ) as unknown as Schema.Schema<string & Brand.Brand<BrandName>>
25
25
 
@@ -100,32 +100,32 @@ export const isValidInstantString = (value: string): boolean => {
100
100
  }
101
101
 
102
102
  export const LocalDateStringSchema = Schema.String.pipe(
103
- Schema.pattern(localDatePattern),
104
- Schema.filter(isValidLocalDateString),
103
+ Schema.check(Schema.isPattern(localDatePattern)),
104
+ Schema.check(Schema.makeFilter((value) => isValidLocalDateString(value))),
105
105
  Schema.brand("LocalDateString")
106
106
  ) as unknown as Schema.Schema<LocalDateString>
107
107
 
108
108
  export const LocalTimeStringSchema = Schema.String.pipe(
109
- Schema.pattern(localTimePattern),
110
- Schema.filter(isValidLocalTimeString),
109
+ Schema.check(Schema.isPattern(localTimePattern)),
110
+ Schema.check(Schema.makeFilter((value) => isValidLocalTimeString(value))),
111
111
  Schema.brand("LocalTimeString")
112
112
  ) as unknown as Schema.Schema<LocalTimeString>
113
113
 
114
114
  export const OffsetTimeStringSchema = Schema.String.pipe(
115
- Schema.pattern(offsetTimePattern),
116
- Schema.filter(isValidOffsetTimeString),
115
+ Schema.check(Schema.isPattern(offsetTimePattern)),
116
+ Schema.check(Schema.makeFilter((value) => isValidOffsetTimeString(value))),
117
117
  Schema.brand("OffsetTimeString")
118
118
  ) as unknown as Schema.Schema<OffsetTimeString>
119
119
 
120
120
  export const LocalDateTimeStringSchema = Schema.String.pipe(
121
- Schema.pattern(localDateTimePattern),
122
- Schema.filter(isValidLocalDateTimeString),
121
+ Schema.check(Schema.isPattern(localDateTimePattern)),
122
+ Schema.check(Schema.makeFilter((value) => isValidLocalDateTimeString(value))),
123
123
  Schema.brand("LocalDateTimeString")
124
124
  ) as unknown as Schema.Schema<LocalDateTimeString>
125
125
 
126
126
  export const InstantStringSchema = Schema.String.pipe(
127
- Schema.pattern(instantPattern),
128
- Schema.filter(isValidInstantString),
127
+ Schema.check(Schema.isPattern(instantPattern)),
128
+ Schema.check(Schema.makeFilter((value) => isValidInstantString(value))),
129
129
  Schema.brand("InstantString")
130
130
  ) as unknown as Schema.Schema<InstantString>
131
131
 
@@ -177,32 +177,29 @@ export const isCanonicalDecimalString = (value: string): boolean => {
177
177
  }
178
178
 
179
179
  export const BigIntStringSchema = Schema.String.pipe(
180
- Schema.filter(isCanonicalBigIntString),
180
+ Schema.check(Schema.makeFilter((value) => isCanonicalBigIntString(value))),
181
181
  Schema.brand("BigIntString")
182
182
  ) as unknown as Schema.Schema<BigIntString>
183
183
 
184
184
  export const DecimalStringSchema = Schema.String.pipe(
185
- Schema.filter(isCanonicalDecimalString),
185
+ Schema.check(Schema.makeFilter((value) => isCanonicalDecimalString(value))),
186
186
  Schema.brand("DecimalString")
187
187
  ) as unknown as Schema.Schema<DecimalString>
188
188
 
189
189
  export const JsonValueSchema: Schema.Schema<JsonValue> = Schema.suspend(() =>
190
- Schema.Union(
190
+ Schema.Union([
191
191
  Schema.String,
192
- Schema.Number.pipe(Schema.finite()),
192
+ Schema.Number.check(Schema.isFinite()),
193
193
  Schema.Boolean,
194
194
  Schema.Null,
195
195
  Schema.Array(JsonValueSchema),
196
- Schema.Record({
197
- key: Schema.String,
198
- value: JsonValueSchema
199
- })
200
- )
196
+ Schema.Record(Schema.String, JsonValueSchema)
197
+ ])
201
198
  )
202
199
 
203
- export const JsonPrimitiveSchema: Schema.Schema<JsonPrimitive> = Schema.Union(
200
+ export const JsonPrimitiveSchema: Schema.Schema<JsonPrimitive> = Schema.Union([
204
201
  Schema.String,
205
- Schema.Number.pipe(Schema.finite()),
202
+ Schema.Number.check(Schema.isFinite()),
206
203
  Schema.Boolean,
207
204
  Schema.Null
208
- )
205
+ ])
@@ -73,7 +73,7 @@ export declare namespace DbType {
73
73
  export interface State<Runtime, Db extends DbType.Any, Nullable extends Nullability, Dialect extends string, Kind extends ScalarKind, Deps extends BindingId = never> {
74
74
  readonly runtime: Runtime;
75
75
  readonly dbType: Db;
76
- readonly runtimeSchema?: Schema.Schema.Any;
76
+ readonly runtimeSchema?: Schema.Top;
77
77
  readonly nullability: Nullable;
78
78
  readonly dialect: Dialect;
79
79
  readonly kind: Kind;
@@ -50,6 +50,7 @@ export declare namespace DbType {
50
50
  readonly runtime?: RuntimeTag
51
51
  readonly compareGroup?: string
52
52
  readonly castTargets?: readonly string[]
53
+ readonly implicitTargets?: readonly string[]
53
54
  readonly traits?: DatatypeTraits
54
55
  readonly driverValueMapping?: DriverValueMapping
55
56
  }
@@ -161,7 +162,7 @@ export interface State<
161
162
  > {
162
163
  readonly runtime: Runtime
163
164
  readonly dbType: Db
164
- readonly runtimeSchema?: Schema.Schema.Any
165
+ readonly runtimeSchema?: Schema.Top
165
166
  readonly driverValueMapping?: DriverValueMapping
166
167
  readonly nullability: Nullable
167
168
  readonly dialect: Dialect
@@ -34,11 +34,11 @@ export type InsertRow<TableName extends string, Fields extends TableFieldMap> =
34
34
  export type UpdateRow<TableName extends string, Fields extends TableFieldMap, PrimaryKey extends keyof Fields> = Simplify<Partial<{
35
35
  [K in UpdateKeys<Fields, PrimaryKey>]: BrandedUpdateType<Fields[K], TableName, Extract<K, string>>;
36
36
  }>>;
37
- type SchemaOfVariant<Variant extends TableSchemaVariant, TableName extends string, Fields extends TableFieldMap, PrimaryKeyColumns extends keyof Fields & string> = Variant extends "select" ? Schema.Schema<SelectRow<TableName, Fields>> : Variant extends "insert" ? Schema.Schema<InsertRow<TableName, Fields>> : Schema.Schema<UpdateRow<TableName, Fields, PrimaryKeyColumns>>;
37
+ type SchemaOfVariant<Variant extends TableSchemaVariant, TableName extends string, Fields extends TableFieldMap, PrimaryKeyColumns extends keyof Fields & string> = Variant extends "select" ? Schema.ConstraintDecoder<SelectRow<TableName, Fields>, never> : Variant extends "insert" ? Schema.ConstraintDecoder<InsertRow<TableName, Fields>, never> : Schema.ConstraintDecoder<UpdateRow<TableName, Fields, PrimaryKeyColumns>, never>;
38
38
  export declare const deriveSchema: <Variant extends TableSchemaVariant, TableName extends string, Fields extends TableFieldMap, PrimaryKeyColumns extends keyof Fields & string>(variant: Variant, tableName: TableName, fields: Fields, primaryKeyColumns: readonly PrimaryKeyColumns[]) => SchemaOfVariant<Variant, TableName, Fields, PrimaryKeyColumns>;
39
- export declare const deriveSelectSchema: <TableName extends string, Fields extends TableFieldMap, PrimaryKeyColumns extends keyof Fields & string>(tableName: TableName, fields: Fields, primaryKeyColumns: readonly PrimaryKeyColumns[]) => Schema.Schema<SelectRow<TableName, Fields>>;
40
- export declare const deriveInsertSchema: <TableName extends string, Fields extends TableFieldMap, PrimaryKeyColumns extends keyof Fields & string>(tableName: TableName, fields: Fields, primaryKeyColumns: readonly PrimaryKeyColumns[]) => Schema.Schema<InsertRow<TableName, Fields>>;
41
- export declare const deriveUpdateSchema: <TableName extends string, Fields extends TableFieldMap, PrimaryKeyColumns extends keyof Fields & string>(tableName: TableName, fields: Fields, primaryKeyColumns: readonly PrimaryKeyColumns[]) => Schema.Schema<UpdateRow<TableName, Fields, PrimaryKeyColumns>>;
39
+ export declare const deriveSelectSchema: <TableName extends string, Fields extends TableFieldMap, PrimaryKeyColumns extends keyof Fields & string>(tableName: TableName, fields: Fields, primaryKeyColumns: readonly PrimaryKeyColumns[]) => Schema.ConstraintDecoder<SelectRow<TableName, Fields>, never>;
40
+ export declare const deriveInsertSchema: <TableName extends string, Fields extends TableFieldMap, PrimaryKeyColumns extends keyof Fields & string>(tableName: TableName, fields: Fields, primaryKeyColumns: readonly PrimaryKeyColumns[]) => Schema.ConstraintDecoder<InsertRow<TableName, Fields>, never>;
41
+ export declare const deriveUpdateSchema: <TableName extends string, Fields extends TableFieldMap, PrimaryKeyColumns extends keyof Fields & string>(tableName: TableName, fields: Fields, primaryKeyColumns: readonly PrimaryKeyColumns[]) => Schema.ConstraintDecoder<UpdateRow<TableName, Fields, PrimaryKeyColumns>, never>;
42
42
  /**
43
43
  * Derives the `select`, `insert`, and `update` schemas for a table.
44
44
  *
@@ -49,8 +49,8 @@ export declare const deriveUpdateSchema: <TableName extends string, Fields exten
49
49
  * `deriveUpdateSchema` so individual variants are derived lazily.
50
50
  */
51
51
  export declare const deriveSchemas: <TableName extends string, Fields extends TableFieldMap, PrimaryKeyColumns extends keyof Fields & string>(tableName: TableName, fields: Fields, primaryKeyColumns: readonly PrimaryKeyColumns[]) => {
52
- readonly select: Schema.Schema<SelectRow<TableName, Fields>>;
53
- readonly insert: Schema.Schema<InsertRow<TableName, Fields>>;
54
- readonly update: Schema.Schema<UpdateRow<TableName, Fields, PrimaryKeyColumns>>;
52
+ readonly select: Schema.ConstraintDecoder<SelectRow<TableName, Fields>, never>;
53
+ readonly insert: Schema.ConstraintDecoder<InsertRow<TableName, Fields>, never>;
54
+ readonly update: Schema.ConstraintDecoder<UpdateRow<TableName, Fields, PrimaryKeyColumns>, never>;
55
55
  };
56
56
  export {};
@@ -105,7 +105,7 @@ const maybeBrandSchema = (
105
105
  column: AnyColumnDefinition,
106
106
  tableName: string,
107
107
  columnName: string
108
- ): Schema.Schema.Any =>
108
+ ): Schema.Top =>
109
109
  column.metadata.brand === true
110
110
  ? Schema.brand(`${tableName}.${columnName}`)(column.schema)
111
111
  : column.schema
@@ -114,7 +114,7 @@ const selectSchema = (
114
114
  column: AnyColumnDefinition,
115
115
  tableName: string,
116
116
  columnName: string
117
- ): Schema.Schema.Any =>
117
+ ): Schema.Top =>
118
118
  column.metadata.nullable ? Schema.NullOr(maybeBrandSchema(column, tableName, columnName)) : maybeBrandSchema(column, tableName, columnName)
119
119
 
120
120
  const insertSchema = (
@@ -151,9 +151,9 @@ type SchemaOfVariant<
151
151
  TableName extends string,
152
152
  Fields extends TableFieldMap,
153
153
  PrimaryKeyColumns extends keyof Fields & string
154
- > = Variant extends "select" ? Schema.Schema<SelectRow<TableName, Fields>>
155
- : Variant extends "insert" ? Schema.Schema<InsertRow<TableName, Fields>>
156
- : Schema.Schema<UpdateRow<TableName, Fields, PrimaryKeyColumns>>
154
+ > = Variant extends "select" ? Schema.ConstraintDecoder<SelectRow<TableName, Fields>, never>
155
+ : Variant extends "insert" ? Schema.ConstraintDecoder<InsertRow<TableName, Fields>, never>
156
+ : Schema.ConstraintDecoder<UpdateRow<TableName, Fields, PrimaryKeyColumns>, never>
157
157
 
158
158
  const fieldSchemaForVariant = (
159
159
  variant: TableSchemaVariant,
@@ -202,7 +202,7 @@ export const deriveSelectSchema = <
202
202
  tableName: TableName,
203
203
  fields: Fields,
204
204
  primaryKeyColumns: readonly PrimaryKeyColumns[]
205
- ): Schema.Schema<SelectRow<TableName, Fields>> =>
205
+ ): Schema.ConstraintDecoder<SelectRow<TableName, Fields>, never> =>
206
206
  deriveSchema("select", tableName, fields, primaryKeyColumns)
207
207
 
208
208
  export const deriveInsertSchema = <
@@ -213,7 +213,7 @@ export const deriveInsertSchema = <
213
213
  tableName: TableName,
214
214
  fields: Fields,
215
215
  primaryKeyColumns: readonly PrimaryKeyColumns[]
216
- ): Schema.Schema<InsertRow<TableName, Fields>> =>
216
+ ): Schema.ConstraintDecoder<InsertRow<TableName, Fields>, never> =>
217
217
  deriveSchema("insert", tableName, fields, primaryKeyColumns)
218
218
 
219
219
  export const deriveUpdateSchema = <
@@ -224,7 +224,7 @@ export const deriveUpdateSchema = <
224
224
  tableName: TableName,
225
225
  fields: Fields,
226
226
  primaryKeyColumns: readonly PrimaryKeyColumns[]
227
- ): Schema.Schema<UpdateRow<TableName, Fields, PrimaryKeyColumns>> =>
227
+ ): Schema.ConstraintDecoder<UpdateRow<TableName, Fields, PrimaryKeyColumns>, never> =>
228
228
  deriveSchema("update", tableName, fields, primaryKeyColumns)
229
229
 
230
230
  /**
@@ -245,9 +245,9 @@ export const deriveSchemas = <
245
245
  fields: Fields,
246
246
  primaryKeyColumns: readonly PrimaryKeyColumns[]
247
247
  ): {
248
- readonly select: Schema.Schema<SelectRow<TableName, Fields>>
249
- readonly insert: Schema.Schema<InsertRow<TableName, Fields>>
250
- readonly update: Schema.Schema<UpdateRow<TableName, Fields, PrimaryKeyColumns>>
248
+ readonly select: Schema.ConstraintDecoder<SelectRow<TableName, Fields>, never>
249
+ readonly insert: Schema.ConstraintDecoder<InsertRow<TableName, Fields>, never>
250
+ readonly update: Schema.ConstraintDecoder<UpdateRow<TableName, Fields, PrimaryKeyColumns>, never>
251
251
  } => ({
252
252
  select: deriveSelectSchema(tableName, fields, primaryKeyColumns),
253
253
  insert: deriveInsertSchema(tableName, fields, primaryKeyColumns),
@@ -114,6 +114,7 @@ import * as ExpressionAst from "./expression-ast.js"
114
114
  import { presenceWitnessesOfSourceLike } from "./implication-runtime.js"
115
115
  import type { JsonNode } from "./json/ast.js"
116
116
  import type { JsonPathUsageError } from "./json/errors.js"
117
+ import { withJsonPathAccess } from "./json/path-access.js"
117
118
  import * as JsonPath from "./json/path.js"
118
119
  import type {
119
120
  JsonConcatResult,
@@ -300,17 +301,21 @@ type ComparableInput<
300
301
  TimestampDb extends Expression.DbType.Any,
301
302
  NullDb extends Expression.DbType.Any,
302
303
  Operator extends string
303
- > = CanCompareDbTypes<
304
- DialectDbTypeOfInput<Left, Dialect, TextDb, NumericDb, BoolDb, TimestampDb, NullDb>,
305
- DialectDbTypeOfInput<Right, Dialect, TextDb, NumericDb, BoolDb, TimestampDb, NullDb>,
306
- Dialect
307
- > extends true ? Right : OperandCompatibilityError<
308
- Operator,
309
- DialectDbTypeOfInput<Left, Dialect, TextDb, NumericDb, BoolDb, TimestampDb, NullDb>,
310
- DialectDbTypeOfInput<Right, Dialect, TextDb, NumericDb, BoolDb, TimestampDb, NullDb>,
311
- Dialect,
312
- "the same db type family"
313
- >
304
+ > = 0 extends (1 & Left)
305
+ ? Right
306
+ : 0 extends (1 & Right)
307
+ ? Right
308
+ : CanCompareDbTypes<
309
+ DialectDbTypeOfInput<Left, Dialect, TextDb, NumericDb, BoolDb, TimestampDb, NullDb>,
310
+ DialectDbTypeOfInput<Right, Dialect, TextDb, NumericDb, BoolDb, TimestampDb, NullDb>,
311
+ Dialect
312
+ > extends true ? Right : OperandCompatibilityError<
313
+ Operator,
314
+ DialectDbTypeOfInput<Left, Dialect, TextDb, NumericDb, BoolDb, TimestampDb, NullDb>,
315
+ DialectDbTypeOfInput<Right, Dialect, TextDb, NumericDb, BoolDb, TimestampDb, NullDb>,
316
+ Dialect,
317
+ "the same db type family"
318
+ >
314
319
 
315
320
  type TextInput<
316
321
  Value extends ExpressionInput,
@@ -1519,7 +1524,7 @@ type NumberWindowExpression<
1519
1524
  */
1520
1525
  type Dialect = "standard"
1521
1526
  type TextDb = ReturnType<typeof standardDatatypes.text>
1522
- type NumericDb = ReturnType<typeof standardDatatypes.float8>
1527
+ type NumericDb = ReturnType<typeof standardDatatypes.real>
1523
1528
  type BoolDb = ReturnType<typeof standardDatatypes.boolean>
1524
1529
  type TimestampDb = ReturnType<typeof standardDatatypes.timestamp>
1525
1530
  type NullDb = Expression.DbType.Base<"standard", "null"> & {
@@ -1533,7 +1538,7 @@ type TypeWitnesses = typeof standardDatatypes
1533
1538
  const profile: QueryDialectProfile<Dialect, TextDb, NumericDb, BoolDb, TimestampDb, NullDb, TypeWitnesses> = {
1534
1539
  dialect: "standard",
1535
1540
  textDb: standardDatatypes.text() as TextDb,
1536
- numericDb: standardDatatypes.float8() as NumericDb,
1541
+ numericDb: standardDatatypes.real() as NumericDb,
1537
1542
  boolDb: standardDatatypes.boolean() as BoolDb,
1538
1543
  timestampDb: standardDatatypes.timestamp() as TimestampDb,
1539
1544
  nullDb: {
@@ -1554,11 +1559,14 @@ const profile: QueryDialectProfile<Dialect, TextDb, NumericDb, BoolDb, Timestamp
1554
1559
 
1555
1560
  const literalSchemaOf = <Value extends LiteralValue>(
1556
1561
  value: Value
1557
- ): Schema.Schema.Any | undefined => {
1562
+ ): Schema.Top | undefined => {
1558
1563
  if (value === null || value instanceof Date) {
1559
1564
  return undefined
1560
1565
  }
1561
- return Schema.Literal(value) as Schema.Schema.Any
1566
+ if (typeof value === "number" && !Number.isFinite(value)) {
1567
+ return undefined
1568
+ }
1569
+ return Schema.Literal(value) as unknown as Schema.Top
1562
1570
  }
1563
1571
 
1564
1572
  const literal = <const Value extends LiteralValue>(
@@ -2339,13 +2347,6 @@ type BinaryPredicateExpression<
2339
2347
 
2340
2348
  const type = {
2341
2349
  ...profile.type,
2342
- array,
2343
- range,
2344
- multirange,
2345
- record,
2346
- domain,
2347
- enum: enum_,
2348
- set,
2349
2350
  custom,
2350
2351
  driverValueMapping
2351
2352
  }
@@ -2403,7 +2404,7 @@ type BinaryPredicateExpression<
2403
2404
  MergeAggregationTuple<typeof expressions>,
2404
2405
  TupleDependencies<typeof expressions>,
2405
2406
  Ast
2406
- > => makeExpression({
2407
+ > => withJsonPathAccess(makeExpression({
2407
2408
  runtime: state.runtime,
2408
2409
  dbType: state.dbType,
2409
2410
  nullability: state.nullability,
@@ -2411,7 +2412,7 @@ type BinaryPredicateExpression<
2411
2412
  kind: mergeAggregationManyRuntime(expressions) as MergeAggregationTuple<typeof expressions>,
2412
2413
 
2413
2414
  dependencies: mergeManyDependencies(expressions)
2414
- }, ast) as AstBackedExpression<
2415
+ }, ast)) as AstBackedExpression<
2415
2416
  Runtime,
2416
2417
  Db,
2417
2418
  Nullability,
@@ -2432,7 +2433,7 @@ type BinaryPredicateExpression<
2432
2433
  const makeJsonLiteralExpression = <Value extends JsonLiteralInput>(
2433
2434
  value: Value,
2434
2435
  dbType: Expression.DbType.Json<any, any> = jsonDb
2435
- ) => makeExpression({
2436
+ ) => withJsonPathAccess(makeExpression({
2436
2437
  runtime: value as JsonRuntime<Value>,
2437
2438
  dbType,
2438
2439
  nullability: (value === null ? "always" : "never") as JsonNullabilityOf<Value>,
@@ -2443,7 +2444,7 @@ type BinaryPredicateExpression<
2443
2444
  }, {
2444
2445
  kind: "literal",
2445
2446
  value
2446
- })
2447
+ }))
2447
2448
 
2448
2449
  const wrapJsonExpression = (
2449
2450
  value: Expression.Any,
@@ -4524,6 +4525,83 @@ type ValidateTargetColumnInput<
4524
4525
  Columns extends DdlColumnInput
4525
4526
  > = ValidateTargetColumns<Target, NormalizeDdlColumns<Columns>> extends never ? never : Columns
4526
4527
 
4528
+ type SameColumnSet<
4529
+ Left extends readonly string[],
4530
+ Right extends readonly string[]
4531
+ > = string extends Left[number] | Right[number]
4532
+ ? false
4533
+ : Exclude<Left[number], Right[number]> extends never
4534
+ ? Exclude<Right[number], Left[number]> extends never
4535
+ ? true
4536
+ : false
4537
+ : false
4538
+
4539
+ type ConflictArbitersOf<Target extends MutationTargetLike> =
4540
+ Target[typeof Table.TypeId]["conflictArbiters"][number]
4541
+
4542
+ type MatchingConflictArbiter<
4543
+ Target extends MutationTargetLike,
4544
+ Columns extends readonly string[],
4545
+ AllowPartial extends boolean
4546
+ > = ConflictArbitersOf<Target> extends infer Arbiter extends Table.ConflictArbiter
4547
+ ? Arbiter extends Table.ConflictArbiter
4548
+ ? SameColumnSet<Arbiter["columns"], Columns> extends true
4549
+ ? Arbiter["scope"] extends "unconditional"
4550
+ ? true
4551
+ : AllowPartial extends true ? true : never
4552
+ : never
4553
+ : never
4554
+ : never
4555
+
4556
+ type HasInlineConflictArbiter<
4557
+ Target extends MutationTargetLike,
4558
+ Columns extends readonly string[]
4559
+ > = Columns extends readonly [infer Column extends Extract<keyof Target[typeof Table.TypeId]["fields"], string>]
4560
+ ? Target[typeof Table.TypeId]["fields"][Column] extends { readonly metadata: { readonly primaryKey: true } | { readonly unique: true } }
4561
+ ? true
4562
+ : false
4563
+ : false
4564
+
4565
+ type HasConflictArbiter<
4566
+ Target extends MutationTargetLike,
4567
+ Columns extends readonly string[],
4568
+ AllowPartial extends boolean
4569
+ > = string extends Extract<keyof Target[typeof Table.TypeId]["fields"], string>
4570
+ ? true
4571
+ : HasInlineConflictArbiter<Target, Columns> extends true
4572
+ ? true
4573
+ : true extends MatchingConflictArbiter<Target, Columns, AllowPartial> ? true : false
4574
+
4575
+ type ConflictTargetArbiterError<
4576
+ Columns,
4577
+ AllowPartial extends boolean
4578
+ > = {
4579
+ readonly __effect_qb_error__: "effect-qb: conflict target columns must match a primary key, unique constraint, or unique index"
4580
+ readonly __effect_qb_conflict_columns__: Columns
4581
+ readonly __effect_qb_partial_target__: AllowPartial
4582
+ readonly __effect_qb_hint__: "Declare the target columns as primaryKey/unique, add a table-level Unique.make(...), or use a simple Pg.Index.uniqueIndex(...)"
4583
+ }
4584
+
4585
+ type ValidateConflictColumnInput<
4586
+ Target extends MutationTargetLike,
4587
+ Columns extends DdlColumnInput,
4588
+ AllowPartial extends boolean
4589
+ > = ValidateTargetColumnInput<Target, Columns> extends never
4590
+ ? never
4591
+ : HasConflictArbiter<Target, NormalizeDdlColumns<Columns>, AllowPartial> extends true
4592
+ ? Columns
4593
+ : ConflictTargetArbiterError<NormalizeDdlColumns<Columns>, AllowPartial>
4594
+
4595
+ type ConflictColumnPlanConstraint<
4596
+ Target extends MutationTargetLike,
4597
+ Columns extends DdlColumnInput,
4598
+ AllowPartial extends boolean
4599
+ > = ValidateTargetColumnInput<Target, Columns> extends never
4600
+ ? never
4601
+ : HasConflictArbiter<Target, NormalizeDdlColumns<Columns>, AllowPartial> extends true
4602
+ ? unknown
4603
+ : ConflictTargetArbiterError<NormalizeDdlColumns<Columns>, AllowPartial>
4604
+
4527
4605
  type CreateIndexOptions<Name extends string = string> = {
4528
4606
  readonly name?: NonEmptyStringInput<Name>
4529
4607
  readonly unique?: boolean
@@ -4964,6 +5042,21 @@ type ConflictConstraintNameConstraint<Target> =
4964
5042
  ? { readonly constraint: NonEmptyStringInput<Constraint> }
4965
5043
  : unknown
4966
5044
 
5045
+ type ConflictTargetHasPredicate<Target> =
5046
+ Target extends { readonly where: PredicateInput } ? true : false
5047
+
5048
+ type ConflictTargetPlanConstraint<
5049
+ Target extends MutationTargetLike,
5050
+ ConflictTarget
5051
+ > =
5052
+ ConflictTarget extends { readonly constraint: string }
5053
+ ? unknown
5054
+ : ConflictTarget extends { readonly columns: infer Columns extends DdlColumnInput }
5055
+ ? ConflictColumnPlanConstraint<Target, Columns, ConflictTargetHasPredicate<ConflictTarget>>
5056
+ : ConflictTarget extends DdlColumnInput
5057
+ ? ConflictColumnPlanConstraint<Target, ConflictTarget, false>
5058
+ : unknown
5059
+
4967
5060
  type ConflictActionInput<
4968
5061
  Target extends MutationTargetLike,
4969
5062
  Dialect extends string,
@@ -6295,7 +6388,7 @@ type AsCurriedResult<
6295
6388
  options?: Options & ConflictActionUpdateNonEmptyConstraint<Options>
6296
6389
  ) =>
6297
6390
  <PlanValue extends QueryPlan<any, any, any, any, any, any, any, any, any, any>>(
6298
- plan: PlanValue & RequireInsertStatement<PlanValue>
6391
+ plan: PlanValue & RequireInsertStatement<PlanValue> & ConflictTargetPlanConstraint<MutationTargetOfPlan<PlanValue>, ConflictTarget>
6299
6392
  ) => QueryPlan<
6300
6393
  SelectionOfPlan<PlanValue>,
6301
6394
  Exclude<RequiredOfPlan<PlanValue> | ConflictRequired<UpdateValues, Options, ConflictTarget>, AvailableNames<AvailableOfPlan<PlanValue>>>,
@@ -6359,7 +6452,7 @@ type AsCurriedResult<
6359
6452
  >(
6360
6453
  target: Target,
6361
6454
  values: Values & MutationValuesDialectConstraint<Values, Dialect, TextDb, NumericDb, BoolDb, TimestampDb, NullDb>,
6362
- conflictColumns: ValidateTargetColumnInput<Target, Columns>,
6455
+ conflictColumns: ValidateConflictColumnInput<Target, Columns, false>,
6363
6456
  updateValues?: UpdateValues & UpdateValuesNonEmptyConstraint<Exclude<UpdateValues, undefined>> & MutationValuesDialectConstraint<Exclude<UpdateValues, undefined>, Dialect, TextDb, NumericDb, BoolDb, TimestampDb, NullDb>
6364
6457
  ) => QueryPlan<
6365
6458
  {},