@prisma/orm-family-sql 8.0.0-rc.18-dev.3 → 8.0.0-rc.18-dev.5

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 (49) hide show
  1. package/dist/builder.d.mts +1 -1
  2. package/dist/builder__runtime.d.mts +3 -3
  3. package/dist/builder__runtime.mjs +1 -1
  4. package/dist/builder__types.d.mts +3 -2
  5. package/dist/collection-methods-BnR4UjcW-tiz3frtf.d.mts +77 -0
  6. package/dist/collection-methods-BnR4UjcW-tiz3frtf.d.mts.map +1 -0
  7. package/dist/collection-methods-DoBrRR69.d.mts +1 -0
  8. package/dist/{db-BmrN9nRS-DEogPltL.d.mts → db-BmrN9nRS-CDq1n2be.d.mts} +3 -2
  9. package/dist/db-BmrN9nRS-CDq1n2be.d.mts.map +1 -0
  10. package/dist/{index-qr6LA3dl.d.mts → index-CmKqLvvO.d.mts} +4 -4
  11. package/dist/{index-qr6LA3dl.d.mts.map → index-CmKqLvvO.d.mts.map} +1 -1
  12. package/dist/{index-reference-CflkzYSd.d.mts → index-reference-DJX-CNsb-D2qUlYq2.d.mts} +12 -3
  13. package/dist/index-reference-DJX-CNsb-D2qUlYq2.d.mts.map +1 -0
  14. package/dist/{index-reference-D693Lu-E.mjs → index-reference-DR62gjQS.mjs} +16 -3
  15. package/dist/index-reference-DR62gjQS.mjs.map +1 -0
  16. package/dist/index-reference-ZZrszBDq.d.mts +1 -0
  17. package/dist/orm-client.d.mts +63 -17
  18. package/dist/orm-client.d.mts.map +1 -1
  19. package/dist/orm-client.mjs +349 -341
  20. package/dist/orm-client.mjs.map +1 -1
  21. package/dist/{prepared-statement-Bs9TKj5u-CInk8vXF.d.mts → prepared-statement-BwHkxfuI-CKkkrS6r.d.mts} +9 -6
  22. package/dist/prepared-statement-BwHkxfuI-CKkkrS6r.d.mts.map +1 -0
  23. package/dist/{query-lane-context-C2AXsoFa-COSQOvZz.d.mts → query-lane-context-C42-u9L1-Bxa4DkI_.d.mts} +7 -2
  24. package/dist/query-lane-context-C42-u9L1-Bxa4DkI_.d.mts.map +1 -0
  25. package/dist/query-lane-context-DW5q2RAY.d.mts +1 -0
  26. package/dist/relational-core.d.mts +3 -3
  27. package/dist/relational-core__aggregate-descriptor-registry.d.mts +1 -1
  28. package/dist/relational-core__codec-descriptor-registry.d.mts +1 -1
  29. package/dist/relational-core__collection-methods.d.mts +3 -0
  30. package/dist/relational-core__collection-methods.mjs +1 -0
  31. package/dist/relational-core__index-reference.d.mts +3 -2
  32. package/dist/relational-core__index-reference.mjs +2 -2
  33. package/dist/relational-core__query-lane-context.d.mts +2 -2
  34. package/dist/relational-core__types.d.mts +2 -2
  35. package/dist/runtime.d.mts +3 -3
  36. package/dist/runtime.mjs +2 -1
  37. package/dist/runtime.mjs.map +1 -1
  38. package/dist/runtime__internal__prepared-query.d.mts +1 -1
  39. package/dist/types-BkA6tyT-.d.mts +1 -0
  40. package/dist/{types-D09NAayg-CNrpjo7Z.d.mts → types-Cl4MLNrS-lbf-K25i.d.mts} +3 -3
  41. package/dist/{types-D09NAayg-CNrpjo7Z.d.mts.map → types-Cl4MLNrS-lbf-K25i.d.mts.map} +1 -1
  42. package/package.json +19 -18
  43. package/dist/db-BmrN9nRS-DEogPltL.d.mts.map +0 -1
  44. package/dist/index-reference-CflkzYSd.d.mts.map +0 -1
  45. package/dist/index-reference-D693Lu-E.mjs.map +0 -1
  46. package/dist/prepared-statement-Bs9TKj5u-CInk8vXF.d.mts.map +0 -1
  47. package/dist/query-lane-context-BsZs5lvB.d.mts +0 -1
  48. package/dist/query-lane-context-C2AXsoFa-COSQOvZz.d.mts.map +0 -1
  49. package/dist/types-DAkmn9FV.d.mts +0 -1
