@prisma/orm-family-sql 8.0.0-rc.17-dev.10 → 8.0.0-rc.17-dev.12

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 (44) hide show
  1. package/dist/{authoring-type-constructors-0Iv2zdwS-DX59Qw3z.mjs → authoring-type-constructors-0Iv2zdwS-CnynTqjm.mjs} +2 -2
  2. package/dist/{authoring-type-constructors-0Iv2zdwS-DX59Qw3z.mjs.map → authoring-type-constructors-0Iv2zdwS-CnynTqjm.mjs.map} +1 -1
  3. package/dist/{config-types-HwU-FfRj.mjs → config-types-DggwpWr3.mjs} +2 -2
  4. package/dist/{config-types-HwU-FfRj.mjs.map → config-types-DggwpWr3.mjs.map} +1 -1
  5. package/dist/{contract-builder-Tmmlb0mv.mjs → contract-builder-J9D4EprQ.mjs} +3 -3
  6. package/dist/{contract-builder-Tmmlb0mv.mjs.map → contract-builder-J9D4EprQ.mjs.map} +1 -1
  7. package/dist/contract-prisma7__provider.mjs +4 -4
  8. package/dist/contract-psl.mjs +1 -1
  9. package/dist/contract-psl__attribute-specs.mjs +1 -1
  10. package/dist/contract-psl__provider.mjs +2 -2
  11. package/dist/contract-ts.mjs +3 -3
  12. package/dist/contract-ts__config-types.mjs +1 -1
  13. package/dist/contract-ts__contract-builder.mjs +2 -2
  14. package/dist/contract.d.mts +2 -2
  15. package/dist/contract.mjs +2 -2
  16. package/dist/contract__validators.d.mts +2 -2
  17. package/dist/contract__validators.mjs +2 -2
  18. package/dist/{control-COI98aRs.mjs → control-Bce-z7el.mjs} +5 -5
  19. package/dist/{control-COI98aRs.mjs.map → control-Bce-z7el.mjs.map} +1 -1
  20. package/dist/{control-BQpDsD3I.d.mts → control-DdyeUFkv.d.mts} +2 -2
  21. package/dist/{control-BQpDsD3I.d.mts.map → control-DdyeUFkv.d.mts.map} +1 -1
  22. package/dist/{derived-checks-RB_lNgFJ-CHamqgFW.mjs → derived-checks-CEK-Ls_a-plK5KxX3.mjs} +45 -7
  23. package/dist/derived-checks-CEK-Ls_a-plK5KxX3.mjs.map +1 -0
  24. package/dist/family.d.mts +2 -2
  25. package/dist/family.mjs +3 -3
  26. package/dist/family__control.d.mts +2 -2
  27. package/dist/family__control.mjs +2 -2
  28. package/dist/family__ir.mjs +1 -1
  29. package/dist/family__pack.mjs +2 -2
  30. package/dist/{interpreter-BTM9k0wn-Bu5eCC-Z.mjs → interpreter-BTM9k0wn-Cya0qReB.mjs} +3 -3
  31. package/dist/{interpreter-BTM9k0wn-Bu5eCC-Z.mjs.map → interpreter-BTM9k0wn-Cya0qReB.mjs.map} +1 -1
  32. package/dist/orm-client.mjs +421 -252
  33. package/dist/orm-client.mjs.map +1 -1
  34. package/dist/{psl-field-resolution-CAJsUfST-DWY_oqor.mjs → psl-field-resolution-CAJsUfST-C4QwwiqV.mjs} +3 -3
  35. package/dist/{psl-field-resolution-CAJsUfST-DWY_oqor.mjs.map → psl-field-resolution-CAJsUfST-C4QwwiqV.mjs.map} +1 -1
  36. package/dist/{sql-contract-serializer-DDaAVCQr-CGG0I8ur.mjs → sql-contract-serializer-DDaAVCQr-CK2KUyq0.mjs} +2 -2
  37. package/dist/{sql-contract-serializer-DDaAVCQr-CGG0I8ur.mjs.map → sql-contract-serializer-DDaAVCQr-CK2KUyq0.mjs.map} +1 -1
  38. package/dist/{validators-CIfn8ezs.mjs → validators-B9prRmOP.mjs} +63 -6
  39. package/dist/validators-B9prRmOP.mjs.map +1 -0
  40. package/dist/{validators-COcD3_iw.d.mts → validators-CudqzmkF.d.mts} +11 -6
  41. package/dist/{validators-COcD3_iw.d.mts.map → validators-CudqzmkF.d.mts.map} +1 -1
  42. package/package.json +18 -18
  43. package/dist/derived-checks-RB_lNgFJ-CHamqgFW.mjs.map +0 -1
  44. package/dist/validators-CIfn8ezs.mjs.map +0 -1
@@ -33,6 +33,20 @@ function aggregateOperationNames(registry) {
33
33
  operationNamesByRegistry.set(registry, names);
34
34
  return names;
35
35
  }
36
+ const contractCache = /* @__PURE__ */ new WeakMap();
37
+ /** Builds a value derived from `contract` once per contract and key. Every key starts with a name that only one function uses, and that function stores its own result type under it. */
38
+ function cachedFor(contract, key, build) {
39
+ let perContract = contractCache.get(contract);
40
+ if (!perContract) {
41
+ perContract = /* @__PURE__ */ new Map();
42
+ contractCache.set(contract, perContract);
43
+ }
44
+ const cacheKey = JSON.stringify(key);
45
+ if (perContract.has(cacheKey)) return blindCast(perContract.get(cacheKey));
46
+ const built = build();
47
+ perContract.set(cacheKey, built);
48
+ return built;
49
+ }
36
50
  function ormError(code, message, options) {
37
51
  return structuredError(code, message, options);
38
52
  }
@@ -76,8 +90,6 @@ function modelOf(contract, namespaceId, name) {
76
90
  const model = contract.domain.namespaces[namespaceId]?.models[name];
77
91
  return model === void 0 ? void 0 : blindCast(model);
78
92
  }
79
- const fieldToColumnCache = /* @__PURE__ */ new WeakMap();
80
- const columnToFieldCache = /* @__PURE__ */ new WeakMap();
81
93
  const polymorphismCache = /* @__PURE__ */ new WeakMap();