@@ -6,7 +6,7 @@ import { C as lockStrengthCapabilities, S as lockOptionCapabilities, T as missin
6
6
  import { a as isExpression, s as toExpr, t as ExpressionImpl } from "./expression-impl-B-XNINxr-vYwKVFeP.mjs";
7
7
  import { n as codecRefForStorageColumn } from "./codec-descriptor-registry-CYK0Wzja.mjs";
8
8
  import { t as createFunctions } from "./functions-0YWByawj.mjs";
9
- import { t as createIndexReferences } from "./index-reference-D693Lu-E.mjs";
9
+ import { t as createIndexReferences } from "./index-reference-DR62gjQS.mjs";
10
10
  import { o as settlementOf } from "./transaction-state-BfXhs7D7-3k10jZ8I.mjs";
11
11
  import { structuredError } from "@prisma/orm-framework/utils/structured-error";
12
12
  import { ifDefined } from "@prisma/orm-framework/utils/defined";
@@ -1252,6 +1252,14 @@ function buildPrimaryKeyJoinOn(left, right, primaryKeyColumns) {
1252
1252
  if (primaryKeyColumns.length === 1 && firstColumn !== void 0) return EqColJoinOn.of(left.column(firstColumn), right.column(firstColumn));
1253
1253
  return AndExpr.of(primaryKeyColumns.map((column) => BinaryExpr.eq(left.column(column), right.column(column))));
1254
1254
  }
1255
+ function labeledVariantColumn(contract, variantTable, column) {
1256
+ const { namespaceId, tableName } = variantTable.storage;
1257
+ return ProjectionItem.of(variantColumnLabel(variantTable, column), variantTable.column(column), codecRefForStorageColumn(contract.storage, namespaceId, tableName, column));
1258
+ }
1259
+ function variantReturning(contract, variantTable, variantModelName, keyColumns) {
1260
+ const { namespaceId, tableName } = variantTable.storage;
1261
+ return getColumnsReadOnTable(contract, namespaceId, variantModelName, tableName).filter((column) => !keyColumns.includes(column)).map((column) => labeledVariantColumn(contract, variantTable, column));
1262
+ }
1255
1263
  function buildMtiJoins(contract, tables, polyInfo, variantValue, selectedColumnsByVariant) {
1256
1264
  const joins = [];
1257
1265
  const projection = [];
@@ -1272,7 +1280,7 @@ function buildMtiJoins(contract, tables, polyInfo, variantValue, selectedColumns
1272
1280
  for (const col of variantColumns) {
1273
1281
  if (pkColumns.includes(col)) continue;
1274
1282
  if (selectedColumnsByVariant !== void 0 && selectedVariantColumns?.has(col) !== true) continue;
1275
- projection.push(ProjectionItem.of(variantColumnLabel(variantTable, col), variantTable.column(col), codecRefForStorageColumn(contract.storage, namespaceId, tableName, col)));
1283
+ projection.push(labeledVariantColumn(contract, variantTable, col));
1276
1284
  }
1277
1285
  }
1278
1286
  return {
@@ -1610,9 +1618,12 @@ function aliasTarget(namespaceId, tableName) {
1610
1618
  tableName
1611
1619
  });
1612
1620
  }
1613
- function projectTableColumns(contract, target, columns) {
1621
+ function projectTableColumn(contract, target, column) {
1614
1622
  const { namespaceId, tableName } = target.storage;
1615
- return columns.map((column) => ProjectionItem.of(column, target.column(column), codecRefForStorageColumn(contract.storage, namespaceId, tableName, column)));
1623
+ return ProjectionItem.of(column, target.column(column), codecRefForStorageColumn(contract.storage, namespaceId, tableName, column));
1624
+ }
1625
+ function projectTableColumns(contract, target, columns) {
1626
+ return columns.map((column) => projectTableColumn(contract, target, column));
1616
1627
  }
1617
1628
  function returningProjection(contract, modelName, target, returningColumns) {
1618
1629
  const { namespaceId, tableName } = target.storage;
@@ -1672,17 +1683,19 @@ function conflictSkipClause(target, conflictSkip) {
1672
1683
  if (conflictSkip.columns.length === 0) return InsertOnConflict.doNothing();
1673
1684
  return InsertOnConflict.on(conflictSkip.columns.map((column) => target.column(column))).doNothing();
1674
1685
  }
1686
+ function insertAst(contract, target, rows, conflictSkip) {
1687
+ const { namespaceId, tableName } = target.storage;
1688
+ const { rows: normalizedRows } = normalizeInsertRows(contract, namespaceId, tableName, rows);
1689
+ return InsertAst.into(target.tableSource(contract)).withRows(normalizedRows).withOnConflict(conflictSkipClause(target, conflictSkip));
1690
+ }
1675
1691
  function compileInsertReturning(contract, namespaceId, modelName, tableName, rows, returningColumns, conflictSkip) {
1676
1692
  const target = aliasTarget(namespaceId, tableName);
1677
- const { rows: normalizedRows } = normalizeInsertRows(contract, namespaceId, tableName, rows);
1678
- const ast = InsertAst.into(target.tableSource(contract)).withRows(normalizedRows).withOnConflict(conflictSkipClause(target, conflictSkip)).withReturning(returningProjection(contract, modelName, target, returningColumns));
1693
+ const ast = insertAst(contract, target, rows, conflictSkip).withReturning(returningProjection(contract, modelName, target, returningColumns));
1679
1694
  const { params } = deriveParamsFromAst(ast);
1680
1695
  return buildOrmQueryPlan(contract, ast, params);
1681
1696
  }
1682
1697
  function compileInsertCount(contract, namespaceId, tableName, rows, conflictSkip) {
1683
- const target = aliasTarget(namespaceId, tableName);
1684
- const { rows: normalizedRows } = normalizeInsertRows(contract, namespaceId, tableName, rows);
1685
- const ast = InsertAst.into(target.tableSource(contract)).withRows(normalizedRows).withOnConflict(conflictSkipClause(target, conflictSkip));
1698
+ const ast = insertAst(contract, aliasTarget(namespaceId, tableName), rows, conflictSkip);
1686
1699
  const { params } = deriveParamsFromAst(ast);
1687
1700
  return buildOrmQueryPlan(contract, ast, params);
1688
1701
  }
@@ -1718,31 +1731,15 @@ function groupRowsByColumnSignature(rows) {
1718
1731
  if (currentGroup.length > 0) groups.push(currentGroup);
1719
1732
  return groups;
1720
1733
  }
1721
- function compileInsertReturningSplit(contract, namespaceId, modelName, tableName, rows, returningColumns, conflictSkip) {
1722
- if (rows.length === 0) throw ormError("ORM.MUTATION_DATA_MISSING", "create() requires at least one row", { meta: {
1723
- method: "create",
1724
- namespaceId,
1725
- tableName
1726
- } });
1727
- return groupRowsByColumnSignature(rows).map((group) => compileInsertReturning(contract, namespaceId, modelName, tableName, group, returningColumns, conflictSkip));
1728
- }
1729
- function compileInsertCountSplit(contract, namespaceId, tableName, rows, conflictSkip) {
1730
- if (rows.length === 0) throw ormError("ORM.MUTATION_DATA_MISSING", "createAndCount() requires at least one row", { meta: {
1731
- method: "createAndCount",
1732
- namespaceId,
1733
- tableName
1734
- } });
1735
- return groupRowsByColumnSignature(rows).map((group) => compileInsertCount(contract, namespaceId, tableName, group, conflictSkip));
1736
- }
1737
- function compileUpsertReturning(contract, namespaceId, modelName, tableName, createValues, updateValues, conflictColumns, returningColumns) {
1734
+ function upsertAst(contract, target, createValues, conflictColumns, updateSet) {
1735
+ const { namespaceId, tableName } = target.storage;
1738
1736
  const createAssignments = toParamAssignments(contract, namespaceId, tableName, createValues);
1739
- const updateAssignments = Object.keys(updateValues).length > 0 ? toParamAssignments(contract, namespaceId, tableName, updateValues) : void 0;
1740
- const target = aliasTarget(namespaceId, tableName);
1741
1737
  const conflictTarget = InsertOnConflict.on(conflictColumns.map((column) => target.column(column)));
1742
- const onConflict = updateAssignments ? conflictTarget.doUpdateSet(updateAssignments.assignments) : conflictTarget.doNothing();
1743
- const ast = InsertAst.into(target.tableSource(contract)).withRows([createAssignments.assignments]).withOnConflict(onConflict).withReturning(returningProjection(contract, modelName, target, returningColumns));
1744
- const { params } = deriveParamsFromAst(ast);
1745
- return buildOrmQueryPlan(contract, ast, params);
1738
+ return InsertAst.into(target.tableSource(contract)).withRows([createAssignments.assignments]).withOnConflict(updateSet === void 0 ? conflictTarget.doNothing() : conflictTarget.doUpdateSet(updateSet));
1739
+ }
1740
+ function updateAssignments(contract, target, values) {
1741
+ const { namespaceId, tableName } = target.storage;
1742
+ return toParamAssignments(contract, namespaceId, tableName, values).assignments;
1746
1743
  }
1747
1744
  function updateAst(contract, tables, setValues, where) {
1748
1745
  const { root } = tables;
@@ -2630,46 +2627,6 @@ function consumeIncludeRows(context, state, namespaceId, modelName, rows) {
2630
2627
  * include query can't observe an already-deleted row, so delete reads
2631
2628
  * its snapshot before issuing the DELETE (see `collection.ts`).
2632
2629
  */
2633
- function reloadMutationRowsByIdentities(options) {
2634
- const { context, runtime, tables, modelName, namespaceId, identityRows, selectedFields, includes } = options;
2635
- const { contract } = context;
2636
- const { tableName } = tables.root.storage;
2637
- if (identityRows.length === 0) return emptyResult();
2638
- const identityColumns = resolveRowIdentityColumns(contract, namespaceId, tableName);
2639
- if (identityColumns.length === 0) throw ormError("ORM.ROW_IDENTITY_MISSING", `Cannot load includes for the mutation result on model "${modelName}": table "${tableName}" has no primary key or unique constraint to key the include read-back on.`, { meta: {
2640
- model: modelName,
2641
- table: tableName
2642
- } });
2643
- const identityFilter = buildIdentityInFilter(contract, tables.root, identityColumns, identityRows);
2644
- if (!identityFilter) return emptyResult();
2645
- return dispatchCollectionRows({
2646
- context,
2647
- runtime,
2648
- state: {
2649
- ...emptyState(tables),
2650
- filters: [identityFilter],
2651
- selectedFields,
2652
- includes
2653
- },
2654
- modelName,
2655
- namespaceId
2656
- });
2657
- }
2658
- function emptyResult() {
2659
- return new AsyncIterableResult((async function* () {})());
2660
- }
2661
- function buildIdentityInFilter(contract, table, identityColumns, identityRows) {
2662
- const { storage } = table;
2663
- const [singleColumn, ...rest] = identityColumns;
2664
- if (singleColumn !== void 0 && rest.length === 0) {
2665
- const values = identityRows.map((row) => row[singleColumn]).filter((value) => value !== void 0);
2666
- if (values.length === 0) return;
2667
- return BinaryExpr.in(table.column(singleColumn), ListExpression.of(values.map((value) => paramRefForStorageColumn(contract, storage, singleColumn, value))));
2668
- }
2669
- if (identityRows.length === 0) return;
2670
- const tuples = identityRows.map((row) => AndExpr.of(identityColumns.map((column) => BinaryExpr.eq(table.column(column), paramRefForStorageColumn(contract, storage, column, row[column])))));
2671
- return OrExpr.of(tuples);
2672
- }
2673
2630
  /**
2674
2631
  * Decode a single-query include payload from a parent row's raw cell
2675
2632
  * into the model-shaped value that downstream consumers see. Recurses
@@ -2928,90 +2885,112 @@ function parseIncludePayload(value) {
2928
2885
  return [];
2929
2886
  }
2930
2887
  }
2931
- function createMutationRowMapper(contract, namespaceId, modelName, tables, variantValue) {
2932
- const polyInfo = resolvePolymorphismInfo(contract, namespaceId, modelName);
2933
- return polyInfo ? (row) => mapPolymorphicRow(contract, namespaceId, modelName, polyInfo, tables, row, variantValue) : (row) => mapStorageRowToModelFields(contract, namespaceId, modelName, row);
2888
+ const tablesByContext = /* @__PURE__ */ new WeakMap();
2889
+ const NO_METHODS = Object.freeze({});
2890
+ function modelKey(namespaceId, modelName) {
2891
+ return JSON.stringify([namespaceId, modelName]);
2934
2892
  }
2935
- function dispatchMutationRows(options) {
2936
- const { context, runtime, compiled, tables, modelName, namespaceId, variantValue, includes, selectedFields, hiddenColumns, mapRow } = options;
2937
- const { contract } = context;
2938
- const mapStorageRow = createMutationRowMapper(contract, namespaceId, modelName, tables, variantValue);
2939
- if (includes.length === 0) return mapResultRows(queryPlanRows(runtime, compiled), (rawRow) => {
2940
- const mapped = mapStorageRow(rawRow);
2941
- if (hiddenColumns.length > 0) stripHiddenMappedFields(contract, namespaceId, modelName, mapped, hiddenColumns);
2942
- return mapRow(mapped);
2943
- });
2944
- const generator = async function* () {
2945
- const identityRows = await queryPlanRows(runtime, compiled).toArray();
2946
- yield* reloadMutationRowsByIdentities({
2947
- context,
2948
- runtime,
2949
- tables,
2950
- modelName,
2951
- namespaceId,
2952
- identityRows,
2953
- selectedFields,
2954
- includes
2893
+ function assertUniqueIds(contributions) {
2894
+ const seen = /* @__PURE__ */ new Set();
2895
+ for (const { id } of contributions) {
2896
+ if (seen.has(id)) throw ormError("ORM.ARGUMENT_INVALID", `Two collection method contributions have the id "${id}".`, {
2897
+ why: "A contribution is registered under its id in CollectionMethodRegistry, so an id names one contribution.",
2898
+ fix: "List each extension once, or give one of the two contributions another id.",
2899
+ meta: { id }
2955
2900
  });
2956
- };
2957
- return new AsyncIterableResult(generator());
2901
+ seen.add(id);
2902
+ }
2958
2903
  }
2959
- function dispatchSplitMutationRows(options) {
2960
- const { context, runtime, plans, tables, modelName, namespaceId, variantValue, includes, selectedFields, hiddenColumns, mapRow } = options;
2904
+ function modelViews(context) {
2961
2905
  const { contract } = context;
2962
- const mapStorageRow = createMutationRowMapper(contract, namespaceId, modelName, tables, variantValue);
2963
- const generator = async function* () {
2964
- if (includes.length > 0) {
2965
- const identityRows = [];
2966
- for (const plan of plans) identityRows.push(...await queryPlanRows(runtime, plan).toArray());
2967
- yield* reloadMutationRowsByIdentities({
2968
- context,
2969
- runtime,
2970
- tables,
2971
- modelName,
2972
- namespaceId,
2973
- identityRows,
2974
- selectedFields,
2975
- includes
2976
- });
2977
- return;
2906
+ const views = [];
2907
+ for (const [namespaceId, namespace] of Object.entries(contract.domain.namespaces)) for (const [name, model] of Object.entries(namespace.models)) {
2908
+ const tableName = model.storage["table"];
2909
+ const resolved = typeof tableName === "string" ? resolveTableForContract(contract, namespaceId, tableName) : void 0;
2910
+ if (resolved === void 0) throw new InternalError(`Model "${name}" in namespace "${namespaceId}" has no storage table the contract declares.`);
2911
+ views.push([modelKey(namespaceId, name), {
2912
+ target: contract.target,
2913
+ name,
2914
+ fields: model.fields,
2915
+ relations: model.relations,
2916
+ table: resolved.table
2917
+ }]);
2918
+ }
2919
+ return views;
2920
+ }
2921
+ function methodsOf(contribution, view) {
2922
+ let methods;
2923
+ try {
2924
+ methods = contribution.methodsFor(view);
2925
+ } catch (cause) {
2926
+ throw ormError("ORM.ARGUMENT_INVALID", `Collection method contribution "${contribution.id}" failed for model "${view.name}".`, {
2927
+ why: "The ORM client asks every contribution for every model's methods when it is created.",
2928
+ fix: `Fix or remove the extension that contributes "${contribution.id}"; the cause is the contribution's own error.`,
2929
+ meta: {
2930
+ model: view.name,
2931
+ contribution: contribution.id
2932
+ },
2933
+ cause
2934
+ });
2935
+ }
2936
+ if (typeof methods !== "object" || methods === null) throw ormError("ORM.ARGUMENT_INVALID", `Collection method contribution "${contribution.id}" returned no object of methods for model "${view.name}".`, {
2937
+ why: "A contribution returns an object holding a model's methods by name, empty when it gives the model none.",
2938
+ fix: `Fix or remove the extension that contributes "${contribution.id}".`,
2939
+ meta: {
2940
+ model: view.name,
2941
+ contribution: contribution.id
2978
2942
  }
2979
- for (const plan of plans) for await (const rawRow of queryPlanRows(runtime, plan)) {
2980
- const mapped = mapStorageRow(rawRow);
2981
- if (hiddenColumns.length > 0) stripHiddenMappedFields(contract, namespaceId, modelName, mapped, hiddenColumns);
2982
- yield mapRow(mapped);
2943
+ });
2944
+ for (const [name, body] of Object.entries(methods)) if (typeof body !== "function") throw ormError("ORM.ARGUMENT_INVALID", `Collection method "${name}" that contribution "${contribution.id}" gives model "${view.name}" is not a function.`, {
2945
+ why: "A contribution returns each of a model's methods as a function of the collection and the caller's arguments.",
2946
+ fix: `Fix or remove the extension that contributes "${contribution.id}".`,
2947
+ meta: {
2948
+ model: view.name,
2949
+ method: name,
2950
+ contribution: contribution.id
2983
2951
  }
2984
- };
2985
- return new AsyncIterableResult(generator());
2952
+ });
2953
+ return blindCast(methods);
2954
+ }
2955
+ function mergedTable(view, contributions) {
2956
+ const methods = Object.create(null);
2957
+ const owners = /* @__PURE__ */ new Map();
2958
+ for (const contribution of contributions) for (const [name, body] of Object.entries(methodsOf(contribution, view))) {
2959
+ const owner = owners.get(name);
2960
+ if (owner !== void 0) throw ormError("ORM.ARGUMENT_INVALID", `Collection method "${name}" of model "${view.name}" is contributed by both "${owner}" and "${contribution.id}".`, {
2961
+ why: "A collection offers one method under each name in `using`.",
2962
+ fix: "Remove one of the extensions that contribute these methods.",
2963
+ meta: {
2964
+ model: view.name,
2965
+ method: name,
2966
+ contributions: [owner, contribution.id]
2967
+ }
2968
+ });
2969
+ owners.set(name, contribution.id);
2970
+ methods[name] = body;
2971
+ }
2972
+ return Object.freeze(methods);
2986
2973
  }
2987
- async function executeMutationReturningSingleRow(options) {
2988
- const { context, runtime, compiled, tables, modelName, namespaceId, variantValue, includes, selectedFields, hiddenColumns, mapRow, operation, onMissingRowMessage } = options;
2989
- const { contract } = context;
2990
- const mapStorageRow = createMutationRowMapper(contract, namespaceId, modelName, tables, variantValue);
2991
- if (includes.length === 0) {
2992
- const first = (await queryPlanRows(runtime, compiled).toArray())[0];
2993
- if (!first) return null;
2994
- const mapped = mapStorageRow(first);
2995
- if (hiddenColumns.length > 0) stripHiddenMappedFields(contract, namespaceId, modelName, mapped, hiddenColumns);
2996
- return mapRow(mapped);
2997
- }
2998
- const identityRows = await queryPlanRows(runtime, compiled).toArray();
2999
- if (identityRows.length === 0) return null;
3000
- for await (const row of reloadMutationRowsByIdentities({
3001
- context,
3002
- runtime,
3003
- tables,
3004
- modelName,
3005
- namespaceId,
3006
- identityRows,
3007
- selectedFields,
3008
- includes
3009
- })) return row;
3010
- throw ormError("ORM.MUTATION_ROW_MISSING", onMissingRowMessage, { meta: {
3011
- operation,
3012
- model: modelName,
3013
- tableName: tables.root.storage.tableName
3014
- } });
2974
+ /**
2975
+ * Asks each contribution for each model's methods, once per execution context. Throws `ORM.ARGUMENT_INVALID` when two contributions share an id, give one model two methods with the same name, fail, or return a method that is not a function.
2976
+ */
2977
+ function collectionMethodTables(context) {
2978
+ const cached = tablesByContext.get(context);
2979
+ if (cached !== void 0) return cached;
2980
+ const contributions = context.collectionMethods ?? [];
2981
+ assertUniqueIds(contributions);
2982
+ const tables = /* @__PURE__ */ new Map();
2983
+ for (const [key, view] of modelViews(context)) tables.set(key, mergedTable(view, contributions));
2984
+ tablesByContext.set(context, tables);
2985
+ return tables;
2986
+ }
2987
+ /** The contributed methods of a model, by name. */
2988
+ function collectionMethodTable(context, namespaceId, modelName) {
2989
+ return collectionMethodTables(context).get(modelKey(namespaceId, modelName)) ?? NO_METHODS;
2990
+ }
2991
+ /** The run-time value of `collection.using`. */
2992
+ function createCollectionMethods(receiver, table) {
2993
+ return Object.freeze(Object.fromEntries(Object.entries(table).map(([name, body]) => [name, (...args) => body(receiver, ...args)])));
3015
2994
  }
3016
2995
  /** The filter expression of a condition: a condition from `fns` becomes its AST. */
3017
2996
  function conditionExpr(condition) {
@@ -3280,6 +3259,7 @@ function defineDeclaredFieldsFragment(declarations, body) {
3280
3259
  });
3281
3260
  }
3282
3261
  const NO_INDEXES = Object.freeze({});
3262
+ const NO_COLLECTION_METHODS = Object.freeze({});
3283
3263
  const collectionsBehindViews = /* @__PURE__ */ new WeakMap();
3284
3264
  const BODY_CHAIN_METHODS = {
3285
3265
  where: true,
@@ -3288,10 +3268,11 @@ const BODY_CHAIN_METHODS = {
3288
3268
  offset: true
3289
3269
  };
3290
3270
  /**
3291
- * The collection as the body of a fragment for any model sees it: a `where` or `orderBy` callback receives `fns` and an `indexes` with no members, as the body does not know its model.
3271
+ * The collection as the body of a fragment for any model sees it: a `where` or `orderBy` callback receives `fns` and an `indexes` with no members, and `using` has no members, as the body does not know its model.
3292
3272
  */
3293
3273
  function withoutIndexes(collection) {
3294
3274
  const view = new Proxy(collection, { get(target, prop) {
3275
+ if (prop === "using") return NO_COLLECTION_METHODS;
3295
3276
  const member = Reflect.get(target, prop, target);
3296
3277
  if (typeof member !== "function") return member;
3297
3278
  if (!Object.hasOwn(BODY_CHAIN_METHODS, prop)) return member.bind(target);
@@ -4593,15 +4574,37 @@ function getRelationDefinitions(contract, namespaceId, modelName) {
4593
4574
  function toFieldName(contract, namespaceId, modelName, columnName) {
4594
4575
  return fieldOfColumn(getModelColumnFields(contract, namespaceId, modelName), modelName, columnName);
4595
4576
  }
4577
+ var Node = class {};
4578
+ function executeStatement$1(ast, run) {
4579
+ return ast.kind === "select" || ast.returning !== void 0 ? run.query(ast) : run.execute(ast);
4580
+ }
4581
+ function rowsResult(rows) {
4582
+ const generator = async function* () {
4583
+ yield* rows;
4584
+ };
4585
+ return new AsyncIterableResult(generator());
4586
+ }
4587
+ var CrossJoin = class extends Node {
4588
+ constructor() {
4589
+ super();
4590
+ Object.freeze(this);
4591
+ }
4592
+ execute(inputs, _run) {
4593
+ const [left] = inputs.left;
4594
+ const [right] = inputs.right;
4595
+ if (left === void 0 || right === void 0) return rowsResult([]);
4596
+ return rowsResult([{
4597
+ ...left,
4598
+ ...right
4599
+ }]);
4600
+ }
4601
+ };
4596
4602
  function executeFiltered(ast, filter, run) {
4597
4603
  if (filter === null) return executeStatement$1(ast, run);
4598
- if (filter.some((conditions) => conditions.length === 0)) return noRows();
4604
+ if (filter.some((conditions) => conditions.length === 0)) return rowsResult([]);
4599
4605
  const where = combineWhereExprs([...ast.where === void 0 ? [] : [ast.where], ...filter.map(anyOf)]);
4600
4606
  return executeStatement$1(ast.withWhere(where), run);
4601
4607
  }
4602
- function executeStatement$1(ast, run) {
4603
- return ast.kind === "select" || ast.returning !== void 0 ? run.query(ast) : run.execute(ast);
4604
- }
4605
4608
  function anyOf(conditions) {
4606
4609
  const [first, ...others] = conditions;
4607
4610
  return first !== void 0 && others.length === 0 ? first : OrExpr.of(conditions);
@@ -4610,12 +4613,8 @@ function withColumns(returned, columns) {
4610
4613
  const present = new Set(returned.map((item) => item.alias));
4611
4614
  return [...returned, ...columns.filter((column) => !present.has(column.alias))];
4612
4615
  }
4613
- function noRows() {
4614
- const generator = async function* () {};
4615
- return new AsyncIterableResult(generator());
4616
- }
4617
- var Node = class {};
4618
- var Delete = class Delete extends Node {
4616
+ var StatementNode = class extends Node {};
4617
+ var Delete = class Delete extends StatementNode {
4619
4618
  ast;
4620
4619
  constructor(ast) {
4621
4620
  super();
@@ -4654,7 +4653,7 @@ var FilterData = class extends Edge {
4654
4653
  return first !== void 0 && others.length === 0 ? first : AndExpr.of(conditions);
4655
4654
  }
4656
4655
  };
4657
- var Find = class Find extends Node {
4656
+ var Find = class Find extends StatementNode {
4658
4657
  ast;
4659
4658
  constructor(ast) {
4660
4659
  super();
@@ -4694,7 +4693,8 @@ var Graph = class {
4694
4693
  reader: id,
4695
4694
  edge
4696
4695
  });
4697
- this.#nodes[edge.from] = this.#nodes[edge.from]?.withReturning(edge.columns.map(([source]) => source));
4696
+ const source = this.#nodes[edge.from];
4697
+ if (source instanceof StatementNode) this.#nodes[edge.from] = source.withReturning(edge.columns.map(([column]) => column));
4698
4698
  }
4699
4699
  return id;
4700
4700
  }
@@ -4703,7 +4703,7 @@ var Graph = class {
4703
4703
  }
4704
4704
  remove(id) {
4705
4705
  for (const edge of Object.values(this.inputsOf(id)).flat()) this.#readers[edge.from] = this.readersOf(edge.from).filter((entry) => entry.edge !== edge);
4706
- for (const { reader, edge } of this.readersOf(id)) this.#inputs[reader] = Object.fromEntries(Object.entries(this.inputsOf(reader)).map(([slot, edges]) => [slot, edges.filter((other) => other !== edge)]));
4706
+ for (const { reader, edge } of this.readersOf(id)) this.#inputs[reader] = Object.fromEntries(Object.entries(this.inputsOf(reader)).map(([name, slot]) => [name, Array.isArray(slot) ? slot.filter((other) => other !== edge) : slot]));
4707
4707
  this.#nodes[id] = void 0;
4708
4708
  this.#inputs[id] = {};
4709
4709
  this.#readers[id] = [];
@@ -4721,7 +4721,88 @@ var Graph = class {
4721
4721
  return this.#readers[id] ?? [];
4722
4722
  }
4723
4723
  };
4724
- var Update = class Update extends Node {
4724
+ var Insert = class Insert extends StatementNode {
4725
+ ast;
4726
+ constructor(ast) {
4727
+ super();
4728
+ this.ast = ast;
4729
+ Object.freeze(this);
4730
+ }
4731
+ get returns() {
4732
+ return this.ast.returning ?? [];
4733
+ }
4734
+ execute(inputs, run) {
4735
+ if (inputs.payload === null) return executeStatement$1(this.ast, run);
4736
+ if (inputs.payload.some((records) => records.length === 0)) return rowsResult([]);
4737
+ const payload = Object.assign({}, ...inputs.payload.map(([record]) => record));
4738
+ const rows = this.ast.rows.map((row) => ({
4739
+ ...row,
4740
+ ...payload
4741
+ }));
4742
+ return executeStatement$1(this.ast.withRows(rows), run);
4743
+ }
4744
+ withReturning(columns) {
4745
+ return new Insert(this.ast.withReturning(withColumns(this.returns, columns)));
4746
+ }
4747
+ };
4748
+ var InsertChunked = class InsertChunked extends StatementNode {
4749
+ asts;
4750
+ constructor(asts) {
4751
+ super();
4752
+ this.asts = Object.freeze([...asts]);
4753
+ Object.freeze(this);
4754
+ }
4755
+ get returns() {
4756
+ return this.asts[0]?.returning ?? [];
4757
+ }
4758
+ execute(_inputs, run) {
4759
+ if (this.returns.length === 0) return this.#sumOfCounts(run);
4760
+ const asts = this.asts;
4761
+ const generator = async function* () {
4762
+ for (const ast of asts) yield* run.query(ast);
4763
+ };
4764
+ return new AsyncIterableResult(generator());
4765
+ }
4766
+ withReturning(columns) {
4767
+ return new InsertChunked(this.asts.map((ast) => ast.withReturning(withColumns(ast.returning ?? [], columns))));
4768
+ }
4769
+ async #sumOfCounts(run) {
4770
+ let count = 0;
4771
+ for (const ast of this.asts) count += await run.execute(ast);
4772
+ return count;
4773
+ }
4774
+ };
4775
+ var PayloadData = class extends Edge {
4776
+ constructor(from, columns) {
4777
+ super(from, columns);
4778
+ Object.freeze(this);
4779
+ }
4780
+ output(sourceRow) {
4781
+ return Object.fromEntries(this.columns.map(([source, target]) => [target.alias, ParamRef.of(sourceRow[source.alias], {
4782
+ name: target.alias,
4783
+ ...ifDefined("codec", target.codec)
4784
+ })]));
4785
+ }
4786
+ };
4787
+ var Rows = class extends Edge {
4788
+ constructor(from, columns) {
4789
+ super(from, columns);
4790
+ Object.freeze(this);
4791
+ }
4792
+ output(sourceRow) {
4793
+ return Object.fromEntries(this.columns.map(([source]) => [source.alias, sourceRow[source.alias]]));
4794
+ }
4795
+ };
4796
+ var UnionAll = class extends Node {
4797
+ constructor() {
4798
+ super();
4799
+ Object.freeze(this);
4800
+ }
4801
+ execute(inputs, _run) {
4802
+ return rowsResult((inputs.rows ?? []).flat());
4803
+ }
4804
+ };
4805
+ var Update = class Update extends StatementNode {
4725
4806
  ast;
4726
4807
  constructor(ast) {
4727
4808
  super();
@@ -4794,6 +4875,61 @@ function deleteFirstGraph(collection) {
4794
4875
  graph.setResult(withIncludes ? find : deleted);
4795
4876
  return graph;
4796
4877
  }
4878
+ function createAllGraph(collection, rows, conflict) {
4879
+ const { context, state } = collection;
4880
+ const graph = new Graph();
4881
+ if (rows.length === 0) return graph;
4882
+ requireIdentityColumnsForIncludes(collection);
4883
+ const { contract } = context;
4884
+ const { root } = state.tables;
4885
+ const inserted = supportsDefaultInInsert(contract) ? graph.add(new Insert(insertAst(contract, root, rows, conflict)), { payload: [] }) : graph.add(new InsertChunked(groupRowsByColumnSignature(rows).map((group) => insertAst(contract, root, group, conflict))), {});
4886
+ graph.setResult(addWithIncludes(graph, collection, inserted));
4887
+ return graph;
4888
+ }
4889
+ function supportsDefaultInInsert(contract) {
4890
+ return contract.capabilities["sql"]?.["defaultInInsert"] === true;
4891
+ }
4892
+ function createAllVariantGraph(collection, variantTable, variantModelName, rows) {
4893
+ const { context, modelName, state } = collection;
4894
+ const { contract } = context;
4895
+ const { root } = state.tables;
4896
+ const graph = new Graph();
4897
+ const keyColumns = resolvePrimaryKeyColumns(contract, root.storage.namespaceId, root.storage.tableName);
4898
+ const keyPairs = keyColumns.map((column) => [projectTableColumn(contract, root, column), projectTableColumn(contract, variantTable, column)]);
4899
+ const baseColumns = returningProjection(contract, modelName, root, void 0);
4900
+ const variantColumns = variantReturning(contract, variantTable, variantModelName, keyColumns);
4901
+ const joins = rows.map((row) => {
4902
+ const baseInsert = insertAst(contract, root, [row.base], void 0).withReturning(baseColumns);
4903
+ const base = graph.add(new Insert(baseInsert), { payload: [] });
4904
+ const variantInsert = insertAst(contract, variantTable, [row.variant], void 0).withReturning(variantColumns);
4905
+ const variant = graph.add(new Insert(variantInsert), { payload: [new PayloadData(base, keyPairs)] });
4906
+ return graph.add(new CrossJoin(), {
4907
+ left: new Rows(base, sameColumns(baseColumns)),
4908
+ right: new Rows(variant, sameColumns(variantColumns))
4909
+ });
4910
+ });
4911
+ const [only, ...others] = joins;
4912
+ if (only !== void 0 && others.length === 0) graph.setResult(only);
4913
+ else if (only !== void 0) {
4914
+ const joined = sameColumns([...baseColumns, ...variantColumns]);
4915
+ graph.setResult(graph.add(new UnionAll(), { rows: joins.map((join) => new Rows(join, joined)) }));
4916
+ }
4917
+ return graph;
4918
+ }
4919
+ function sameColumns(columns) {
4920
+ return columns.map((column) => [column, column]);
4921
+ }
4922
+ function upsertGraph(collection, create, update, conflictColumns) {
4923
+ const { context, state } = collection;
4924
+ const { root } = state.tables;
4925
+ const graph = new Graph();
4926
+ requireIdentityColumnsForIncludes(collection);
4927
+ const updateSet = Object.keys(update).length > 0 ? updateAssignments(context.contract, root, update) : Object.fromEntries(conflictColumns.slice(0, 1).map((column) => [column, ColumnRef.of("excluded", column)]));
4928
+ const upsert = upsertAst(context.contract, root, create, conflictColumns, updateSet);
4929
+ const upserted = graph.add(new Insert(upsert), { payload: [] });
4930
+ graph.setResult(addWithIncludes(graph, collection, upserted));
4931
+ return graph;
4932
+ }
4797
4933
  function addWithIncludes(graph, collection, written) {
4798
4934
  const { state } = collection;
4799
4935
  if (state.includes.length === 0) return written;
@@ -4872,7 +5008,7 @@ async function executeGraph(graph, ctx, annotations) {
4872
5008
  function returnCallerColumns(graph, callerRows) {
4873
5009
  const { context, modelName, state } = callerRows;
4874
5010
  const columns = returningProjection(context.contract, modelName, state.tables.root, state.selectedFields);
4875
- for (const [id, node] of graph.nodes()) if (id === graph.result) graph.replace(id, node.withReturning(columns));
5011
+ for (const [id, node] of graph.nodes()) if (id === graph.result && node instanceof StatementNode) graph.replace(id, node.withReturning(columns));
4876
5012
  }
4877
5013
  function runAllNodes(graph, ctx, annotations, callerRows) {
4878
5014
  if (graph.nodes().length > 1) return withMutationScope(ctx.runtime, (scope) => runNodesInOrder(graph, {
@@ -4901,11 +5037,9 @@ async function runNodesInOrder(graph, ctx, annotations, callerRows) {
4901
5037
  }
4902
5038
  function inputsOf(graph, id, collected) {
4903
5039
  const outputs = {};
4904
- const slots = graph.inputsOf(id);
4905
- for (const slot in slots) {
4906
- const edges = slots[slot] ?? [];
4907
- outputs[slot] = edges.length === 0 ? null : edges.map((edge) => rowsOf(collected[edge.from]).map((row) => edge.output(row)));
4908
- }
5040
+ const outputOf = (edge) => rowsOf(collected[edge.from]).map((row) => edge.output(row));
5041
+ for (const [name, slot] of Object.entries(graph.inputsOf(id))) if (!Array.isArray(slot)) outputs[name] = outputOf(slot);
5042
+ else outputs[name] = slot.length === 0 ? null : slot.map(outputOf);
4909
5043
  return outputs;
4910
5044
  }
4911
5045
  function runOn(ctx, annotations) {
@@ -5099,6 +5233,7 @@ var CollectionBase = class CollectionBase {
5099
5233
  registry;
5100
5234
  /** @internal */
5101
5235
  includeRefinementMode;
5236
+ #using;
5102
5237
  constructor(ctx, modelName, options) {
5103
5238
  this.ctx = ctx;
5104
5239
  this.contract = ctx.context.contract;
@@ -5164,6 +5299,13 @@ var CollectionBase = class CollectionBase {
5164
5299
  filters: [...this.state.filters, filter]
5165
5300
  });
5166
5301
  }
5302
+ /**
5303
+ * The collection methods packages contribute for this model. Each contribution reads the model and names its methods. Each method returns this collection with the method's filter and order added.
5304
+ */
5305
+ get using() {
5306
+ this.#using ??= createCollectionMethods(blindCast(this), collectionMethodTable(this.ctx.context, this.namespaceId, this.modelName));
5307
+ return blindCast(this.#using);
5308
+ }
5167
5309
  whereUnique(criterion) {
5168
5310
  if (this.includeRefinementMode) throw ormError("ORM.INCLUDE_INVALID", "whereUnique() is not available inside include() refinement callbacks", { meta: { action: "whereUnique()" } });
5169
5311
  if (!hasCompleteUniqueKey(this.contract, this.namespaceId, this.modelName, criterion)) throw ormError("ORM.ARGUMENT_INVALID", `whereUnique() for model "${this.modelName}" needs a value for every field of the primary key or of one unique constraint`, { meta: {
@@ -5523,40 +5665,16 @@ var CollectionBase = class CollectionBase {
5523
5665
  assertReturningCapability(this.contract, "createAll()");
5524
5666
  const rows = blindCast(data);
5525
5667
  const mtiContext = this.#resolveMtiCreateContext();
5526
- if (mtiContext) return this.#executeMtiCreate(rows, mtiContext);
5668
+ if (mtiContext) {
5669
+ const variantTable = requireVariantTable(this.state.tables, mtiContext.variant.value);
5670
+ return queryGraph(createAllVariantGraph(this.#descriptionWithoutIncludes(), variantTable, mtiContext.variant.modelName, this.#variantCreateRows(rows, mtiContext, variantTable)), this.ctx, annotationsMap, this.#descriptionWithoutIncludes());
5671
+ }
5672
+ return queryGraph(createAllGraph(this.#descriptionOptions(), this.#createValues(rows), conflictSkip), this.ctx, annotationsMap, this.#descriptionOptions());
5673
+ }
5674
+ #createValues(rows) {
5527
5675
  const mappedRows = this.#mapCreateRows(rows);
5528
5676
  applyCreateDefaults(this.ctx, this.namespaceId, this.tableName, mappedRows);
5529
- const { selectedForQuery: selectedForInsert, hiddenColumns } = this.#augmentMutationSelection();
5530
- if (this.contract.capabilities?.["sql"]?.["defaultInInsert"] !== true) {
5531
- const plans = compileInsertReturningSplit(this.contract, this.namespaceId, this.modelName, this.tableName, mappedRows, selectedForInsert, conflictSkip).map((plan) => mergeAnnotations(plan, annotationsMap));
5532
- return dispatchSplitMutationRows({
5533
- context: this.ctx.context,
5534
- runtime: this.ctx.runtime,
5535
- plans,
5536
- tables: this.state.tables,
5537
- modelName: this.modelName,
5538
- namespaceId: this.namespaceId,
5539
- variantValue: this.state.variantValue,
5540
- includes: this.state.includes,
5541
- selectedFields: this.state.selectedFields,
5542
- hiddenColumns,
5543
- mapRow: (mapped) => blindCast(mapped)
5544
- });
5545
- }
5546
- const compiled = mergeAnnotations(compileInsertReturning(this.contract, this.namespaceId, this.modelName, this.tableName, mappedRows, selectedForInsert, conflictSkip), annotationsMap);
5547
- return dispatchMutationRows({
5548
- context: this.ctx.context,
5549
- runtime: this.ctx.runtime,
5550
- compiled,
5551
- tables: this.state.tables,
5552
- modelName: this.modelName,
5553
- namespaceId: this.namespaceId,
5554
- variantValue: this.state.variantValue,
5555
- includes: this.state.includes,
5556
- selectedFields: this.state.selectedFields,
5557
- hiddenColumns,
5558
- mapRow: (mapped) => blindCast(mapped)
5559
- });
5677
+ return mappedRows;
5560
5678
  }
5561
5679
  #resolveConflictSkip(options, method) {
5562
5680
  if (options === void 0) return void 0;
@@ -5595,76 +5713,39 @@ var CollectionBase = class CollectionBase {
5595
5713
  if (!polyInfo) return null;
5596
5714
  const variant = polyInfo.variants.get(variantValue);
5597
5715
  if (!isMtiVariantInfo(variant)) return null;
5598
- const baseFieldToColumn = getModelFieldColumns(this.contract, this.namespaceId, this.modelName);
5599
- const variantFieldToColumn = getOwnFieldColumns(this.contract, variant.namespaceId, variant.modelName);
5600
- const pkColumns = resolvePrimaryKeyColumns(this.contract, this.namespaceId, this.tableName);
5601
5716
  return {
5602
5717
  polyInfo,
5603
5718
  variant,
5604
- baseFieldToColumn,
5605
- variantFieldToColumn,
5606
- mergedFieldToColumn: getModelAndVariantFieldColumns(this.contract, this.namespaceId, this.modelName, variant.value),
5607
- pkColumns
5719
+ baseFieldToColumn: getModelFieldColumns(this.contract, this.namespaceId, this.modelName),
5720
+ variantFieldToColumn: getOwnFieldColumns(this.contract, variant.namespaceId, variant.modelName),
5721
+ mergedFieldToColumn: getModelAndVariantFieldColumns(this.contract, this.namespaceId, this.modelName, variant.value)
5608
5722
  };
5609
5723
  }
5610
- #executeMtiCreate(data, mtiCtx) {
5611
- const { polyInfo, variant, baseFieldToColumn, variantFieldToColumn, mergedFieldToColumn, pkColumns } = mtiCtx;
5612
- const contract = this.contract;
5613
- const collectionCtx = this.ctx;
5614
- const runtime = collectionCtx.runtime;
5615
- const tableName = this.tableName;
5616
- const modelName = this.modelName;
5617
- const namespaceId = this.namespaceId;
5618
- const tables = this.state.tables;
5619
- const variantTable = requireVariantTable(tables, variant.value);
5724
+ #variantCreateRows(data, mtiCtx, variantTable) {
5725
+ const { polyInfo, variant, baseFieldToColumn, variantFieldToColumn, mergedFieldToColumn } = mtiCtx;
5620
5726
  const baseFieldColumns = new Set(Object.values(baseFieldToColumn));
5621
5727
  const variantFieldColumns = new Set(Object.values(variantFieldToColumn));
5622
- const generator = async function* () {
5623
- const defaultValueCache = /* @__PURE__ */ new Map();
5624
- for (const row of data) {
5625
- const allMapped = {};
5626
- for (const [fieldName, value] of Object.entries(row)) {
5627
- if (value === void 0) continue;
5628
- allMapped[columnOfCallerField(contract, variant.namespaceId, mergedFieldToColumn, variant.modelName, fieldName)] = value;
5629
- }
5630
- allMapped[polyInfo.discriminatorColumn] = variant.value;
5631
- const baseRow = {};
5632
- const variantRow = {};
5633
- for (const [col, val] of Object.entries(allMapped)) {
5634
- if (baseFieldColumns.has(col) || col === polyInfo.discriminatorColumn) baseRow[col] = val;
5635
- if (variantFieldColumns.has(col)) variantRow[col] = val;
5636
- }
5637
- yield blindCast(await withMutationScope(runtime, async (scope) => {
5638
- applyCreateDefaults(collectionCtx, namespaceId, tableName, [baseRow], defaultValueCache);
5639
- const baseCreated = (await queryPlanRows(scope, compileInsertReturning(contract, namespaceId, modelName, tableName, [baseRow], void 0)).toArray())[0];
5640
- if (!baseCreated) throw ormError("ORM.MUTATION_ROW_MISSING", `MTI base INSERT for model "${modelName}" did not return a row`, { meta: {
5641
- operation: "create",
5642
- model: modelName,
5643
- table: tableName,
5644
- phase: "mti-base"
5645
- } });
5646
- for (const pkColumn of pkColumns) variantRow[pkColumn] = baseCreated[pkColumn];
5647
- applyCreateDefaults(collectionCtx, variantTable.storage.namespaceId, variantTable.storage.tableName, [variantRow], defaultValueCache);
5648
- const variantCreated = (await queryPlanRows(scope, compileInsertReturning(contract, variantTable.storage.namespaceId, variant.modelName, variantTable.storage.tableName, [variantRow], void 0)).toArray())[0];
5649
- if (!variantCreated) throw ormError("ORM.MUTATION_ROW_MISSING", `MTI variant INSERT for model "${modelName}" into "${variant.table}" did not return a row`, { meta: {
5650
- operation: "create",
5651
- model: modelName,
5652
- table: variant.table,
5653
- phase: "mti-variant"
5654
- } });
5655
- const prefixedVariant = {};
5656
- for (const [col, val] of Object.entries(variantCreated)) {
5657
- if (pkColumns.includes(col)) continue;
5658
- prefixedVariant[variantColumnLabel(variantTable, col)] = val;
5659
- }
5660
- return mapPolymorphicRow(contract, namespaceId, modelName, polyInfo, tables, {
5661
- ...baseCreated,
5662
- ...prefixedVariant
5663
- }, variant.value);
5664
- }));
5728
+ const defaultValueCache = /* @__PURE__ */ new Map();
5729
+ return data.map((row) => {
5730
+ const allMapped = {};
5731
+ for (const [fieldName, value] of Object.entries(row)) {
5732
+ if (value === void 0) continue;
5733
+ allMapped[columnOfCallerField(this.contract, this.namespaceId, mergedFieldToColumn, variant.modelName, fieldName)] = value;
5665
5734
  }
5666
- };
5667
- return new AsyncIterableResult(generator());
5735
+ allMapped[polyInfo.discriminatorColumn] = variant.value;
5736
+ const baseRow = {};
5737
+ const variantRow = {};
5738
+ for (const [column, value] of Object.entries(allMapped)) {
5739
+ if (baseFieldColumns.has(column) || column === polyInfo.discriminatorColumn) baseRow[column] = value;
5740
+ if (variantFieldColumns.has(column)) variantRow[column] = value;
5741
+ }
5742
+ applyCreateDefaults(this.ctx, this.namespaceId, this.tableName, [baseRow], defaultValueCache);
5743
+ applyCreateDefaults(this.ctx, variantTable.storage.namespaceId, variantTable.storage.tableName, [variantRow], defaultValueCache);
5744
+ return {
5745
+ base: baseRow,
5746
+ variant: variantRow
5747
+ };
5748
+ });
5668
5749
  }
5669
5750
  #mapCreateRows(data) {
5670
5751
  const variantValue = this.state.variantValue;
@@ -5717,19 +5798,7 @@ var CollectionBase = class CollectionBase {
5717
5798
  this.#assertNotMtiVariant("createAndCount()");
5718
5799
  const annotationsMap = this.#collectAnnotationsFromMeta(configureCallback, "write", "createAndCount");
5719
5800
  const rows = blindCast(data);
5720
- const mappedRows = this.#mapCreateRows(rows);
5721
- applyCreateDefaults(this.ctx, this.namespaceId, this.tableName, mappedRows);
5722
- if (this.contract.capabilities?.["sql"]?.["defaultInInsert"] !== true) {
5723
- const plans = compileInsertCountSplit(this.contract, this.namespaceId, this.tableName, mappedRows, conflictSkip).map((plan) => mergeAnnotations(plan, annotationsMap));
5724
- let affectedRows = 0;
5725
- for (const plan of plans) {
5726
- const stats = await this.ctx.runtime.execute(plan);
5727
- affectedRows += stats.affectedRows;
5728
- }
5729
- return affectedRows;
5730
- }
5731
- const compiled = mergeAnnotations(compileInsertCount(this.contract, this.namespaceId, this.tableName, mappedRows, conflictSkip), annotationsMap);
5732
- return (await this.ctx.runtime.execute(compiled)).affectedRows;
5801
+ return (await executeGraph(createAllGraph(this.#descriptionWithoutIncludes(), this.#createValues(rows), conflictSkip), this.ctx, annotationsMap)).affectedRows;
5733
5802
  }
5734
5803
  async upsert(input, configure) {
5735
5804
  assertLockCompatible(this.state, "mutation");
@@ -5739,36 +5808,14 @@ var CollectionBase = class CollectionBase {
5739
5808
  const createValues = this.#mapCreateRows([blindCast(input.create)])[0] ?? {};
5740
5809
  applyCreateDefaults(this.ctx, this.namespaceId, this.tableName, [createValues]);
5741
5810
  const updateValues = mapModelDataToStorageRow(this.contract, this.namespaceId, this.modelName, input.update);
5742
- const hasUpdateValues = Object.keys(updateValues).length > 0;
5743
- if (hasUpdateValues) applyUpdateDefaults(this.ctx, this.namespaceId, this.tableName, updateValues);
5811
+ if (Object.keys(updateValues).length > 0) applyUpdateDefaults(this.ctx, this.namespaceId, this.tableName, updateValues);
5744
5812
  const conflictColumns = resolveUpsertConflictColumns(this.contract, this.namespaceId, this.modelName, blindCast(input.conflictOn));
5745
5813
  if (conflictColumns.length === 0) throw ormError("ORM.ARGUMENT_INVALID", `upsert() for model "${this.modelName}" requires conflict columns`, { meta: {
5746
5814
  method: "upsert",
5747
5815
  model: this.modelName
5748
5816
  } });
5749
- const { selectedForQuery: selectedForUpsert, hiddenColumns } = this.#augmentMutationSelection();
5750
- const compiled = mergeAnnotations(compileUpsertReturning(this.contract, this.namespaceId, this.modelName, this.tableName, createValues, updateValues, conflictColumns, selectedForUpsert), annotationsMap);
5751
- const row = await executeMutationReturningSingleRow({
5752
- context: this.ctx.context,
5753
- runtime: this.ctx.runtime,
5754
- compiled,
5755
- tables: this.state.tables,
5756
- modelName: this.modelName,
5757
- namespaceId: this.namespaceId,
5758
- variantValue: this.state.variantValue,
5759
- includes: this.state.includes,
5760
- selectedFields: this.state.selectedFields,
5761
- hiddenColumns,
5762
- mapRow: (mapped) => blindCast(mapped),
5763
- operation: "upsert",
5764
- onMissingRowMessage: `upsert() for model "${this.modelName}" did not return a row`
5765
- });
5817
+ const row = await consumeFirstRow(queryGraph(upsertGraph(this.#descriptionOptions(), createValues, updateValues, conflictColumns), this.ctx, annotationsMap, this.#descriptionOptions()));
5766
5818
  if (row) return row;
5767
- if (!hasUpdateValues) {
5768
- const conflictCriterion = this.#buildUpsertConflictCriterion(createValues, conflictColumns);
5769
- const existing = await this.#reloadMutationRowByCriterion(conflictCriterion, "upsert conflict");
5770
- if (existing) return existing;
5771
- }
5772
5819
  throw ormError("ORM.MUTATION_ROW_MISSING", `upsert() for model "${this.modelName}" did not return a row`, { meta: {
5773
5820
  operation: "upsert",
5774
5821
  model: this.modelName
@@ -5845,46 +5892,6 @@ var CollectionBase = class CollectionBase {
5845
5892
  if (Object.keys(values).length > 0) applyUpdateDefaults(this.ctx, this.namespaceId, this.tableName, values);
5846
5893
  return values;
5847
5894
  }
5848
- #buildUpsertConflictCriterion(createValues, conflictColumns) {
5849
- const criterion = {};
5850
- for (const columnName of conflictColumns) {
5851
- if (!(columnName in createValues)) throw ormError("ORM.ARGUMENT_INVALID", `upsert() for model "${this.modelName}" requires create value for conflict column "${columnName}"`, { meta: {
5852
- method: "upsert",
5853
- model: this.modelName,
5854
- column: columnName
5855
- } });
5856
- const fieldName = fieldOfColumn(getModelColumnFields(this.contract, this.namespaceId, this.modelName), this.modelName, columnName);
5857
- criterion[fieldName] = createValues[columnName];
5858
- }
5859
- return criterion;
5860
- }
5861
- /**
5862
- * Shape the projection for a mutation's `RETURNING` clause.
5863
- *
5864
- * Without includes, the mutation returns the caller's projection
5865
- * directly. With includes, it returns only the row identity columns
5866
- * (PK / unique): those rows are reloaded through the read path
5867
- * (`reloadMutationRowsByIdentities`), which re-selects the caller's
5868
- * projection together with the relations, so the `RETURNING` clause
5869
- * need only carry enough to key that read-back.
5870
- */
5871
- #augmentMutationSelection() {
5872
- if (this.state.includes.length > 0) {
5873
- const identityColumns = resolveRowIdentityColumns(this.contract, this.namespaceId, this.tableName);
5874
- if (identityColumns.length === 0) throw ormError("ORM.ROW_IDENTITY_MISSING", `Cannot load includes for the mutation result on model "${this.modelName}": table "${this.tableName}" has no primary key or unique constraint to key the include read-back on.`, { meta: {
5875
- model: this.modelName,
5876
- table: this.tableName
5877
- } });
5878
- return {
5879
- selectedForQuery: identityColumns,
5880
- hiddenColumns: []
5881
- };
5882
- }
5883
- return {
5884
- selectedForQuery: this.state.selectedFields,
5885
- hiddenColumns: []
5886
- };
5887
- }
5888
5895
  async #reloadMutationRowByIdentity(criterion) {
5889
5896
  return this.#reloadMutationRowByCriterion(criterion, "row identity");
5890
5897
  }
@@ -6048,6 +6055,7 @@ function assertAggregateOperationsNotReserved(registry) {
6048
6055
  function orm(options) {
6049
6056
  const { runtime, collections, context } = options;
6050
6057
  assertAggregateOperationsNotReserved(context.aggregateDescriptors);
6058
+ collectionMethodTables(context);
6051
6059
  const contract = context.contract;
6052
6060
  const ctx = {
6053
6061
  runtime,