82
94
  function resolvePolymorphismInfo(contract, namespaceId, modelName) {
83
95
  let perContract = polymorphismCache.get(contract);
@@ -99,7 +111,7 @@ function resolvePolymorphismInfo(contract, namespaceId, modelName) {
99
111
  return;
100
112
  }
101
113
  const discriminatorField = model.discriminator.field;
102
- const discriminatorColumn = resolveFieldToColumn(contract, namespaceId, modelName, discriminatorField);
114
+ const discriminatorColumn = columnOfContractField(contract, namespaceId, modelName, discriminatorField);
103
115
  const variants = /* @__PURE__ */ new Map();
104
116
  const variantsByValue = /* @__PURE__ */ new Map();
105
117
  const mtiVariants = [];
@@ -129,81 +141,235 @@ function resolvePolymorphismInfo(contract, namespaceId, modelName) {
129
141
  perContract.set(cacheKey, result);
130
142
  return result;
131
143
  }
132
- function resolveFieldToColumn(contract, namespaceId, modelName, fieldName) {
133
- return getFieldToColumnMap(contract, namespaceId, modelName)[fieldName] ?? fieldName;
144
+ /** The column each of the model's own fields maps, keyed by field name. */
145
+ function getOwnFieldColumns(contract, namespaceId, modelName) {
146
+ return cachedFor(contract, [
147
+ "ownFieldColumns",
148
+ namespaceId,
149
+ modelName
150
+ ], () => {
151
+ const storageFields = modelsOf(contract, namespaceId)[modelName]?.storage?.fields ?? {};
152
+ const columns = {};
153
+ for (const [field, storage] of Object.entries(storageFields)) if (storage?.column) columns[field] = storage.column;
154
+ return columns;
155
+ });
134
156
  }
135
157
  /**
136
- * Map the fields that an MTI variant contributes to `{ table, column }` refs
137
- * qualified against the variant's own table — the table the read path joins
138
- * into the correlated child SELECT. STI variants contribute nothing here:
139
- * their columns live on the base table and resolve through the ordinary
140
- * base-table field map. Base fields are intentionally absent so callers can
141
- * gate variant qualification strictly to variant-owned fields.
158
+ * A model's fields, keyed by field name, with the table and column each maps: its own fields on its own table, and the fields it inherits from its base model on the base model's table. This is the one list of a model's fields; a column no field maps has no entry.
159
+ */
160
+ function getModelFields(contract, namespaceId, modelName) {
161
+ return cachedFor(contract, [
162
+ "modelFields",
163
+ namespaceId,
164
+ modelName
165
+ ], () => {
166
+ const model = modelOf(contract, namespaceId, modelName);
167
+ const table = model?.storage?.table;
168
+ const own = table === void 0 ? {} : Object.fromEntries(Object.entries(getOwnFieldColumns(contract, namespaceId, modelName)).map(([field, column]) => [field, {
169
+ table,
170
+ column
171
+ }]));
172
+ const base = model?.base;
173
+ return {
174
+ ...base === void 0 ? {} : getModelFields(contract, base.namespace, base.model),
175
+ ...own
176
+ };
177
+ });
178
+ }
179
+ /** The column each of a model's own and inherited fields maps, keyed by field name. */
180
+ function getModelFieldColumns(contract, namespaceId, modelName) {
181
+ return cachedFor(contract, [
182
+ "modelFieldColumns",
183
+ namespaceId,
184
+ modelName
185
+ ], () => Object.fromEntries(Object.entries(getModelFields(contract, namespaceId, modelName)).map(([field, { column }]) => [field, column])));
186
+ }
187
+ /**
188
+ * The column each field of the model and of the variant `variantName` maps, keyed by field name. Without a variant, the model's fields alone.
142
189
  *
143
- * Uncached on purpose: `resolvePolymorphismInfo` already memoizes the variant
144
- * lookup, and the remaining work is one pass over the variant's field→column
145
- * map, so a second cache layer would buy nothing.
190
+ * A surface accepts a variant's field only when it can place that field's column on the variant's table. A collection narrowed to a variant reads that variant's table, so `select`, the `where` and `orderBy` accessor and a variant create accept the narrowed variant's fields. A collection that is not narrowed reads the base table only, so only `select`, whose polymorphic projection joins each variant's table, accepts variant fields there (`getModelAndEveryVariantFieldColumns`).
191
+ */
192
+ function getModelAndVariantFieldColumns(contract, namespaceId, modelName, variantName) {
193
+ return cachedFor(contract, [
194
+ "modelAndVariantFieldColumns",
195
+ namespaceId,
196
+ modelName,
197
+ variantName ?? null
198
+ ], () => ({
199
+ ...variantName === void 0 ? {} : getOwnFieldColumns(contract, namespaceId, variantName),
200
+ ...getModelFieldColumns(contract, namespaceId, modelName)
201
+ }));
202
+ }
203
+ /**
204
+ * Every column each field of the model and of every one of its variants maps, keyed by field name. Two variants may map one field name to different columns, so a name can map several columns.
205
+ */
206
+ function getModelAndEveryVariantFieldColumns(contract, namespaceId, modelName) {
207
+ return cachedFor(contract, [
208
+ "modelAndEveryVariantFieldColumns",
209
+ namespaceId,
210
+ modelName
211
+ ], () => {
212
+ const columns = {};
213
+ const add = (fieldColumns) => {
214
+ for (const [field, column] of Object.entries(fieldColumns)) {
215
+ const existing = columns[field] ?? [];
216
+ if (!existing.includes(column)) existing.push(column);
217
+ columns[field] = existing;
218
+ }
219
+ };
220
+ add(getModelFieldColumns(contract, namespaceId, modelName));
221
+ const modelFields = new Set(Object.keys(columns));
222
+ for (const variant of resolvePolymorphismInfo(contract, namespaceId, modelName)?.variants.keys() ?? []) add(Object.fromEntries(Object.entries(getOwnFieldColumns(contract, namespaceId, variant)).filter(([field]) => !modelFields.has(field))));
223
+ return columns;
224
+ });
225
+ }
226
+ /** The field each column of the model's own fields maps, keyed by column. */
227
+ function getOwnColumnFields(contract, namespaceId, modelName) {
228
+ return cachedFor(contract, [
229
+ "ownColumnFields",
230
+ namespaceId,
231
+ modelName
232
+ ], () => invert(getOwnFieldColumns(contract, namespaceId, modelName)));
233
+ }
234
+ /** The field each column of the model's own and inherited fields maps, keyed by column. */
235
+ function getModelColumnFields(contract, namespaceId, modelName) {
236
+ return cachedFor(contract, [
237
+ "modelColumnFields",
238
+ namespaceId,
239
+ modelName
240
+ ], () => invert(getModelFieldColumns(contract, namespaceId, modelName)));
241
+ }
242
+ function invert(map) {
243
+ return Object.fromEntries(Object.entries(map).map(([key, value]) => [value, key]));
244
+ }
245
+ /**
246
+ * The column a name a caller passed maps in `fieldColumns`. A name that is not a field is refused with `ORM.FIELD_UNKNOWN`, so no caller reaches a column by its column name, including a column no field maps.
247
+ */
248
+ function columnOfCallerField(contract, namespaceId, fieldColumns, modelName, fieldName) {
249
+ const column = Object.hasOwn(fieldColumns, fieldName) ? fieldColumns[fieldName] : void 0;
250
+ if (column === void 0) throw callerFieldUnknown(contract, namespaceId, fieldColumns, modelName, fieldName);
251
+ return column;
252
+ }
253
+ /**
254
+ * The refusal of a name a caller passed that is not a field of the model it addressed. When the name is the column of one of the fields in `fieldColumns`, or a column that no field maps on a table of the model's hierarchy, the message says so and names the table.
255
+ */
256
+ function callerFieldUnknown(contract, namespaceId, fieldColumns, modelName, fieldName) {
257
+ const unknown = `Model "${modelName}" has no field "${fieldName}"`;
258
+ const fieldForColumn = Object.entries(fieldColumns).find(([, columns]) => typeof columns === "string" ? columns === fieldName : columns.includes(fieldName))?.[0];
259
+ if (fieldForColumn !== void 0) return ormError("ORM.FIELD_UNKNOWN", `${unknown}. "${fieldName}" is the column of field "${fieldForColumn}"; pass the field name.`, { meta: {
260
+ model: modelName,
261
+ field: fieldName,
262
+ fieldForColumn
263
+ } });
264
+ const unmapped = getUnmappedColumns(contract, namespaceId, modelName).find(({ column }) => column === fieldName);
265
+ return ormError("ORM.FIELD_UNKNOWN", `${unknown}${unmapped === void 0 ? "" : `. Table "${unmapped.table}" has a column "${fieldName}" that no field maps, so the ORM cannot read or write it.`}`, { meta: {
266
+ model: modelName,
267
+ field: fieldName
268
+ } });
269
+ }
270
+ /** The columns of the tables of a model's hierarchy that no field of the hierarchy maps. */
271
+ function getUnmappedColumns(contract, namespaceId, modelName) {
272
+ return cachedFor(contract, [
273
+ "unmappedColumns",
274
+ namespaceId,
275
+ modelName
276
+ ], () => {
277
+ const root = hierarchyRootName(contract, namespaceId, modelName);
278
+ const rootTable = domainModelTableInNamespace(contract, namespaceId, root);
279
+ if (rootTable === void 0) return [];
280
+ const variants = resolvePolymorphismInfo(contract, namespaceId, root)?.variants.values();
281
+ return [.../* @__PURE__ */ new Set([rootTable, ...[...variants ?? []].map((variant) => variant.table)])].flatMap((table) => {
282
+ const read = new Set(getColumnsReadOnTable(contract, namespaceId, root, table));
283
+ return getAllTableColumns(contract, namespaceId, table).filter((column) => !read.has(column)).map((column) => ({
284
+ table,
285
+ column
286
+ }));
287
+ });
288
+ });
289
+ }
290
+ function hierarchyRootName(contract, namespaceId, modelName) {
291
+ const base = modelOf(contract, namespaceId, modelName)?.base;
292
+ return base === void 0 || base.namespace !== namespaceId ? modelName : hierarchyRootName(contract, namespaceId, base.model);
293
+ }
294
+ /**
295
+ * The column a field name the contract itself gives maps among the model's own and inherited fields, such as a relation's join field or a discriminator. The contract was validated, so a name that is not a field is an internal error.
296
+ */
297
+ function columnOfContractField(contract, namespaceId, modelName, fieldName) {
298
+ const fieldColumns = getModelFieldColumns(contract, namespaceId, modelName);
299
+ const column = Object.hasOwn(fieldColumns, fieldName) ? fieldColumns[fieldName] : void 0;
300
+ if (column === void 0) throw new InternalError(`Model "${modelName}" has no field "${fieldName}" the contract names`);
301
+ return column;
302
+ }
303
+ /**
304
+ * The field that maps `column` in `columnFields`. The ORM only asks this for a column it chose itself, such as a key column or a column it projected, so a column no field maps is an internal error.
305
+ */
306
+ function fieldOfColumn(columnFields, modelName, column) {
307
+ const field = Object.hasOwn(columnFields, column) ? columnFields[column] : void 0;
308
+ if (field === void 0) throw new InternalError(`Column "${column}" of model "${modelName}" is mapped by no field`);
309
+ return field;
310
+ }
311
+ /**
312
+ * The columns a relation's target fields name. A relation through a junction table names the junction's columns there, not fields of the target model.
313
+ */
314
+ function resolveRelationTargetColumns(contract, relation) {
315
+ if (relation.through !== void 0) return [...relation.on.targetFields];
316
+ return relation.on.targetFields.map((field) => columnOfContractField(contract, relation.toNamespace, relation.to, field));
317
+ }
318
+ /**
319
+ * The fields a multi-table variant declares, with the table and column each maps, which is the variant's own table the read path joins. A single-table variant's columns are on the base table, and inherited fields are on the base model's table, so neither appears here.
146
320
  */
147
321
  function resolveVariantFieldColumns(contract, namespaceId, baseModelName, variantName) {
148
322
  const variant = resolvePolymorphismInfo(contract, namespaceId, baseModelName)?.variants.get(variantName);
149
- const result = {};
150
- if (variant && variant.strategy === "mti") {
151
- const variantFieldToColumn = getFieldToColumnMap(contract, namespaceId, variant.modelName);
152
- for (const [field, column] of Object.entries(variantFieldToColumn)) result[field] = {
153
- table: variant.table,
154
- column
155
- };
156
- }
157
- return result;
323
+ if (variant?.strategy !== "mti") return {};
324
+ return Object.fromEntries(Object.entries(getModelFields(contract, namespaceId, variant.modelName)).filter(([, field]) => field.table === variant.table));
158
325
  }
159
- function getFieldToColumnMap(contract, namespaceId, modelName) {
160
- let perContract = fieldToColumnCache.get(contract);
161
- if (!perContract) {
162
- perContract = /* @__PURE__ */ new Map();
163
- fieldToColumnCache.set(contract, perContract);
164
- }
165
- const cacheKey = metadataCacheKey(namespaceId, modelName);
166
- let cached = perContract.get(cacheKey);
167
- if (cached) return cached;
168
- const storageFields = modelsOf(contract, namespaceId)[modelName]?.storage?.fields ?? {};
169
- cached = {};
170
- for (const [f, s] of Object.entries(storageFields)) if (s?.column) cached[f] = s.column;
171
- perContract.set(cacheKey, cached);
172
- return cached;
173
- }
174
- function getColumnToFieldMap(contract, namespaceId, modelName) {
175
- let perContract = columnToFieldCache.get(contract);
176
- if (!perContract) {
177
- perContract = /* @__PURE__ */ new Map();
178
- columnToFieldCache.set(contract, perContract);
326
+ /** Every column of a table, in table order. */
327
+ function getAllTableColumns(contract, namespaceId, tableName) {
328
+ try {
329
+ return Object.keys(storageTableForContract(contract, namespaceId, tableName).columns);
330
+ } catch (error) {
331
+ if (error instanceof Error && error.message.includes("ambiguous")) throw error;
332
+ throw ormError("ORM.TABLE_UNKNOWN", `Unknown table "${tableName}" in SQL ORM query planner`, { meta: {
333
+ namespaceId,
334
+ tableName
335
+ } });
179
336
  }
180
- const cacheKey = metadataCacheKey(namespaceId, modelName);
181
- let cached = perContract.get(cacheKey);
182
- if (cached) return cached;
183
- const storageFields = modelsOf(contract, namespaceId)[modelName]?.storage?.fields ?? {};
184
- cached = {};
185
- for (const [f, s] of Object.entries(storageFields)) if (s?.column) cached[s.column] = f;
186
- perContract.set(cacheKey, cached);
187
- return cached;
188
337
  }
189
- const completeColumnToFieldCache = /* @__PURE__ */ new WeakMap();
338
+ function isMultiTableVariantTable(contract, namespaceId, modelName, tableName) {
339
+ const base = modelOf(contract, namespaceId, modelName)?.base;
340
+ return base !== void 0 && domainModelTableInNamespace(contract, namespaceId, modelName) === tableName && domainModelTableInNamespace(contract, base.namespace, base.model) !== tableName;
341
+ }
190
342
  /**
191
- * Like getColumnToFieldMap, but a field without a storage `column` maps under its own name.
343
+ * The columns of `tableName` a query on `modelName` reads, in table order: the columns on that table of the model's own and inherited fields and of its variants' fields, and, on a multi-table variant's table, the key the variant inherits. Any other column of the table is storage the model does not map, and the ORM never reads it into a row.
192
344
  */
193
- function getCompleteColumnToFieldMap(contract, namespaceId, modelName) {
194
- let perContract = completeColumnToFieldCache.get(contract);
195
- if (!perContract) {
196
- perContract = /* @__PURE__ */ new Map();
197
- completeColumnToFieldCache.set(contract, perContract);
198
- }
199
- const cacheKey = metadataCacheKey(namespaceId, modelName);
200
- let cached = perContract.get(cacheKey);
201
- if (cached) return cached;
202
- const storageFields = modelsOf(contract, namespaceId)[modelName]?.storage?.fields ?? {};
203
- cached = {};
204
- for (const [f, s] of Object.entries(storageFields)) cached[s?.column ?? f] = f;
205
- perContract.set(cacheKey, cached);
206
- return cached;
345
+ function getColumnsReadOnTable(contract, namespaceId, modelName, tableName) {
346
+ return cachedFor(contract, [
347
+ "columnsReadOnTable",
348
+ namespaceId,
349
+ modelName,
350
+ tableName
351
+ ], () => {
352
+ const read = /* @__PURE__ */ new Set();
353
+ const addFieldsOnTable = (name) => {
354
+ for (const field of Object.values(getModelFields(contract, namespaceId, name))) if (field.table === tableName) read.add(field.column);
355
+ };
356
+ const addInheritedKey = () => {
357
+ for (const column of resolvePrimaryKeyColumns(contract, namespaceId, tableName)) read.add(column);
358
+ };
359
+ addFieldsOnTable(modelName);
360
+ if (isMultiTableVariantTable(contract, namespaceId, modelName, tableName)) addInheritedKey();
361
+ const variants = resolvePolymorphismInfo(contract, namespaceId, modelName)?.variants.values();
362
+ for (const variant of variants ?? []) {
363
+ if (variant.table !== tableName) continue;
364
+ addFieldsOnTable(variant.modelName);
365
+ if (variant.strategy === "mti") addInheritedKey();
366
+ }
367
+ return getAllTableColumns(contract, namespaceId, tableName).filter((column) => read.has(column));
368
+ });
369
+ }
370
+ /** The model a query or write addresses: the variant it is narrowed to, otherwise the collection's model. */
371
+ function addressedModelName(modelName, variantName) {
372
+ return variantName ?? modelName;
207
373
  }
208
374
  function resolveIncludeRelation(contract, namespaceId, baseModelName, relationName, variantName) {
209
375
  const polymorphism = resolvePolymorphismInfo(contract, namespaceId, baseModelName);
@@ -212,22 +378,24 @@ function resolveIncludeRelation(contract, namespaceId, baseModelName, relationNa
212
378
  let localTableName = resolveModelTableName(contract, namespaceId, baseModelName);
213
379
  let relation;
214
380
  if (variant !== void 0) {
215
- const candidate = resolveModelRelations(contract, namespaceId, variant.modelName)[relationName];
381
+ const variantRelations = resolveModelRelations(contract, namespaceId, variant.modelName);
382
+ const candidate = Object.hasOwn(variantRelations, relationName) ? variantRelations[relationName] : void 0;
216
383
  if (candidate !== void 0) {
217
384
  relation = candidate;
218
385
  declaringModelName = variant.modelName;
219
386
  localTableName = variant.table;
220
387
  }
221
388
  }
222
- relation ??= resolveModelRelations(contract, namespaceId, baseModelName)[relationName];
389
+ const baseRelations = resolveModelRelations(contract, namespaceId, baseModelName);
390
+ relation ??= Object.hasOwn(baseRelations, relationName) ? baseRelations[relationName] : void 0;
223
391
  if (!relation) throw ormError("ORM.RELATION_UNKNOWN", `Relation '${relationName}' not found on model '${baseModelName}'`, { meta: {
224
392
  model: baseModelName,
225
393
  relation: relationName
226
394
  } });
227
395
  const { localFields, targetFields } = relation.on;
228
396
  if (localFields.length === 0 || localFields.length !== targetFields.length) throw new InternalError(`Relation '${relationName}' on model '${declaringModelName}' has incomplete join metadata: ${localFields.length} local field(s), ${targetFields.length} target field(s)`);
229
- const localColumns = localFields.map((field) => resolveFieldToColumn(contract, namespaceId, declaringModelName, field));
230
- const targetColumns = targetFields.map((field) => resolveFieldToColumn(contract, relation.toNamespace, relation.to, field));
397
+ const localColumns = localFields.map((field) => columnOfContractField(contract, namespaceId, declaringModelName, field));
398
+ const targetColumns = resolveRelationTargetColumns(contract, relation);
231
399
  const relatedTableName = resolveModelTableName(contract, relation.toNamespace, relation.to);
232
400
  let through;
233
401
  if (relation.through !== void 0) through = {
@@ -307,7 +475,8 @@ function parseRelationCardinality(value) {
307
475
  }
308
476
  function resolveUpsertConflictColumns(contract, namespaceId, modelName, conflictOn) {
309
477
  if (conflictOn && typeof conflictOn === "object") {
310
- const columns = Object.keys(conflictOn).map((fieldName) => resolveFieldToColumn(contract, namespaceId, modelName, fieldName));
478
+ const fieldColumns = getModelFieldColumns(contract, namespaceId, modelName);
479
+ const columns = Object.keys(conflictOn).map((fieldName) => columnOfCallerField(contract, namespaceId, fieldColumns, modelName, fieldName));
311
480
  if (columns.length > 0) return columns;
312
481
  }
313
482
  return [...storageTableForContract(contract, namespaceId, resolveModelTableName(contract, namespaceId, modelName)).primaryKey?.columns ?? []];
@@ -352,17 +521,9 @@ function requireCapability(contract, action, capability) {
352
521
  action
353
522
  } });
354
523
  }
355
- function resolveInsertConflictColumns(contract, namespaceId, modelName, conflictOn, action) {
356
- const fieldToColumn = getFieldToColumnMap(contract, namespaceId, modelName);
357
- return conflictOn.map((fieldName) => {
358
- const column = fieldToColumn[fieldName];
359
- if (column === void 0) throw ormError("ORM.ARGUMENT_INVALID", `${action} conflictOn field "${fieldName}" is not a scalar field of model "${modelName}"`, { meta: {
360
- action,
361
- model: modelName,
362
- field: fieldName
363
- } });
364
- return column;
365
- });
524
+ function resolveInsertConflictColumns(contract, namespaceId, modelName, conflictOn) {
525
+ const fieldColumns = getModelFieldColumns(contract, namespaceId, modelName);
526
+ return conflictOn.map((fieldName) => columnOfCallerField(contract, namespaceId, fieldColumns, modelName, fieldName));
366
527
  }
367
528
  function assertDistinctOnCapability(contract, methodName) {
368
529
  if (contract.capabilities["postgres"]?.["distinctOn"] === true) return;
@@ -405,10 +566,10 @@ function isToOneCardinality(cardinality) {
405
566
  * to the same registry.
406
567
  */
407
568
  function createAggregateBuilder(contract, aggregates, namespaceId, modelName) {
408
- const fieldToColumn = getFieldToColumnMap(contract, namespaceId, modelName);
569
+ const fieldColumns = getModelFieldColumns(contract, namespaceId, modelName);
409
570
  const builder = {};
410
571
  for (const operation of aggregateOperationNames(aggregates)) builder[operation] = (field) => {
411
- const column = field === void 0 ? void 0 : fieldToColumn[field] ?? field;
572
+ const column = field === void 0 ? void 0 : columnOfCallerField(contract, namespaceId, fieldColumns, modelName, field);
412
573
  return {
413
574
  kind: "aggregate",
414
575
  fn: operation,
@@ -486,41 +647,48 @@ function inputCodecRef(query) {
486
647
  function emptyAggregateResult(result, codec) {
487
648
  return result.nullable ? null : codec.decodeJson(result.emptyResultJson);
488
649
  }
650
+ /** The columns of a model's own and inherited fields, for operations that apply each column to the model's table: `groupBy`, `distinct` and `distinctOn`. */
489
651
  function mapFieldsToColumns(contract, namespaceId, modelName, fieldNames) {
490
- const fieldToColumn = getFieldToColumnMap(contract, namespaceId, modelName);
491
- return fieldNames.map((fieldName) => fieldToColumn[fieldName] ?? fieldName);
652
+ const fieldColumns = getModelFieldColumns(contract, namespaceId, modelName);
653
+ return fieldNames.map((fieldName) => columnOfCallerField(contract, namespaceId, fieldColumns, modelName, fieldName));
654
+ }
655
+ /** The columns a `select` names: the narrowed variant's fields too, or, when the collection is not narrowed, every variant's fields, each name reading every column a variant maps it to. See `getModelAndVariantFieldColumns` for why `select` accepts more than other surfaces. */
656
+ function mapSelectedFieldsToColumns(contract, namespaceId, modelName, variantName, fieldNames) {
657
+ const addressed = addressedModelName(modelName, variantName);
658
+ if (variantName !== void 0) {
659
+ const fieldColumns = getModelAndVariantFieldColumns(contract, namespaceId, modelName, variantName);
660
+ return fieldNames.map((fieldName) => columnOfCallerField(contract, namespaceId, fieldColumns, addressed, fieldName));
661
+ }
662
+ const fieldColumns = getModelAndEveryVariantFieldColumns(contract, namespaceId, modelName);
663
+ return fieldNames.flatMap((fieldName) => {
664
+ const columns = Object.hasOwn(fieldColumns, fieldName) ? fieldColumns[fieldName] : void 0;
665
+ if (columns === void 0) throw callerFieldUnknown(contract, namespaceId, fieldColumns, addressed, fieldName);
666
+ return [...columns];
667
+ });
492
668
  }
493
669
  function mapCursorValuesToColumns(contract, namespaceId, modelName, cursorValues) {
494
- const fieldToColumn = getFieldToColumnMap(contract, namespaceId, modelName);
670
+ const fieldColumns = getModelFieldColumns(contract, namespaceId, modelName);
495
671
  const mappedCursor = {};
496
672
  for (const [fieldName, value] of Object.entries(cursorValues)) {
497
673
  if (value === void 0) continue;
498
- const columnName = fieldToColumn[fieldName] ?? fieldName;
499
- mappedCursor[columnName] = value;
674
+ mappedCursor[columnOfCallerField(contract, namespaceId, fieldColumns, modelName, fieldName)] = value;
500
675
  }
501
676
  return mappedCursor;
502
677
  }
503
678
  function stripHiddenMappedFields(contract, namespaceId, modelName, mapped, hiddenColumns) {
504
679
  if (hiddenColumns.length === 0) return;
505
- const columnToField = getColumnToFieldMap(contract, namespaceId, modelName);
680
+ const columnToField = getModelColumnFields(contract, namespaceId, modelName);
506
681
  for (const hiddenColumn of hiddenColumns) {
507
- const fieldName = columnToField[hiddenColumn] ?? hiddenColumn;
508
- delete mapped[fieldName];
682
+ const fieldName = Object.hasOwn(columnToField, hiddenColumn) ? columnToField[hiddenColumn] : void 0;
683
+ if (fieldName !== void 0) delete mapped[fieldName];
509
684
  }
510
685
  }
511
686
  function mapStorageRowToModelFields(contract, namespaceId, modelName, row) {
512
- const columnToField = getColumnToFieldMap(contract, namespaceId, modelName);
513
- if (Object.keys(columnToField).length === 0) return { ...row };
514
- return mapColumnNames(row, columnToField);
687
+ return mapKnownColumnNames(row, getModelColumnFields(contract, namespaceId, modelName));
515
688
  }
516
689
  function createStorageRowMapper(contract, namespaceId, modelName) {
517
- const columnToField = getColumnToFieldMap(contract, namespaceId, modelName);
518
- return Object.keys(columnToField).length === 0 ? (row) => ({ ...row }) : (row) => mapColumnNames(row, columnToField);
519
- }
520
- function mapColumnNames(row, columnToField) {
521
- const mapped = {};
522
- for (const [columnName, value] of Object.entries(row)) mapped[columnToField[columnName] ?? columnName] = value;
523
- return mapped;
690
+ const columnToField = getModelColumnFields(contract, namespaceId, modelName);
691
+ return (row) => mapKnownColumnNames(row, columnToField);
524
692
  }
525
693
  const mergedColumnToFieldCache = /* @__PURE__ */ new WeakMap();
526
694
  function getMergedColumnToFieldMap(contract, namespaceId, baseModelName, variantModelName, variantTable) {
@@ -532,8 +700,8 @@ function getMergedColumnToFieldMap(contract, namespaceId, baseModelName, variant
532
700
  }
533
701
  const cached = perContract.get(cacheKey);
534
702
  if (cached) return cached;
535
- const baseMap = getCompleteColumnToFieldMap(contract, namespaceId, baseModelName);
536
- const variantMap = getCompleteColumnToFieldMap(contract, namespaceId, variantModelName);
703
+ const baseMap = getModelColumnFields(contract, namespaceId, baseModelName);
704
+ const variantMap = getOwnColumnFields(contract, namespaceId, variantModelName);
537
705
  const merged = { ...baseMap };
538
706
  for (const [col, field] of Object.entries(variantMap)) if (variantTable) merged[`${variantTable}__${col}`] = field;
539
707
  else merged[col] = field;
@@ -543,12 +711,12 @@ function getMergedColumnToFieldMap(contract, namespaceId, baseModelName, variant
543
711
  function mapPolymorphicRow(contract, namespaceId, baseModelName, polyInfo, row, variantName) {
544
712
  const discriminatorValue = row[polyInfo.discriminatorColumn] ?? row["__prisma_polymorphic_discriminator"];
545
713
  const variant = variantName ? polyInfo.variants.get(variantName) : typeof discriminatorValue === "string" ? polyInfo.variantsByValue.get(discriminatorValue) : void 0;
546
- if (!variant) return mapKnownColumnNames(row, getCompleteColumnToFieldMap(contract, namespaceId, baseModelName));
714
+ if (!variant) return mapKnownColumnNames(row, getModelColumnFields(contract, namespaceId, baseModelName));
547
715
  const mtiTable = variant.strategy === "mti" ? variant.table : void 0;
548
716
  return mapKnownColumnNames(row, getMergedColumnToFieldMap(contract, namespaceId, baseModelName, variant.modelName, mtiTable));
549
717
  }
550
718
  function createPolymorphicRowMapper(contract, namespaceId, baseModelName, polyInfo, variantName) {
551
- const baseMapper = captureColumnMapper(() => getCompleteColumnToFieldMap(contract, namespaceId, baseModelName));
719
+ const baseMapper = captureColumnMapper(() => getModelColumnFields(contract, namespaceId, baseModelName));
552
720
  const mappersByValue = /* @__PURE__ */ new Map();
553
721
  let pinnedMapper = baseMapper;
554
722
  for (const [name, variant] of polyInfo.variants) {
@@ -573,21 +741,26 @@ function captureColumnMapper(resolve) {
573
741
  };
574
742
  }
575
743
  }
744
+ /** Maps a row from columns to fields. A column no field maps is dropped. */
576
745
  function mapKnownColumnNames(row, columns) {
577
746
  const mapped = {};
578
747
  for (const [col, val] of Object.entries(row)) {
579
- const field = columns[col];
748
+ const field = Object.hasOwn(columns, col) ? columns[col] : void 0;
580
749
  if (field !== void 0) mapped[field] = val;
581
750
  }
582
751
  return mapped;
583
752
  }
753
+ /** Refuses any name in `data` with a value that is not a field of the model, as `mapModelDataToStorageRow` would, before anything reads or writes a row. */
754
+ function assertModelFieldNames(contract, namespaceId, modelName, data) {
755
+ const fieldColumns = getModelFieldColumns(contract, namespaceId, modelName);
756
+ for (const [fieldName, value] of Object.entries(data)) if (value !== void 0) columnOfCallerField(contract, namespaceId, fieldColumns, modelName, fieldName);
757
+ }
584
758
  function mapModelDataToStorageRow(contract, namespaceId, modelName, row) {
585
- const fieldToColumn = getFieldToColumnMap(contract, namespaceId, modelName);
759
+ const fieldColumns = getModelFieldColumns(contract, namespaceId, modelName);
586
760
  const mapped = {};
587
761
  for (const [fieldName, value] of Object.entries(row)) {
588
762
  if (value === void 0) continue;
589
- const columnName = fieldToColumn[fieldName] ?? fieldName;
590
- mapped[columnName] = value;
763
+ mapped[columnOfCallerField(contract, namespaceId, fieldColumns, modelName, fieldName)] = value;
591
764
  }
592
765
  return mapped;
593
766
  }
@@ -647,17 +820,6 @@ function checkedOrderByItem(dir, expr, options) {
647
820
  function deriveParamsFromAst(ast) {
648
821
  return { params: collectOrderedParamRefs(ast).map((p) => p.kind === "param-ref" ? p.value : void 0) };
649
822
  }
650
- function resolveTableColumns(contract, namespaceId, tableName) {
651
- try {
652
- return Object.keys(storageTableForContract(contract, namespaceId, tableName).columns);
653
- } catch (error) {
654
- if (error instanceof Error && error.message.includes("ambiguous")) throw error;
655
- throw ormError("ORM.TABLE_UNKNOWN", `Unknown table "${tableName}" in SQL ORM query planner`, { meta: {
656
- namespaceId,
657
- tableName
658
- } });
659
- }
660
- }
661
823
  function buildOrmPlanMeta(contract, annotations) {
662
824
  const annotationRecord = annotations !== void 0 && annotations.size > 0 ? Object.freeze(Object.fromEntries(annotations)) : void 0;
663
825
  return {
@@ -973,7 +1135,7 @@ function buildMtiJoins(contract, namespaceId, polyInfo, variantName, selectedCol
973
1135
  const joinOn = buildPrimaryKeyJoinOn(polyInfo.baseTable, variant.table, pkColumns);
974
1136
  const join = joinType === "inner" ? JoinAst.inner(tableSourceForContract(contract, namespaceId, variant.table), joinOn) : JoinAst.left(tableSourceForContract(contract, namespaceId, variant.table), joinOn);
975
1137
  joins.push(join);
976
- const variantColumns = resolveTableColumns(contract, namespaceId, variant.table);
1138
+ const variantColumns = getColumnsReadOnTable(contract, namespaceId, variant.modelName, variant.table);
977
1139
  const selectedVariantColumns = selectedColumnsByTable?.get(variant.table);
978
1140
  for (const col of variantColumns) {
979
1141
  if (pkColumns.includes(col)) continue;
@@ -1303,8 +1465,8 @@ function compileGroupedAggregate(contract, aggregates, namespaceId, tableName, p
1303
1465
  const { params } = deriveParamsFromAst(ast);
1304
1466
  return buildOrmQueryPlan(contract, ast, params);
1305
1467
  }
1306
- function buildReturningColumns(contract, namespaceId, tableName, returningColumns) {
1307
- return (returningColumns && returningColumns.length > 0 ? [...returningColumns] : resolveTableColumns(contract, namespaceId, tableName)).map((column) => ProjectionItem.of(column, ColumnRef.of(tableName, column), codecRefForStorageColumn(contract.storage, namespaceId, tableName, column)));
1468
+ function buildReturningColumns(contract, namespaceId, modelName, tableName, returningColumns) {
1469
+ return (returningColumns && returningColumns.length > 0 ? [...returningColumns] : getColumnsReadOnTable(contract, namespaceId, modelName, tableName)).map((column) => ProjectionItem.of(column, ColumnRef.of(tableName, column), codecRefForStorageColumn(contract.storage, namespaceId, tableName, column)));
1308
1470
  }
1309
1471
  function toParamAssignments(contract, namespaceId, tableName, values) {
1310
1472
  const assignments = {};
@@ -1360,9 +1522,9 @@ function conflictSkipClause(tableName, conflictSkip) {
1360
1522
  if (conflictSkip.columns.length === 0) return InsertOnConflict.doNothing();
1361
1523
  return InsertOnConflict.on(conflictSkip.columns.map((column) => ColumnRef.of(tableName, column))).doNothing();
1362
1524
  }
1363
- function compileInsertReturning(contract, namespaceId, tableName, rows, returningColumns, conflictSkip) {
1525
+ function compileInsertReturning(contract, namespaceId, modelName, tableName, rows, returningColumns, conflictSkip) {
1364
1526
  const { rows: normalizedRows } = normalizeInsertRows(contract, namespaceId, tableName, rows);
1365
- const ast = InsertAst.into(tableSourceForContract(contract, namespaceId, tableName)).withRows(normalizedRows).withOnConflict(conflictSkipClause(tableName, conflictSkip)).withReturning(buildReturningColumns(contract, namespaceId, tableName, returningColumns));
1527
+ const ast = InsertAst.into(tableSourceForContract(contract, namespaceId, tableName)).withRows(normalizedRows).withOnConflict(conflictSkipClause(tableName, conflictSkip)).withReturning(buildReturningColumns(contract, namespaceId, modelName, tableName, returningColumns));
1366
1528
  const { params } = deriveParamsFromAst(ast);
1367
1529
  return buildOrmQueryPlan(contract, ast, params);
1368
1530
  }
@@ -1419,13 +1581,13 @@ function groupRowsByColumnSignature(rows) {
1419
1581
  if (currentGroup.length > 0) groups.push(currentGroup);
1420
1582
  return groups;
1421
1583
  }
1422
- function compileInsertReturningSplit(contract, namespaceId, tableName, rows, returningColumns, conflictSkip) {
1584
+ function compileInsertReturningSplit(contract, namespaceId, modelName, tableName, rows, returningColumns, conflictSkip) {
1423
1585
  if (rows.length === 0) throw ormError("ORM.MUTATION_DATA_MISSING", "create() requires at least one row", { meta: {
1424
1586
  method: "create",
1425
1587
  namespaceId,
1426
1588
  tableName
1427
1589
  } });
1428
- return groupRowsByColumnSignature(rows).map((group) => compileInsertReturning(contract, namespaceId, tableName, group, returningColumns, conflictSkip));
1590
+ return groupRowsByColumnSignature(rows).map((group) => compileInsertReturning(contract, namespaceId, modelName, tableName, group, returningColumns, conflictSkip));
1429
1591
  }
1430
1592
  function compileInsertCountSplit(contract, namespaceId, tableName, rows, conflictSkip) {
1431
1593
  if (rows.length === 0) throw ormError("ORM.MUTATION_DATA_MISSING", "createAndCount() requires at least one row", { meta: {
@@ -1435,18 +1597,18 @@ function compileInsertCountSplit(contract, namespaceId, tableName, rows, conflic
1435
1597
  } });
1436
1598
  return groupRowsByColumnSignature(rows).map((group) => compileInsertCount(contract, namespaceId, tableName, group, conflictSkip));
1437
1599
  }
1438
- function compileUpsertReturning(contract, namespaceId, tableName, createValues, updateValues, conflictColumns, returningColumns) {
1600
+ function compileUpsertReturning(contract, namespaceId, modelName, tableName, createValues, updateValues, conflictColumns, returningColumns) {
1439
1601
  const createAssignments = toParamAssignments(contract, namespaceId, tableName, createValues);
1440
1602
  const updateAssignments = Object.keys(updateValues).length > 0 ? toParamAssignments(contract, namespaceId, tableName, updateValues) : void 0;
1441
1603
  const onConflict = updateAssignments ? InsertOnConflict.on(conflictColumns.map((column) => ColumnRef.of(tableName, column))).doUpdateSet(updateAssignments.assignments) : InsertOnConflict.on(conflictColumns.map((column) => ColumnRef.of(tableName, column))).doNothing();
1442
- const ast = InsertAst.into(tableSourceForContract(contract, namespaceId, tableName)).withRows([createAssignments.assignments]).withOnConflict(onConflict).withReturning(buildReturningColumns(contract, namespaceId, tableName, returningColumns));
1604
+ const ast = InsertAst.into(tableSourceForContract(contract, namespaceId, tableName)).withRows([createAssignments.assignments]).withOnConflict(onConflict).withReturning(buildReturningColumns(contract, namespaceId, modelName, tableName, returningColumns));
1443
1605
  const { params } = deriveParamsFromAst(ast);
1444
1606
  return buildOrmQueryPlan(contract, ast, params);
1445
1607
  }
1446
- function compileUpdateReturning(contract, namespaceId, tableName, setValues, filters, returningColumns) {
1608
+ function compileUpdateReturning(contract, namespaceId, modelName, tableName, setValues, filters, returningColumns) {
1447
1609
  const where = combineWhereExprs(filters);
1448
1610
  const { assignments } = toParamAssignments(contract, namespaceId, tableName, setValues);
1449
- let ast = UpdateAst.table(tableSourceForContract(contract, namespaceId, tableName)).withSet(assignments).withReturning(buildReturningColumns(contract, namespaceId, tableName, returningColumns));
1611
+ let ast = UpdateAst.table(tableSourceForContract(contract, namespaceId, tableName)).withSet(assignments).withReturning(buildReturningColumns(contract, namespaceId, modelName, tableName, returningColumns));
1450
1612
  if (where) ast = ast.withWhere(where);
1451
1613
  const { params } = deriveParamsFromAst(ast);
1452
1614
  return buildOrmQueryPlan(contract, ast, params);
@@ -1459,9 +1621,9 @@ function compileUpdateCount(contract, namespaceId, tableName, setValues, filters
1459
1621
  const { params } = deriveParamsFromAst(ast);
1460
1622
  return buildOrmQueryPlan(contract, ast, params);
1461
1623
  }
1462
- function compileDeleteReturning(contract, namespaceId, tableName, filters, returningColumns) {
1624
+ function compileDeleteReturning(contract, namespaceId, modelName, tableName, filters, returningColumns) {
1463
1625
  const where = combineWhereExprs(filters);
1464
- let ast = DeleteAst.from(tableSourceForContract(contract, namespaceId, tableName)).withReturning(buildReturningColumns(contract, namespaceId, tableName, returningColumns));
1626
+ let ast = DeleteAst.from(tableSourceForContract(contract, namespaceId, tableName)).withReturning(buildReturningColumns(contract, namespaceId, modelName, tableName, returningColumns));
1465
1627
  if (where) ast = ast.withWhere(where);
1466
1628
  const { params } = deriveParamsFromAst(ast);
1467
1629
  return buildOrmQueryPlan(contract, ast, params);
@@ -1542,8 +1704,8 @@ function jsonEntryProjection(value, identity) {
1542
1704
  if (identity.document === true) return new JsonDocumentProjection(value);
1543
1705
  return new NativeJsonValueProjection(value);
1544
1706
  }
1545
- function buildProjection(contract, namespaceId, tableName, selectedFields, tableRef = tableName) {
1546
- return (selectedFields !== void 0 ? [...selectedFields] : resolveTableColumns(contract, namespaceId, tableName)).map((column) => ProjectionItem.of(column, ColumnRef.of(tableRef, column), codecRefForStorageColumn(contract.storage, namespaceId, tableName, column)));
1707
+ function buildProjection(contract, namespaceId, modelName, tableName, selectedFields, tableRef = tableName) {
1708
+ return (selectedFields !== void 0 ? [...selectedFields] : getColumnsReadOnTable(contract, namespaceId, modelName, tableName)).map((column) => ProjectionItem.of(column, ColumnRef.of(tableRef, column), codecRefForStorageColumn(contract.storage, namespaceId, tableName, column)));
1547
1709
  }
1548
1710
  function appendUnique(values, value) {
1549
1711
  if (!values.includes(value)) values.push(value);
@@ -1554,22 +1716,21 @@ function resolvePolymorphicProjectionSelection(contract, namespaceId, modelName,
1554
1716
  selectedMtiColumnsByTable: void 0,
1555
1717
  needsHiddenDiscriminator: false
1556
1718
  };
1557
- const baseTableColumns = new Set(resolveTableColumns(contract, namespaceId, polyInfo.baseTable));
1558
- const baseFieldToColumn = getFieldToColumnMap(contract, namespaceId, modelName);
1559
- const variantFieldMaps = Array.from(polyInfo.variants.values(), (variant) => ({
1719
+ const baseColumnToField = getModelColumnFields(contract, namespaceId, modelName);
1720
+ const variantColumnMaps = Array.from(polyInfo.variants.values(), (variant) => ({
1560
1721
  variant,
1561
- columnToField: getCompleteColumnToFieldMap(contract, namespaceId, variant.modelName)
1722
+ columnToField: getOwnColumnFields(contract, namespaceId, variant.modelName)
1562
1723
  }));
1563
1724
  const baseSelectedFields = [];
1564
1725
  const selectedMtiColumnsByTable = /* @__PURE__ */ new Map();
1565
1726
  let hasVariantOwnedSelection = false;
1566
- for (const selectedField of state.selectedFields) {
1567
- const baseColumn = baseFieldToColumn[selectedField] ?? (baseTableColumns.has(selectedField) ? selectedField : void 0);
1568
- if (baseColumn !== void 0) appendUnique(baseSelectedFields, baseColumn);
1569
- let matchedVariantField = false;
1570
- for (const { variant, columnToField } of variantFieldMaps) for (const [column, field] of Object.entries(columnToField)) {
1571
- if (selectedField !== field && selectedField !== column) continue;
1572
- matchedVariantField = true;
1727
+ for (const column of state.selectedFields) {
1728
+ const isBaseColumn = Object.hasOwn(baseColumnToField, column);
1729
+ if (isBaseColumn) appendUnique(baseSelectedFields, column);
1730
+ let isVariantColumn = false;
1731
+ for (const { variant, columnToField } of variantColumnMaps) {
1732
+ if (!Object.hasOwn(columnToField, column)) continue;
1733
+ isVariantColumn = true;
1573
1734
  hasVariantOwnedSelection = true;
1574
1735
  if (variant.strategy === "sti") {
1575
1736
  appendUnique(baseSelectedFields, column);
@@ -1582,7 +1743,7 @@ function resolvePolymorphicProjectionSelection(contract, namespaceId, modelName,
1582
1743
  }
1583
1744
  selectedColumns.add(column);
1584
1745
  }
1585
- if (baseColumn === void 0 && !matchedVariantField) appendUnique(baseSelectedFields, selectedField);
1746
+ if (!isBaseColumn && !isVariantColumn) throw new InternalError(`Selected column "${column}" is mapped by no field of model "${modelName}" or its variants; select() resolves field names before they reach the projection`);
1586
1747
  }
1587
1748
  return {
1588
1749
  baseSelectedFields,
@@ -1792,7 +1953,7 @@ function buildIncludeChildRowsSelect(contract, aggregates, parentSource, include
1792
1953
  junctionJoins
1793
1954
  });
1794
1955
  const polyJoinsAndProjection = buildChildPolymorphismJoinsAndProjection(contract, include, childTableAlias, childTableRef);
1795
- const scalarProjection = buildProjection(contract, include.relatedNamespaceId, include.relatedTableName, polyJoinsAndProjection.baseSelectedFields, childTableRef);
1956
+ const scalarProjection = buildProjection(contract, include.relatedNamespaceId, addressedModelName(include.relatedModelName, include.nested.variantName), include.relatedTableName, polyJoinsAndProjection.baseSelectedFields, childTableRef);
1796
1957
  const nestedProjections = buildNestedIncludeProjections(contract, aggregates, {
1797
1958
  baseTableName: include.relatedTableName,
1798
1959
  tableRef: childTableRef,
@@ -1843,7 +2004,7 @@ function buildDistinctNonLeafChildRowsSelect(options) {
1843
2004
  selectedFields: selectedForQuery
1844
2005
  }
1845
2006
  }, childTableAlias, childTableRef);
1846
- const innerScalarProjection = buildProjection(contract, include.relatedNamespaceId, include.relatedTableName, queryPolyProjection.baseSelectedFields, childTableRef);
2007
+ const innerScalarProjection = buildProjection(contract, include.relatedNamespaceId, addressedModelName(include.relatedModelName, include.nested.variantName), include.relatedTableName, queryPolyProjection.baseSelectedFields, childTableRef);
1847
2008
  const innerMtiProjection = mergeProjectionByAlias(queryPolyProjection.projection, buildRequiredMtiJoinKeyProjection(contract, include));
1848
2009
  let baseInner = SelectAst.from(tableSourceForContract(contract, include.relatedNamespaceId, include.relatedTableName, childTableAlias)).withProjection([
1849
2010
  ...innerScalarProjection,
@@ -1866,7 +2027,7 @@ function buildDistinctNonLeafChildRowsSelect(options) {
1866
2027
  if (childState.limit !== void 0) innerSelect = innerSelect.withLimit(childState.limit);
1867
2028
  if (childState.offset !== void 0) innerSelect = innerSelect.withOffset(childState.offset);
1868
2029
  const distinctAlias = `${include.relationName}__distinct`;
1869
- const outerScalarProjection = buildProjection(contract, include.relatedNamespaceId, include.relatedTableName, visiblePolyProjection.baseSelectedFields, distinctAlias);
2030
+ const outerScalarProjection = buildProjection(contract, include.relatedNamespaceId, addressedModelName(include.relatedModelName, include.nested.variantName), include.relatedTableName, visiblePolyProjection.baseSelectedFields, distinctAlias);
1870
2031
  const outerNestedProjections = buildNestedIncludeProjections(contract, aggregates, {
1871
2032
  baseTableName: include.relatedTableName,
1872
2033
  tableRef: distinctAlias,
@@ -2063,14 +2224,15 @@ function buildCorrelatedIncludeProjection(contract, aggregates, parentSource, in
2063
2224
  const aggregateQuery = buildIncludeChildRowsAggregateSelect(contract, aggregates, parentSource, include);
2064
2225
  return { projection: ProjectionItem.of(include.relationName, SubqueryExpr.of(aggregateQuery)) };
2065
2226
  }
2066
- function buildSelectAst(contract, tableName, state, options) {
2227
+ function buildSelectAst(contract, modelName, tableName, state, options) {
2067
2228
  const namespaceId = options.namespaceId;
2068
2229
  if (state.distinctOn !== void 0 && state.distinctOn.length > 0) {
2069
2230
  assertDistinctOnCapability(contract, "distinctOn");
2070
2231
  assertDistinctOnCompatibleOrder(state.orderBy, state.distinctOn.length);
2071
2232
  }
2072
- const projection = [...buildProjection(contract, namespaceId, tableName, state.selectedFields, tableName), ...options.includeProjection ?? []];
2073
- const { source: fromSource, where: effectiveWhere } = buildDedupedTableSource(contract, namespaceId, tableName, state, options.where ?? buildStateWhere(contract, tableName, state, { namespaceId }), resolveTableColumns(contract, namespaceId, tableName).map((column) => ProjectionItem.of(column, ColumnRef.of(tableName, column))));
2233
+ const addressed = addressedModelName(modelName, state.variantName);
2234
+ const projection = [...buildProjection(contract, namespaceId, addressed, tableName, state.selectedFields, tableName), ...options.includeProjection ?? []];
2235
+ const { source: fromSource, where: effectiveWhere } = buildDedupedTableSource(contract, namespaceId, tableName, state, options.where ?? buildStateWhere(contract, tableName, state, { namespaceId }), getColumnsReadOnTable(contract, namespaceId, addressed, tableName).map((column) => ProjectionItem.of(column, ColumnRef.of(tableName, column))));
2074
2236
  let ast = SelectAst.from(fromSource).withProjection(projection);
2075
2237
  if (effectiveWhere) ast = ast.withWhere(effectiveWhere);
2076
2238
  if (state.orderBy) ast = ast.withOrderBy(state.orderBy);
@@ -2082,18 +2244,18 @@ function buildSelectAst(contract, tableName, state, options) {
2082
2244
  if (state.locking !== void 0) ast = ast.withLocking(state.locking);
2083
2245
  return ast;
2084
2246
  }
2085
- function compileSelect(contract, namespaceId, tableName, state, modelName) {
2247
+ function compileSelect(contract, namespaceId, modelName, tableName, state) {
2086
2248
  assertLockCompatible(state);
2087
2249
  if (state.distinctOn !== void 0 && state.distinctOn.length > 0) assertDistinctOnCapability(contract, "distinctOn");
2088
- const polyInfo = modelName ? resolvePolymorphismInfo(contract, namespaceId, modelName) : void 0;
2089
- const selection = polyInfo && modelName ? resolvePolymorphicProjectionSelection(contract, namespaceId, modelName, polyInfo, state) : void 0;
2250
+ const polyInfo = resolvePolymorphismInfo(contract, namespaceId, modelName);
2251
+ const selection = polyInfo ? resolvePolymorphicProjectionSelection(contract, namespaceId, modelName, polyInfo, state) : void 0;
2090
2252
  const projectionState = selection ? {
2091
2253
  ...state,
2092
2254
  selectedFields: selection.baseSelectedFields
2093
2255
  } : state;
2094
2256
  const mtiArtifacts = polyInfo && polyInfo.mtiVariants.length > 0 ? buildMtiJoins(contract, namespaceId, polyInfo, state.variantName, selection?.selectedMtiColumnsByTable) : void 0;
2095
2257
  const hiddenProjection = polyInfo && selection ? buildHiddenDiscriminatorProjection(contract, namespaceId, polyInfo, tableName, selection.needsHiddenDiscriminator) : [];
2096
- const ast = buildSelectAst(contract, tableName, {
2258
+ const ast = buildSelectAst(contract, modelName, tableName, {
2097
2259
  ...projectionState,
2098
2260
  includes: []
2099
2261
  }, {
@@ -2104,13 +2266,13 @@ function compileSelect(contract, namespaceId, tableName, state, modelName) {
2104
2266
  const { params } = deriveParamsFromAst(ast);
2105
2267
  return buildOrmQueryPlan(contract, ast, params, state.annotations);
2106
2268
  }
2107
- function compileSelectWithIncludes(contract, aggregates, namespaceId, tableName, state, modelName) {
2269
+ function compileSelectWithIncludes(contract, aggregates, namespaceId, modelName, tableName, state) {
2108
2270
  assertLockCompatible(state);
2109
2271
  const includeJoins = [];
2110
2272
  const includeProjection = [];
2111
2273
  const topLevelWhere = buildStateWhere(contract, tableName, state, { namespaceId });
2112
- const polyInfo = modelName ? resolvePolymorphismInfo(contract, namespaceId, modelName) : void 0;
2113
- const selection = polyInfo && modelName ? resolvePolymorphicProjectionSelection(contract, namespaceId, modelName, polyInfo, state) : void 0;
2274
+ const polyInfo = resolvePolymorphismInfo(contract, namespaceId, modelName);
2275
+ const selection = polyInfo ? resolvePolymorphicProjectionSelection(contract, namespaceId, modelName, polyInfo, state) : void 0;
2114
2276
  const projectionState = selection ? {
2115
2277
  ...state,
2116
2278
  selectedFields: selection.baseSelectedFields
@@ -2132,7 +2294,7 @@ function compileSelectWithIncludes(contract, aggregates, namespaceId, tableName,
2132
2294
  const artifact = buildCorrelatedIncludeProjection(contract, aggregates, parentSource, include);
2133
2295
  includeProjection.push(artifact.projection);
2134
2296
  }
2135
- const ast = buildSelectAst(contract, tableName, {
2297
+ const ast = buildSelectAst(contract, modelName, tableName, {
2136
2298
  ...projectionState,
2137
2299
  includes: []
2138
2300
  }, {
@@ -2158,7 +2320,7 @@ function describeExecutionRows(options) {
2158
2320
  const { contract } = context;
2159
2321
  const polyInfo = resolvePolymorphismInfo(contract, namespaceId, modelName);
2160
2322
  if (state.includes.length === 0) {
2161
- const compiled = compileSelect(contract, namespaceId, tableName, state, modelName);
2323
+ const compiled = compileSelect(contract, namespaceId, modelName, tableName, state);
2162
2324
  const mapper = polyInfo ? (rawRow) => blindCast(mapPolymorphicRow(contract, namespaceId, modelName, polyInfo, rawRow, state.variantName)) : (rawRow) => blindCast(mapStorageRowToModelFields(contract, namespaceId, modelName, rawRow));
2163
2325
  return {
2164
2326
  plan: compiled,
@@ -2166,7 +2328,7 @@ function describeExecutionRows(options) {
2166
2328
  };
2167
2329
  }
2168
2330
  return {
2169
- plan: compileSelectWithIncludes(contract, context.aggregateDescriptors, namespaceId, tableName, state, modelName),
2331
+ plan: compileSelectWithIncludes(contract, context.aggregateDescriptors, namespaceId, modelName, tableName, state),
2170
2332
  consume: (rows) => consumeIncludeRows(context, state, namespaceId, modelName, rows)
2171
2333
  };
2172
2334
  }
@@ -2231,10 +2393,10 @@ function createPreparedIncludeConsumer(context, include) {
2231
2393
  }
2232
2394
  const mapRow = createPreparedMapper(contract, include.relatedNamespaceId, include.relatedModelName, include.nested.variantName);
2233
2395
  const bindings = deferResolution(() => {
2234
- const tables = contract.storage.namespaces[include.relatedNamespaceId]?.entries.table;
2235
- const keys = new Set(Object.keys(tables?.[include.relatedTableName]?.columns ?? {}));
2236
- const polyInfo = resolvePolymorphismInfo(contract, include.relatedNamespaceId, include.relatedModelName);
2237
- for (const variant of polyInfo?.mtiVariants ?? []) for (const column of Object.keys(tables?.[variant.table]?.columns ?? {})) keys.add(`${variant.table}__${column}`);
2396
+ const namespace = include.relatedNamespaceId;
2397
+ const keys = new Set(getColumnsReadOnTable(contract, namespace, addressedModelName(include.relatedModelName, include.nested.variantName), include.relatedTableName));
2398
+ const polyInfo = resolvePolymorphismInfo(contract, namespace, include.relatedModelName);
2399
+ for (const variant of polyInfo?.mtiVariants ?? []) for (const column of getColumnsReadOnTable(contract, namespace, variant.modelName, variant.table)) keys.add(`${variant.table}__${column}`);
2238
2400
  return new Map([...keys].map((key) => [key, deferResolution(() => resolveIncludedColumnBinding(contract, context, include, key))]));
2239
2401
  });
2240
2402
  const bindingFor = (key) => bindings().get(key)?.() ?? null;
@@ -2261,19 +2423,19 @@ function createPreparedIncludedRowDecoder(contract, include, bindingFor) {
2261
2423
  const namespace = include.relatedNamespaceId;
2262
2424
  const model = include.relatedModelName;
2263
2425
  if (resolvePolymorphismInfo(contract, namespace, model)) return void 0;
2264
- const fieldToColumn = getFieldToColumnMap(contract, namespace, model);
2265
- const columnToField = getColumnToFieldMap(contract, namespace, model);
2266
- const columns = (include.nested.selectedFields ?? Object.keys(fieldToColumn)).map((field) => Object.hasOwn(fieldToColumn, field) ? fieldToColumn[field] ?? field : field);
2426
+ const columnToField = getModelColumnFields(contract, namespace, model);
2427
+ const columns = include.nested.selectedFields ?? getColumnsReadOnTable(contract, namespace, model, include.relatedTableName);
2267
2428
  const aliases = include.nested.includes.map((child) => child.relationName);
2268
2429
  const table = contract.storage.namespaces[namespace]?.entries.table?.[include.relatedTableName];
2269
2430
  if (aliases.some((alias) => table?.columns[alias] !== void 0)) return void 0;
2270
2431
  const keys = [...columns, ...aliases];
2271
2432
  if (keys.includes("__proto__") || new Set(keys).size !== keys.length) return void 0;
2433
+ const fieldOf = (key) => aliases.includes(key) ? key : fieldOfColumn(columnToField, model, key);
2272
2434
  const operations = keys.map((key) => {
2273
2435
  const binding = deferResolution(() => bindingFor(key));
2274
2436
  return {
2275
2437
  key,
2276
- field: Object.hasOwn(columnToField, key) ? columnToField[key] ?? key : key,
2438
+ field: fieldOf(key),
2277
2439
  decode(value) {
2278
2440
  if (value === null || value === void 0) return value;
2279
2441
  const resolved = binding();
@@ -2766,12 +2928,11 @@ function all() {
2766
2928
  function shorthandToWhereExpr(context, namespaceId, modelName, filters) {
2767
2929
  const contract = context.contract;
2768
2930
  const tableName = resolveModelTableName(contract, namespaceId, modelName);
2769
- const fieldToColumn = getFieldToColumnMap(contract, namespaceId, modelName);
2931
+ const fieldColumns = getModelFieldColumns(contract, namespaceId, modelName);
2770
2932
  const exprs = [];
2771
2933
  for (const [fieldName, value] of Object.entries(filters)) {
2772
2934
  if (value === void 0) continue;
2773
- const columnName = fieldToColumn[fieldName] ?? fieldName;
2774
- const left = ColumnRef.of(tableName, columnName);
2935
+ const left = ColumnRef.of(tableName, columnOfCallerField(contract, namespaceId, fieldColumns, modelName, fieldName));
2775
2936
  if (value === null) {
2776
2937
  exprs.push(NullCheckExpr.isNull(left));
2777
2938
  continue;
@@ -2931,7 +3092,7 @@ function assertDeclaredFieldsFragmentFields(collection, fields) {
2931
3092
  const { contract } = collection.ctx.context;
2932
3093
  const { modelName, namespaceId } = collection;
2933
3094
  const label = modelLabel(collection);
2934
- const model = modelOf(contract, namespaceId, modelName);
3095
+ const modelFields = getModelFields(contract, namespaceId, modelName);
2935
3096
  for (const [name, spec] of fields) {
2936
3097
  const declared = `The fragment was declared for models that have a ${spec.many === false ? "field" : "list field"} ${name} ${describeField(spec)}.`;
2937
3098
  const meta = {
@@ -2942,14 +3103,14 @@ function assertDeclaredFieldsFragmentFields(collection, fields) {
2942
3103
  nullable: spec.nullable,
2943
3104
  many: spec.many
2944
3105
  };
2945
- const modelFields = model?.fields ?? {};
2946
- if (!Object.hasOwn(modelFields, name)) throw ormError("ORM.FIELD_UNKNOWN", `Cannot apply a fragment to ${label}: it has no field ${name}`, {
3106
+ const fieldColumn = Object.hasOwn(modelFields, name) ? modelFields[name] : void 0;
3107
+ if (fieldColumn === void 0) throw ormError("ORM.FIELD_UNKNOWN", `Cannot apply a fragment to ${label}: it has no field ${name}`, {
2947
3108
  why: declared,
2948
3109
  fix: `Apply the fragment to a model that has a field ${name}, or remove ${name} from the declaration in the fragment.`,
2949
3110
  meta
2950
3111
  });
2951
- const fieldMany = multiplicity(modelFields[name]?.many);
2952
- const column = resolveColumn(contract, namespaceId, collection.tableName, resolveFieldToColumn(contract, namespaceId, modelName, name));
3112
+ const fieldMany = multiplicity(domainFieldOf(contract, namespaceId, modelName, name)?.many);
3113
+ const column = resolveColumn(contract, namespaceId, fieldColumn.table, fieldColumn.column);
2953
3114
  const actual = column === void 0 ? `${label}.${name} has no column.` : fieldMany === false ? `${label}.${name} has codec ${column.codecId} and ${nullability(column.nullable)}.` : `${label}.${name} is a list ${describeField({
2954
3115
  codecId: column.codecId,
2955
3116
  nullable: column.nullable,
@@ -2998,23 +3159,35 @@ function cutNote(subject, value) {
2998
3159
  }
2999
3160
  function fieldCodecId(collection, field) {
3000
3161
  const { contract } = collection.ctx.context;
3001
- const column = resolveFieldToColumn(contract, collection.namespaceId, collection.modelName, field);
3002
- return resolveColumn(contract, collection.namespaceId, collection.tableName, column)?.codecId;
3162
+ const modelFields = getModelFields(contract, collection.namespaceId, collection.modelName);
3163
+ const fieldColumn = Object.hasOwn(modelFields, field) ? modelFields[field] : void 0;
3164
+ if (fieldColumn === void 0) return void 0;
3165
+ return resolveColumn(contract, collection.namespaceId, fieldColumn.table, fieldColumn.column)?.codecId;
3166
+ }
3167
+ /** The domain declaration of a model's own or inherited field. */
3168
+ function domainFieldOf(contract, namespaceId, modelName, name) {
3169
+ let model = modelOf(contract, namespaceId, modelName);
3170
+ while (model !== void 0) {
3171
+ const fields = model.fields ?? {};
3172
+ if (Object.hasOwn(fields, name)) return fields[name];
3173
+ const base = model.base;
3174
+ model = base === void 0 ? void 0 : modelOf(contract, base.namespace, base.model);
3175
+ }
3003
3176
  }
3004
3177
  function canOrder(collection, field) {
3005
3178
  const codecId = fieldCodecId(collection, field);
3006
3179
  return codecId !== void 0 && hasTrait(collection.ctx.context, codecId, "order");
3007
3180
  }
3008
3181
  function orderableFieldNames(collection) {
3009
- const model = modelOf(collection.ctx.context.contract, collection.namespaceId, collection.modelName);
3010
- return Object.keys(model?.fields ?? {}).filter((field) => canOrder(collection, field));
3182
+ const modelFields = getModelFields(collection.ctx.context.contract, collection.namespaceId, collection.modelName);
3183
+ return Object.keys(modelFields).filter((field) => canOrder(collection, field));
3011
3184
  }
3012
3185
  function whyNotOrderable(collection, name) {
3013
3186
  const { modelName } = collection;
3014
3187
  const model = modelOf(collection.ctx.context.contract, collection.namespaceId, modelName);
3015
3188
  const quoted = shown(name).text;
3016
3189
  if (Object.hasOwn(model?.relations ?? {}, name)) return `${quoted} is a relation of ${modelName}, not a field.`;
3017
- if (!Object.hasOwn(model?.fields ?? {}, name)) return `${modelName} has no field ${quoted}.`;
3190
+ if (!Object.hasOwn(getModelFields(collection.ctx.context.contract, collection.namespaceId, modelName), name)) return `${modelName} has no field ${quoted}.`;
3018
3191
  return canOrder(collection, name) ? `${quoted} is not one of the fields allowed for ordering.` : `The codec ${fieldCodecId(collection, name)} of ${modelName}.${name} cannot be ordered.`;
3019
3192
  }
3020
3193
  /**
@@ -3177,7 +3350,7 @@ function createModelAccessor(context, namespaceId, modelName, variantName) {
3177
3350
  }
3178
3351
  function createModelAccessorInScope(context, namespaceId, modelName, variantName, scope) {
3179
3352
  const contract = context.contract;
3180
- const fieldToColumn = getFieldToColumnMap(contract, namespaceId, modelName);
3353
+ const fieldColumns = getModelAndVariantFieldColumns(contract, namespaceId, modelName, variantName);
3181
3354
  const tableName = resolveModelTableName(contract, namespaceId, modelName);
3182
3355
  const modelRelations = resolveModelRelations(contract, namespaceId, modelName);
3183
3356
  const variantFieldColumns = variantName ? resolveVariantFieldColumns(contract, namespaceId, modelName, variantName) : {};
@@ -3205,20 +3378,23 @@ function createModelAccessorInScope(context, namespaceId, modelName, variantName
3205
3378
  if (self.traits.every((t) => descriptorTraits.includes(t))) registerOp(descriptor.codecId, op);
3206
3379
  }
3207
3380
  }
3208
- return blindCast(new Proxy({}, { get(_target, prop) {
3381
+ return blindCast(new Proxy({}, { get(target, prop) {
3209
3382
  if (typeof prop !== "string") return;
3210
- if (variantCoordinates) {
3383
+ if (variantCoordinates && Object.hasOwn(variantCoordinates.relations, prop)) {
3211
3384
  const variantRelation = variantCoordinates.relations[prop];
3212
3385
  if (variantRelation) return createRelationFilterAccessor(context, namespaceId, variantCoordinates.name, scope.forJoinedSource(namespaceId, variantCoordinates.tableName), variantRelation);
3213
3386
  }
3214
- const relation = modelRelations[prop];
3387
+ const relation = Object.hasOwn(modelRelations, prop) ? modelRelations[prop] : void 0;
3215
3388
  if (relation) return createRelationFilterAccessor(context, namespaceId, modelName, scope, relation);
3216
- const variantField = variantFieldColumns[prop];
3389
+ const variantField = Object.hasOwn(variantFieldColumns, prop) ? variantFieldColumns[prop] : void 0;
3390
+ if (variantField === void 0 && !Object.hasOwn(fieldColumns, prop)) {
3391
+ if (isProbedByRuntime(prop)) return probedValue(target, prop);
3392
+ }
3217
3393
  const resolvedTable = variantField?.table ?? tableName;
3218
3394
  const fieldBinding = scope.forJoinedSource(namespaceId, resolvedTable).current;
3219
- const columnName = variantField?.column ?? fieldToColumn[prop] ?? prop;
3395
+ const columnName = variantField?.column ?? columnOfCallerField(contract, namespaceId, fieldColumns, addressedModelName(modelName, variantName), prop);
3220
3396
  const column = resolveColumn(contract, namespaceId, resolvedTable, columnName);
3221
- if (!column) return;
3397
+ if (!column) throw new InternalError(`Field "${modelName}.${prop}" maps column "${columnName}", which table "${resolvedTable}" does not have`);
3222
3398
  const traits = codecTraits(context, column.codecId);
3223
3399
  const operations = opsByCodecId.get(column.codecId) ?? [];
3224
3400
  const codec = codecRefForStorageColumn(contract.storage, namespaceId, resolvedTable, columnName);
@@ -3278,6 +3454,7 @@ function createRelationFilterAccessor(context, parentNamespaceId, parentModelNam
3278
3454
  if (typeof prop !== "string") return void 0;
3279
3455
  if (Object.hasOwn(target, prop)) return Reflect.get(target, prop);
3280
3456
  if (RELATION_ACCESSOR_METHOD_NAMES.has(prop)) return void 0;
3457
+ if (isProbedByRuntime(prop) && !Object.hasOwn(getModelFieldColumns(context.contract, relation.toNamespace, relation.to), prop)) return probedValue(target, prop);
3281
3458
  return relatedOrderableField(context, relation, relatedTableName, correlate, prop);
3282
3459
  } });
3283
3460
  return {
@@ -3285,6 +3462,15 @@ function createRelationFilterAccessor(context, parentNamespaceId, parentModelNam
3285
3462
  count: (predicate) => createOrderable(() => buildRelationCountExpr(context, relation, correlate(), predicate))
3286
3463
  };
3287
3464
  }
3465
+ /**
3466
+ * Whether the JavaScript runtime or a common library reads `prop` from an object it is handed: `then` when a value is awaited or resolved as a promise, `toJSON` when it is stringified, and the `Object.prototype` members such as `toString`. An accessor answers these like a plain object, so a name that is not a field is refused only when the caller asks for it.
3467
+ */
3468
+ function isProbedByRuntime(prop) {
3469
+ return prop === "then" || prop === "toJSON" || prop in Object.prototype;
3470
+ }
3471
+ function probedValue(target, prop) {
3472
+ return prop === "then" || prop === "toJSON" ? void 0 : Reflect.get(target, prop);
3473
+ }
3288
3474
  function createOrderable(buildExpr) {
3289
3475
  return {
3290
3476
  asc: (options) => checkedOrderByItem("asc", buildExpr(), options),
@@ -3292,10 +3478,7 @@ function createOrderable(buildExpr) {
3292
3478
  };
3293
3479
  }
3294
3480
  function relatedOrderableField(context, relation, relatedTableName, correlate, fieldName) {
3295
- const fieldToColumn = getFieldToColumnMap(context.contract, relation.toNamespace, relation.to);
3296
- if (!Object.hasOwn(fieldToColumn, fieldName)) return void 0;
3297
- const columnName = fieldToColumn[fieldName];
3298
- if (columnName === void 0) return void 0;
3481
+ const columnName = columnOfCallerField(context.contract, relation.toNamespace, getModelFieldColumns(context.contract, relation.toNamespace, relation.to), relation.to, fieldName);
3299
3482
  const column = resolveColumn(context.contract, relation.toNamespace, relatedTableName, columnName);
3300
3483
  if (!column || !hasTrait(context, column.codecId, "order")) return void 0;
3301
3484
  return createOrderable(() => {
@@ -3312,7 +3495,7 @@ function correlateRelatedRows(context, parentNamespaceId, parentModelName, paren
3312
3495
  const { through } = relation;
3313
3496
  const { childScope, junctionBinding } = parentScope.forManyToManyRelation(relation.toNamespace, relatedTableName, through.namespaceId, through.table);
3314
3497
  const junctionJoinOn = buildPairedColumnExprs(junctionBinding, through.childColumns, childScope.current, through.targetColumns);
3315
- const parentLocalColumns = relation.on.localFields.map((field) => resolveFieldToColumn(context.contract, parentNamespaceId, parentModelName, field));
3498
+ const parentLocalColumns = relation.on.localFields.map((field) => columnOfContractField(context.contract, parentNamespaceId, parentModelName, field));
3316
3499
  return {
3317
3500
  childScope,
3318
3501
  source: SelectAst.from(childScope.current.tableSource(context.contract)).withJoins([JoinAst.inner(junctionBinding.tableSource(context.contract), junctionJoinOn)]),
@@ -3325,7 +3508,7 @@ function correlateRelatedRows(context, parentNamespaceId, parentModelName, paren
3325
3508
  childScope,
3326
3509
  source: SelectAst.from(childScope.current.tableSource(context.contract)),
3327
3510
  correlation: buildJoinWhere(context.contract, parentNamespaceId, parentModelName, parentScope.current, childScope.current, relation),
3328
- keyColumn: firstTargetColumn(context.contract, relation) ?? "id"
3511
+ keyColumn: firstJoinColumn(resolveRelationTargetColumns(context.contract, relation), "targetFields")
3329
3512
  };
3330
3513
  }
3331
3514
  function buildExistsExpr(context, relation, rows, mode, predicate) {
@@ -3377,14 +3560,12 @@ function toRelationWhereExpr(context, relatedNamespaceId, relatedModelName, pred
3377
3560
  if (!predicate) return;
3378
3561
  const accessor = createModelAccessorInScope(context, relatedNamespaceId, relatedModelName, void 0, scope);
3379
3562
  if (typeof predicate === "function") return predicate(accessor);
3563
+ assertModelFieldNames(context.contract, relatedNamespaceId, relatedModelName, predicate);
3380
3564
  const exprs = [];
3381
3565
  for (const [fieldName, value] of Object.entries(predicate)) {
3382
3566
  if (value === void 0) continue;
3383
3567
  const fieldAccessor = blindCast(accessor)[fieldName];
3384
- if (!fieldAccessor) throw ormError("ORM.FIELD_UNKNOWN", `Shorthand filter on "${relatedModelName}.${fieldName}": field is not defined on the model`, { meta: {
3385
- model: relatedModelName,
3386
- field: fieldName
3387
- } });
3568
+ if (!fieldAccessor) throw new InternalError(`Shorthand filter on "${relatedModelName}.${fieldName}": the field's column is missing from its table`);
3388
3569
  if (value === null) {
3389
3570
  if (!fieldAccessor.isNull) throw new InternalError(`Shorthand filter on "${relatedModelName}.${fieldName}": isNull is unexpectedly missing — this is a bug in trait gating`);
3390
3571
  exprs.push(fieldAccessor.isNull());
@@ -3409,8 +3590,8 @@ function buildJoinWhere(contract, parentNamespaceId, parentModelName, parentTabl
3409
3590
  const localField = localFields[i];
3410
3591
  const targetField = targetFields[i];
3411
3592
  if (!localField || !targetField) continue;
3412
- const localColumn = resolveFieldToColumn(contract, parentNamespaceId, parentModelName, localField);
3413
- const targetColumn = resolveFieldToColumn(contract, relation.toNamespace, relation.to, targetField);
3593
+ const localColumn = columnOfContractField(contract, parentNamespaceId, parentModelName, localField);
3594
+ const targetColumn = columnOfContractField(contract, relation.toNamespace, relation.to, targetField);
3414
3595
  joinExprs.push(BinaryExpr.eq(relatedTable.column(targetColumn), parentTable.column(localColumn)));
3415
3596
  }
3416
3597
  if (joinExprs.length === 0) throw new InternalError("Relation metadata is missing join columns");
@@ -3418,11 +3599,6 @@ function buildJoinWhere(contract, parentNamespaceId, parentModelName, parentTabl
3418
3599
  if (joinExprs.length === 1 && firstExpr !== void 0) return firstExpr;
3419
3600
  return and(...joinExprs);
3420
3601
  }
3421
- function firstTargetColumn(contract, relation) {
3422
- const firstField = (relation.on?.targetFields)?.[0];
3423
- if (!firstField) return;
3424
- return resolveFieldToColumn(contract, relation.toNamespace, relation.to, firstField);
3425
- }
3426
3602
  var GroupedCollection = class GroupedCollection {
3427
3603
  ctx;
3428
3604
  contract;
@@ -3560,7 +3736,7 @@ var GroupedCollection = class GroupedCollection {
3560
3736
  * dynamic invocation.
3561
3737
  */
3562
3738
  function createHavingBuilder(contract, aggregates, namespaceId, modelName, tableName) {
3563
- const fieldToColumn = getFieldToColumnMap(contract, namespaceId, modelName);
3739
+ const fieldColumns = getModelFieldColumns(contract, namespaceId, modelName);
3564
3740
  const builder = {};
3565
3741
  for (const operation of aggregateOperationNames(aggregates)) builder[operation] = (field) => {
3566
3742
  if (!isAggregateFn(operation)) throw ormError("ORM.AGGREGATE_PROJECTION_ONLY", `Aggregate operation '${operation}' is projection-only: it has no plain SQL form for HAVING, ORDER BY, or comparison positions.`, {
@@ -3568,13 +3744,14 @@ function createHavingBuilder(contract, aggregates, namespaceId, modelName, table
3568
3744
  fix: `Project '${operation}' in a select and filter or order on the projected value, or use an operation from the SQL aggregate alphabet.`,
3569
3745
  meta: { operation }
3570
3746
  });
3571
- return createHavingComparisonMethods(new AggregateExpr(operation, field === void 0 ? void 0 : ColumnRef.of(tableName, fieldToColumn[field] ?? field)), () => resolveAggregate({
3747
+ const column = field === void 0 ? void 0 : columnOfCallerField(contract, namespaceId, fieldColumns, modelName, field);
3748
+ return createHavingComparisonMethods(new AggregateExpr(operation, column === void 0 ? void 0 : ColumnRef.of(tableName, column)), () => resolveAggregate({
3572
3749
  aggregates,
3573
3750
  contract,
3574
3751
  namespaceId,
3575
3752
  tableName,
3576
3753
  fn: operation,
3577
- column: field === void 0 ? void 0 : fieldToColumn[field] ?? field
3754
+ column
3578
3755
  }).codec.codecId);
3579
3756
  };
3580
3757
  return blindCast(builder);
@@ -3781,7 +3958,7 @@ async function updateFirstGraph(scope, context, namespaceId, modelName, filters,
3781
3958
  for (const def of appliedUpdateDefaults) mappedUpdateData[def.field] = def.value;
3782
3959
  const identityWhere = shorthandToWhereExpr(context, namespaceId, modelName, castAs(buildRowIdentityFilterFromRow(contract, namespaceId, modelName, existingRow)));
3783
3960
  if (!identityWhere) throw new InternalError(`Failed to build row identity filter for model "${modelName}"`);
3784
- const updatedRaw = (await queryPlanRows(scope, compileUpdateReturning(contract, namespaceId, tableName, mappedUpdateData, [identityWhere], void 0)).toArray())[0];
3961
+ const updatedRaw = (await queryPlanRows(scope, compileUpdateReturning(contract, namespaceId, modelName, tableName, mappedUpdateData, [identityWhere], void 0)).toArray())[0];
3785
3962
  if (updatedRaw) parentRow = mapStorageRowToModelFields(contract, namespaceId, modelName, updatedRaw);
3786
3963
  }
3787
3964
  for (const relationMutation of childOwned) await applyChildOwnedMutation(scope, context, namespaceId, modelName, parentRow, relationMutation.relation, relationMutation.mutation);
@@ -4104,7 +4281,7 @@ async function insertSingleRow(scope, context, namespaceId, modelName, data) {
4104
4281
  values: mappedData
4105
4282
  });
4106
4283
  for (const def of applied) mappedData[def.field] = def.value;
4107
- const firstRow = (await queryPlanRows(scope, compileInsertReturning(contract, namespaceId, tableName, [mappedData], void 0)).toArray())[0];
4284
+ const firstRow = (await queryPlanRows(scope, compileInsertReturning(contract, namespaceId, modelName, tableName, [mappedData], void 0)).toArray())[0];
4108
4285
  if (!firstRow) throw ormError("ORM.MUTATION_ROW_MISSING", `Nested create for model "${modelName}" did not return a row`, { meta: {
4109
4286
  operation: "create",
4110
4287
  model: modelName,
@@ -4120,7 +4297,7 @@ async function findRowByCriterion(scope, context, namespaceId, modelName, criter
4120
4297
  model: modelName,
4121
4298
  problem: "empty-criterion"
4122
4299
  } });
4123
- const firstRow = (await queryPlanRows(scope, compileSelect(contract, namespaceId, resolveModelTableName(contract, namespaceId, modelName), {
4300
+ const firstRow = (await queryPlanRows(scope, compileSelect(contract, namespaceId, modelName, resolveModelTableName(contract, namespaceId, modelName), {
4124
4301
  ...emptyState(),
4125
4302
  filters: [whereExpr],
4126
4303
  limit: 1
@@ -4129,7 +4306,7 @@ async function findRowByCriterion(scope, context, namespaceId, modelName, criter
4129
4306
  return mapStorageRowToModelFields(contract, namespaceId, modelName, firstRow);
4130
4307
  }
4131
4308
  async function findFirstByFilters(scope, contract, namespaceId, modelName, filters) {
4132
- const firstRow = (await queryPlanRows(scope, compileSelect(contract, namespaceId, resolveModelTableName(contract, namespaceId, modelName), {
4309
+ const firstRow = (await queryPlanRows(scope, compileSelect(contract, namespaceId, modelName, resolveModelTableName(contract, namespaceId, modelName), {
4133
4310
  ...emptyState(),
4134
4311
  filters,
4135
4312
  limit: 1
@@ -4158,8 +4335,8 @@ function getRelationDefinitions(contract, namespaceId, modelName) {
4158
4335
  relatedNamespaceId: relation.toNamespace,
4159
4336
  relatedTableName: resolveModelTableName(contract, relation.toNamespace, relation.to),
4160
4337
  cardinality: relation.cardinality,
4161
- localColumns: relation.on.localFields.map((f) => resolveFieldToColumn(contract, namespaceId, modelName, f)),
4162
- targetColumns: relation.on.targetFields.map((f) => resolveFieldToColumn(contract, relation.toNamespace, relation.to, f)),
4338
+ localColumns: relation.on.localFields.map((f) => columnOfContractField(contract, namespaceId, modelName, f)),
4339
+ targetColumns: resolveRelationTargetColumns(contract, relation),
4163
4340
  through: relation.through ? {
4164
4341
  table: relation.through.table,
4165
4342
  namespaceId: relation.through.namespaceId,
@@ -4173,7 +4350,7 @@ function getRelationDefinitions(contract, namespaceId, modelName) {
4173
4350
  return definitions;
4174
4351
  }
4175
4352
  function toFieldName(contract, namespaceId, modelName, columnName) {
4176
- return getColumnToFieldMap(contract, namespaceId, modelName)[columnName] ?? columnName;
4353
+ return fieldOfColumn(getModelColumnFields(contract, namespaceId, modelName), modelName, columnName);
4177
4354
  }
4178
4355
  function normalizeWhereArg(arg, options) {
4179
4356
  if (arg === void 0) return;
@@ -4385,7 +4562,7 @@ var CollectionBase = class CollectionBase {
4385
4562
  */
4386
4563
  #includeScalarReducer(operation, field) {
4387
4564
  this.#assertIncludeRefinementMode(`${operation}()`);
4388
- const column = field === void 0 ? void 0 : resolveFieldToColumn(this.contract, this.namespaceId, this.modelName, field);
4565
+ const column = field === void 0 ? void 0 : columnOfCallerField(this.contract, this.namespaceId, getModelFieldColumns(this.contract, this.namespaceId, this.modelName), this.modelName, field);
4389
4566
  return createIncludeScalar(operation, this.state, column);
4390
4567
  }
4391
4568
  where(input) {
@@ -4494,7 +4671,7 @@ var CollectionBase = class CollectionBase {
4494
4671
  return this.#cloneWithRow({ includes: [...this.state.includes, includeExpr] });
4495
4672
  }
4496
4673
  select(...fields) {
4497
- const selectedFields = mapFieldsToColumns(this.contract, this.namespaceId, this.modelName, fields);
4674
+ const selectedFields = mapSelectedFieldsToColumns(this.contract, this.namespaceId, this.modelName, this.state.variantName, fields);
4498
4675
  return this.#cloneWithRow({ selectedFields });
4499
4676
  }
4500
4677
  orderBy(selection) {
@@ -4782,7 +4959,7 @@ var CollectionBase = class CollectionBase {
4782
4959
  applyCreateDefaults(this.ctx, this.namespaceId, this.tableName, mappedRows);
4783
4960
  const { selectedForQuery: selectedForInsert, hiddenColumns } = this.#augmentMutationSelection();
4784
4961
  if (this.contract.capabilities?.["sql"]?.["defaultInInsert"] !== true) {
4785
- const plans = compileInsertReturningSplit(this.contract, this.namespaceId, this.tableName, mappedRows, selectedForInsert, conflictSkip).map((plan) => mergeAnnotations(plan, annotationsMap));
4962
+ const plans = compileInsertReturningSplit(this.contract, this.namespaceId, this.modelName, this.tableName, mappedRows, selectedForInsert, conflictSkip).map((plan) => mergeAnnotations(plan, annotationsMap));
4786
4963
  return dispatchSplitMutationRows({
4787
4964
  context: this.ctx.context,
4788
4965
  runtime: this.ctx.runtime,
@@ -4797,7 +4974,7 @@ var CollectionBase = class CollectionBase {
4797
4974
  mapRow: (mapped) => blindCast(mapped)
4798
4975
  });
4799
4976
  }
4800
- const compiled = mergeAnnotations(compileInsertReturning(this.contract, this.namespaceId, this.tableName, mappedRows, selectedForInsert, conflictSkip), annotationsMap);
4977
+ const compiled = mergeAnnotations(compileInsertReturning(this.contract, this.namespaceId, this.modelName, this.tableName, mappedRows, selectedForInsert, conflictSkip), annotationsMap);
4801
4978
  return dispatchMutationRows({
4802
4979
  context: this.ctx.context,
4803
4980
  runtime: this.ctx.runtime,
@@ -4822,7 +4999,7 @@ var CollectionBase = class CollectionBase {
4822
4999
  else this.#assertNotMtiVariant(method);
4823
5000
  const conflictOn = options.conflictOn ?? [];
4824
5001
  assertInsertConflictSkipCapability(this.contract, method, conflictOn.length > 0);
4825
- return { columns: resolveInsertConflictColumns(this.contract, this.namespaceId, this.modelName, conflictOn, method) };
5002
+ return { columns: resolveInsertConflictColumns(this.contract, this.namespaceId, this.modelName, conflictOn) };
4826
5003
  }
4827
5004
  #assertNotMtiVariant(method) {
4828
5005
  this.#refuseOnMtiVariant(method, `${method} is not supported for MTI variant "${this.state.variantName}" on model "${this.modelName}". Use createAll() instead.`);
@@ -4846,16 +5023,20 @@ var CollectionBase = class CollectionBase {
4846
5023
  if (!polyInfo) return null;
4847
5024
  const variant = polyInfo.variants.get(variantName);
4848
5025
  if (!isMtiVariantInfo(variant)) return null;
5026
+ const baseFieldToColumn = getModelFieldColumns(this.contract, this.namespaceId, this.modelName);
5027
+ const variantFieldToColumn = getOwnFieldColumns(this.contract, this.namespaceId, variant.modelName);
5028
+ const pkColumns = resolvePrimaryKeyColumns(this.contract, this.namespaceId, this.tableName);
4849
5029
  return {
4850
5030
  polyInfo,
4851
5031
  variant,
4852
- baseFieldToColumn: getFieldToColumnMap(this.contract, this.namespaceId, this.modelName),
4853
- variantFieldToColumn: getFieldToColumnMap(this.contract, this.namespaceId, variant.modelName),
4854
- pkColumns: resolvePrimaryKeyColumns(this.contract, this.namespaceId, this.tableName)
5032
+ baseFieldToColumn,
5033
+ variantFieldToColumn,
5034
+ mergedFieldToColumn: getModelAndVariantFieldColumns(this.contract, this.namespaceId, this.modelName, variant.modelName),
5035
+ pkColumns
4855
5036
  };
4856
5037
  }
4857
5038
  #executeMtiCreate(data, mtiCtx) {
4858
- const { polyInfo, variant, baseFieldToColumn, variantFieldToColumn, pkColumns } = mtiCtx;
5039
+ const { polyInfo, variant, baseFieldToColumn, variantFieldToColumn, mergedFieldToColumn, pkColumns } = mtiCtx;
4859
5040
  const contract = this.contract;
4860
5041
  const collectionCtx = this.ctx;
4861
5042
  const runtime = collectionCtx.runtime;
@@ -4864,18 +5045,13 @@ var CollectionBase = class CollectionBase {
4864
5045
  const namespaceId = this.namespaceId;
4865
5046
  const baseFieldColumns = new Set(Object.values(baseFieldToColumn));
4866
5047
  const variantFieldColumns = new Set(Object.values(variantFieldToColumn));
4867
- const mergedFieldToColumn = {
4868
- ...baseFieldToColumn,
4869
- ...variantFieldToColumn
4870
- };
4871
5048
  const generator = async function* () {
4872
5049
  const defaultValueCache = /* @__PURE__ */ new Map();
4873
5050
  for (const row of data) {
4874
5051
  const allMapped = {};
4875
5052
  for (const [fieldName, value] of Object.entries(row)) {
4876
5053
  if (value === void 0) continue;
4877
- const columnName = mergedFieldToColumn[fieldName] ?? fieldName;
4878
- allMapped[columnName] = value;
5054
+ allMapped[columnOfCallerField(contract, namespaceId, mergedFieldToColumn, variant.modelName, fieldName)] = value;
4879
5055
  }
4880
5056
  allMapped[polyInfo.discriminatorColumn] = variant.value;
4881
5057
  const baseRow = {};
@@ -4886,7 +5062,7 @@ var CollectionBase = class CollectionBase {
4886
5062
  }
4887
5063
  yield blindCast(await withMutationScope(runtime, async (scope) => {
4888
5064
  applyCreateDefaults(collectionCtx, namespaceId, tableName, [baseRow], defaultValueCache);
4889
- const baseCreated = (await queryPlanRows(scope, compileInsertReturning(contract, namespaceId, tableName, [baseRow], void 0)).toArray())[0];
5065
+ const baseCreated = (await queryPlanRows(scope, compileInsertReturning(contract, namespaceId, modelName, tableName, [baseRow], void 0)).toArray())[0];
4890
5066
  if (!baseCreated) throw ormError("ORM.MUTATION_ROW_MISSING", `MTI base INSERT for model "${modelName}" did not return a row`, { meta: {
4891
5067
  operation: "create",
4892
5068
  model: modelName,
@@ -4895,7 +5071,7 @@ var CollectionBase = class CollectionBase {
4895
5071
  } });
4896
5072
  for (const pkColumn of pkColumns) variantRow[pkColumn] = baseCreated[pkColumn];
4897
5073
  applyCreateDefaults(collectionCtx, namespaceId, variant.table, [variantRow], defaultValueCache);
4898
- const variantCreated = (await queryPlanRows(scope, compileInsertReturning(contract, namespaceId, variant.table, [variantRow], void 0)).toArray())[0];
5074
+ const variantCreated = (await queryPlanRows(scope, compileInsertReturning(contract, namespaceId, variant.modelName, variant.table, [variantRow], void 0)).toArray())[0];
4899
5075
  if (!variantCreated) throw ormError("ORM.MUTATION_ROW_MISSING", `MTI variant INSERT for model "${modelName}" into "${variant.table}" did not return a row`, { meta: {
4900
5076
  operation: "create",
4901
5077
  model: modelName,
@@ -4923,18 +5099,12 @@ var CollectionBase = class CollectionBase {
4923
5099
  if (!polyInfo) return data.map((row) => mapModelDataToStorageRow(this.contract, this.namespaceId, this.modelName, row));
4924
5100
  const variant = polyInfo.variants.get(variantName);
4925
5101
  if (!variant) return data.map((row) => mapModelDataToStorageRow(this.contract, this.namespaceId, this.modelName, row));
4926
- const baseFieldToColumn = getFieldToColumnMap(this.contract, this.namespaceId, this.modelName);
4927
- const variantFieldToColumn = getFieldToColumnMap(this.contract, this.namespaceId, variant.modelName);
4928
- const mergedFieldToColumn = {
4929
- ...baseFieldToColumn,
4930
- ...variantFieldToColumn
4931
- };
5102
+ const mergedFieldToColumn = getModelAndVariantFieldColumns(this.contract, this.namespaceId, this.modelName, variant.modelName);
4932
5103
  return data.map((row) => {
4933
5104
  const mapped = {};
4934
5105
  for (const [fieldName, value] of Object.entries(row)) {
4935
5106
  if (value === void 0) continue;
4936
- const columnName = mergedFieldToColumn[fieldName] ?? fieldName;
4937
- mapped[columnName] = value;
5107
+ mapped[columnOfCallerField(this.contract, this.namespaceId, mergedFieldToColumn, variant.modelName, fieldName)] = value;
4938
5108
  }
4939
5109
  mapped[polyInfo.discriminatorColumn] = variant.value;
4940
5110
  return mapped;
@@ -5003,7 +5173,7 @@ var CollectionBase = class CollectionBase {
5003
5173
  model: this.modelName
5004
5174
  } });
5005
5175
  const { selectedForQuery: selectedForUpsert, hiddenColumns } = this.#augmentMutationSelection();
5006
- const compiled = mergeAnnotations(compileUpsertReturning(this.contract, this.namespaceId, this.tableName, createValues, updateValues, conflictColumns, selectedForUpsert), annotationsMap);
5176
+ const compiled = mergeAnnotations(compileUpsertReturning(this.contract, this.namespaceId, this.modelName, this.tableName, createValues, updateValues, conflictColumns, selectedForUpsert), annotationsMap);
5007
5177
  const row = await executeMutationReturningSingleRow({
5008
5178
  context: this.ctx.context,
5009
5179
  runtime: this.ctx.runtime,
@@ -5048,6 +5218,7 @@ var CollectionBase = class CollectionBase {
5048
5218
  const identityCriterion = buildRowIdentityFilterFromRow(this.contract, this.namespaceId, this.modelName, updatedRow);
5049
5219
  return this.#reloadMutationRowByIdentity(identityCriterion);
5050
5220
  }
5221
+ assertModelFieldNames(this.contract, this.namespaceId, this.modelName, blindCast(data));
5051
5222
  return withMutationScope(this.ctx.runtime, async (scope) => {
5052
5223
  const scoped = this.#withRuntime(scope);
5053
5224
  const identityWhere = await scoped.#findFirstMatchingRowIdentityWhere();
@@ -5069,7 +5240,7 @@ var CollectionBase = class CollectionBase {
5069
5240
  }
5070
5241
  applyUpdateDefaults(this.ctx, this.namespaceId, this.tableName, mappedData);
5071
5242
  const { selectedForQuery: selectedForUpdate, hiddenColumns } = this.#augmentMutationSelection();
5072
- const compiled = mergeAnnotations(compileUpdateReturning(this.contract, this.namespaceId, this.tableName, mappedData, this.state.filters, selectedForUpdate), annotationsMap);
5243
+ const compiled = mergeAnnotations(compileUpdateReturning(this.contract, this.namespaceId, this.modelName, this.tableName, mappedData, this.state.filters, selectedForUpdate), annotationsMap);
5073
5244
  return dispatchMutationRows({
5074
5245
  context: this.ctx.context,
5075
5246
  runtime: this.ctx.runtime,
@@ -5121,7 +5292,7 @@ var CollectionBase = class CollectionBase {
5121
5292
  #executeDeleteReturning(annotationsMap) {
5122
5293
  if (this.state.includes.length > 0) return this.#executeDeleteReturningWithIncludes(annotationsMap);
5123
5294
  const { selectedForQuery: selectedForDelete, hiddenColumns } = this.#augmentMutationSelection();
5124
- const compiled = mergeAnnotations(compileDeleteReturning(this.contract, this.namespaceId, this.tableName, this.state.filters, selectedForDelete), annotationsMap);
5295
+ const compiled = mergeAnnotations(compileDeleteReturning(this.contract, this.namespaceId, this.modelName, this.tableName, this.state.filters, selectedForDelete), annotationsMap);
5125
5296
  return dispatchMutationRows({
5126
5297
  context: this.ctx.context,
5127
5298
  runtime: this.ctx.runtime,
@@ -5177,7 +5348,6 @@ var CollectionBase = class CollectionBase {
5177
5348
  return (await this.ctx.runtime.execute(compiled)).affectedRows;
5178
5349
  }
5179
5350
  #buildUpsertConflictCriterion(createValues, conflictColumns) {
5180
- const columnToField = getColumnToFieldMap(this.contract, this.namespaceId, this.modelName);
5181
5351
  const criterion = {};
5182
5352
  for (const columnName of conflictColumns) {
5183
5353
  if (!(columnName in createValues)) throw ormError("ORM.ARGUMENT_INVALID", `upsert() for model "${this.modelName}" requires create value for conflict column "${columnName}"`, { meta: {
@@ -5185,7 +5355,7 @@ var CollectionBase = class CollectionBase {
5185
5355
  model: this.modelName,
5186
5356
  column: columnName
5187
5357
  } });
5188
- const fieldName = columnToField[columnName] ?? columnName;
5358
+ const fieldName = fieldOfColumn(getModelColumnFields(this.contract, this.namespaceId, this.modelName), this.modelName, columnName);
5189
5359
  criterion[fieldName] = createValues[columnName];
5190
5360
  }
5191
5361
  return criterion;
@@ -5230,10 +5400,9 @@ var CollectionBase = class CollectionBase {
5230
5400
  includes: []
5231
5401
  }).first();
5232
5402
  if (!firstRow) return null;
5233
- const columnToField = getColumnToFieldMap(this.contract, this.namespaceId, this.modelName);
5234
5403
  const criterion = {};
5235
5404
  for (const column of identityColumns) {
5236
- const fieldName = columnToField[column] ?? column;
5405
+ const fieldName = fieldOfColumn(getModelColumnFields(this.contract, this.namespaceId, this.modelName), this.modelName, column);
5237
5406
  const value = blindCast(firstRow)[fieldName];
5238
5407
  if (value === void 0) throw new InternalError(`Missing identity field "${fieldName}" while resolving single-row scope for model "${this.modelName}"`);
5239
5408
  criterion[fieldName] = value;