@prisma/orm-family-sql 8.0.0-rc.17-dev.23 → 8.0.0-rc.17-dev.25

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.
@@ -377,7 +377,7 @@ function resolveIncludeRelation(contract, namespaceId, baseModelName, relationNa
377
377
  const polymorphism = resolvePolymorphismInfo(contract, namespaceId, baseModelName);
378
378
  const variant = variantName === void 0 ? void 0 : polymorphism?.variants.get(variantName);
379
379
  let declaringModelName = baseModelName;
380
- let localTableName = resolveModelTableName(contract, namespaceId, baseModelName);
380
+ let localVariantName;
381
381
  let relation;
382
382
  if (variant !== void 0) {
383
383
  const variantRelations = resolveModelRelations(contract, namespaceId, variant.modelName);
@@ -385,7 +385,7 @@ function resolveIncludeRelation(contract, namespaceId, baseModelName, relationNa
385
385
  if (candidate !== void 0) {
386
386
  relation = candidate;
387
387
  declaringModelName = variant.modelName;
388
- localTableName = variant.table;
388
+ localVariantName = variant.strategy === "mti" ? variant.modelName : void 0;
389
389
  }
390
390
  }
391
391
  const baseRelations = resolveModelRelations(contract, namespaceId, baseModelName);
@@ -412,7 +412,7 @@ function resolveIncludeRelation(contract, namespaceId, baseModelName, relationNa
412
412
  relatedModelName: relation.to,
413
413
  relatedNamespaceId: relation.toNamespace,
414
414
  relatedTableName,
415
- localTableName,
415
+ ...ifDefined("localVariantName", localVariantName),
416
416
  targetColumns,
417
417
  localColumns,
418
418
  cardinality: relation.cardinality,
@@ -505,6 +505,23 @@ function resolveRowIdentityColumns(contract, namespaceId, tableName) {
505
505
  for (const unique of table.uniques) if (unique.columns.length > 0) return unique.columns;
506
506
  return [];
507
507
  }
508
+ function resolveUniqueKeyColumnSets(contract, namespaceId, tableName) {
509
+ const table = storageTableForContract(contract, namespaceId, tableName);
510
+ return [table.primaryKey?.columns ?? [], ...table.uniques.map((unique) => unique.columns)].filter((columns) => columns.length > 0);
511
+ }
512
+ function hasCompleteUniqueKey(contract, namespaceId, modelName, criterion) {
513
+ if (typeof criterion !== "object" || criterion === null || Array.isArray(criterion)) return false;
514
+ const tableName = resolveModelTableName(contract, namespaceId, modelName);
515
+ const fields = getModelFields(contract, namespaceId, modelName);
516
+ const fieldColumns = getModelFieldColumns(contract, namespaceId, modelName);
517
+ const columnsWithValue = /* @__PURE__ */ new Set();
518
+ for (const [fieldName, value] of Object.entries(criterion)) {
519
+ if (value === void 0) continue;
520
+ const column = columnOfCallerField(contract, namespaceId, fieldColumns, modelName, fieldName);
521
+ if (value !== null && !isExpression(value) && fields[fieldName]?.table === tableName) columnsWithValue.add(column);
522
+ }
523
+ return resolveUniqueKeyColumnSets(contract, namespaceId, tableName).some((columns) => columns.every((column) => columnsWithValue.has(column)));
524
+ }
508
525
  function assertReturningCapability(contract, action) {
509
526
  if (hasContractCapability(contract, "returning")) return;
510
527
  throw ormError("ORM.CAPABILITY_MISSING", `${action} requires contract capability "returning"`, { meta: {
@@ -677,6 +694,108 @@ function mapCursorValuesToColumns(contract, namespaceId, modelName, cursorValues
677
694
  }
678
695
  return mappedCursor;
679
696
  }
697
+ const MAX_ALIAS_BYTES = 63;
698
+ const encoder = new TextEncoder();
699
+ function shortenToBytes(value, maxBytes) {
700
+ let shortened = "";
701
+ let bytes = 0;
702
+ for (const character of value) {
703
+ bytes += encoder.encode(character).length;
704
+ if (bytes > maxBytes) break;
705
+ shortened += character;
706
+ }
707
+ return shortened;
708
+ }
709
+ var TableScopeImpl = class TableScopeImpl {
710
+ #aliases;
711
+ constructor(aliases = []) {
712
+ this.#aliases = new Set(aliases);
713
+ }
714
+ alias(preferred) {
715
+ for (let n = 1;; n += 1) {
716
+ const suffix = n === 1 ? "" : `_${n}`;
717
+ const candidate = `${shortenToBytes(preferred, MAX_ALIAS_BYTES - suffix.length)}${suffix}`;
718
+ if (!this.#aliases.has(candidate)) {
719
+ this.#aliases.add(candidate);
720
+ return candidate;
721
+ }
722
+ }
723
+ }
724
+ aliasTable(storage) {
725
+ const alias = this.alias(storage.tableName);
726
+ const coordinate = Object.freeze({ ...storage });
727
+ return Object.freeze({
728
+ alias,
729
+ storage: coordinate,
730
+ column: (name) => ColumnRef.of(alias, name),
731
+ tableSource: (contract) => tableSourceForContract(contract, coordinate.namespaceId, coordinate.tableName, alias)
732
+ });
733
+ }
734
+ copy() {
735
+ return new TableScopeImpl(this.#aliases);
736
+ }
737
+ };
738
+ function createTableScope() {
739
+ return new TableScopeImpl();
740
+ }
741
+ function createModelTables(contract, scope, namespaceId, modelName, tableName) {
742
+ const root = scope.aliasTable({
743
+ namespaceId,
744
+ tableName
745
+ });
746
+ const variants = /* @__PURE__ */ new Map();
747
+ const mtiVariants = resolvePolymorphismInfo(contract, namespaceId, modelName)?.mtiVariants ?? [];
748
+ for (const variant of mtiVariants) variants.set(variant.modelName, scope.aliasTable({
749
+ namespaceId,
750
+ tableName: variant.table
751
+ }));
752
+ return {
753
+ scope,
754
+ root,
755
+ variants
756
+ };
757
+ }
758
+ function createCollectionTables(contract, namespaceId, modelName, tableName = resolveModelTableName(contract, namespaceId, modelName)) {
759
+ return createModelTables(contract, createTableScope(), namespaceId, modelName, tableName);
760
+ }
761
+ function createIncludeTables(contract, parent, relation) {
762
+ const scope = parent.scope.copy();
763
+ return {
764
+ tables: createModelTables(contract, scope, relation.relatedNamespaceId, relation.relatedModelName, relation.relatedTableName),
765
+ junction: relation.through === void 0 ? void 0 : scope.aliasTable({
766
+ namespaceId: relation.through.namespaceId,
767
+ tableName: relation.through.table
768
+ })
769
+ };
770
+ }
771
+ function createStatementTables(storage) {
772
+ const scope = createTableScope();
773
+ return {
774
+ scope,
775
+ root: scope.aliasTable(storage),
776
+ variants: /* @__PURE__ */ new Map()
777
+ };
778
+ }
779
+ function withScopeCopy(tables) {
780
+ return {
781
+ ...tables,
782
+ scope: tables.scope.copy()
783
+ };
784
+ }
785
+ function requireVariantTable(tables, variantModelName) {
786
+ const variantTable = tables.variants.get(variantModelName);
787
+ if (variantTable === void 0) throw new InternalError(`Collection state has no aliased table for variant "${variantModelName}"`);
788
+ return variantTable;
789
+ }
790
+ function tableAliases(tables) {
791
+ return new Map([tables.root, ...tables.variants.values()].map((table) => [table.alias, table.storage]));
792
+ }
793
+ function variantColumnLabelPrefix(variantTable) {
794
+ return `${variantTable.alias}__`;
795
+ }
796
+ function variantColumnLabel(variantTable, column) {
797
+ return `${variantColumnLabelPrefix(variantTable)}${column}`;
798
+ }
680
799
  function stripHiddenMappedFields(contract, namespaceId, modelName, mapped, hiddenColumns) {
681
800
  if (hiddenColumns.length === 0) return;
682
801
  const columnToField = getModelColumnFields(contract, namespaceId, modelName);
@@ -694,7 +813,7 @@ function createStorageRowMapper(contract, namespaceId, modelName) {
694
813
  }
695
814
  const mergedColumnToFieldCache = /* @__PURE__ */ new WeakMap();
696
815
  function getMergedColumnToFieldMap(contract, namespaceId, baseModelName, variantModelName, variantTable) {
697
- const cacheKey = `${namespaceId}:${baseModelName}:${variantModelName}:${variantTable ?? ""}`;
816
+ const cacheKey = `${namespaceId}:${baseModelName}:${variantModelName}:${variantTable?.alias ?? ""}`;
698
817
  let perContract = mergedColumnToFieldCache.get(contract);
699
818
  if (!perContract) {
700
819
  perContract = /* @__PURE__ */ new Map();
@@ -705,25 +824,27 @@ function getMergedColumnToFieldMap(contract, namespaceId, baseModelName, variant
705
824
  const baseMap = getModelColumnFields(contract, namespaceId, baseModelName);
706
825
  const variantMap = getOwnColumnFields(contract, namespaceId, variantModelName);
707
826
  const merged = { ...baseMap };
708
- for (const [col, field] of Object.entries(variantMap)) if (variantTable) merged[`${variantTable}__${col}`] = field;
827
+ for (const [col, field] of Object.entries(variantMap)) if (variantTable) merged[variantColumnLabel(variantTable, col)] = field;
709
828
  else merged[col] = field;
710
829
  perContract.set(cacheKey, merged);
711
830
  return merged;
712
831
  }
713
- function mapPolymorphicRow(contract, namespaceId, baseModelName, polyInfo, row, variantName) {
832
+ function variantTableOf(tables, variant) {
833
+ return variant.strategy === "mti" ? requireVariantTable(tables, variant.modelName) : void 0;
834
+ }
835
+ function mapPolymorphicRow(contract, namespaceId, baseModelName, polyInfo, tables, row, variantName) {
714
836
  const discriminatorValue = row[polyInfo.discriminatorColumn] ?? row["__prisma_polymorphic_discriminator"];
715
837
  const variant = variantName ? polyInfo.variants.get(variantName) : typeof discriminatorValue === "string" ? polyInfo.variantsByValue.get(discriminatorValue) : void 0;
716
838
  if (!variant) return mapKnownColumnNames(row, getModelColumnFields(contract, namespaceId, baseModelName));
717
- const mtiTable = variant.strategy === "mti" ? variant.table : void 0;
718
- return mapKnownColumnNames(row, getMergedColumnToFieldMap(contract, namespaceId, baseModelName, variant.modelName, mtiTable));
839
+ return mapKnownColumnNames(row, getMergedColumnToFieldMap(contract, namespaceId, baseModelName, variant.modelName, variantTableOf(tables, variant)));
719
840
  }
720
- function createPolymorphicRowMapper(contract, namespaceId, baseModelName, polyInfo, variantName) {
841
+ function createPolymorphicRowMapper(contract, namespaceId, baseModelName, polyInfo, tables, variantName) {
721
842
  const baseMapper = captureColumnMapper(() => getModelColumnFields(contract, namespaceId, baseModelName));
722
843
  const mappersByValue = /* @__PURE__ */ new Map();
723
844
  let pinnedMapper = baseMapper;
724
845
  for (const [name, variant] of polyInfo.variants) {
725
846
  if (variantName && name !== variantName) continue;
726
- const mapper = captureColumnMapper(() => getMergedColumnToFieldMap(contract, namespaceId, baseModelName, variant.modelName, variant.strategy === "mti" ? variant.table : void 0));
847
+ const mapper = captureColumnMapper(() => getMergedColumnToFieldMap(contract, namespaceId, baseModelName, variant.modelName, variantTableOf(tables, variant)));
727
848
  if (variantName) pinnedMapper = mapper;
728
849
  for (const [value, candidate] of polyInfo.variantsByValue) if (candidate === variant) mappersByValue.set(value, mapper);
729
850
  }
@@ -872,43 +993,43 @@ function mergeAnnotations(plan, annotations) {
872
993
  })
873
994
  });
874
995
  }
875
- function namespaceCoordinateForSource(source) {
876
- return source.kind === "table-source" ? source.namespaceId : void 0;
996
+ function bindWhereExpr(contract, expr, aliases) {
997
+ return bindWhereExprInScope(contract, expr, aliases);
877
998
  }
878
- function bindWhereExpr(contract, expr, namespaceId) {
999
+ function bindWhereExprInScope(contract, expr, aliases) {
879
1000
  return expr.accept({
880
1001
  columnRef(expr) {
881
- return bindExpression(contract, expr);
1002
+ return bindExpression(contract, expr, aliases);
882
1003
  },
883
1004
  identifierRef(expr) {
884
1005
  return expr;
885
1006
  },
886
1007
  subquery(expr) {
887
- return bindExpression(contract, expr);
1008
+ return bindExpression(contract, expr, aliases);
888
1009
  },
889
1010
  operation(expr) {
890
- return bindExpression(contract, expr);
1011
+ return bindExpression(contract, expr, aliases);
891
1012
  },
892
1013
  aggregate(expr) {
893
- return bindExpression(contract, expr);
1014
+ return bindExpression(contract, expr, aliases);
894
1015
  },
895
1016
  windowFunc(expr) {
896
- return bindExpression(contract, expr);
1017
+ return bindExpression(contract, expr, aliases);
897
1018
  },
898
1019
  functionCall(expr) {
899
- return bindExpression(contract, expr);
1020
+ return bindExpression(contract, expr, aliases);
900
1021
  },
901
1022
  cast(expr) {
902
- return bindExpression(contract, expr);
1023
+ return bindExpression(contract, expr, aliases);
903
1024
  },
904
1025
  case(expr) {
905
- return bindExpression(contract, expr);
1026
+ return bindExpression(contract, expr, aliases);
906
1027
  },
907
1028
  jsonObject(expr) {
908
- return bindExpression(contract, expr);
1029
+ return bindExpression(contract, expr, aliases);
909
1030
  },
910
1031
  jsonArrayAgg(expr) {
911
- return bindExpression(contract, expr);
1032
+ return bindExpression(contract, expr, aliases);
912
1033
  },
913
1034
  literal(expr) {
914
1035
  return expr;
@@ -920,81 +1041,92 @@ function bindWhereExpr(contract, expr, namespaceId) {
920
1041
  return expr;
921
1042
  },
922
1043
  list(expr) {
923
- return bindExpression(contract, expr);
1044
+ return bindExpression(contract, expr, aliases);
924
1045
  },
925
1046
  binary(expr) {
926
- const left = bindExpression(contract, expr.left);
1047
+ const left = bindExpression(contract, expr.left, aliases);
927
1048
  const bindingColumn = left.kind === "column-ref" ? left : void 0;
928
- return new BinaryExpr(expr.op, left, bindComparable(contract, expr.right, bindingColumn, namespaceId));
1049
+ return new BinaryExpr(expr.op, left, bindComparable(contract, expr.right, bindingColumn, aliases));
929
1050
  },
930
1051
  and(expr) {
931
- return AndExpr.of(expr.exprs.map((part) => bindWhereExpr(contract, part, namespaceId)));
1052
+ return AndExpr.of(expr.exprs.map((part) => bindWhereExprInScope(contract, part, aliases)));
932
1053
  },
933
1054
  or(expr) {
934
- return OrExpr.of(expr.exprs.map((part) => bindWhereExpr(contract, part, namespaceId)));
1055
+ return OrExpr.of(expr.exprs.map((part) => bindWhereExprInScope(contract, part, aliases)));
935
1056
  },
936
1057
  exists(expr) {
937
- return expr.notExists ? ExistsExpr.notExists(bindSelectAst(contract, expr.subquery)) : ExistsExpr.exists(bindSelectAst(contract, expr.subquery));
1058
+ return expr.notExists ? ExistsExpr.notExists(bindSelectAst(contract, expr.subquery, aliases)) : ExistsExpr.exists(bindSelectAst(contract, expr.subquery, aliases));
938
1059
  },
939
1060
  nullCheck(expr) {
940
- return expr.isNull ? NullCheckExpr.isNull(bindExpression(contract, expr.expr)) : NullCheckExpr.isNotNull(bindExpression(contract, expr.expr));
1061
+ return expr.isNull ? NullCheckExpr.isNull(bindExpression(contract, expr.expr, aliases)) : NullCheckExpr.isNotNull(bindExpression(contract, expr.expr, aliases));
941
1062
  },
942
1063
  not(expr) {
943
- return new NotExpr(bindWhereExpr(contract, expr.expr, namespaceId));
1064
+ return new NotExpr(bindWhereExprInScope(contract, expr.expr, aliases));
944
1065
  },
945
1066
  rawExpr(expr) {
946
1067
  return expr;
947
1068
  }
948
1069
  });
949
1070
  }
950
- function bindComparable(contract, comparable, bindingColumn, namespaceId) {
951
- if (comparable.kind === "param-ref" || bindingColumn === void 0) return comparable.kind === "param-ref" ? comparable : comparable.kind === "literal" || comparable.kind === "list" ? comparable : bindExpression(contract, comparable);
952
- if (comparable.kind === "literal") return createParamRef(contract, bindingColumn, comparable.value, namespaceId);
953
- if (comparable.kind === "list") return ListExpression.of(comparable.values.map((value) => value.kind === "literal" ? createParamRef(contract, bindingColumn, value.value, namespaceId) : value));
954
- return bindExpression(contract, comparable);
955
- }
956
- function createParamRef(contract, columnRef, value, namespaceId) {
957
- const resolved = resolveStorageTable(contract.storage, columnRef.table, namespaceId);
958
- if (resolved === void 0 || !resolved.table.columns[columnRef.column]) throw ormError("ORM.COLUMN_UNKNOWN", `Unknown column "${columnRef.column}" in table "${columnRef.table}"`, { meta: {
959
- tableName: columnRef.table,
960
- column: columnRef.column
1071
+ function bindComparable(contract, comparable, bindingColumn, aliases) {
1072
+ if (comparable.kind === "param-ref" || bindingColumn === void 0) return comparable.kind === "param-ref" ? comparable : comparable.kind === "literal" || comparable.kind === "list" ? comparable : bindExpression(contract, comparable, aliases);
1073
+ if (comparable.kind === "literal") return paramRefForAlias(contract, bindingColumn, comparable.value, aliases);
1074
+ if (comparable.kind === "list") return ListExpression.of(comparable.values.map((value) => value.kind === "literal" ? paramRefForAlias(contract, bindingColumn, value.value, aliases) : value));
1075
+ return bindExpression(contract, comparable, aliases);
1076
+ }
1077
+ function unknownColumn(alias, column) {
1078
+ return ormError("ORM.COLUMN_UNKNOWN", `Unknown column "${column}" in table "${alias}"`, { meta: {
1079
+ tableName: alias,
1080
+ column
961
1081
  } });
962
- const codec = codecRefForStorageColumn(contract.storage, resolved.namespaceId, columnRef.table, columnRef.column);
963
- return ParamRef.of(value, codec ? { codec } : void 0);
964
1082
  }
965
- function createExpressionBinder(contract) {
966
- return { select: (ast) => bindSelectAst(contract, ast) };
1083
+ function paramRefForAlias(contract, columnRef, value, aliases) {
1084
+ const coordinate = aliases.get(columnRef.table);
1085
+ if (coordinate === void 0) throw unknownColumn(columnRef.table, columnRef.column);
1086
+ return paramRefForTable(contract, coordinate, columnRef.table, columnRef.column, value);
1087
+ }
1088
+ function paramRefForTable(contract, coordinate, alias, column, value) {
1089
+ const resolved = resolveStorageTable(contract.storage, coordinate.tableName, coordinate.namespaceId);
1090
+ if (resolved === void 0 || !resolved.table.columns[column]) throw unknownColumn(alias, column);
1091
+ const codec = codecRefForStorageColumn(contract.storage, resolved.namespaceId, coordinate.tableName, column);
1092
+ return ParamRef.of(value, codec ? { codec } : void 0);
967
1093
  }
968
- function bindExpression(contract, expr) {
969
- return expr.rewrite(createExpressionBinder(contract));
1094
+ function paramRefForStorageColumn(contract, storage, column, value) {
1095
+ return paramRefForTable(contract, storage, storage.tableName, column, value);
970
1096
  }
971
- function bindProjectionExpr(contract, expr) {
972
- return expr.kind === "literal" ? expr : bindExpression(contract, expr);
1097
+ function bindExpression(contract, expr, aliases) {
1098
+ return expr.rewrite({ select: (ast) => bindSelectAst(contract, ast, aliases) });
973
1099
  }
974
- function bindOrderByItem(contract, orderItem) {
975
- return orderItem.withExpr(bindExpression(contract, orderItem.expr));
1100
+ function bindProjectionExpr(contract, expr, aliases) {
1101
+ return expr.kind === "literal" ? expr : bindExpression(contract, expr, aliases);
976
1102
  }
977
- function bindJoin(contract, join) {
978
- const namespaceId = namespaceCoordinateForSource(join.source);
979
- return new JoinAst(join.joinType, bindFromSource(contract, join.source), join.on.kind === "eq-col-join-on" ? join.on : bindWhereExpr(contract, join.on, namespaceId), join.lateral);
1103
+ function bindJoin(contract, join, aliases) {
1104
+ return new JoinAst(join.joinType, bindFromSource(contract, join.source, aliases), join.on.kind === "eq-col-join-on" ? join.on : bindWhereExprInScope(contract, join.on, aliases), join.lateral);
980
1105
  }
981
- function bindFromSource(contract, source) {
982
- if (source.kind === "table-source") return source;
983
- if (source.kind === "derived-table-source") return DerivedTableSource.as(source.alias, bindSelectAst(contract, source.query));
1106
+ function bindFromSource(contract, source, aliases) {
1107
+ if (source.kind === "derived-table-source") return DerivedTableSource.as(source.alias, bindSelectAst(contract, source.query, aliases));
984
1108
  return source;
985
1109
  }
986
- function bindSelectAst(contract, ast) {
987
- const namespaceId = ast.from !== void 0 ? namespaceCoordinateForSource(ast.from) : void 0;
1110
+ function aliasesWithSources(outer, sources) {
1111
+ const aliases = new Map(outer);
1112
+ for (const source of sources) if (source.kind === "table-source") aliases.set(source.alias ?? source.name, {
1113
+ namespaceId: source.namespaceId,
1114
+ tableName: source.name
1115
+ });
1116
+ return aliases;
1117
+ }
1118
+ function bindSelectAst(contract, ast, outer) {
1119
+ const aliases = aliasesWithSources(outer, [...ast.from !== void 0 ? [ast.from] : [], ...(ast.joins ?? []).map((join) => join.source)]);
988
1120
  return new SelectAst({
989
- ...ast.from !== void 0 ? { from: bindFromSource(contract, ast.from) } : {},
990
- joins: ast.joins?.map((join) => bindJoin(contract, join)),
991
- projection: ast.projection.map((projection) => new ProjectionItem(projection.alias, bindProjectionExpr(contract, projection.expr), projection.codec)),
992
- where: ast.where ? bindWhereExpr(contract, ast.where, namespaceId) : void 0,
993
- orderBy: ast.orderBy?.map((orderItem) => bindOrderByItem(contract, orderItem)),
1121
+ ...ast.from !== void 0 ? { from: bindFromSource(contract, ast.from, outer) } : {},
1122
+ joins: ast.joins?.map((join) => bindJoin(contract, join, aliases)),
1123
+ projection: ast.projection.map((projection) => new ProjectionItem(projection.alias, bindProjectionExpr(contract, projection.expr, aliases), projection.codec)),
1124
+ where: ast.where ? bindWhereExprInScope(contract, ast.where, aliases) : void 0,
1125
+ orderBy: ast.orderBy?.map((orderItem) => orderItem.withExpr(bindExpression(contract, orderItem.expr, aliases))),
994
1126
  distinct: ast.distinct,
995
- distinctOn: ast.distinctOn?.map((expr) => bindExpression(contract, expr)),
996
- groupBy: ast.groupBy?.map((expr) => bindExpression(contract, expr)),
997
- having: ast.having ? bindWhereExpr(contract, ast.having, namespaceId) : void 0,
1127
+ distinctOn: ast.distinctOn?.map((expr) => bindExpression(contract, expr, aliases)),
1128
+ groupBy: ast.groupBy?.map((expr) => bindExpression(contract, expr, aliases)),
1129
+ having: ast.having ? bindWhereExprInScope(contract, ast.having, aliases) : void 0,
998
1130
  limit: ast.limit,
999
1131
  offset: ast.offset,
1000
1132
  locking: ast.locking,
@@ -1006,14 +1138,14 @@ function combineWhereExprs(filters) {
1006
1138
  if (filters.length === 1) return filters[0];
1007
1139
  return AndExpr.of(filters);
1008
1140
  }
1009
- function createBoundaryExpr(tableName, entry) {
1010
- return new BinaryExpr(entry.direction === "asc" ? "gt" : "lt", ColumnRef.of(tableName, entry.column), LiteralExpr.of(entry.value));
1141
+ function createBoundaryExpr(contract, table, entry) {
1142
+ return new BinaryExpr(entry.direction === "asc" ? "gt" : "lt", table.column(entry.column), paramRefForStorageColumn(contract, table.storage, entry.column, entry.value));
1011
1143
  }
1012
- function buildLexicographicCursorWhere(tableName, entries) {
1144
+ function buildLexicographicCursorWhere(contract, table, entries) {
1013
1145
  const branches = entries.map((entry, index) => {
1014
1146
  const branchExprs = [];
1015
- for (const prefixEntry of entries.slice(0, index)) branchExprs.push(BinaryExpr.eq(ColumnRef.of(tableName, prefixEntry.column), LiteralExpr.of(prefixEntry.value)));
1016
- branchExprs.push(createBoundaryExpr(tableName, entry));
1147
+ for (const prefixEntry of entries.slice(0, index)) branchExprs.push(BinaryExpr.eq(table.column(prefixEntry.column), paramRefForStorageColumn(contract, table.storage, prefixEntry.column, prefixEntry.value)));
1148
+ branchExprs.push(createBoundaryExpr(contract, table, entry));
1017
1149
  if (branchExprs.length === 1) {
1018
1150
  const branch = branchExprs[0];
1019
1151
  assertDefined(branch, "cursor branch contains its boundary expression");
@@ -1028,7 +1160,7 @@ function buildLexicographicCursorWhere(tableName, entries) {
1028
1160
  }
1029
1161
  return OrExpr.of(branches);
1030
1162
  }
1031
- function buildCursorWhere(tableName, orderBy, cursor) {
1163
+ function buildCursorWhere(contract, table, orderBy, cursor) {
1032
1164
  if (!cursor || !orderBy || orderBy.length === 0) return;
1033
1165
  assertCursorCompatibleOrder(orderBy);
1034
1166
  const entries = [];
@@ -1044,28 +1176,12 @@ function buildCursorWhere(tableName, orderBy, cursor) {
1044
1176
  });
1045
1177
  }
1046
1178
  const firstEntry = entries[0];
1047
- if (entries.length === 1 && firstEntry !== void 0) return createBoundaryExpr(tableName, firstEntry);
1048
- return buildLexicographicCursorWhere(tableName, entries);
1049
- }
1050
- function createTableRefRemapper$1(fromTable, toTable) {
1051
- return {
1052
- columnRef: (col) => col.table === fromTable ? ColumnRef.of(toTable, col.column) : col,
1053
- tableSource: (source) => {
1054
- if (source.alias === fromTable) return TableSource.named(source.name, toTable, source.namespaceId);
1055
- if (!source.alias && source.name === fromTable) return TableSource.named(source.name, toTable, source.namespaceId);
1056
- return source;
1057
- },
1058
- eqColJoinOn: (on) => EqColJoinOn.of(on.left.table === fromTable ? ColumnRef.of(toTable, on.left.column) : on.left, on.right.table === fromTable ? ColumnRef.of(toTable, on.right.column) : on.right)
1059
- };
1179
+ if (entries.length === 1 && firstEntry !== void 0) return createBoundaryExpr(contract, table, firstEntry);
1180
+ return buildLexicographicCursorWhere(contract, table, entries);
1060
1181
  }
1061
- function buildStateWhere(contract, tableName, state, options) {
1062
- const filterTableName = options?.filterTableName;
1063
- const cursorWhere = buildCursorWhere(filterTableName ?? tableName, state.orderBy, state.cursor);
1064
- const boundFilters = state.filters.map((filter) => bindWhereExpr(contract, filter, options?.namespaceId));
1065
- const remappedFilters = filterTableName && filterTableName !== tableName ? boundFilters.map((filter) => filter.rewrite(createTableRefRemapper$1(filterTableName, tableName))) : boundFilters;
1066
- const boundCursorWhere = cursorWhere ? bindWhereExpr(contract, cursorWhere, options?.namespaceId) : void 0;
1067
- const remappedCursorWhere = boundCursorWhere && filterTableName && filterTableName !== tableName ? boundCursorWhere.rewrite(createTableRefRemapper$1(filterTableName, tableName)) : boundCursorWhere;
1068
- return combineWhereExprs(remappedCursorWhere ? [...remappedFilters, remappedCursorWhere] : remappedFilters);
1182
+ function buildStateWhere(contract, state) {
1183
+ const cursorWhere = buildCursorWhere(contract, state.tables.root, state.orderBy, state.cursor);
1184
+ return combineWhereExprs(cursorWhere ? [...state.filters, cursorWhere] : state.filters);
1069
1185
  }
1070
1186
  /**
1071
1187
  * Wrap a base SELECT in a `ROW_NUMBER() OVER (PARTITION BY … ORDER BY …) = 1`
@@ -1098,32 +1214,33 @@ function wrapWithRowNumberDedup(options) {
1098
1214
  }
1099
1215
  /**
1100
1216
  * FROM source + WHERE for `state.distinct`: wraps in a `ROW_NUMBER`-ranked
1101
- * derived table aliased back to `tableName`, so callers need no rewriting.
1217
+ * derived table aliased back to the root alias, so callers need no rewriting.
1102
1218
  */
1103
- function buildDedupedTableSource(contract, namespaceId, tableName, state, where, wrapProjection, joins) {
1219
+ function buildDedupedTableSource(contract, state, where, wrapProjection, joins) {
1220
+ const { root } = state.tables;
1104
1221
  if (!hasEntries(state.distinct)) return {
1105
- source: tableSourceForContract(contract, namespaceId, tableName),
1222
+ source: root.tableSource(contract),
1106
1223
  where
1107
1224
  };
1108
- const distinctColumnRefs = state.distinct.map((column) => ColumnRef.of(tableName, column));
1225
+ const distinctColumnRefs = state.distinct.map((column) => root.column(column));
1109
1226
  const rankingOrderBy = hasEntries(state.orderBy) ? state.orderBy : distinctColumnRefs.map((expr) => OrderByItem.asc(expr));
1110
- let inner = SelectAst.from(tableSourceForContract(contract, namespaceId, tableName)).withProjection([...wrapProjection, ProjectionItem.of("__prisma_distinct_rn", WindowFuncExpr.rowNumber({
1227
+ let inner = SelectAst.from(root.tableSource(contract)).withProjection([...wrapProjection, ProjectionItem.of("__prisma_distinct_rn", WindowFuncExpr.rowNumber({
1111
1228
  partitionBy: distinctColumnRefs,
1112
1229
  orderBy: rankingOrderBy
1113
1230
  }))]);
1114
1231
  if (joins && joins.length > 0) inner = inner.withJoins(joins);
1115
1232
  if (where) inner = inner.withWhere(where);
1116
1233
  return {
1117
- source: DerivedTableSource.as(tableName, inner),
1118
- where: BinaryExpr.eq(ColumnRef.of(tableName, "__prisma_distinct_rn"), LiteralExpr.of(1))
1234
+ source: DerivedTableSource.as(root.alias, inner),
1235
+ where: BinaryExpr.eq(root.column("__prisma_distinct_rn"), LiteralExpr.of(1))
1119
1236
  };
1120
1237
  }
1121
- function buildPrimaryKeyJoinOn(leftTable, rightTable, primaryKeyColumns) {
1238
+ function buildPrimaryKeyJoinOn(left, right, primaryKeyColumns) {
1122
1239
  const [firstColumn] = primaryKeyColumns;
1123
- if (primaryKeyColumns.length === 1 && firstColumn !== void 0) return EqColJoinOn.of(ColumnRef.of(leftTable, firstColumn), ColumnRef.of(rightTable, firstColumn));
1124
- return AndExpr.of(primaryKeyColumns.map((column) => BinaryExpr.eq(ColumnRef.of(leftTable, column), ColumnRef.of(rightTable, column))));
1240
+ if (primaryKeyColumns.length === 1 && firstColumn !== void 0) return EqColJoinOn.of(left.column(firstColumn), right.column(firstColumn));
1241
+ return AndExpr.of(primaryKeyColumns.map((column) => BinaryExpr.eq(left.column(column), right.column(column))));
1125
1242
  }
1126
- function buildMtiJoins(contract, namespaceId, polyInfo, variantName, selectedColumnsByTable) {
1243
+ function buildMtiJoins(contract, tables, polyInfo, variantName, selectedColumnsByVariant) {
1127
1244
  const joins = [];
1128
1245
  const projection = [];
1129
1246
  const variantsToJoin = variantName ? polyInfo.mtiVariants.filter((v) => v.modelName === variantName) : polyInfo.mtiVariants;
@@ -1131,19 +1248,19 @@ function buildMtiJoins(contract, namespaceId, polyInfo, variantName, selectedCol
1131
1248
  joins,
1132
1249
  projection
1133
1250
  };
1134
- const pkColumns = resolvePrimaryKeyColumns(contract, namespaceId, polyInfo.baseTable);
1251
+ const { root } = tables;
1252
+ const pkColumns = resolvePrimaryKeyColumns(contract, root.storage.namespaceId, root.storage.tableName);
1135
1253
  for (const variant of variantsToJoin) {
1136
- const joinType = variantName ? "inner" : "left";
1137
- const joinOn = buildPrimaryKeyJoinOn(polyInfo.baseTable, variant.table, pkColumns);
1138
- const join = joinType === "inner" ? JoinAst.inner(tableSourceForContract(contract, namespaceId, variant.table), joinOn) : JoinAst.left(tableSourceForContract(contract, namespaceId, variant.table), joinOn);
1139
- joins.push(join);
1140
- const variantColumns = getColumnsReadOnTable(contract, namespaceId, variant.modelName, variant.table);
1141
- const selectedVariantColumns = selectedColumnsByTable?.get(variant.table);
1254
+ const variantTable = requireVariantTable(tables, variant.modelName);
1255
+ const joinOn = buildPrimaryKeyJoinOn(root, variantTable, pkColumns);
1256
+ joins.push(variantName ? JoinAst.inner(variantTable.tableSource(contract), joinOn) : JoinAst.left(variantTable.tableSource(contract), joinOn));
1257
+ const { namespaceId, tableName } = variantTable.storage;
1258
+ const variantColumns = getColumnsReadOnTable(contract, namespaceId, variant.modelName, tableName);
1259
+ const selectedVariantColumns = selectedColumnsByVariant?.get(variant.modelName);
1142
1260
  for (const col of variantColumns) {
1143
1261
  if (pkColumns.includes(col)) continue;
1144
- if (selectedColumnsByTable !== void 0 && selectedVariantColumns?.has(col) !== true) continue;
1145
- const alias = `${variant.table}__${col}`;
1146
- projection.push(ProjectionItem.of(alias, ColumnRef.of(variant.table, col), codecRefForStorageColumn(contract.storage, namespaceId, variant.table, col)));
1262
+ if (selectedColumnsByVariant !== void 0 && selectedVariantColumns?.has(col) !== true) continue;
1263
+ projection.push(ProjectionItem.of(variantColumnLabel(variantTable, col), variantTable.column(col), codecRefForStorageColumn(contract.storage, namespaceId, tableName, col)));
1147
1264
  }
1148
1265
  }
1149
1266
  return {
@@ -1155,30 +1272,31 @@ function hasEntries(value) {
1155
1272
  return value !== void 0 && value.length > 0;
1156
1273
  }
1157
1274
  /**
1158
- * The rows an aggregate reduces over, one SELECT aliased to `tableName` — an
1275
+ * The rows an aggregate reduces over, one SELECT aliased to the root alias — an
1159
1276
  * aggregate has no outer level of its own, so where/joins/distinct/orderBy/
1160
1277
  * limit/offset all have to live in this one wrap.
1161
1278
  */
1162
- function buildAggregateInput(contract, namespaceId, tableName, state, modelName, projection) {
1163
- const polyInfo = modelName ? resolvePolymorphismInfo(contract, namespaceId, modelName) : void 0;
1164
- const variantJoins = polyInfo && polyInfo.mtiVariants.length > 0 ? buildMtiJoins(contract, namespaceId, polyInfo, state.variantName, void 0).joins : [];
1165
- const where = buildStateWhere(contract, tableName, state, { namespaceId });
1166
- const hiddenOrders = hasEntries(state.distinct) ? projectExpressionOrders(tableName, state.orderBy) : void 0;
1167
- const { source, where: effectiveWhere } = buildDedupedTableSource(contract, namespaceId, tableName, state, where, [...projection, ...hiddenOrders?.projection ?? []], variantJoins);
1279
+ function buildAggregateInput(contract, state, modelName, projection) {
1280
+ const { root } = state.tables;
1281
+ const polyInfo = modelName ? resolvePolymorphismInfo(contract, root.storage.namespaceId, modelName) : void 0;
1282
+ const variantJoins = polyInfo && polyInfo.mtiVariants.length > 0 ? buildMtiJoins(contract, state.tables, polyInfo, state.variantName, void 0).joins : [];
1283
+ const where = buildStateWhere(contract, state);
1284
+ const hiddenOrders = hasEntries(state.distinct) ? projectExpressionOrders(root, state.orderBy) : void 0;
1285
+ const { source, where: effectiveWhere } = buildDedupedTableSource(contract, state, where, [...projection, ...hiddenOrders?.projection ?? []], variantJoins);
1168
1286
  let inner = SelectAst.from(source).withProjection(projection);
1169
1287
  if (!hasEntries(state.distinct) && variantJoins.length > 0) inner = inner.withJoins(variantJoins);
1170
1288
  if (effectiveWhere) inner = inner.withWhere(effectiveWhere);
1171
- if (hasEntries(state.distinctOn)) inner = inner.withDistinctOn(state.distinctOn.map((column) => ColumnRef.of(tableName, column)));
1289
+ if (hasEntries(state.distinctOn)) inner = inner.withDistinctOn(state.distinctOn.map((column) => root.column(column)));
1172
1290
  const orderBy = hiddenOrders?.orderBy ?? state.orderBy;
1173
1291
  if (hasEntries(orderBy)) inner = inner.withOrderBy(orderBy);
1174
1292
  if (state.limit !== void 0) inner = inner.withLimit(state.limit);
1175
1293
  if (state.offset !== void 0) inner = inner.withOffset(state.offset);
1176
- return { source: DerivedTableSource.as(tableName, inner) };
1294
+ return { source: DerivedTableSource.as(root.alias, inner) };
1177
1295
  }
1178
1296
  /**
1179
1297
  * The dedup wrap exposes only its projection, so an order over an expression (a relation order, a count, an operation result) cannot be evaluated above it. Each such order is projected inside the wrap as a hidden `__order_N` column and the outer order reads that column.
1180
1298
  */
1181
- function projectExpressionOrders(tableName, orderBy) {
1299
+ function projectExpressionOrders(root, orderBy) {
1182
1300
  const projection = [];
1183
1301
  return {
1184
1302
  projection,
@@ -1186,7 +1304,7 @@ function projectExpressionOrders(tableName, orderBy) {
1186
1304
  if (item.expr.kind === "column-ref") return item;
1187
1305
  const alias = `__order_${index}`;
1188
1306
  projection.push(ProjectionItem.of(alias, item.expr));
1189
- return item.withExpr(ColumnRef.of(tableName, alias));
1307
+ return item.withExpr(root.column(alias));
1190
1308
  })
1191
1309
  };
1192
1310
  }
@@ -1199,8 +1317,9 @@ function predicateComparison(op, left, right) {
1199
1317
  function predicateExpression(value) {
1200
1318
  if (isExpression(value)) return value.buildAst();
1201
1319
  }
1202
- function emptyState() {
1320
+ function emptyState(tables) {
1203
1321
  return {
1322
+ tables,
1204
1323
  filters: [],
1205
1324
  includes: [],
1206
1325
  orderBy: void 0,
@@ -1300,7 +1419,8 @@ const COMPARISON_METHODS_META = {
1300
1419
  create: (left) => () => NullCheckExpr.isNotNull(left)
1301
1420
  }
1302
1421
  };
1303
- function toAggregateProjection(contract, aggregates, namespaceId, tableName, selector) {
1422
+ function toAggregateProjection(contract, aggregates, root, selector) {
1423
+ const { namespaceId, tableName } = root.storage;
1304
1424
  const { codec, input: inputCodec, lower } = resolveAggregate({
1305
1425
  aggregates,
1306
1426
  contract,
@@ -1309,7 +1429,7 @@ function toAggregateProjection(contract, aggregates, namespaceId, tableName, sel
1309
1429
  fn: selector.fn,
1310
1430
  column: selector.column
1311
1431
  });
1312
- const inputExpr = selector.column === void 0 ? void 0 : ColumnRef.of(tableName, selector.column);
1432
+ const inputExpr = selector.column === void 0 ? void 0 : root.column(selector.column);
1313
1433
  return {
1314
1434
  expr: lower !== void 0 ? lower({
1315
1435
  expr: inputExpr,
@@ -1383,14 +1503,16 @@ function validateGroupedHavingExpr(expr) {
1383
1503
  rawExpr: rejectHavingExpr
1384
1504
  });
1385
1505
  }
1386
- function aggregateInputColumns(tableName, entries, orderBy, groupByColumns = []) {
1506
+ function aggregateInputColumns(root, entries, orderBy, groupByColumns = []) {
1387
1507
  const columns = new Set(groupByColumns);
1388
1508
  for (const [, selector] of entries) if (selector.column !== void 0) columns.add(selector.column);
1389
1509
  for (const item of orderBy ?? []) if (item.expr.kind === "column-ref") columns.add(item.expr.column);
1390
1510
  if (columns.size === 0) return [ProjectionItem.of("__row", LiteralExpr.of(1))];
1391
- return Array.from(columns, (column) => ProjectionItem.of(column, ColumnRef.of(tableName, column)));
1511
+ return Array.from(columns, (column) => ProjectionItem.of(column, root.column(column)));
1392
1512
  }
1393
- function compileAggregate(contract, aggregates, namespaceId, tableName, state, aggregateSpec, modelName) {
1513
+ function compileAggregate(contract, aggregates, state, aggregateSpec, modelName) {
1514
+ const { root } = state.tables;
1515
+ const { namespaceId, tableName } = root.storage;
1394
1516
  const entries = Object.entries(aggregateSpec);
1395
1517
  if (entries.length === 0) throw ormError("ORM.AGGREGATE_SELECTOR_MISSING", "aggregate() requires at least one aggregation selector", { meta: {
1396
1518
  method: "aggregate",
@@ -1404,9 +1526,9 @@ function compileAggregate(contract, aggregates, namespaceId, tableName, state, a
1404
1526
  const hasPagination = state.limit !== void 0 || state.offset !== void 0;
1405
1527
  const hasDistinct = state.distinct !== void 0 && state.distinct.length > 0 || state.distinctOn !== void 0 && state.distinctOn.length > 0;
1406
1528
  if (hasPagination || hasDistinct) {
1407
- const { source } = buildAggregateInput(contract, namespaceId, tableName, state, modelName, aggregateInputColumns(tableName, entries, state.orderBy));
1529
+ const { source } = buildAggregateInput(contract, state, modelName, aggregateInputColumns(root, entries, state.orderBy));
1408
1530
  const projection = entries.map(([alias, selector]) => {
1409
- const { expr, codec } = toAggregateProjection(contract, aggregates, namespaceId, tableName, selector);
1531
+ const { expr, codec } = toAggregateProjection(contract, aggregates, root, selector);
1410
1532
  return ProjectionItem.of(alias, expr, codec);
1411
1533
  });
1412
1534
  const ast = SelectAst.from(source).withProjection(projection);
@@ -1414,19 +1536,21 @@ function compileAggregate(contract, aggregates, namespaceId, tableName, state, a
1414
1536
  return buildOrmQueryPlan(contract, ast, params);
1415
1537
  }
1416
1538
  const polyInfo = modelName ? resolvePolymorphismInfo(contract, namespaceId, modelName) : void 0;
1417
- const variantJoins = polyInfo && polyInfo.mtiVariants.length > 0 ? buildMtiJoins(contract, namespaceId, polyInfo, state.variantName, void 0).joins : [];
1418
- const where = buildStateWhere(contract, tableName, state, { namespaceId });
1539
+ const variantJoins = polyInfo && polyInfo.mtiVariants.length > 0 ? buildMtiJoins(contract, state.tables, polyInfo, state.variantName, void 0).joins : [];
1540
+ const where = buildStateWhere(contract, state);
1419
1541
  const projection = entries.map(([alias, selector]) => {
1420
- const { expr, codec } = toAggregateProjection(contract, aggregates, namespaceId, tableName, selector);
1542
+ const { expr, codec } = toAggregateProjection(contract, aggregates, root, selector);
1421
1543
  return ProjectionItem.of(alias, expr, codec);
1422
1544
  });
1423
- let ast = SelectAst.from(tableSourceForContract(contract, namespaceId, tableName)).withProjection(projection);
1545
+ let ast = SelectAst.from(root.tableSource(contract)).withProjection(projection);
1424
1546
  if (variantJoins.length > 0) ast = ast.withJoins(variantJoins);
1425
1547
  if (where) ast = ast.withWhere(where);
1426
1548
  const { params } = deriveParamsFromAst(ast);
1427
1549
  return buildOrmQueryPlan(contract, ast, params);
1428
1550
  }
1429
- function compileGroupedAggregate(contract, aggregates, namespaceId, tableName, preGroupState, groupByColumns, aggregateSpec, havingExpr, modelName, postGroup = emptyGroupPagingState()) {
1551
+ function compileGroupedAggregate(contract, aggregates, preGroupState, groupByColumns, aggregateSpec, havingExpr, modelName, postGroup = emptyGroupPagingState()) {
1552
+ const { root } = preGroupState.tables;
1553
+ const { namespaceId, tableName } = root.storage;
1430
1554
  if (groupByColumns.length === 0) throw ormError("ORM.GROUP_BY_FIELD_MISSING", "groupBy() requires at least one field", { meta: {
1431
1555
  namespaceId,
1432
1556
  tableName
@@ -1441,8 +1565,8 @@ function compileGroupedAggregate(contract, aggregates, namespaceId, tableName, p
1441
1565
  assertDistinctOnCapability(contract, "distinctOn");
1442
1566
  assertDistinctOnCompatibleOrder(preGroupState.orderBy, preGroupState.distinctOn.length);
1443
1567
  }
1444
- const projection = [...groupByColumns.map((column) => ProjectionItem.of(column, ColumnRef.of(tableName, column), codecRefForStorageColumn(contract.storage, namespaceId, tableName, column))), ...entries.map(([alias, selector]) => {
1445
- const { expr, codec } = toAggregateProjection(contract, aggregates, namespaceId, tableName, selector);
1568
+ const projection = [...groupByColumns.map((column) => ProjectionItem.of(column, root.column(column), codecRefForStorageColumn(contract.storage, namespaceId, tableName, column))), ...entries.map(([alias, selector]) => {
1569
+ const { expr, codec } = toAggregateProjection(contract, aggregates, root, selector);
1446
1570
  return ProjectionItem.of(alias, expr, codec);
1447
1571
  })];
1448
1572
  const hasPagination = preGroupState.limit !== void 0 || preGroupState.offset !== void 0;
@@ -1450,14 +1574,15 @@ function compileGroupedAggregate(contract, aggregates, namespaceId, tableName, p
1450
1574
  const needsInputSelect = hasPagination || hasDistinct;
1451
1575
  let ast;
1452
1576
  if (needsInputSelect) {
1453
- const { source } = buildAggregateInput(contract, namespaceId, tableName, preGroupState, modelName, aggregateInputColumns(tableName, entries, preGroupState.orderBy, groupByColumns));
1454
- ast = SelectAst.from(source).withProjection(projection).withGroupBy(groupByColumns.map((column) => ColumnRef.of(tableName, column)));
1577
+ const { source } = buildAggregateInput(contract, preGroupState, modelName, aggregateInputColumns(root, entries, preGroupState.orderBy, groupByColumns));
1578
+ ast = SelectAst.from(source).withProjection(projection).withGroupBy(groupByColumns.map((column) => root.column(column)));
1455
1579
  } else {
1456
1580
  const polyInfo = modelName ? resolvePolymorphismInfo(contract, namespaceId, modelName) : void 0;
1457
- const variantJoins = polyInfo && polyInfo.mtiVariants.length > 0 ? buildMtiJoins(contract, namespaceId, polyInfo, preGroupState.variantName, void 0).joins : [];
1458
- ast = SelectAst.from(tableSourceForContract(contract, namespaceId, tableName)).withProjection(projection).withGroupBy(groupByColumns.map((column) => ColumnRef.of(tableName, column)));
1581
+ const { tables, variantName } = preGroupState;
1582
+ const variantJoins = polyInfo && polyInfo.mtiVariants.length > 0 ? buildMtiJoins(contract, tables, polyInfo, variantName, void 0).joins : [];
1583
+ ast = SelectAst.from(root.tableSource(contract)).withProjection(projection).withGroupBy(groupByColumns.map((column) => root.column(column)));
1459
1584
  if (variantJoins.length > 0) ast = ast.withJoins(variantJoins);
1460
- const where = buildStateWhere(contract, tableName, preGroupState, { namespaceId });
1585
+ const where = buildStateWhere(contract, preGroupState);
1461
1586
  if (where) ast = ast.withWhere(where);
1462
1587
  }
1463
1588
  if (havingExpr) ast = ast.withHaving(validateGroupedHavingExpr(havingExpr));
@@ -1467,8 +1592,15 @@ function compileGroupedAggregate(contract, aggregates, namespaceId, tableName, p
1467
1592
  const { params } = deriveParamsFromAst(ast);
1468
1593
  return buildOrmQueryPlan(contract, ast, params);
1469
1594
  }
1470
- function buildReturningColumns(contract, namespaceId, modelName, tableName, returningColumns) {
1471
- 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)));
1595
+ function aliasTarget(namespaceId, tableName) {
1596
+ return createTableScope().aliasTable({
1597
+ namespaceId,
1598
+ tableName
1599
+ });
1600
+ }
1601
+ function buildReturningColumns(contract, modelName, target, returningColumns) {
1602
+ const { namespaceId, tableName } = target.storage;
1603
+ return (returningColumns && returningColumns.length > 0 ? [...returningColumns] : getColumnsReadOnTable(contract, namespaceId, modelName, tableName)).map((column) => ProjectionItem.of(column, target.column(column), codecRefForStorageColumn(contract.storage, namespaceId, tableName, column)));
1472
1604
  }
1473
1605
  function toParamAssignments(contract, namespaceId, tableName, values) {
1474
1606
  const assignments = {};
@@ -1519,20 +1651,22 @@ function normalizeInsertRows(contract, namespaceId, tableName, rows) {
1519
1651
  return normalizedRow;
1520
1652
  }) };
1521
1653
  }
1522
- function conflictSkipClause(tableName, conflictSkip) {
1654
+ function conflictSkipClause(target, conflictSkip) {
1523
1655
  if (!conflictSkip) return void 0;
1524
1656
  if (conflictSkip.columns.length === 0) return InsertOnConflict.doNothing();
1525
- return InsertOnConflict.on(conflictSkip.columns.map((column) => ColumnRef.of(tableName, column))).doNothing();
1657
+ return InsertOnConflict.on(conflictSkip.columns.map((column) => target.column(column))).doNothing();
1526
1658
  }
1527
1659
  function compileInsertReturning(contract, namespaceId, modelName, tableName, rows, returningColumns, conflictSkip) {
1660
+ const target = aliasTarget(namespaceId, tableName);
1528
1661
  const { rows: normalizedRows } = normalizeInsertRows(contract, namespaceId, tableName, rows);
1529
- const ast = InsertAst.into(tableSourceForContract(contract, namespaceId, tableName)).withRows(normalizedRows).withOnConflict(conflictSkipClause(tableName, conflictSkip)).withReturning(buildReturningColumns(contract, namespaceId, modelName, tableName, returningColumns));
1662
+ const ast = InsertAst.into(target.tableSource(contract)).withRows(normalizedRows).withOnConflict(conflictSkipClause(target, conflictSkip)).withReturning(buildReturningColumns(contract, modelName, target, returningColumns));
1530
1663
  const { params } = deriveParamsFromAst(ast);
1531
1664
  return buildOrmQueryPlan(contract, ast, params);
1532
1665
  }
1533
1666
  function compileInsertCount(contract, namespaceId, tableName, rows, conflictSkip) {
1667
+ const target = aliasTarget(namespaceId, tableName);
1534
1668
  const { rows: normalizedRows } = normalizeInsertRows(contract, namespaceId, tableName, rows);
1535
- const ast = InsertAst.into(tableSourceForContract(contract, namespaceId, tableName)).withRows(normalizedRows).withOnConflict(conflictSkipClause(tableName, conflictSkip));
1669
+ const ast = InsertAst.into(target.tableSource(contract)).withRows(normalizedRows).withOnConflict(conflictSkipClause(target, conflictSkip));
1536
1670
  const { params } = deriveParamsFromAst(ast);
1537
1671
  return buildOrmQueryPlan(contract, ast, params);
1538
1672
  }
@@ -1541,29 +1675,14 @@ function stripUndefinedValues(row) {
1541
1675
  for (const [key, value] of Object.entries(row)) if (value !== void 0) result[key] = value;
1542
1676
  return result;
1543
1677
  }
1544
- function createTableRefRemapper(fromTable, toTable) {
1545
- return {
1546
- columnRef: (col) => col.table === fromTable ? ColumnRef.of(toTable, col.column) : col,
1547
- tableSource: (source) => {
1548
- if (source.alias === fromTable) return TableSource.named(source.name, toTable, source.namespaceId);
1549
- if (!source.alias && source.name === fromTable) return TableSource.named(source.name, toTable, source.namespaceId);
1550
- return source;
1551
- },
1552
- eqColJoinOn: (on) => EqColJoinOn.of(on.left.table === fromTable ? ColumnRef.of(toTable, on.left.column) : on.left, on.right.table === fromTable ? ColumnRef.of(toTable, on.right.column) : on.right)
1553
- };
1554
- }
1555
- function buildCountMutationWhere(contract, namespaceId, tableName, filters, variantName, modelName) {
1556
- if (!variantName || !modelName) return combineWhereExprs(filters);
1557
- const polyInfo = resolvePolymorphismInfo(contract, namespaceId, modelName);
1558
- const variant = polyInfo?.variants.get(variantName);
1559
- if (!polyInfo || !variant || variant.strategy !== "mti") return combineWhereExprs(filters);
1560
- const pkColumns = resolvePrimaryKeyColumns(contract, namespaceId, tableName);
1561
- const baseTableRef = `${tableName}__write_filter`;
1562
- const remapper = createTableRefRemapper(tableName, baseTableRef);
1563
- const innerFilters = filters.map((filter) => filter.rewrite(remapper));
1564
- const where = combineWhereExprs([...pkColumns.map((column) => BinaryExpr.eq(ColumnRef.of(baseTableRef, column), ColumnRef.of(tableName, column))), ...innerFilters]);
1565
- const joinOn = buildPrimaryKeyJoinOn(baseTableRef, variant.table, pkColumns);
1566
- let subquery = SelectAst.from(TableSource.named(tableName, baseTableRef, namespaceId)).withProjection(pkColumns.map((column) => ProjectionItem.of(column, ColumnRef.of(baseTableRef, column)))).withJoins([JoinAst.inner(tableSourceForContract(contract, namespaceId, variant.table), joinOn)]);
1678
+ function buildCountMutationWhere(contract, tables, filters, variantName) {
1679
+ const variantTable = variantName === void 0 ? void 0 : tables.variants.get(variantName);
1680
+ if (variantTable === void 0) return combineWhereExprs(filters);
1681
+ const { root } = tables;
1682
+ const pkColumns = resolvePrimaryKeyColumns(contract, root.storage.namespaceId, root.storage.tableName);
1683
+ const rootCopy = tables.scope.copy().aliasTable(root.storage);
1684
+ const where = combineWhereExprs([...pkColumns.map((column) => BinaryExpr.eq(rootCopy.column(column), root.column(column))), ...filters]);
1685
+ let subquery = SelectAst.from(rootCopy.tableSource(contract)).withProjection(pkColumns.map((column) => ProjectionItem.of(column, rootCopy.column(column)))).withJoins([JoinAst.inner(variantTable.tableSource(contract), buildPrimaryKeyJoinOn(rootCopy, variantTable, pkColumns))]);
1567
1686
  if (where) subquery = subquery.withWhere(where);
1568
1687
  return ExistsExpr.exists(subquery);
1569
1688
  }
@@ -1602,37 +1721,44 @@ function compileInsertCountSplit(contract, namespaceId, tableName, rows, conflic
1602
1721
  function compileUpsertReturning(contract, namespaceId, modelName, tableName, createValues, updateValues, conflictColumns, returningColumns) {
1603
1722
  const createAssignments = toParamAssignments(contract, namespaceId, tableName, createValues);
1604
1723
  const updateAssignments = Object.keys(updateValues).length > 0 ? toParamAssignments(contract, namespaceId, tableName, updateValues) : void 0;
1605
- 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();
1606
- const ast = InsertAst.into(tableSourceForContract(contract, namespaceId, tableName)).withRows([createAssignments.assignments]).withOnConflict(onConflict).withReturning(buildReturningColumns(contract, namespaceId, modelName, tableName, returningColumns));
1724
+ const target = aliasTarget(namespaceId, tableName);
1725
+ const conflictTarget = InsertOnConflict.on(conflictColumns.map((column) => target.column(column)));
1726
+ const onConflict = updateAssignments ? conflictTarget.doUpdateSet(updateAssignments.assignments) : conflictTarget.doNothing();
1727
+ const ast = InsertAst.into(target.tableSource(contract)).withRows([createAssignments.assignments]).withOnConflict(onConflict).withReturning(buildReturningColumns(contract, modelName, target, returningColumns));
1607
1728
  const { params } = deriveParamsFromAst(ast);
1608
1729
  return buildOrmQueryPlan(contract, ast, params);
1609
1730
  }
1610
- function compileUpdateReturning(contract, namespaceId, modelName, tableName, setValues, filters, returningColumns) {
1731
+ function compileUpdateReturning(contract, modelName, tables, setValues, filters, returningColumns) {
1732
+ const { root } = tables;
1733
+ const { namespaceId, tableName } = root.storage;
1611
1734
  const where = combineWhereExprs(filters);
1612
1735
  const { assignments } = toParamAssignments(contract, namespaceId, tableName, setValues);
1613
- let ast = UpdateAst.table(tableSourceForContract(contract, namespaceId, tableName)).withSet(assignments).withReturning(buildReturningColumns(contract, namespaceId, modelName, tableName, returningColumns));
1736
+ let ast = UpdateAst.table(root.tableSource(contract)).withSet(assignments).withReturning(buildReturningColumns(contract, modelName, root, returningColumns));
1614
1737
  if (where) ast = ast.withWhere(where);
1615
1738
  const { params } = deriveParamsFromAst(ast);
1616
1739
  return buildOrmQueryPlan(contract, ast, params);
1617
1740
  }
1618
- function compileUpdateCount(contract, namespaceId, tableName, setValues, filters, variantName, modelName) {
1619
- const where = buildCountMutationWhere(contract, namespaceId, tableName, filters, variantName, modelName);
1741
+ function compileUpdateCount(contract, tables, setValues, filters, variantName) {
1742
+ const { root } = tables;
1743
+ const { namespaceId, tableName } = root.storage;
1744
+ const where = buildCountMutationWhere(contract, tables, filters, variantName);
1620
1745
  const { assignments } = toParamAssignments(contract, namespaceId, tableName, setValues);
1621
- let ast = UpdateAst.table(tableSourceForContract(contract, namespaceId, tableName)).withSet(assignments);
1746
+ let ast = UpdateAst.table(root.tableSource(contract)).withSet(assignments);
1622
1747
  if (where) ast = ast.withWhere(where);
1623
1748
  const { params } = deriveParamsFromAst(ast);
1624
1749
  return buildOrmQueryPlan(contract, ast, params);
1625
1750
  }
1626
- function compileDeleteReturning(contract, namespaceId, modelName, tableName, filters, returningColumns) {
1751
+ function compileDeleteReturning(contract, modelName, tables, filters, returningColumns) {
1752
+ const { root } = tables;
1627
1753
  const where = combineWhereExprs(filters);
1628
- let ast = DeleteAst.from(tableSourceForContract(contract, namespaceId, tableName)).withReturning(buildReturningColumns(contract, namespaceId, modelName, tableName, returningColumns));
1754
+ let ast = DeleteAst.from(root.tableSource(contract)).withReturning(buildReturningColumns(contract, modelName, root, returningColumns));
1629
1755
  if (where) ast = ast.withWhere(where);
1630
1756
  const { params } = deriveParamsFromAst(ast);
1631
1757
  return buildOrmQueryPlan(contract, ast, params);
1632
1758
  }
1633
- function compileDeleteCount(contract, namespaceId, tableName, filters, variantName, modelName) {
1634
- const where = buildCountMutationWhere(contract, namespaceId, tableName, filters, variantName, modelName);
1635
- let ast = DeleteAst.from(tableSourceForContract(contract, namespaceId, tableName));
1759
+ function compileDeleteCount(contract, tables, filters, variantName) {
1760
+ const where = buildCountMutationWhere(contract, tables, filters, variantName);
1761
+ let ast = DeleteAst.from(tables.root.tableSource(contract));
1636
1762
  if (where) ast = ast.withWhere(where);
1637
1763
  const { params } = deriveParamsFromAst(ast);
1638
1764
  return buildOrmQueryPlan(contract, ast, params);
@@ -1706,8 +1832,9 @@ function jsonEntryProjection(value, identity) {
1706
1832
  if (identity.document === true) return new JsonDocumentProjection(value);
1707
1833
  return new NativeJsonValueProjection(value);
1708
1834
  }
1709
- function buildProjection(contract, namespaceId, modelName, tableName, selectedFields, tableRef = tableName) {
1710
- 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)));
1835
+ function buildProjection(contract, modelName, table, selectedFields, projectedThrough) {
1836
+ const { namespaceId, tableName } = table.storage;
1837
+ return (selectedFields !== void 0 ? [...selectedFields] : getColumnsReadOnTable(contract, namespaceId, modelName, tableName)).map((column) => ProjectionItem.of(column, projectedThrough === void 0 ? table.column(column) : ColumnRef.of(projectedThrough, column), codecRefForStorageColumn(contract.storage, namespaceId, tableName, column)));
1711
1838
  }
1712
1839
  function appendUnique(values, value) {
1713
1840
  if (!values.includes(value)) values.push(value);
@@ -1715,7 +1842,7 @@ function appendUnique(values, value) {
1715
1842
  function resolvePolymorphicProjectionSelection(contract, namespaceId, modelName, polyInfo, state) {
1716
1843
  if (state.selectedFields === void 0) return {
1717
1844
  baseSelectedFields: void 0,
1718
- selectedMtiColumnsByTable: void 0,
1845
+ selectedMtiColumnsByVariant: void 0,
1719
1846
  needsHiddenDiscriminator: false
1720
1847
  };
1721
1848
  const baseColumnToField = getModelColumnFields(contract, namespaceId, modelName);
@@ -1724,7 +1851,7 @@ function resolvePolymorphicProjectionSelection(contract, namespaceId, modelName,
1724
1851
  columnToField: getOwnColumnFields(contract, namespaceId, variant.modelName)
1725
1852
  }));
1726
1853
  const baseSelectedFields = [];
1727
- const selectedMtiColumnsByTable = /* @__PURE__ */ new Map();
1854
+ const selectedMtiColumnsByVariant = /* @__PURE__ */ new Map();
1728
1855
  let hasVariantOwnedSelection = false;
1729
1856
  for (const column of state.selectedFields) {
1730
1857
  const isBaseColumn = Object.hasOwn(baseColumnToField, column);
@@ -1738,10 +1865,10 @@ function resolvePolymorphicProjectionSelection(contract, namespaceId, modelName,
1738
1865
  appendUnique(baseSelectedFields, column);
1739
1866
  continue;
1740
1867
  }
1741
- let selectedColumns = selectedMtiColumnsByTable.get(variant.table);
1868
+ let selectedColumns = selectedMtiColumnsByVariant.get(variant.modelName);
1742
1869
  if (selectedColumns === void 0) {
1743
1870
  selectedColumns = /* @__PURE__ */ new Set();
1744
- selectedMtiColumnsByTable.set(variant.table, selectedColumns);
1871
+ selectedMtiColumnsByVariant.set(variant.modelName, selectedColumns);
1745
1872
  }
1746
1873
  selectedColumns.add(column);
1747
1874
  }
@@ -1749,13 +1876,13 @@ function resolvePolymorphicProjectionSelection(contract, namespaceId, modelName,
1749
1876
  }
1750
1877
  return {
1751
1878
  baseSelectedFields,
1752
- selectedMtiColumnsByTable,
1879
+ selectedMtiColumnsByVariant,
1753
1880
  needsHiddenDiscriminator: state.variantName === void 0 && hasVariantOwnedSelection && !baseSelectedFields.includes(polyInfo.discriminatorColumn)
1754
1881
  };
1755
1882
  }
1756
- function buildHiddenDiscriminatorProjection(contract, namespaceId, polyInfo, tableRef, needed) {
1883
+ function buildHiddenDiscriminatorProjection(contract, table, polyInfo, needed) {
1757
1884
  if (!needed) return [];
1758
- return [ProjectionItem.of(POLYMORPHIC_DISCRIMINATOR_ALIAS, ColumnRef.of(tableRef, polyInfo.discriminatorColumn), codecRefForStorageColumn(contract.storage, namespaceId, polyInfo.baseTable, polyInfo.discriminatorColumn))];
1885
+ return [ProjectionItem.of(POLYMORPHIC_DISCRIMINATOR_ALIAS, table.column(polyInfo.discriminatorColumn), codecRefForStorageColumn(contract.storage, table.storage.namespaceId, table.storage.tableName, polyInfo.discriminatorColumn))];
1759
1886
  }
1760
1887
  function buildIncludeOrderArtifacts(relationName, rowAlias, childOrderBy) {
1761
1888
  if (!childOrderBy || childOrderBy.length === 0) return {
@@ -1777,41 +1904,34 @@ function buildIncludeOrderArtifacts(relationName, rowAlias, childOrderBy) {
1777
1904
  function localColumnsForRowInclude(include) {
1778
1905
  return include.through?.parentLocalColumns ?? include.localColumns;
1779
1906
  }
1780
- function buildIncludeJoinExpr(include, childTableRef, parentLocalRefs) {
1907
+ function buildIncludeJoinExpr(include, child, parentLocalRefs) {
1781
1908
  invariant(parentLocalRefs.length === include.targetColumns.length, `Include '${include.relationName}' has mismatched join column counts: ${parentLocalRefs.length} local, ${include.targetColumns.length} target`);
1782
1909
  const joinExprs = include.targetColumns.map((targetColumn, i) => {
1783
1910
  const parentLocalRef = parentLocalRefs[i];
1784
1911
  assertDefined(parentLocalRef, `Include '${include.relationName}': no local column at ${i}`);
1785
- return BinaryExpr.eq(ColumnRef.of(childTableRef, targetColumn), parentLocalRef);
1912
+ return BinaryExpr.eq(child.column(targetColumn), parentLocalRef);
1786
1913
  });
1787
1914
  const [firstExpr] = joinExprs;
1788
1915
  assertDefined(firstExpr, `Include '${include.relationName}' has no join columns`);
1789
1916
  return joinExprs.length === 1 ? firstExpr : AndExpr.of(joinExprs);
1790
1917
  }
1791
- function resolveParentLocalRefs(parentSource, include, localColumns) {
1918
+ function localTable(tables, include) {
1919
+ return include.localVariantName === void 0 ? tables.root : requireVariantTable(tables, include.localVariantName);
1920
+ }
1921
+ function resolveParentLocalRefs(parent, include, localColumns) {
1922
+ const local = localTable(parent.tables, include);
1923
+ const { projectedThrough } = parent;
1792
1924
  return localColumns.map((column) => {
1793
- if (include.localTableName === parentSource.baseTableName) return ColumnRef.of(parentSource.tableRef, column);
1794
- if (parentSource.variantColumnsProjected) return ColumnRef.of(parentSource.tableRef, `${include.localTableName}__${column}`);
1795
- return ColumnRef.of(include.localTableName, column);
1925
+ if (projectedThrough === void 0) return local.column(column);
1926
+ return ColumnRef.of(projectedThrough, local === parent.tables.root ? column : variantColumnLabel(local, column));
1796
1927
  });
1797
1928
  }
1798
- function resolveChildTableSource(include, parentLocalRefs) {
1799
- const alias = parentLocalRefs.some((ref) => ref.table === include.relatedTableName) ? `${include.relationName}__child` : void 0;
1800
- return {
1801
- alias,
1802
- tableRef: alias ?? include.relatedTableName
1803
- };
1929
+ function requireJunction(include) {
1930
+ if (include.junction === void 0) throw new InternalError(`Include '${include.relationName}' goes through a junction table but carries no aliased table for it`);
1931
+ return include.junction;
1804
1932
  }
1805
- /**
1806
- * Recursively build the correlated-subquery projections for the nested
1807
- * includes attached to a child SELECT. Used by `buildIncludeChildRowsSelect`
1808
- * to wire depth-2+ aggregates into the inner SELECT at each level.
1809
- *
1810
- * Each nested include contributes a single projection item whose
1811
- * expression is a correlated subquery.
1812
- */
1813
- function buildNestedIncludeProjections(contract, aggregates, parentSource, includes) {
1814
- return includes.map((nested) => buildCorrelatedIncludeProjection(contract, aggregates, parentSource, nested).projection);
1933
+ function buildNestedIncludeProjections(contract, aggregates, scope, parent, includes) {
1934
+ return includes.map((nested) => buildCorrelatedIncludeProjection(contract, aggregates, scope, parent, nested).projection);
1815
1935
  }
1816
1936
  /**
1817
1937
  * The aliases a level's nested includes contribute. Each such subquery
@@ -1829,13 +1949,8 @@ function documentAliasesOf(nestedProjections) {
1829
1949
  * variant-specific columns live on the base table and reach the row through
1830
1950
  * the ordinary base-column projection (`buildProjection`); only the MTI
1831
1951
  * variant tables need a join.
1832
- *
1833
- * When the child base table is aliased (self-relations), `buildMtiJoins`
1834
- * emits a join `ON` against the unaliased base table name, which would fall
1835
- * out of scope. Remap it to the child alias — the same remap the row builder
1836
- * already applies to `orderBy`/`where`.
1837
1952
  */
1838
- function buildChildPolymorphismJoinsAndProjection(contract, include, childTableAlias, childTableRef) {
1953
+ function buildChildPolymorphismJoinsAndProjection(contract, include) {
1839
1954
  const polyInfo = resolvePolymorphismInfo(contract, include.relatedNamespaceId, include.relatedModelName);
1840
1955
  if (!polyInfo) return {
1841
1956
  joins: [],
@@ -1844,35 +1959,25 @@ function buildChildPolymorphismJoinsAndProjection(contract, include, childTableA
1844
1959
  baseSelectedFields: include.nested.selectedFields
1845
1960
  };
1846
1961
  const selection = resolvePolymorphicProjectionSelection(contract, include.relatedNamespaceId, include.relatedModelName, polyInfo, include.nested);
1847
- const { joins, projection } = buildMtiJoins(contract, include.relatedNamespaceId, polyInfo, include.nested.variantName, selection.selectedMtiColumnsByTable);
1848
- const hiddenProjection = buildHiddenDiscriminatorProjection(contract, include.relatedNamespaceId, polyInfo, childTableRef, selection.needsHiddenDiscriminator);
1849
- if (!childTableAlias) return {
1850
- joins,
1851
- projection,
1852
- hiddenProjection,
1853
- baseSelectedFields: selection.baseSelectedFields
1854
- };
1855
- const remapper = createTableRefRemapper$1(polyInfo.baseTable, childTableRef);
1962
+ const { joins, projection } = buildMtiJoins(contract, include.nested.tables, polyInfo, include.nested.variantName, selection.selectedMtiColumnsByVariant);
1856
1963
  return {
1857
- joins: joins.map((join) => join.rewrite(remapper)),
1964
+ joins,
1858
1965
  projection,
1859
- hiddenProjection,
1966
+ hiddenProjection: buildHiddenDiscriminatorProjection(contract, include.nested.tables.root, polyInfo, selection.needsHiddenDiscriminator),
1860
1967
  baseSelectedFields: selection.baseSelectedFields
1861
1968
  };
1862
1969
  }
1863
1970
  function buildRequiredMtiJoinKeyProjection(contract, include) {
1864
- const polyInfo = resolvePolymorphismInfo(contract, include.relatedNamespaceId, include.relatedModelName);
1865
- if (!polyInfo) return [];
1866
- const mtiTables = new Set(polyInfo.mtiVariants.map((variant) => variant.table));
1867
1971
  const aliases = /* @__PURE__ */ new Set();
1868
1972
  const projection = [];
1869
1973
  for (const nested of include.nested.includes) {
1870
- if (!mtiTables.has(nested.localTableName)) continue;
1974
+ if (nested.localVariantName === void 0) continue;
1975
+ const variantTable = requireVariantTable(include.nested.tables, nested.localVariantName);
1871
1976
  for (const column of localColumnsForRowInclude(nested)) {
1872
- const alias = `${nested.localTableName}__${column}`;
1977
+ const alias = variantColumnLabel(variantTable, column);
1873
1978
  if (aliases.has(alias)) continue;
1874
1979
  aliases.add(alias);
1875
- projection.push(ProjectionItem.of(alias, ColumnRef.of(nested.localTableName, column), codecRefForStorageColumn(contract.storage, include.relatedNamespaceId, nested.localTableName, column)));
1980
+ projection.push(ProjectionItem.of(alias, variantTable.column(column), codecRefForStorageColumn(contract.storage, variantTable.storage.namespaceId, variantTable.storage.tableName, column)));
1876
1981
  }
1877
1982
  }
1878
1983
  return projection;
@@ -1892,61 +1997,54 @@ function mergeProjectionByAlias(projection, additional) {
1892
1997
  * (AND-ed across all column pairs for composite keys). The junction JOIN
1893
1998
  * connects child rows to the junction via the child columns.
1894
1999
  */
1895
- function buildManyToManyJunctionArtifacts(parentLocalRefs, childTableRef, through) {
1896
- const { table: junctionTable, parentColumns, childColumns, targetColumns, namespaceId } = through;
2000
+ function buildManyToManyJunctionArtifacts(contract, parentLocalRefs, child, junction, through) {
2001
+ const { table: junctionTable, parentColumns, childColumns, targetColumns } = through;
1897
2002
  invariant(childColumns.length === targetColumns.length, `M:N junction '${junctionTable}': childColumns (${childColumns.length}) and targetColumns (${targetColumns.length}) must have equal length`);
1898
2003
  invariant(parentColumns.length === parentLocalRefs.length, `M:N junction '${junctionTable}': parentColumns (${parentColumns.length}) and parentLocalColumns (${parentLocalRefs.length}) must have equal length`);
1899
2004
  const joinOnPairs = childColumns.map((junctionCol, i) => {
1900
2005
  const targetCol = targetColumns[i];
1901
2006
  assertDefined(targetCol, `M:N junction '${junctionTable}': missing target column at index ${i}`);
1902
- return BinaryExpr.eq(ColumnRef.of(junctionTable, junctionCol), ColumnRef.of(childTableRef, targetCol));
2007
+ return BinaryExpr.eq(junction.column(junctionCol), child.column(targetCol));
1903
2008
  });
1904
2009
  const firstJoinPair = joinOnPairs[0];
1905
2010
  const joinOn = joinOnPairs.length === 1 && firstJoinPair ? firstJoinPair : AndExpr.of(joinOnPairs);
1906
2011
  const correlationPairs = parentColumns.map((junctionCol, i) => {
1907
2012
  const parentLocalRef = parentLocalRefs[i];
1908
2013
  assertDefined(parentLocalRef, `M:N junction '${junctionTable}': missing parent-local column ref at index ${i}`);
1909
- return BinaryExpr.eq(ColumnRef.of(junctionTable, junctionCol), parentLocalRef);
2014
+ return BinaryExpr.eq(junction.column(junctionCol), parentLocalRef);
1910
2015
  });
1911
2016
  const firstCorrelationPair = correlationPairs[0];
1912
2017
  return {
1913
2018
  whereExpr: correlationPairs.length === 1 && firstCorrelationPair ? firstCorrelationPair : AndExpr.of(correlationPairs),
1914
- junctionJoin: JoinAst.inner(TableSource.named(junctionTable, void 0, namespaceId), joinOn, false)
2019
+ junctionJoin: JoinAst.inner(junction.tableSource(contract), joinOn, false)
1915
2020
  };
1916
2021
  }
1917
- function buildIncludeChildRowsSelect(contract, aggregates, parentSource, include) {
2022
+ function buildIncludeChildRowsSelect(contract, aggregates, scope, parent, include) {
1918
2023
  const childState = include.nested;
1919
2024
  if (childState.distinctOn !== void 0 && childState.distinctOn.length > 0) {
1920
2025
  assertDistinctOnCapability(contract, "distinctOn");
1921
2026
  assertDistinctOnCompatibleOrder(childState.orderBy, childState.distinctOn.length);
1922
2027
  }
1923
- const parentLocalRefs = resolveParentLocalRefs(parentSource, include, localColumnsForRowInclude(include));
1924
- const childSource = resolveChildTableSource(include, parentLocalRefs);
1925
- const childTableAlias = childSource.alias;
1926
- const childTableRef = childSource.tableRef;
1927
- const rowsAlias = `${include.relationName}__rows`;
1928
- const remappedChildOrderBy = childTableAlias && childState.orderBy ? childState.orderBy.map((item) => item.rewrite(createTableRefRemapper$1(include.relatedTableName, childTableRef))) : childState.orderBy;
1929
- const { childOrderBy, hiddenOrderProjection, aggregateOrderBy } = buildIncludeOrderArtifacts(include.relationName, rowsAlias, remappedChildOrderBy);
1930
- const childWhere = buildStateWhere(contract, childTableRef, childState, {
1931
- filterTableName: include.relatedTableName,
1932
- namespaceId: include.relatedNamespaceId
1933
- });
2028
+ const child = childState.tables.root;
2029
+ const parentLocalRefs = resolveParentLocalRefs(parent, include, localColumnsForRowInclude(include));
2030
+ const rowsAlias = scope.alias(`${include.relationName}__rows`);
2031
+ const { childOrderBy, hiddenOrderProjection, aggregateOrderBy } = buildIncludeOrderArtifacts(include.relationName, rowsAlias, childState.orderBy);
2032
+ const childWhere = buildStateWhere(contract, childState);
1934
2033
  let whereExpr;
1935
2034
  let junctionJoins = [];
1936
2035
  if (include.through !== void 0) {
1937
- const artifacts = buildManyToManyJunctionArtifacts(parentLocalRefs, childTableRef, include.through);
2036
+ const artifacts = buildManyToManyJunctionArtifacts(contract, parentLocalRefs, child, requireJunction(include), include.through);
1938
2037
  whereExpr = childWhere ? AndExpr.of([artifacts.whereExpr, childWhere]) : artifacts.whereExpr;
1939
2038
  junctionJoins = [artifacts.junctionJoin];
1940
2039
  } else {
1941
- const joinExpr = buildIncludeJoinExpr(include, childTableRef, parentLocalRefs);
2040
+ const joinExpr = buildIncludeJoinExpr(include, child, parentLocalRefs);
1942
2041
  whereExpr = childWhere ? AndExpr.of([joinExpr, childWhere]) : joinExpr;
1943
2042
  }
1944
2043
  if (childState.distinct !== void 0 && childState.distinct.length > 0 && childState.includes.length > 0) return buildDistinctNonLeafChildRowsSelect({
1945
2044
  contract,
1946
2045
  aggregates,
2046
+ scope,
1947
2047
  include,
1948
- childTableAlias,
1949
- childTableRef,
1950
2048
  rowsAlias,
1951
2049
  childOrderBy,
1952
2050
  hiddenOrderProjection,
@@ -1954,30 +2052,26 @@ function buildIncludeChildRowsSelect(contract, aggregates, parentSource, include
1954
2052
  whereExpr,
1955
2053
  junctionJoins
1956
2054
  });
1957
- const polyJoinsAndProjection = buildChildPolymorphismJoinsAndProjection(contract, include, childTableAlias, childTableRef);
1958
- const scalarProjection = buildProjection(contract, include.relatedNamespaceId, addressedModelName(include.relatedModelName, include.nested.variantName), include.relatedTableName, polyJoinsAndProjection.baseSelectedFields, childTableRef);
1959
- const nestedProjections = buildNestedIncludeProjections(contract, aggregates, {
1960
- baseTableName: include.relatedTableName,
1961
- tableRef: childTableRef,
1962
- variantColumnsProjected: false
1963
- }, childState.includes);
2055
+ const polyJoinsAndProjection = buildChildPolymorphismJoinsAndProjection(contract, include);
2056
+ const scalarProjection = buildProjection(contract, addressedModelName(include.relatedModelName, include.nested.variantName), child, polyJoinsAndProjection.baseSelectedFields);
2057
+ const nestedProjections = buildNestedIncludeProjections(contract, aggregates, scope, { tables: childState.tables }, childState.includes);
1964
2058
  const childProjection = [
1965
2059
  ...scalarProjection,
1966
2060
  ...polyJoinsAndProjection.projection,
1967
2061
  ...polyJoinsAndProjection.hiddenProjection,
1968
2062
  ...nestedProjections
1969
2063
  ];
1970
- let childRows = SelectAst.from(tableSourceForContract(contract, include.relatedNamespaceId, include.relatedTableName, childTableAlias)).withProjection([...childProjection, ...hiddenOrderProjection]).withWhere(whereExpr);
2064
+ let childRows = SelectAst.from(child.tableSource(contract)).withProjection([...childProjection, ...hiddenOrderProjection]).withWhere(whereExpr);
1971
2065
  if (polyJoinsAndProjection.joins.length > 0) childRows = childRows.withJoins([...polyJoinsAndProjection.joins]);
1972
2066
  if (junctionJoins.length > 0) childRows = childRows.withJoins(junctionJoins);
1973
2067
  if (childState.distinctOn && childState.distinctOn.length > 0) {
1974
- childRows = childRows.withDistinctOn(childState.distinctOn.map((column) => ColumnRef.of(childTableRef, column)));
2068
+ childRows = childRows.withDistinctOn(childState.distinctOn.map((column) => child.column(column)));
1975
2069
  if (childOrderBy) childRows = childRows.withOrderBy(childOrderBy);
1976
2070
  } else if (childState.distinct && childState.distinct.length > 0) {
1977
- const rankedAlias = `${include.relationName}__distinct`;
2071
+ const rankedAlias = scope.alias(`${include.relationName}__distinct`);
1978
2072
  childRows = wrapWithRowNumberDedup({
1979
2073
  base: childRows,
1980
- distinctColumnRefs: childState.distinct.map((column) => ColumnRef.of(childTableRef, column)),
2074
+ distinctColumnRefs: childState.distinct.map((column) => child.column(column)),
1981
2075
  rankingOrderBy: childOrderBy ?? [],
1982
2076
  rankedAlias
1983
2077
  });
@@ -1994,21 +2088,22 @@ function buildIncludeChildRowsSelect(contract, aggregates, parentSource, include
1994
2088
  };
1995
2089
  }
1996
2090
  function buildDistinctNonLeafChildRowsSelect(options) {
1997
- const { contract, aggregates, include, childTableAlias, childTableRef, rowsAlias, childOrderBy, hiddenOrderProjection, aggregateOrderBy, whereExpr, junctionJoins } = options;
2091
+ const { contract, aggregates, scope, include, rowsAlias, childOrderBy, hiddenOrderProjection, aggregateOrderBy, whereExpr, junctionJoins } = options;
1998
2092
  const childState = include.nested;
1999
- const grandchildJoinColumns = Array.from(new Set(childState.includes.flatMap((nested) => nested.localTableName === include.relatedTableName ? localColumnsForRowInclude(nested) : [])));
2093
+ const child = childState.tables.root;
2094
+ const grandchildJoinColumns = Array.from(new Set(childState.includes.flatMap((nested) => nested.localVariantName === void 0 ? localColumnsForRowInclude(nested) : [])));
2000
2095
  const { selectedForQuery } = augmentSelectionForJoinColumns(childState.selectedFields, grandchildJoinColumns);
2001
- const visiblePolyProjection = buildChildPolymorphismJoinsAndProjection(contract, include, childTableAlias, childTableRef);
2096
+ const visiblePolyProjection = buildChildPolymorphismJoinsAndProjection(contract, include);
2002
2097
  const queryPolyProjection = buildChildPolymorphismJoinsAndProjection(contract, {
2003
2098
  ...include,
2004
2099
  nested: {
2005
2100
  ...childState,
2006
2101
  selectedFields: selectedForQuery
2007
2102
  }
2008
- }, childTableAlias, childTableRef);
2009
- const innerScalarProjection = buildProjection(contract, include.relatedNamespaceId, addressedModelName(include.relatedModelName, include.nested.variantName), include.relatedTableName, queryPolyProjection.baseSelectedFields, childTableRef);
2103
+ });
2104
+ const innerScalarProjection = buildProjection(contract, addressedModelName(include.relatedModelName, include.nested.variantName), child, queryPolyProjection.baseSelectedFields);
2010
2105
  const innerMtiProjection = mergeProjectionByAlias(queryPolyProjection.projection, buildRequiredMtiJoinKeyProjection(contract, include));
2011
- let baseInner = SelectAst.from(tableSourceForContract(contract, include.relatedNamespaceId, include.relatedTableName, childTableAlias)).withProjection([
2106
+ let baseInner = SelectAst.from(child.tableSource(contract)).withProjection([
2012
2107
  ...innerScalarProjection,
2013
2108
  ...innerMtiProjection,
2014
2109
  ...queryPolyProjection.hiddenProjection,
@@ -2018,22 +2113,21 @@ function buildDistinctNonLeafChildRowsSelect(options) {
2018
2113
  if (distinctExtraJoins.length > 0) baseInner = baseInner.withJoins(distinctExtraJoins);
2019
2114
  const distinctColumns = childState.distinct;
2020
2115
  if (distinctColumns === void 0 || distinctColumns.length === 0) throw new InternalError("buildDistinctNonLeafChildRowsSelect requires a non-empty `distinct` selection");
2021
- const rankedAlias = `${include.relationName}__ranked`;
2116
+ const rankedAlias = scope.alias(`${include.relationName}__ranked`);
2022
2117
  let innerSelect = wrapWithRowNumberDedup({
2023
2118
  base: baseInner,
2024
- distinctColumnRefs: distinctColumns.map((column) => ColumnRef.of(childTableRef, column)),
2119
+ distinctColumnRefs: distinctColumns.map((column) => child.column(column)),
2025
2120
  rankingOrderBy: childOrderBy ?? [],
2026
2121
  rankedAlias
2027
2122
  });
2028
2123
  if (childOrderBy) innerSelect = innerSelect.withOrderBy(childOrderBy.map((item, index) => item.withExpr(ColumnRef.of(rankedAlias, `${include.relationName}__order_${index}`))));
2029
2124
  if (childState.limit !== void 0) innerSelect = innerSelect.withLimit(childState.limit);
2030
2125
  if (childState.offset !== void 0) innerSelect = innerSelect.withOffset(childState.offset);
2031
- const distinctAlias = `${include.relationName}__distinct`;
2032
- const outerScalarProjection = buildProjection(contract, include.relatedNamespaceId, addressedModelName(include.relatedModelName, include.nested.variantName), include.relatedTableName, visiblePolyProjection.baseSelectedFields, distinctAlias);
2033
- const outerNestedProjections = buildNestedIncludeProjections(contract, aggregates, {
2034
- baseTableName: include.relatedTableName,
2035
- tableRef: distinctAlias,
2036
- variantColumnsProjected: true
2126
+ const distinctAlias = scope.alias(`${include.relationName}__distinct`);
2127
+ const outerScalarProjection = buildProjection(contract, addressedModelName(include.relatedModelName, include.nested.variantName), child, visiblePolyProjection.baseSelectedFields, distinctAlias);
2128
+ const outerNestedProjections = buildNestedIncludeProjections(contract, aggregates, scope, {
2129
+ tables: childState.tables,
2130
+ projectedThrough: distinctAlias
2037
2131
  }, childState.includes);
2038
2132
  const outerPolyProjection = visiblePolyProjection.projection.map((proj) => ProjectionItem.of(proj.alias, ColumnRef.of(distinctAlias, proj.alias), proj.codec));
2039
2133
  const outerHiddenProjection = visiblePolyProjection.hiddenProjection.map((proj) => ProjectionItem.of(proj.alias, ColumnRef.of(distinctAlias, proj.alias), proj.codec));
@@ -2078,7 +2172,7 @@ function buildDistinctNonLeafChildRowsSelect(options) {
2078
2172
  * `distinct`) is dropped at the SQL level since reordering does not
2079
2173
  * change which rows are aggregated.
2080
2174
  */
2081
- function buildIncludeChildScalarSelect(contract, aggregates, parentSource, include, scalar) {
2175
+ function buildIncludeChildScalarSelect(contract, aggregates, scope, parent, include, scalar) {
2082
2176
  const { codec: resultCodec, input: inputCodec, lower: resultLowering } = resolveAggregate({
2083
2177
  aggregates,
2084
2178
  contract,
@@ -2087,65 +2181,58 @@ function buildIncludeChildScalarSelect(contract, aggregates, parentSource, inclu
2087
2181
  fn: scalar.fn,
2088
2182
  column: scalar.column
2089
2183
  });
2090
- const parentLocalRefs = resolveParentLocalRefs(parentSource, include, localColumnsForRowInclude(include));
2091
- const childSource = resolveChildTableSource(include, parentLocalRefs);
2092
- const childTableAlias = childSource.alias;
2093
- const childTableRef = childSource.tableRef;
2184
+ const parentLocalRefs = resolveParentLocalRefs(parent, include, localColumnsForRowInclude(include));
2094
2185
  const state = scalar.state;
2186
+ const child = state.tables.root;
2095
2187
  if (state.distinctOn !== void 0 && state.distinctOn.length > 0) {
2096
2188
  assertDistinctOnCapability(contract, "distinctOn");
2097
2189
  assertDistinctOnCompatibleOrder(state.orderBy, state.distinctOn.length);
2098
2190
  }
2099
- const childWhere = buildStateWhere(contract, childTableRef, state, {
2100
- filterTableName: include.relatedTableName,
2101
- namespaceId: include.relatedNamespaceId
2102
- });
2191
+ const childWhere = buildStateWhere(contract, state);
2103
2192
  let whereExpr;
2104
2193
  let junctionJoins = [];
2105
2194
  if (include.through !== void 0) {
2106
- const artifacts = buildManyToManyJunctionArtifacts(parentLocalRefs, childTableRef, include.through);
2195
+ const artifacts = buildManyToManyJunctionArtifacts(contract, parentLocalRefs, child, requireJunction(include), include.through);
2107
2196
  whereExpr = childWhere ? AndExpr.of([artifacts.whereExpr, childWhere]) : artifacts.whereExpr;
2108
2197
  junctionJoins = [artifacts.junctionJoin];
2109
2198
  } else {
2110
- const joinExpr = buildIncludeJoinExpr(include, childTableRef, parentLocalRefs);
2199
+ const joinExpr = buildIncludeJoinExpr(include, child, parentLocalRefs);
2111
2200
  whereExpr = childWhere ? AndExpr.of([joinExpr, childWhere]) : joinExpr;
2112
2201
  }
2113
- const remappedOrderBy = childTableAlias && state.orderBy ? state.orderBy.map((item) => item.rewrite(createTableRefRemapper$1(include.relatedTableName, childTableRef))) : state.orderBy;
2114
2202
  const hasPagination = state.limit !== void 0 || state.offset !== void 0;
2115
2203
  const hasDistinct = state.distinct !== void 0 && state.distinct.length > 0 || state.distinctOn !== void 0 && state.distinctOn.length > 0;
2116
2204
  if (!(hasPagination || hasDistinct)) {
2117
- const aggregateExpr = buildIncludeAggregateExpr(scalar, childTableRef, resultLowering, inputCodec);
2205
+ const aggregateExpr = buildIncludeAggregateExpr(scalar, scalar.column === void 0 ? void 0 : child.column(scalar.column), resultLowering, inputCodec);
2118
2206
  const jsonObjectExpr = JsonObjectExpr.fromEntries([JsonObjectExpr.entry("value", jsonEntryProjection(aggregateExpr, { codec: resultCodec }))]);
2119
- let select = SelectAst.from(tableSourceForContract(contract, include.relatedNamespaceId, include.relatedTableName, childTableAlias)).withProjection([ProjectionItem.of(include.relationName, jsonObjectExpr)]).withWhere(whereExpr);
2207
+ let select = SelectAst.from(child.tableSource(contract)).withProjection([ProjectionItem.of(include.relationName, jsonObjectExpr)]).withWhere(whereExpr);
2120
2208
  if (junctionJoins.length > 0) select = select.withJoins(junctionJoins);
2121
2209
  return select;
2122
2210
  }
2123
- const innerAlias = `${include.relationName}__scalar`;
2124
- const hiddenOrderProjection = state.distinct !== void 0 && state.distinct.length > 0 && remappedOrderBy !== void 0 && remappedOrderBy.length > 0 ? remappedOrderBy.map((item, index) => ProjectionItem.of(`${include.relationName}__order_${index}`, item.expr)) : [];
2125
- const innerProjection = [...scalar.column !== void 0 ? [ProjectionItem.of(scalar.column, ColumnRef.of(childTableRef, scalar.column))] : [ProjectionItem.of("__row", LiteralExpr.of(1))], ...hiddenOrderProjection];
2126
- let inner = SelectAst.from(tableSourceForContract(contract, include.relatedNamespaceId, include.relatedTableName, childTableAlias)).withProjection(innerProjection).withWhere(whereExpr);
2211
+ const innerAlias = scope.alias(`${include.relationName}__scalar`);
2212
+ const hiddenOrderProjection = state.distinct !== void 0 && state.distinct.length > 0 && state.orderBy !== void 0 && state.orderBy.length > 0 ? state.orderBy.map((item, index) => ProjectionItem.of(`${include.relationName}__order_${index}`, item.expr)) : [];
2213
+ const innerProjection = [...scalar.column !== void 0 ? [ProjectionItem.of(scalar.column, child.column(scalar.column))] : [ProjectionItem.of("__row", LiteralExpr.of(1))], ...hiddenOrderProjection];
2214
+ let inner = SelectAst.from(child.tableSource(contract)).withProjection(innerProjection).withWhere(whereExpr);
2127
2215
  if (junctionJoins.length > 0) inner = inner.withJoins(junctionJoins);
2128
2216
  if (state.distinctOn !== void 0 && state.distinctOn.length > 0) {
2129
- inner = inner.withDistinctOn(state.distinctOn.map((column) => ColumnRef.of(childTableRef, column)));
2130
- if (remappedOrderBy !== void 0 && remappedOrderBy.length > 0) inner = inner.withOrderBy(remappedOrderBy);
2217
+ inner = inner.withDistinctOn(state.distinctOn.map((column) => child.column(column)));
2218
+ if (state.orderBy !== void 0 && state.orderBy.length > 0) inner = inner.withOrderBy(state.orderBy);
2131
2219
  } else if (state.distinct !== void 0 && state.distinct.length > 0) {
2132
- const rankedAlias = `${include.relationName}__scalar_distinct`;
2220
+ const rankedAlias = scope.alias(`${include.relationName}__scalar_distinct`);
2133
2221
  inner = wrapWithRowNumberDedup({
2134
2222
  base: inner,
2135
- distinctColumnRefs: state.distinct.map((column) => ColumnRef.of(childTableRef, column)),
2136
- rankingOrderBy: remappedOrderBy ?? [],
2223
+ distinctColumnRefs: state.distinct.map((column) => child.column(column)),
2224
+ rankingOrderBy: state.orderBy ?? [],
2137
2225
  rankedAlias
2138
2226
  });
2139
- if (remappedOrderBy !== void 0 && remappedOrderBy.length > 0) inner = inner.withOrderBy(remappedOrderBy.map((item, index) => item.withExpr(ColumnRef.of(rankedAlias, `${include.relationName}__order_${index}`))));
2140
- } else if (remappedOrderBy !== void 0 && remappedOrderBy.length > 0) inner = inner.withOrderBy(remappedOrderBy);
2227
+ if (state.orderBy !== void 0 && state.orderBy.length > 0) inner = inner.withOrderBy(state.orderBy.map((item, index) => item.withExpr(ColumnRef.of(rankedAlias, `${include.relationName}__order_${index}`))));
2228
+ } else if (state.orderBy !== void 0 && state.orderBy.length > 0) inner = inner.withOrderBy(state.orderBy);
2141
2229
  if (state.limit !== void 0) inner = inner.withLimit(state.limit);
2142
2230
  if (state.offset !== void 0) inner = inner.withOffset(state.offset);
2143
- const outerAggregateExpr = buildIncludeAggregateExpr(scalar, innerAlias, resultLowering, inputCodec);
2231
+ const outerAggregateExpr = buildIncludeAggregateExpr(scalar, scalar.column === void 0 ? void 0 : ColumnRef.of(innerAlias, scalar.column), resultLowering, inputCodec);
2144
2232
  const outerJsonObjectExpr = JsonObjectExpr.fromEntries([JsonObjectExpr.entry("value", jsonEntryProjection(outerAggregateExpr, { codec: resultCodec }))]);
2145
2233
  return SelectAst.from(DerivedTableSource.as(innerAlias, inner)).withProjection([ProjectionItem.of(include.relationName, outerJsonObjectExpr)]);
2146
2234
  }
2147
- function buildIncludeAggregateExpr(scalar, childTableRef, lower, inputCodec) {
2148
- const expr = scalar.column === void 0 ? void 0 : ColumnRef.of(childTableRef, scalar.column);
2235
+ function buildIncludeAggregateExpr(scalar, expr, lower, inputCodec) {
2149
2236
  if (lower !== void 0) return lower({
2150
2237
  expr,
2151
2238
  inputCodec
@@ -2171,13 +2258,13 @@ function buildIncludeAggregateExpr(scalar, childTableRef, lower, inputCodec) {
2171
2258
  * branch fan out naturally because the row builder is invoked with
2172
2259
  * a synthetic IncludeExpr whose `nested` is the branch's state.
2173
2260
  */
2174
- function buildIncludeChildCombineSelect(contract, aggregates, parentSource, include, branches) {
2261
+ function buildIncludeChildCombineSelect(contract, aggregates, scope, parent, include, branches) {
2175
2262
  const branchEntries = Object.entries(branches);
2176
2263
  if (branchEntries.length === 0) throw ormError("ORM.INCLUDE_INVALID", `combine() include "${include.relationName}" has no branches`, { meta: { relation: include.relationName } });
2177
2264
  const compiledBranches = branchEntries.map(([name, branch]) => ({
2178
2265
  name,
2179
- alias: `${include.relationName}__combine__${name}`,
2180
- select: buildIncludeChildCombineBranchSelect(contract, aggregates, parentSource, include, branch)
2266
+ alias: scope.alias(`${include.relationName}__combine__${name}`),
2267
+ select: buildIncludeChildCombineBranchSelect(contract, aggregates, scope, parent, include, branch)
2181
2268
  }));
2182
2269
  const jsonObjectExpr = JsonObjectExpr.fromEntries(compiledBranches.map((branch) => JsonObjectExpr.entry(branch.name, jsonEntryProjection(ColumnRef.of(branch.alias, include.relationName), { document: true }))));
2183
2270
  const [firstBranch, ...restBranches] = compiledBranches;
@@ -2191,9 +2278,9 @@ function buildIncludeChildCombineSelect(contract, aggregates, parentSource, incl
2191
2278
  * relation name. Dispatches to the standalone scalar / row builders
2192
2279
  * with the branch's state spliced into a synthetic IncludeExpr.
2193
2280
  */
2194
- function buildIncludeChildCombineBranchSelect(contract, aggregates, parentSource, include, branch) {
2195
- if (branch.kind === "scalar") return buildIncludeChildScalarSelect(contract, aggregates, parentSource, include, branch.selector);
2196
- return buildIncludeChildRowsAggregateSelect(contract, aggregates, parentSource, {
2281
+ function buildIncludeChildCombineBranchSelect(contract, aggregates, scope, parent, include, branch) {
2282
+ if (branch.kind === "scalar") return buildIncludeChildScalarSelect(contract, aggregates, scope, parent, include, branch.selector);
2283
+ return buildIncludeChildRowsAggregateSelect(contract, aggregates, scope, parent, {
2197
2284
  ...include,
2198
2285
  nested: branch.state,
2199
2286
  scalar: void 0,
@@ -2206,103 +2293,98 @@ function buildIncludeChildCombineBranchSelect(contract, aggregates, parentSource
2206
2293
  * name. Used by both the standalone row correlated-subquery path and
2207
2294
  * by combine's row branches.
2208
2295
  */
2209
- function buildIncludeChildRowsAggregateSelect(contract, aggregates, parentSource, include) {
2210
- const { childRows, childProjection, documentAliases, rowsAlias, aggregateOrderBy } = buildIncludeChildRowsSelect(contract, aggregates, parentSource, include);
2296
+ function buildIncludeChildRowsAggregateSelect(contract, aggregates, scope, parent, include) {
2297
+ const { childRows, childProjection, documentAliases, rowsAlias, aggregateOrderBy } = buildIncludeChildRowsSelect(contract, aggregates, scope, parent, include);
2211
2298
  const jsonObjectExpr = JsonObjectExpr.fromEntries(childProjection.map((item) => JsonObjectExpr.entry(item.alias, jsonEntryProjection(ColumnRef.of(rowsAlias, item.alias), {
2212
2299
  codec: item.codec,
2213
2300
  document: documentAliases.has(item.alias)
2214
2301
  }))));
2215
2302
  return SelectAst.from(DerivedTableSource.as(rowsAlias, childRows)).withProjection([ProjectionItem.of(include.relationName, JsonArrayAggExpr.of(jsonEntryProjection(jsonObjectExpr, { document: true }), "emptyArray", aggregateOrderBy))]);
2216
2303
  }
2217
- function buildCorrelatedIncludeProjection(contract, aggregates, parentSource, include) {
2304
+ function buildCorrelatedIncludeProjection(contract, aggregates, scope, parent, include) {
2218
2305
  if (include.scalar) {
2219
- const scalarSelect = buildIncludeChildScalarSelect(contract, aggregates, parentSource, include, include.scalar);
2306
+ const scalarSelect = buildIncludeChildScalarSelect(contract, aggregates, scope, parent, include, include.scalar);
2220
2307
  return { projection: ProjectionItem.of(include.relationName, SubqueryExpr.of(scalarSelect)) };
2221
2308
  }
2222
2309
  if (include.combine) {
2223
- const combineSelect = buildIncludeChildCombineSelect(contract, aggregates, parentSource, include, include.combine);
2310
+ const combineSelect = buildIncludeChildCombineSelect(contract, aggregates, scope, parent, include, include.combine);
2224
2311
  return { projection: ProjectionItem.of(include.relationName, SubqueryExpr.of(combineSelect)) };
2225
2312
  }
2226
- const aggregateQuery = buildIncludeChildRowsAggregateSelect(contract, aggregates, parentSource, include);
2313
+ const aggregateQuery = buildIncludeChildRowsAggregateSelect(contract, aggregates, scope, parent, include);
2227
2314
  return { projection: ProjectionItem.of(include.relationName, SubqueryExpr.of(aggregateQuery)) };
2228
2315
  }
2229
- function buildSelectAst(contract, modelName, tableName, state, options) {
2230
- const namespaceId = options.namespaceId;
2316
+ function buildSelectAst(contract, modelName, state, options) {
2317
+ const { root } = state.tables;
2318
+ const { namespaceId, tableName } = root.storage;
2231
2319
  if (state.distinctOn !== void 0 && state.distinctOn.length > 0) {
2232
2320
  assertDistinctOnCapability(contract, "distinctOn");
2233
2321
  assertDistinctOnCompatibleOrder(state.orderBy, state.distinctOn.length);
2234
2322
  }
2235
2323
  const addressed = addressedModelName(modelName, state.variantName);
2236
- const projection = [...buildProjection(contract, namespaceId, addressed, tableName, state.selectedFields, tableName), ...options.includeProjection ?? []];
2237
- 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))));
2324
+ const projection = [...buildProjection(contract, addressed, root, state.selectedFields), ...options.includeProjection ?? []];
2325
+ const { source: fromSource, where: effectiveWhere } = buildDedupedTableSource(contract, state, options.where ?? buildStateWhere(contract, state), getColumnsReadOnTable(contract, namespaceId, addressed, tableName).map((column) => ProjectionItem.of(column, root.column(column))));
2238
2326
  let ast = SelectAst.from(fromSource).withProjection(projection);
2239
2327
  if (effectiveWhere) ast = ast.withWhere(effectiveWhere);
2240
2328
  if (state.orderBy) ast = ast.withOrderBy(state.orderBy);
2241
2329
  if (state.selectedFields === void 0) ast = ast.withSelectAllIntent({ table: tableName });
2242
- if (state.distinctOn && state.distinctOn.length > 0) ast = ast.withDistinctOn(state.distinctOn.map((column) => ColumnRef.of(tableName, column)));
2330
+ if (state.distinctOn && state.distinctOn.length > 0) ast = ast.withDistinctOn(state.distinctOn.map((column) => root.column(column)));
2243
2331
  if (state.limit !== void 0) ast = ast.withLimit(state.limit);
2244
2332
  if (state.offset !== void 0) ast = ast.withOffset(state.offset);
2245
2333
  if (options.joins && options.joins.length > 0) ast = ast.withJoins(options.joins);
2246
2334
  if (state.locking !== void 0) ast = ast.withLocking(state.locking);
2247
2335
  return ast;
2248
2336
  }
2249
- function compileSelect(contract, namespaceId, modelName, tableName, state) {
2337
+ function buildRootPolymorphism(contract, state, modelName) {
2338
+ const { root } = state.tables;
2339
+ const { namespaceId } = root.storage;
2340
+ const polyInfo = resolvePolymorphismInfo(contract, namespaceId, modelName);
2341
+ if (!polyInfo) return {
2342
+ projectionState: state,
2343
+ joins: [],
2344
+ projection: []
2345
+ };
2346
+ const selection = resolvePolymorphicProjectionSelection(contract, namespaceId, modelName, polyInfo, state);
2347
+ const mtiArtifacts = polyInfo.mtiVariants.length > 0 ? buildMtiJoins(contract, state.tables, polyInfo, state.variantName, selection.selectedMtiColumnsByVariant) : void 0;
2348
+ return {
2349
+ projectionState: {
2350
+ ...state,
2351
+ selectedFields: selection.baseSelectedFields
2352
+ },
2353
+ joins: mtiArtifacts?.joins ?? [],
2354
+ projection: [...mtiArtifacts?.projection ?? [], ...buildHiddenDiscriminatorProjection(contract, root, polyInfo, selection.needsHiddenDiscriminator)]
2355
+ };
2356
+ }
2357
+ function compileSelect(contract, modelName, state) {
2250
2358
  assertLockCompatible(state);
2251
2359
  if (state.distinctOn !== void 0 && state.distinctOn.length > 0) assertDistinctOnCapability(contract, "distinctOn");
2252
- const polyInfo = resolvePolymorphismInfo(contract, namespaceId, modelName);
2253
- const selection = polyInfo ? resolvePolymorphicProjectionSelection(contract, namespaceId, modelName, polyInfo, state) : void 0;
2254
- const projectionState = selection ? {
2255
- ...state,
2256
- selectedFields: selection.baseSelectedFields
2257
- } : state;
2258
- const mtiArtifacts = polyInfo && polyInfo.mtiVariants.length > 0 ? buildMtiJoins(contract, namespaceId, polyInfo, state.variantName, selection?.selectedMtiColumnsByTable) : void 0;
2259
- const hiddenProjection = polyInfo && selection ? buildHiddenDiscriminatorProjection(contract, namespaceId, polyInfo, tableName, selection.needsHiddenDiscriminator) : [];
2260
- const ast = buildSelectAst(contract, modelName, tableName, {
2261
- ...projectionState,
2360
+ const polymorphism = buildRootPolymorphism(contract, state, modelName);
2361
+ const ast = buildSelectAst(contract, modelName, {
2362
+ ...polymorphism.projectionState,
2262
2363
  includes: []
2263
2364
  }, {
2264
- joins: mtiArtifacts?.joins ?? [],
2265
- includeProjection: [...mtiArtifacts?.projection ?? [], ...hiddenProjection],
2266
- namespaceId
2365
+ joins: polymorphism.joins,
2366
+ includeProjection: polymorphism.projection
2267
2367
  });
2268
2368
  const { params } = deriveParamsFromAst(ast);
2269
2369
  return buildOrmQueryPlan(contract, ast, params, state.annotations);
2270
2370
  }
2271
- function compileSelectWithIncludes(contract, aggregates, namespaceId, modelName, tableName, state) {
2371
+ function compileSelectWithIncludes(contract, aggregates, modelName, state) {
2272
2372
  assertLockCompatible(state);
2273
- const includeJoins = [];
2274
- const includeProjection = [];
2275
- const topLevelWhere = buildStateWhere(contract, tableName, state, { namespaceId });
2276
- const polyInfo = resolvePolymorphismInfo(contract, namespaceId, modelName);
2277
- const selection = polyInfo ? resolvePolymorphicProjectionSelection(contract, namespaceId, modelName, polyInfo, state) : void 0;
2278
- const projectionState = selection ? {
2279
- ...state,
2280
- selectedFields: selection.baseSelectedFields
2281
- } : state;
2282
- if (polyInfo && selection) {
2283
- if (polyInfo.mtiVariants.length > 0) {
2284
- const mtiArtifacts = buildMtiJoins(contract, namespaceId, polyInfo, state.variantName, selection.selectedMtiColumnsByTable);
2285
- includeJoins.push(...mtiArtifacts.joins);
2286
- includeProjection.push(...mtiArtifacts.projection);
2287
- }
2288
- includeProjection.push(...buildHiddenDiscriminatorProjection(contract, namespaceId, polyInfo, tableName, selection.needsHiddenDiscriminator));
2289
- }
2290
- const parentSource = {
2291
- baseTableName: tableName,
2292
- tableRef: tableName,
2293
- variantColumnsProjected: false
2294
- };
2373
+ const topLevelWhere = buildStateWhere(contract, state);
2374
+ const polymorphism = buildRootPolymorphism(contract, state, modelName);
2375
+ const includeProjection = [...polymorphism.projection];
2376
+ const scope = state.tables.scope.copy();
2377
+ const parent = { tables: state.tables };
2295
2378
  for (const include of state.includes) {
2296
- const artifact = buildCorrelatedIncludeProjection(contract, aggregates, parentSource, include);
2379
+ const artifact = buildCorrelatedIncludeProjection(contract, aggregates, scope, parent, include);
2297
2380
  includeProjection.push(artifact.projection);
2298
2381
  }
2299
- const ast = buildSelectAst(contract, modelName, tableName, {
2300
- ...projectionState,
2382
+ const ast = buildSelectAst(contract, modelName, {
2383
+ ...polymorphism.projectionState,
2301
2384
  includes: []
2302
2385
  }, {
2303
- joins: includeJoins,
2386
+ joins: polymorphism.joins,
2304
2387
  includeProjection,
2305
- namespaceId,
2306
2388
  ...ifDefined("where", topLevelWhere)
2307
2389
  });
2308
2390
  const { params } = deriveParamsFromAst(ast);
@@ -2318,19 +2400,19 @@ function describeCollectionRows(options) {
2318
2400
  };
2319
2401
  }
2320
2402
  function describeExecutionRows(options) {
2321
- const { context, state, tableName, modelName, namespaceId } = options;
2403
+ const { context, state, modelName, namespaceId } = options;
2322
2404
  const { contract } = context;
2323
2405
  const polyInfo = resolvePolymorphismInfo(contract, namespaceId, modelName);
2324
2406
  if (state.includes.length === 0) {
2325
- const compiled = compileSelect(contract, namespaceId, modelName, tableName, state);
2326
- const mapper = polyInfo ? (rawRow) => blindCast(mapPolymorphicRow(contract, namespaceId, modelName, polyInfo, rawRow, state.variantName)) : (rawRow) => blindCast(mapStorageRowToModelFields(contract, namespaceId, modelName, rawRow));
2407
+ const compiled = compileSelect(contract, modelName, state);
2408
+ const mapper = polyInfo ? (rawRow) => blindCast(mapPolymorphicRow(contract, namespaceId, modelName, polyInfo, state.tables, rawRow, state.variantName)) : (rawRow) => blindCast(mapStorageRowToModelFields(contract, namespaceId, modelName, rawRow));
2327
2409
  return {
2328
2410
  plan: compiled,
2329
2411
  consume: (rows) => mapResultRows(rows, mapper)
2330
2412
  };
2331
2413
  }
2332
2414
  return {
2333
- plan: compileSelectWithIncludes(contract, context.aggregateDescriptors, namespaceId, modelName, tableName, state),
2415
+ plan: compileSelectWithIncludes(contract, context.aggregateDescriptors, modelName, state),
2334
2416
  consume: (rows) => consumeIncludeRows(context, state, namespaceId, modelName, rows)
2335
2417
  };
2336
2418
  }
@@ -2344,16 +2426,16 @@ function deferResolution(resolve) {
2344
2426
  };
2345
2427
  }
2346
2428
  }
2347
- function createPreparedMapper(contract, namespaceId, modelName, variantName) {
2429
+ function createPreparedMapper(contract, namespaceId, modelName, state) {
2348
2430
  const resolved = deferResolution(() => {
2349
2431
  const polyInfo = resolvePolymorphismInfo(contract, namespaceId, modelName);
2350
- return polyInfo ? createPolymorphicRowMapper(contract, namespaceId, modelName, polyInfo, variantName) : createStorageRowMapper(contract, namespaceId, modelName);
2432
+ return polyInfo ? createPolymorphicRowMapper(contract, namespaceId, modelName, polyInfo, state.tables, state.variantName) : createStorageRowMapper(contract, namespaceId, modelName);
2351
2433
  });
2352
2434
  return (row) => resolved()(row);
2353
2435
  }
2354
2436
  function createPreparedRowsConsumer(options) {
2355
2437
  const { context, state, namespaceId, modelName } = options;
2356
- const mapRow = createPreparedMapper(context.contract, namespaceId, modelName, state.variantName);
2438
+ const mapRow = createPreparedMapper(context.contract, namespaceId, modelName, state);
2357
2439
  const includes = state.includes.map((include) => createPreparedIncludeConsumer(context, include));
2358
2440
  const castRow = (row) => blindCast(row);
2359
2441
  if (includes.length === 0) return (rows) => mapResultRows(rows, (row) => castRow(mapRow(row)));
@@ -2393,12 +2475,15 @@ function createPreparedIncludeConsumer(context, include) {
2393
2475
  }
2394
2476
  };
2395
2477
  }
2396
- const mapRow = createPreparedMapper(contract, include.relatedNamespaceId, include.relatedModelName, include.nested.variantName);
2478
+ const mapRow = createPreparedMapper(contract, include.relatedNamespaceId, include.relatedModelName, include.nested);
2397
2479
  const bindings = deferResolution(() => {
2398
2480
  const namespace = include.relatedNamespaceId;
2399
2481
  const keys = new Set(getColumnsReadOnTable(contract, namespace, addressedModelName(include.relatedModelName, include.nested.variantName), include.relatedTableName));
2400
2482
  const polyInfo = resolvePolymorphismInfo(contract, namespace, include.relatedModelName);
2401
- for (const variant of polyInfo?.mtiVariants ?? []) for (const column of getColumnsReadOnTable(contract, namespace, variant.modelName, variant.table)) keys.add(`${variant.table}__${column}`);
2483
+ for (const variant of polyInfo?.mtiVariants ?? []) {
2484
+ const variantTable = requireVariantTable(include.nested.tables, variant.modelName);
2485
+ for (const column of getColumnsReadOnTable(contract, variantTable.storage.namespaceId, variant.modelName, variantTable.storage.tableName)) keys.add(variantColumnLabel(variantTable, column));
2486
+ }
2402
2487
  return new Map([...keys].map((key) => [key, deferResolution(() => resolveIncludedColumnBinding(contract, context, include, key))]));
2403
2488
  });
2404
2489
  const bindingFor = (key) => bindings().get(key)?.() ?? null;
@@ -2482,11 +2567,10 @@ function describeCollectionFirstOrThrow(options) {
2482
2567
  };
2483
2568
  }
2484
2569
  function dispatchCollectionRows(options) {
2485
- const { context, runtime, state, tableName, modelName, namespaceId } = options;
2570
+ const { context, runtime, state, modelName, namespaceId } = options;
2486
2571
  const descriptionOptions = {
2487
2572
  context,
2488
2573
  state,
2489
- tableName,
2490
2574
  modelName,
2491
2575
  namespaceId
2492
2576
  };
@@ -2510,7 +2594,7 @@ function consumeIncludeRows(context, state, namespaceId, modelName, rows) {
2510
2594
  const parentRows = parentRowsRaw.map((row) => {
2511
2595
  return {
2512
2596
  raw: row,
2513
- mapped: polyInfo ? mapPolymorphicRow(contract, namespaceId, modelName, polyInfo, row, state.variantName) : mapStorageRowToModelFields(contract, namespaceId, modelName, row)
2597
+ mapped: polyInfo ? mapPolymorphicRow(contract, namespaceId, modelName, polyInfo, state.tables, row, state.variantName) : mapStorageRowToModelFields(contract, namespaceId, modelName, row)
2514
2598
  };
2515
2599
  });
2516
2600
  const bindings = /* @__PURE__ */ new WeakMap();
@@ -2538,26 +2622,26 @@ function consumeIncludeRows(context, state, namespaceId, modelName, rows) {
2538
2622
  * its snapshot before issuing the DELETE (see `collection.ts`).
2539
2623
  */
2540
2624
  function reloadMutationRowsByIdentities(options) {
2541
- const { context, runtime, tableName, modelName, namespaceId, identityRows, selectedFields, includes } = options;
2625
+ const { context, runtime, tables, modelName, namespaceId, identityRows, selectedFields, includes } = options;
2542
2626
  const { contract } = context;
2627
+ const { tableName } = tables.root.storage;
2543
2628
  if (identityRows.length === 0) return emptyResult();
2544
2629
  const identityColumns = resolveRowIdentityColumns(contract, namespaceId, tableName);
2545
2630
  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: {
2546
2631
  model: modelName,
2547
2632
  table: tableName
2548
2633
  } });
2549
- const identityFilter = buildIdentityInFilter(contract, namespaceId, tableName, identityColumns, identityRows);
2634
+ const identityFilter = buildIdentityInFilter(contract, tables.root, identityColumns, identityRows);
2550
2635
  if (!identityFilter) return emptyResult();
2551
2636
  return dispatchCollectionRows({
2552
2637
  context,
2553
2638
  runtime,
2554
2639
  state: {
2555
- ...emptyState(),
2640
+ ...emptyState(tables),
2556
2641
  filters: [identityFilter],
2557
2642
  selectedFields,
2558
2643
  includes
2559
2644
  },
2560
- tableName,
2561
2645
  modelName,
2562
2646
  namespaceId
2563
2647
  });
@@ -2565,16 +2649,17 @@ function reloadMutationRowsByIdentities(options) {
2565
2649
  function emptyResult() {
2566
2650
  return new AsyncIterableResult((async function* () {})());
2567
2651
  }
2568
- function buildIdentityInFilter(contract, namespaceId, tableName, identityColumns, identityRows) {
2652
+ function buildIdentityInFilter(contract, table, identityColumns, identityRows) {
2653
+ const { storage } = table;
2569
2654
  const [singleColumn, ...rest] = identityColumns;
2570
2655
  if (singleColumn !== void 0 && rest.length === 0) {
2571
2656
  const values = identityRows.map((row) => row[singleColumn]).filter((value) => value !== void 0);
2572
2657
  if (values.length === 0) return;
2573
- return bindWhereExpr(contract, BinaryExpr.in(ColumnRef.of(tableName, singleColumn), ListExpression.fromValues(values)), namespaceId);
2658
+ return BinaryExpr.in(table.column(singleColumn), ListExpression.of(values.map((value) => paramRefForStorageColumn(contract, storage, singleColumn, value))));
2574
2659
  }
2575
2660
  if (identityRows.length === 0) return;
2576
- const tuples = identityRows.map((row) => AndExpr.of(identityColumns.map((column) => BinaryExpr.eq(ColumnRef.of(tableName, column), LiteralExpr.of(row[column])))));
2577
- return bindWhereExpr(contract, OrExpr.of(tuples), namespaceId);
2661
+ const tuples = identityRows.map((row) => AndExpr.of(identityColumns.map((column) => BinaryExpr.eq(table.column(column), paramRefForStorageColumn(contract, storage, column, row[column])))));
2662
+ return OrExpr.of(tuples);
2578
2663
  }
2579
2664
  /**
2580
2665
  * Decode a single-query include payload from a parent row's raw cell
@@ -2602,7 +2687,7 @@ function decodeIncludePayload(contract, context, include, raw, bindings) {
2602
2687
  if (include.combine) return decodeCombineIncludePayload(contract, context, include, include.combine, raw, bindings);
2603
2688
  const rawChildren = parseIncludedRows(include, raw);
2604
2689
  const polyInfo = resolvePolymorphismInfo(contract, include.relatedNamespaceId, include.relatedModelName);
2605
- const mapChildRow = polyInfo ? (childRow) => mapPolymorphicRow(contract, include.relatedNamespaceId, include.relatedModelName, polyInfo, childRow, include.nested.variantName) : createStorageRowMapper(contract, include.relatedNamespaceId, include.relatedModelName);
2690
+ const mapChildRow = polyInfo ? (childRow) => mapPolymorphicRow(contract, include.relatedNamespaceId, include.relatedModelName, polyInfo, include.nested.tables, childRow, include.nested.variantName) : createStorageRowMapper(contract, include.relatedNamespaceId, include.relatedModelName);
2606
2691
  let columns = bindings.get(include);
2607
2692
  if (!columns) {
2608
2693
  columns = /* @__PURE__ */ new Map();
@@ -2646,17 +2731,18 @@ function decodeIncludedStorageRow(row, bindingFor) {
2646
2731
  function resolveIncludedColumnBinding(contract, context, include, key) {
2647
2732
  const ref = resolveIncludedColumnRef(contract, include, key);
2648
2733
  if (!ref) return null;
2649
- const codec = context.contractCodecs.forColumn(include.relatedNamespaceId, ref.table, ref.column);
2734
+ const codec = context.contractCodecs.forColumn(ref.namespaceId, ref.table, ref.column);
2650
2735
  if (!codec) return null;
2651
2736
  return {
2652
2737
  ref,
2653
2738
  codec,
2654
- codecId: context.codecDescriptors.codecRefForColumn(include.relatedNamespaceId, ref.table, ref.column)?.codecId ?? ref.storageColumn.codecId
2739
+ codecId: context.codecDescriptors.codecRefForColumn(ref.namespaceId, ref.table, ref.column)?.codecId ?? ref.storageColumn.codecId
2655
2740
  };
2656
2741
  }
2657
2742
  function resolveIncludedColumnRef(contract, include, key) {
2658
2743
  const baseColumn = resolveColumn(contract, include.relatedNamespaceId, include.relatedTableName, key);
2659
2744
  if (baseColumn) return {
2745
+ namespaceId: include.relatedNamespaceId,
2660
2746
  table: include.relatedTableName,
2661
2747
  column: key,
2662
2748
  storageColumn: baseColumn
@@ -2664,12 +2750,15 @@ function resolveIncludedColumnRef(contract, include, key) {
2664
2750
  const polyInfo = resolvePolymorphismInfo(contract, include.relatedNamespaceId, include.relatedModelName);
2665
2751
  if (!polyInfo) return;
2666
2752
  for (const variant of polyInfo.mtiVariants) {
2667
- const prefix = `${variant.table}__`;
2753
+ const variantTable = requireVariantTable(include.nested.tables, variant.modelName);
2754
+ const prefix = variantColumnLabelPrefix(variantTable);
2668
2755
  if (!key.startsWith(prefix)) continue;
2669
2756
  const column = key.slice(prefix.length);
2670
- const variantColumn = resolveColumn(contract, include.relatedNamespaceId, variant.table, column);
2757
+ const { namespaceId, tableName } = variantTable.storage;
2758
+ const variantColumn = resolveColumn(contract, namespaceId, tableName, column);
2671
2759
  if (variantColumn) return {
2672
- table: variant.table,
2760
+ namespaceId,
2761
+ table: tableName,
2673
2762
  column,
2674
2763
  storageColumn: variantColumn
2675
2764
  };
@@ -2830,14 +2919,14 @@ function parseIncludePayload(value) {
2830
2919
  return [];
2831
2920
  }
2832
2921
  }
2833
- function createMutationRowMapper(contract, namespaceId, modelName, variantName) {
2922
+ function createMutationRowMapper(contract, namespaceId, modelName, tables, variantName) {
2834
2923
  const polyInfo = resolvePolymorphismInfo(contract, namespaceId, modelName);
2835
- return polyInfo ? (row) => mapPolymorphicRow(contract, namespaceId, modelName, polyInfo, row, variantName) : (row) => mapStorageRowToModelFields(contract, namespaceId, modelName, row);
2924
+ return polyInfo ? (row) => mapPolymorphicRow(contract, namespaceId, modelName, polyInfo, tables, row, variantName) : (row) => mapStorageRowToModelFields(contract, namespaceId, modelName, row);
2836
2925
  }
2837
2926
  function dispatchMutationRows(options) {
2838
- const { context, runtime, compiled, tableName, modelName, namespaceId, variantName, includes, selectedFields, hiddenColumns, mapRow } = options;
2927
+ const { context, runtime, compiled, tables, modelName, namespaceId, variantName, includes, selectedFields, hiddenColumns, mapRow } = options;
2839
2928
  const { contract } = context;
2840
- const mapStorageRow = createMutationRowMapper(contract, namespaceId, modelName, variantName);
2929
+ const mapStorageRow = createMutationRowMapper(contract, namespaceId, modelName, tables, variantName);
2841
2930
  if (includes.length === 0) return mapResultRows(queryPlanRows(runtime, compiled), (rawRow) => {
2842
2931
  const mapped = mapStorageRow(rawRow);
2843
2932
  if (hiddenColumns.length > 0) stripHiddenMappedFields(contract, namespaceId, modelName, mapped, hiddenColumns);
@@ -2848,7 +2937,7 @@ function dispatchMutationRows(options) {
2848
2937
  yield* reloadMutationRowsByIdentities({
2849
2938
  context,
2850
2939
  runtime,
2851
- tableName,
2940
+ tables,
2852
2941
  modelName,
2853
2942
  namespaceId,
2854
2943
  identityRows,
@@ -2859,9 +2948,9 @@ function dispatchMutationRows(options) {
2859
2948
  return new AsyncIterableResult(generator());
2860
2949
  }
2861
2950
  function dispatchSplitMutationRows(options) {
2862
- const { context, runtime, plans, tableName, modelName, namespaceId, variantName, includes, selectedFields, hiddenColumns, mapRow } = options;
2951
+ const { context, runtime, plans, tables, modelName, namespaceId, variantName, includes, selectedFields, hiddenColumns, mapRow } = options;
2863
2952
  const { contract } = context;
2864
- const mapStorageRow = createMutationRowMapper(contract, namespaceId, modelName, variantName);
2953
+ const mapStorageRow = createMutationRowMapper(contract, namespaceId, modelName, tables, variantName);
2865
2954
  const generator = async function* () {
2866
2955
  if (includes.length > 0) {
2867
2956
  const identityRows = [];
@@ -2869,7 +2958,7 @@ function dispatchSplitMutationRows(options) {
2869
2958
  yield* reloadMutationRowsByIdentities({
2870
2959
  context,
2871
2960
  runtime,
2872
- tableName,
2961
+ tables,
2873
2962
  modelName,
2874
2963
  namespaceId,
2875
2964
  identityRows,
@@ -2887,9 +2976,9 @@ function dispatchSplitMutationRows(options) {
2887
2976
  return new AsyncIterableResult(generator());
2888
2977
  }
2889
2978
  async function executeMutationReturningSingleRow(options) {
2890
- const { context, runtime, compiled, tableName, modelName, namespaceId, variantName, includes, selectedFields, hiddenColumns, mapRow, operation, onMissingRowMessage } = options;
2979
+ const { context, runtime, compiled, tables, modelName, namespaceId, variantName, includes, selectedFields, hiddenColumns, mapRow, operation, onMissingRowMessage } = options;
2891
2980
  const { contract } = context;
2892
- const mapStorageRow = createMutationRowMapper(contract, namespaceId, modelName, variantName);
2981
+ const mapStorageRow = createMutationRowMapper(contract, namespaceId, modelName, tables, variantName);
2893
2982
  if (includes.length === 0) {
2894
2983
  const first = (await queryPlanRows(runtime, compiled).toArray())[0];
2895
2984
  if (!first) return null;
@@ -2902,7 +2991,7 @@ async function executeMutationReturningSingleRow(options) {
2902
2991
  for await (const row of reloadMutationRowsByIdentities({
2903
2992
  context,
2904
2993
  runtime,
2905
- tableName,
2994
+ tables,
2906
2995
  modelName,
2907
2996
  namespaceId,
2908
2997
  identityRows,
@@ -2912,7 +3001,7 @@ async function executeMutationReturningSingleRow(options) {
2912
3001
  throw ormError("ORM.MUTATION_ROW_MISSING", onMissingRowMessage, { meta: {
2913
3002
  operation,
2914
3003
  model: modelName,
2915
- tableName
3004
+ tableName: tables.root.storage.tableName
2916
3005
  } });
2917
3006
  }
2918
3007
  /** The filter expression of a condition: a condition from `fns` becomes its AST. */
@@ -2938,20 +3027,20 @@ function not(expr) {
2938
3027
  function all() {
2939
3028
  return AndExpr.true();
2940
3029
  }
2941
- function shorthandToWhereExpr(context, namespaceId, modelName, filters) {
3030
+ function shorthandToWhereExpr(context, namespaceId, modelName, filters, table) {
2942
3031
  const contract = context.contract;
2943
- const tableName = resolveModelTableName(contract, namespaceId, modelName);
2944
3032
  const fieldColumns = getModelFieldColumns(contract, namespaceId, modelName);
2945
3033
  const exprs = [];
2946
3034
  for (const [fieldName, value] of Object.entries(filters)) {
2947
3035
  if (value === void 0) continue;
2948
- const left = ColumnRef.of(tableName, columnOfCallerField(contract, namespaceId, fieldColumns, modelName, fieldName));
3036
+ const columnName = columnOfCallerField(contract, namespaceId, fieldColumns, modelName, fieldName);
3037
+ const left = table.column(columnName);
2949
3038
  if (value === null) {
2950
3039
  exprs.push(NullCheckExpr.isNull(left));
2951
3040
  continue;
2952
3041
  }
2953
3042
  assertFieldHasEqualityTrait(context, namespaceId, modelName, fieldName);
2954
- exprs.push(predicateComparison("eq", left, predicateExpression(value) ?? LiteralExpr.of(value)));
3043
+ exprs.push(predicateComparison("eq", left, predicateExpression(value) ?? paramRefForStorageColumn(contract, table.storage, columnName, value)));
2955
3044
  }
2956
3045
  if (exprs.length === 0) return;
2957
3046
  return exprs.length === 1 ? exprs[0] : and(...exprs);
@@ -3419,103 +3508,21 @@ function createCallbackTools(context, indexes) {
3419
3508
  function hasThrough$1(relation) {
3420
3509
  return relation.through !== void 0;
3421
3510
  }
3422
- var SqlTableBinding = class SqlTableBinding {
3423
- #storage;
3424
- #reference;
3425
- constructor(storage, reference) {
3426
- this.#storage = Object.freeze({ ...storage });
3427
- this.#reference = reference;
3428
- Object.freeze(this);
3429
- }
3430
- static unaliased(storage) {
3431
- return new SqlTableBinding(storage, storage.tableName);
3432
- }
3433
- static aliased(storage, alias) {
3434
- return new SqlTableBinding(storage, alias);
3435
- }
3436
- column(columnName) {
3437
- return ColumnRef.of(this.#reference, columnName);
3438
- }
3439
- tableSource(contract) {
3440
- return tableSourceForContract(contract, this.#storage.namespaceId, this.#storage.tableName, this.#reference);
3441
- }
3442
- isReferencedAs(candidate) {
3443
- return this.#reference === candidate;
3444
- }
3445
- isStoredAt(namespaceId, tableName) {
3446
- return this.#storage.namespaceId === namespaceId && this.#storage.tableName === tableName;
3447
- }
3448
- };
3449
- var ModelAccessorScope = class ModelAccessorScope {
3450
- current;
3451
- #visibleBindings;
3452
- #aliasCounter;
3453
- constructor(current, visibleBindings, aliasCounter) {
3454
- this.current = current;
3455
- this.#visibleBindings = Object.freeze([...visibleBindings]);
3456
- this.#aliasCounter = aliasCounter;
3457
- Object.freeze(this);
3458
- }
3459
- static root(namespaceId, tableName) {
3460
- const binding = SqlTableBinding.unaliased({
3461
- namespaceId,
3462
- tableName
3463
- });
3464
- return new ModelAccessorScope(binding, [binding], { nextId: 1 });
3465
- }
3466
- forRelation(namespaceId, tableName) {
3467
- const binding = this.#allocateBinding(namespaceId, tableName, "rel");
3468
- return new ModelAccessorScope(binding, [...this.#visibleBindings, binding], this.#aliasCounter);
3469
- }
3470
- forManyToManyRelation(childNamespaceId, childTableName, junctionNamespaceId, junctionTableName) {
3471
- const initialChildScope = this.forRelation(childNamespaceId, childTableName);
3472
- const junctionBinding = initialChildScope.#allocateBinding(junctionNamespaceId, junctionTableName, "junction");
3473
- return {
3474
- childScope: new ModelAccessorScope(initialChildScope.current, [...initialChildScope.#visibleBindings, junctionBinding], this.#aliasCounter),
3475
- junctionBinding
3476
- };
3477
- }
3478
- forJoinedSource(namespaceId, tableName) {
3479
- if (this.current.isStoredAt(namespaceId, tableName)) return this;
3480
- const binding = SqlTableBinding.unaliased({
3481
- namespaceId,
3482
- tableName
3483
- });
3484
- return new ModelAccessorScope(binding, [...this.#visibleBindings, binding], this.#aliasCounter);
3485
- }
3486
- #allocateBinding(namespaceId, tableName, aliasKind) {
3487
- const storage = {
3488
- namespaceId,
3489
- tableName
3490
- };
3491
- if (!this.#visibleBindings.some((binding) => binding.isReferencedAs(tableName))) return SqlTableBinding.unaliased(storage);
3492
- return SqlTableBinding.aliased(storage, this.#allocateAlias(aliasKind));
3493
- }
3494
- #allocateAlias(kind) {
3495
- while (true) {
3496
- const alias = `__orm_${kind}_${this.#aliasCounter.nextId}`;
3497
- this.#aliasCounter.nextId += 1;
3498
- if (!this.#visibleBindings.some((binding) => binding.isReferencedAs(alias))) return alias;
3499
- }
3500
- }
3501
- };
3502
- function createModelAccessor(context, namespaceId, modelName, variantName) {
3503
- const tableName = resolveModelTableName(context.contract, namespaceId, modelName);
3504
- return createModelAccessorInScope(context, namespaceId, modelName, variantName, ModelAccessorScope.root(namespaceId, tableName));
3511
+ function createModelAccessor(context, namespaceId, modelName, tables, variantName) {
3512
+ return createModelAccessorInScope(context, namespaceId, modelName, variantName, tables.scope, tables.root, variantName === void 0 ? void 0 : tables.variants.get(variantName));
3505
3513
  }
3506
3514
  /**
3507
3515
  * The second argument of a `where` or `orderBy` callback on a collection of the model: the SQL query builder's functions, and the indexes of the model's table.
3508
3516
  */
3509
- function createModelCallbackTools(context, namespaceId, modelName) {
3510
- const tableName = resolveModelTableName(context.contract, namespaceId, modelName);
3511
- return callbackToolsFor(context, namespaceId, modelName, ModelAccessorScope.root(namespaceId, tableName));
3517
+ function createModelCallbackTools(context, modelName, tables) {
3518
+ return callbackToolsFor(context, modelName, tables.root);
3512
3519
  }
3513
- function callbackToolsFor(context, namespaceId, modelName, scope) {
3514
- return createCallbackTools(context, () => indexReferencesOf(context, namespaceId, modelName, scope.current));
3520
+ function callbackToolsFor(context, modelName, aliasedTable) {
3521
+ return createCallbackTools(context, () => indexReferencesOf(context, modelName, aliasedTable));
3515
3522
  }
3516
- function indexReferencesOf(context, namespaceId, modelName, binding) {
3523
+ function indexReferencesOf(context, modelName, aliasedTable) {
3517
3524
  const { contract } = context;
3518
- const tableName = resolveModelTableName(contract, namespaceId, modelName);
3525
+ const { namespaceId, tableName } = aliasedTable.storage;
3519
3526
  const resolved = resolveTableForContract(contract, namespaceId, tableName);
3520
3527
  if (!resolved) throw new InternalError(`Model "${modelName}" is stored in table "${tableName}", which the contract does not have`);
3521
3528
  const { table } = resolved;
@@ -3532,22 +3539,21 @@ function indexReferencesOf(context, namespaceId, modelName, binding) {
3532
3539
  nullable: column.nullable,
3533
3540
  ...ifDefined("codec", codecRefForStorageColumn(contract.storage, namespaceId, tableName, columnName))
3534
3541
  },
3535
- buildAst: () => binding.column(columnName)
3542
+ buildAst: () => aliasedTable.column(columnName)
3536
3543
  };
3537
3544
  }
3538
3545
  });
3539
3546
  }
3540
- function createModelAccessorInScope(context, namespaceId, modelName, variantName, scope) {
3547
+ function createModelAccessorInScope(context, namespaceId, modelName, variantName, scope, table, variantTable) {
3541
3548
  const contract = context.contract;
3542
3549
  const fieldColumns = getModelAndVariantFieldColumns(contract, namespaceId, modelName, variantName);
3543
- const tableName = resolveModelTableName(contract, namespaceId, modelName);
3544
3550
  const modelRelations = resolveModelRelations(contract, namespaceId, modelName);
3545
3551
  const variantFieldColumns = variantName ? resolveVariantFieldColumns(contract, namespaceId, modelName, variantName) : {};
3546
3552
  const variantCoordinates = variantName ? {
3547
3553
  name: variantName,
3548
- relations: resolveModelRelations(contract, namespaceId, variantName),
3549
- tableName: resolvePolymorphismInfo(contract, namespaceId, modelName)?.variants.get(variantName)?.table ?? tableName
3554
+ relations: resolveModelRelations(contract, namespaceId, variantName)
3550
3555
  } : void 0;
3556
+ const variantFieldTable = variantTable ?? table;
3551
3557
  const opsByCodecId = /* @__PURE__ */ new Map();
3552
3558
  function registerOp(codecId, op) {
3553
3559
  let existing = opsByCodecId.get(codecId);
@@ -3571,27 +3577,27 @@ function createModelAccessorInScope(context, namespaceId, modelName, variantName
3571
3577
  if (typeof prop !== "string") return;
3572
3578
  if (variantCoordinates && Object.hasOwn(variantCoordinates.relations, prop)) {
3573
3579
  const variantRelation = variantCoordinates.relations[prop];
3574
- if (variantRelation) return createRelationFilterAccessor(context, namespaceId, variantCoordinates.name, scope.forJoinedSource(namespaceId, variantCoordinates.tableName), variantRelation);
3580
+ if (variantRelation) return createRelationFilterAccessor(context, namespaceId, variantCoordinates.name, scope, variantFieldTable, variantRelation);
3575
3581
  }
3576
3582
  const relation = Object.hasOwn(modelRelations, prop) ? modelRelations[prop] : void 0;
3577
- if (relation) return createRelationFilterAccessor(context, namespaceId, modelName, scope, relation);
3583
+ if (relation) return createRelationFilterAccessor(context, namespaceId, modelName, scope, table, relation);
3578
3584
  const variantField = Object.hasOwn(variantFieldColumns, prop) ? variantFieldColumns[prop] : void 0;
3579
3585
  if (variantField === void 0 && !Object.hasOwn(fieldColumns, prop)) {
3580
3586
  if (isProbedByRuntime(prop)) return probedValue(target, prop);
3581
3587
  }
3582
- const resolvedTable = variantField?.table ?? tableName;
3583
- const fieldBinding = scope.forJoinedSource(namespaceId, resolvedTable).current;
3588
+ const fieldTable = variantField ? variantFieldTable : table;
3589
+ const fieldStorage = fieldTable.storage;
3584
3590
  const columnName = variantField?.column ?? columnOfCallerField(contract, namespaceId, fieldColumns, addressedModelName(modelName, variantName), prop);
3585
- const column = resolveColumn(contract, namespaceId, resolvedTable, columnName);
3586
- if (!column) throw new InternalError(`Field "${modelName}.${prop}" maps column "${columnName}", which table "${resolvedTable}" does not have`);
3591
+ const column = resolveColumn(contract, fieldStorage.namespaceId, fieldStorage.tableName, columnName);
3592
+ if (!column) throw new InternalError(`Field "${modelName}.${prop}" maps column "${columnName}", which table "${fieldStorage.tableName}" does not have`);
3587
3593
  const traits = codecTraits(context, column.codecId);
3588
3594
  const operations = opsByCodecId.get(column.codecId) ?? [];
3589
- const codec = codecRefForStorageColumn(contract.storage, namespaceId, resolvedTable, columnName);
3590
- return createScalarFieldAccessor(fieldBinding, columnName, column.codecId, column.nullable, codec, traits, operations, context);
3595
+ const codec = codecRefForStorageColumn(contract.storage, fieldStorage.namespaceId, fieldStorage.tableName, columnName);
3596
+ return createScalarFieldAccessor(fieldTable, columnName, column.codecId, column.nullable, codec, traits, operations, context);
3591
3597
  } }));
3592
3598
  }
3593
- function createScalarFieldAccessor(tableBinding, columnName, codecId, nullable, codec, traits, operations, context) {
3594
- const column = tableBinding.column(columnName);
3599
+ function createScalarFieldAccessor(table, columnName, codecId, nullable, codec, traits, operations, context) {
3600
+ const column = table.column(columnName);
3595
3601
  const comparisonEntries = [];
3596
3602
  for (const [name, meta] of Object.entries(COMPARISON_METHODS_META)) {
3597
3603
  if (meta.traits.some((t) => !traits.includes(t))) continue;
@@ -3631,13 +3637,13 @@ const RELATION_ACCESSOR_METHOD_NAMES = /* @__PURE__ */ new Set([
3631
3637
  "none",
3632
3638
  "count"
3633
3639
  ]);
3634
- function createRelationFilterAccessor(context, parentNamespaceId, parentModelName, parentScope, relation) {
3640
+ function createRelationFilterAccessor(context, parentNamespaceId, parentModelName, scope, parentTable, relation) {
3635
3641
  const relatedTableName = resolveModelTableName(context.contract, relation.toNamespace, relation.to);
3636
- const correlate = () => correlateRelatedRows(context, parentNamespaceId, parentModelName, parentScope, relatedTableName, relation);
3642
+ const correlate = () => correlateRelatedRows(context, parentNamespaceId, parentModelName, scope, parentTable, relatedTableName, relation);
3637
3643
  const filters = {
3638
- some: (predicate) => buildExistsExpr(context, relation, correlate(), "some", predicate),
3639
- every: (predicate) => buildExistsExpr(context, relation, correlate(), "every", predicate),
3640
- none: (predicate) => buildExistsExpr(context, relation, correlate(), "none", predicate)
3644
+ some: (predicate) => buildExistsExpr(context, relation, scope, correlate(), "some", predicate),
3645
+ every: (predicate) => buildExistsExpr(context, relation, scope, correlate(), "every", predicate),
3646
+ none: (predicate) => buildExistsExpr(context, relation, scope, correlate(), "none", predicate)
3641
3647
  };
3642
3648
  if (isToOneCardinality(relation.cardinality)) return new Proxy(filters, { get(target, prop) {
3643
3649
  if (typeof prop !== "string") return void 0;
@@ -3648,7 +3654,7 @@ function createRelationFilterAccessor(context, parentNamespaceId, parentModelNam
3648
3654
  } });
3649
3655
  return {
3650
3656
  ...filters,
3651
- count: (predicate) => createOrderable(() => buildRelationCountExpr(context, relation, correlate(), predicate))
3657
+ count: (predicate) => createOrderable(() => buildRelationCountExpr(context, relation, scope, correlate(), predicate))
3652
3658
  };
3653
3659
  }
3654
3660
  /**
@@ -3672,39 +3678,45 @@ function relatedOrderableField(context, relation, relatedTableName, correlate, f
3672
3678
  if (!column || !hasTrait(context, column.codecId, "order")) return void 0;
3673
3679
  return createOrderable(() => {
3674
3680
  const rows = correlate();
3675
- return SubqueryExpr.of(rows.source.withProjection([ProjectionItem.of(columnName, rows.childScope.current.column(columnName))]).withWhere(rows.correlation));
3681
+ return SubqueryExpr.of(rows.source.withProjection([ProjectionItem.of(columnName, rows.child.column(columnName))]).withWhere(rows.correlation));
3676
3682
  });
3677
3683
  }
3678
- function buildRelationCountExpr(context, relation, rows, predicate) {
3679
- const childWhere = toRelationWhereExpr(context, relation.toNamespace, relation.to, predicate, rows.childScope);
3684
+ function buildRelationCountExpr(context, relation, scope, rows, predicate) {
3685
+ const childWhere = toRelationWhereExpr(context, relation.toNamespace, relation.to, predicate, scope, rows.child);
3680
3686
  return SubqueryExpr.of(rows.source.withProjection([ProjectionItem.of("count", plainAggregateExpr("count", void 0))]).withWhere(childWhere ? and(rows.correlation, childWhere) : rows.correlation));
3681
3687
  }
3682
- function correlateRelatedRows(context, parentNamespaceId, parentModelName, parentScope, relatedTableName, relation) {
3688
+ function correlateRelatedRows(context, parentNamespaceId, parentModelName, scope, parentTable, relatedTableName, relation) {
3689
+ const child = scope.aliasTable({
3690
+ namespaceId: relation.toNamespace,
3691
+ tableName: relatedTableName
3692
+ });
3683
3693
  if (hasThrough$1(relation)) {
3684
3694
  const { through } = relation;
3685
- const { childScope, junctionBinding } = parentScope.forManyToManyRelation(relation.toNamespace, relatedTableName, through.namespaceId, through.table);
3686
- const junctionJoinOn = buildPairedColumnExprs(junctionBinding, through.childColumns, childScope.current, through.targetColumns);
3695
+ const junction = scope.aliasTable({
3696
+ namespaceId: through.namespaceId,
3697
+ tableName: through.table
3698
+ });
3699
+ const junctionJoinOn = buildPairedColumnExprs(junction, through.childColumns, child, through.targetColumns);
3687
3700
  const parentLocalColumns = relation.on.localFields.map((field) => columnOfContractField(context.contract, parentNamespaceId, parentModelName, field));
3688
3701
  return {
3689
- childScope,
3690
- source: SelectAst.from(childScope.current.tableSource(context.contract)).withJoins([JoinAst.inner(junctionBinding.tableSource(context.contract), junctionJoinOn)]),
3691
- correlation: buildPairedColumnExprs(junctionBinding, through.parentColumns, parentScope.current, parentLocalColumns),
3702
+ child,
3703
+ source: SelectAst.from(child.tableSource(context.contract)).withJoins([JoinAst.inner(junction.tableSource(context.contract), junctionJoinOn)]),
3704
+ correlation: buildPairedColumnExprs(junction, through.parentColumns, parentTable, parentLocalColumns),
3692
3705
  keyColumn: firstJoinColumn(through.targetColumns, "targetColumns")
3693
3706
  };
3694
3707
  }
3695
- const childScope = parentScope.forRelation(relation.toNamespace, relatedTableName);
3696
3708
  return {
3697
- childScope,
3698
- source: SelectAst.from(childScope.current.tableSource(context.contract)),
3699
- correlation: buildJoinWhere(context.contract, parentNamespaceId, parentModelName, parentScope.current, childScope.current, relation),
3709
+ child,
3710
+ source: SelectAst.from(child.tableSource(context.contract)),
3711
+ correlation: buildJoinWhere(context.contract, parentNamespaceId, parentModelName, parentTable, child, relation),
3700
3712
  keyColumn: firstJoinColumn(resolveRelationTargetColumns(context.contract, relation), "targetFields")
3701
3713
  };
3702
3714
  }
3703
- function buildExistsExpr(context, relation, rows, mode, predicate) {
3704
- const childWhere = toRelationWhereExpr(context, relation.toNamespace, relation.to, predicate, rows.childScope);
3715
+ function buildExistsExpr(context, relation, scope, rows, mode, predicate) {
3716
+ const childWhere = toRelationWhereExpr(context, relation.toNamespace, relation.to, predicate, scope, rows.child);
3705
3717
  const filterPlan = planRelationFilterMode(rows.correlation, childWhere, mode);
3706
3718
  if (filterPlan.kind === "constantTrue") return AndExpr.true();
3707
- const subquery = rows.source.withProjection([ProjectionItem.of("_exists", rows.childScope.current.column(rows.keyColumn))]).withWhere(filterPlan.where);
3719
+ const subquery = rows.source.withProjection([ProjectionItem.of("_exists", rows.child.column(rows.keyColumn))]).withWhere(filterPlan.where);
3708
3720
  return filterPlan.notExists ? ExistsExpr.notExists(subquery) : ExistsExpr.exists(subquery);
3709
3721
  }
3710
3722
  function planRelationFilterMode(joinWhere, childWhere, mode) {
@@ -3745,10 +3757,10 @@ function buildPairedColumnExprs(leftTable, leftColumns, rightTable, rightColumns
3745
3757
  if (exprs.length === 1 && exprs[0]) return exprs[0];
3746
3758
  return and(...exprs);
3747
3759
  }
3748
- function toRelationWhereExpr(context, relatedNamespaceId, relatedModelName, predicate, scope) {
3760
+ function toRelationWhereExpr(context, relatedNamespaceId, relatedModelName, predicate, scope, table) {
3749
3761
  if (!predicate) return;
3750
- const accessor = createModelAccessorInScope(context, relatedNamespaceId, relatedModelName, void 0, scope);
3751
- if (typeof predicate === "function") return conditionExpr(predicate(accessor, callbackToolsFor(context, relatedNamespaceId, relatedModelName, scope)));
3762
+ const accessor = createModelAccessorInScope(context, relatedNamespaceId, relatedModelName, void 0, scope, table, void 0);
3763
+ if (typeof predicate === "function") return conditionExpr(predicate(accessor, callbackToolsFor(context, relatedModelName, table)));
3752
3764
  assertModelFieldNames(context.contract, relatedNamespaceId, relatedModelName, predicate);
3753
3765
  const exprs = [];
3754
3766
  for (const [fieldName, value] of Object.entries(predicate)) {
@@ -3824,7 +3836,7 @@ var GroupedCollection = class GroupedCollection {
3824
3836
  }));
3825
3837
  }
3826
3838
  having(predicate) {
3827
- const havingExpr = predicate(createHavingBuilder(this.contract, this.ctx.context.aggregateDescriptors, this.namespaceId, this.modelName, this.tableName));
3839
+ const havingExpr = predicate(createHavingBuilder(this.contract, this.ctx.context.aggregateDescriptors, this.namespaceId, this.modelName, this.preGroupState.tables.root));
3828
3840
  return this.#clone({ havingFilters: [...this.havingFilters, havingExpr] });
3829
3841
  }
3830
3842
  /**
@@ -3839,12 +3851,19 @@ var GroupedCollection = class GroupedCollection {
3839
3851
  method: "orderBy",
3840
3852
  model: this.modelName
3841
3853
  } });
3842
- const accessor = createModelAccessor(this.ctx.context, this.namespaceId, this.modelName);
3854
+ const tables = withScopeCopy(this.preGroupState.tables);
3855
+ const accessor = createModelAccessor(this.ctx.context, this.namespaceId, this.modelName, tables);
3843
3856
  const nextOrders = selectors.map((selector) => selector(accessor));
3844
- return this.#clone({ postGroup: {
3845
- ...this.postGroup,
3846
- orderBy: [...this.postGroup.orderBy, ...nextOrders]
3847
- } });
3857
+ return this.#clone({
3858
+ preGroupState: {
3859
+ ...this.preGroupState,
3860
+ tables
3861
+ },
3862
+ postGroup: {
3863
+ ...this.postGroup,
3864
+ orderBy: [...this.postGroup.orderBy, ...nextOrders]
3865
+ }
3866
+ });
3848
3867
  }
3849
3868
  /**
3850
3869
  * Apply `LIMIT n` to the grouped rows. Replaces any previous post-group
@@ -3900,7 +3919,7 @@ var GroupedCollection = class GroupedCollection {
3900
3919
  configure(meta);
3901
3920
  if (meta.annotations.size > 0) annotationsMap = meta.annotations;
3902
3921
  }
3903
- const compiled = mergeAnnotations(compileGroupedAggregate(this.contract, this.ctx.context.aggregateDescriptors, this.namespaceId, this.tableName, this.preGroupState, this.groupByColumns, aggregateSpec, combineWhereExprs(this.havingFilters), this.modelName, this.postGroup), annotationsMap);
3922
+ const compiled = mergeAnnotations(compileGroupedAggregate(this.contract, this.ctx.context.aggregateDescriptors, this.preGroupState, this.groupByColumns, aggregateSpec, combineWhereExprs(this.havingFilters), this.modelName, this.postGroup), annotationsMap);
3904
3923
  const mapRow = createStorageRowMapper(this.contract, this.namespaceId, this.modelName);
3905
3924
  return {
3906
3925
  plan: compiled,
@@ -3924,7 +3943,8 @@ var GroupedCollection = class GroupedCollection {
3924
3943
  * refused. The typed surface already excludes it; the runtime refusal covers
3925
3944
  * dynamic invocation.
3926
3945
  */
3927
- function createHavingBuilder(contract, aggregates, namespaceId, modelName, tableName) {
3946
+ function createHavingBuilder(contract, aggregates, namespaceId, modelName, root) {
3947
+ const { tableName } = root.storage;
3928
3948
  const fieldColumns = getModelFieldColumns(contract, namespaceId, modelName);
3929
3949
  const builder = {};
3930
3950
  for (const operation of aggregateOperationNames(aggregates)) builder[operation] = (field) => {
@@ -3934,7 +3954,7 @@ function createHavingBuilder(contract, aggregates, namespaceId, modelName, table
3934
3954
  meta: { operation }
3935
3955
  });
3936
3956
  const column = field === void 0 ? void 0 : columnOfCallerField(contract, namespaceId, fieldColumns, modelName, field);
3937
- return createHavingComparisonMethods(new AggregateExpr(operation, column === void 0 ? void 0 : ColumnRef.of(tableName, column)), () => resolveAggregate({
3957
+ return createHavingComparisonMethods(new AggregateExpr(operation, column === void 0 ? void 0 : root.column(column)), () => resolveAggregate({
3938
3958
  aggregates,
3939
3959
  contract,
3940
3960
  namespaceId,
@@ -4054,7 +4074,7 @@ async function executeNestedCreateMutation(options) {
4054
4074
  return withMutationScope(options.runtime, async (scope) => createGraph(scope, options.context, options.namespaceId, options.modelName, options.data));
4055
4075
  }
4056
4076
  async function executeNestedUpdateMutation(options) {
4057
- return withMutationScope(options.runtime, async (scope) => updateFirstGraph(scope, options.context, options.namespaceId, options.modelName, options.filters, options.data));
4077
+ return withMutationScope(options.runtime, async (scope) => updateFirstGraph(scope, options.context, options.namespaceId, options.modelName, options.tables, options.filters, options.data));
4058
4078
  }
4059
4079
  function buildRowIdentityFilterFromRow(contract, namespaceId, modelName, row) {
4060
4080
  const tableName = resolveModelTableName(contract, namespaceId, modelName);
@@ -4125,9 +4145,9 @@ async function createGraph(scope, context, namespaceId, modelName, input) {
4125
4145
  for (const relationMutation of junctionOwned) await applyJunctionOwnedMutation(scope, context, namespaceId, modelName, parentRow, relationMutation.relation, relationMutation.mutation);
4126
4146
  return parentRow;
4127
4147
  }
4128
- async function updateFirstGraph(scope, context, namespaceId, modelName, filters, input) {
4148
+ async function updateFirstGraph(scope, context, namespaceId, modelName, tables, filters, input) {
4129
4149
  const contract = context.contract;
4130
- const existingRow = await findFirstByFilters(scope, contract, namespaceId, modelName, filters);
4150
+ const existingRow = await findFirstByFilters(scope, contract, namespaceId, modelName, tables, filters);
4131
4151
  if (!existingRow) return null;
4132
4152
  const parsed = parseMutationInput(contract, namespaceId, modelName, input);
4133
4153
  const { parentOwned, childOwned, junctionOwned } = partitionByOwnership(parsed.relationMutations);
@@ -4145,9 +4165,9 @@ async function updateFirstGraph(scope, context, namespaceId, modelName, filters,
4145
4165
  values: mappedUpdateData
4146
4166
  });
4147
4167
  for (const def of appliedUpdateDefaults) mappedUpdateData[def.field] = def.value;
4148
- const identityWhere = shorthandToWhereExpr(context, namespaceId, modelName, castAs(buildRowIdentityFilterFromRow(contract, namespaceId, modelName, existingRow)));
4168
+ const identityWhere = shorthandToWhereExpr(context, namespaceId, modelName, castAs(buildRowIdentityFilterFromRow(contract, namespaceId, modelName, existingRow)), tables.root);
4149
4169
  if (!identityWhere) throw new InternalError(`Failed to build row identity filter for model "${modelName}"`);
4150
- const updatedRaw = (await queryPlanRows(scope, compileUpdateReturning(contract, namespaceId, modelName, tableName, mappedUpdateData, [identityWhere], void 0)).toArray())[0];
4170
+ const updatedRaw = (await queryPlanRows(scope, compileUpdateReturning(contract, modelName, tables, mappedUpdateData, [identityWhere], void 0)).toArray())[0];
4151
4171
  if (updatedRaw) parentRow = mapStorageRowToModelFields(contract, namespaceId, modelName, updatedRaw);
4152
4172
  }
4153
4173
  for (const relationMutation of childOwned) await applyChildOwnedMutation(scope, context, namespaceId, modelName, parentRow, relationMutation.relation, relationMutation.mutation);
@@ -4266,7 +4286,8 @@ async function applyChildOwnedMutation(scope, context, parentNamespaceId, parent
4266
4286
  }
4267
4287
  if (mutation.kind === "connect") {
4268
4288
  for (const criterion of mutation.criteria) {
4269
- const criterionWhere = shorthandToWhereExpr(context, relation.relatedNamespaceId, relation.relatedModelName, castAs(criterion));
4289
+ const related = createRelatedTables(relation);
4290
+ const criterionWhere = shorthandToWhereExpr(context, relation.relatedNamespaceId, relation.relatedModelName, castAs(criterion), related.root);
4270
4291
  if (!criterionWhere) throw ormError("ORM.RELATION_MUTATION_INVALID", `connect() nested mutation for relation "${relation.relationName}" requires non-empty criterion`, { meta: {
4271
4292
  kind: "connect",
4272
4293
  relation: relation.relationName,
@@ -4274,26 +4295,26 @@ async function applyChildOwnedMutation(scope, context, parentNamespaceId, parent
4274
4295
  } });
4275
4296
  const setValues = {};
4276
4297
  for (const [childColumn, parentValue] of parentValues.entries()) setValues[childColumn] = parentValue;
4277
- await executeUpdateCount(scope, contract, relation.relatedNamespaceId, relation.relatedTableName, setValues, [criterionWhere]);
4298
+ await executeUpdateCount(scope, contract, related, setValues, [criterionWhere]);
4278
4299
  }
4279
4300
  return;
4280
4301
  }
4281
4302
  const setValues = {};
4282
4303
  for (const childColumn of parentValues.keys()) setValues[childColumn] = null;
4283
4304
  if (!mutation.criteria || mutation.criteria.length === 0) {
4284
- const parentJoinWhere = buildChildJoinWhere(relation, parentValues);
4285
- await executeUpdateCount(scope, contract, relation.relatedNamespaceId, relation.relatedTableName, setValues, [parentJoinWhere]);
4305
+ const related = createRelatedTables(relation);
4306
+ await executeUpdateCount(scope, contract, related, setValues, [buildChildJoinWhere(contract, related.root, parentValues)]);
4286
4307
  return;
4287
4308
  }
4288
4309
  for (const criterion of mutation.criteria) {
4289
- const criterionWhere = shorthandToWhereExpr(context, relation.relatedNamespaceId, relation.relatedModelName, castAs(criterion));
4310
+ const related = createRelatedTables(relation);
4311
+ const criterionWhere = shorthandToWhereExpr(context, relation.relatedNamespaceId, relation.relatedModelName, castAs(criterion), related.root);
4290
4312
  if (!criterionWhere) throw ormError("ORM.RELATION_MUTATION_INVALID", `disconnect() nested mutation for relation "${relation.relationName}" requires non-empty criterion`, { meta: {
4291
4313
  kind: "disconnect",
4292
4314
  relation: relation.relationName,
4293
4315
  problem: "empty-criterion"
4294
4316
  } });
4295
- const parentJoinWhere = buildChildJoinWhere(relation, parentValues);
4296
- await executeUpdateCount(scope, contract, relation.relatedNamespaceId, relation.relatedTableName, setValues, [and(parentJoinWhere, criterionWhere)]);
4317
+ await executeUpdateCount(scope, contract, related, setValues, [and(buildChildJoinWhere(contract, related.root, parentValues), criterionWhere)]);
4297
4318
  }
4298
4319
  }
4299
4320
  async function applyJunctionOwnedMutation(scope, context, parentNamespaceId, parentModelName, parentRow, relation, mutation) {
@@ -4432,11 +4453,15 @@ async function deleteJunctionLink(scope, context, relation, parentPkValues, targ
4432
4453
  const junctionRow = {};
4433
4454
  for (const [column, value] of parentPkValues.entries()) writeJunctionColumn(junctionRow, through, column, value, relation.relationName);
4434
4455
  for (const [column, value] of targetPkValues.entries()) writeJunctionColumn(junctionRow, through, column, value, relation.relationName);
4456
+ const junction = createStatementTables({
4457
+ namespaceId: through.namespaceId,
4458
+ tableName: through.table
4459
+ });
4435
4460
  const exprs = [];
4436
- for (const [column, value] of Object.entries(junctionRow)) exprs.push(BinaryExpr.eq(ColumnRef.of(through.table, column), LiteralExpr.of(value)));
4461
+ for (const [column, value] of Object.entries(junctionRow)) exprs.push(BinaryExpr.eq(junction.root.column(column), paramRefForStorageColumn(context.contract, junction.root.storage, column, value)));
4437
4462
  const first = exprs[0];
4438
4463
  const where = exprs.length === 1 && first !== void 0 ? first : and(...exprs);
4439
- const compiled = compileDeleteCount(context.contract, through.namespaceId, through.table, [where]);
4464
+ const compiled = compileDeleteCount(context.contract, junction, [where]);
4440
4465
  await scope.execute(compiled);
4441
4466
  }
4442
4467
  function readParentColumnValues(contract, parentNamespaceId, parentModelName, relation, parentRow) {
@@ -4452,9 +4477,15 @@ function readParentColumnValues(contract, parentNamespaceId, parentModelName, re
4452
4477
  }
4453
4478
  return values;
4454
4479
  }
4455
- function buildChildJoinWhere(relation, childValues) {
4480
+ function createRelatedTables(relation) {
4481
+ return createStatementTables({
4482
+ namespaceId: relation.relatedNamespaceId,
4483
+ tableName: relation.relatedTableName
4484
+ });
4485
+ }
4486
+ function buildChildJoinWhere(contract, related, childValues) {
4456
4487
  const exprs = [];
4457
- for (const [childColumn, parentValue] of childValues.entries()) exprs.push(BinaryExpr.eq(ColumnRef.of(relation.relatedTableName, childColumn), LiteralExpr.of(parentValue)));
4488
+ for (const [childColumn, parentValue] of childValues.entries()) exprs.push(BinaryExpr.eq(related.column(childColumn), paramRefForStorageColumn(contract, related.storage, childColumn, parentValue)));
4458
4489
  const first = exprs[0];
4459
4490
  if (exprs.length === 1 && first !== void 0) return first;
4460
4491
  return and(...exprs);
@@ -4480,31 +4511,35 @@ async function insertSingleRow(scope, context, namespaceId, modelName, data) {
4480
4511
  }
4481
4512
  async function findRowByCriterion(scope, context, namespaceId, modelName, criterion) {
4482
4513
  const contract = context.contract;
4483
- const whereExpr = shorthandToWhereExpr(context, namespaceId, modelName, castAs(criterion));
4514
+ const tables = createStatementTables({
4515
+ namespaceId,
4516
+ tableName: resolveModelTableName(contract, namespaceId, modelName)
4517
+ });
4518
+ const whereExpr = shorthandToWhereExpr(context, namespaceId, modelName, castAs(criterion), tables.root);
4484
4519
  if (!whereExpr) throw ormError("ORM.RELATION_MUTATION_INVALID", `Nested connect for model "${modelName}" requires non-empty criterion`, { meta: {
4485
4520
  kind: "connect",
4486
4521
  model: modelName,
4487
4522
  problem: "empty-criterion"
4488
4523
  } });
4489
- const firstRow = (await queryPlanRows(scope, compileSelect(contract, namespaceId, modelName, resolveModelTableName(contract, namespaceId, modelName), {
4490
- ...emptyState(),
4524
+ const firstRow = (await queryPlanRows(scope, compileSelect(contract, modelName, {
4525
+ ...emptyState(tables),
4491
4526
  filters: [whereExpr],
4492
4527
  limit: 1
4493
4528
  })).toArray())[0];
4494
4529
  if (!firstRow) return null;
4495
4530
  return mapStorageRowToModelFields(contract, namespaceId, modelName, firstRow);
4496
4531
  }
4497
- async function findFirstByFilters(scope, contract, namespaceId, modelName, filters) {
4498
- const firstRow = (await queryPlanRows(scope, compileSelect(contract, namespaceId, modelName, resolveModelTableName(contract, namespaceId, modelName), {
4499
- ...emptyState(),
4532
+ async function findFirstByFilters(scope, contract, namespaceId, modelName, tables, filters) {
4533
+ const firstRow = (await queryPlanRows(scope, compileSelect(contract, modelName, {
4534
+ ...emptyState(tables),
4500
4535
  filters,
4501
4536
  limit: 1
4502
4537
  })).toArray())[0];
4503
4538
  if (!firstRow) return null;
4504
4539
  return mapStorageRowToModelFields(contract, namespaceId, modelName, firstRow);
4505
4540
  }
4506
- async function executeUpdateCount(scope, contract, namespaceId, tableName, setValues, filters) {
4507
- const compiled = compileUpdateCount(contract, namespaceId, tableName, setValues, filters);
4541
+ async function executeUpdateCount(scope, contract, tables, setValues, filters) {
4542
+ const compiled = compileUpdateCount(contract, tables, setValues, filters);
4508
4543
  await scope.execute(compiled);
4509
4544
  }
4510
4545
  const relationDefsCache = /* @__PURE__ */ new WeakMap();
@@ -4544,9 +4579,9 @@ function toFieldName(contract, namespaceId, modelName, columnName) {
4544
4579
  function normalizeWhereArg(arg, options) {
4545
4580
  if (arg === void 0) return;
4546
4581
  if (arg === null) throw ormError("ORM.ARGUMENT_INVALID", "WhereArg cannot be null. Pass undefined or a valid WhereExpr/ToWhereExpr payload.", { meta: { argument: "where" } });
4547
- if (isToWhereExpr(arg)) return arg.toWhereExpr();
4548
- if (options?.contract) return bindWhereExpr(options.contract, arg, options.namespaceId);
4549
- return arg;
4582
+ const expr = isToWhereExpr(arg) ? arg.toWhereExpr() : arg;
4583
+ if (!options) return expr;
4584
+ return bindWhereExpr(options.contract, expr, options.tables);
4550
4585
  }
4551
4586
  function isToWhereExpr(arg) {
4552
4587
  return typeof arg === "object" && arg !== null && "toWhereExpr" in arg && !isWhereExpr(arg);
@@ -4707,7 +4742,7 @@ var CollectionBase = class CollectionBase {
4707
4742
  this.modelName = modelName;
4708
4743
  this.namespaceId = options.namespaceId;
4709
4744
  this.tableName = options.tableName ?? resolveModelTableName(this.contract, options.namespaceId, modelName);
4710
- this.state = options.state ?? emptyState();
4745
+ this.state = options.state ?? emptyState(createCollectionTables(this.contract, options.namespaceId, modelName, this.tableName));
4711
4746
  this.registry = options.registry ?? /* @__PURE__ */ new Map();
4712
4747
  this.includeRefinementMode = options.includeRefinementMode ?? false;
4713
4748
  this.#installAggregateReducers();
@@ -4755,15 +4790,36 @@ var CollectionBase = class CollectionBase {
4755
4790
  return createIncludeScalar(operation, this.state, column);
4756
4791
  }
4757
4792
  where(input) {
4758
- const filter = normalizeWhereArg(typeof input === "function" ? whereArgOf(input(createModelAccessor(this.ctx.context, this.namespaceId, this.modelName, this.state.variantName), this.#callbackTools())) : isWhereDirectInput(input) ? input : shorthandToWhereExpr(this.ctx.context, this.namespaceId, this.modelName, input), {
4793
+ const tables = withScopeCopy(this.state.tables);
4794
+ const filter = normalizeWhereArg(typeof input === "function" ? whereArgOf(input(createModelAccessor(this.ctx.context, this.namespaceId, this.modelName, tables, this.state.variantName), this.#callbackTools(tables))) : isWhereDirectInput(input) ? input : shorthandToWhereExpr(this.ctx.context, this.namespaceId, this.modelName, input, tables.root), {
4759
4795
  contract: this.contract,
4760
- namespaceId: this.namespaceId
4796
+ tables: tableAliases(tables)
4761
4797
  });
4762
4798
  if (!filter) return blindCast(this);
4763
- return this.#cloneSelf({ filters: [...this.state.filters, filter] });
4799
+ return this.#cloneSelf({
4800
+ tables,
4801
+ filters: [...this.state.filters, filter]
4802
+ });
4803
+ }
4804
+ whereUnique(criterion) {
4805
+ if (this.includeRefinementMode) throw ormError("ORM.INCLUDE_INVALID", "whereUnique() is not available inside include() refinement callbacks", { meta: { action: "whereUnique()" } });
4806
+ 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: {
4807
+ method: "whereUnique",
4808
+ argument: "criterion",
4809
+ model: this.modelName
4810
+ } });
4811
+ const tables = withScopeCopy(this.state.tables);
4812
+ const filter = normalizeWhereArg(shorthandToWhereExpr(this.ctx.context, this.namespaceId, this.modelName, criterion, tables.root), {
4813
+ contract: this.contract,
4814
+ tables: tableAliases(tables)
4815
+ });
4816
+ return this.#cloneSelf(filter ? {
4817
+ tables,
4818
+ filters: [...this.state.filters, filter]
4819
+ } : {});
4764
4820
  }
4765
- #callbackTools() {
4766
- return createModelCallbackTools(this.ctx.context, this.namespaceId, this.modelName);
4821
+ #callbackTools(tables) {
4822
+ return createModelCallbackTools(this.ctx.context, this.modelName, tables);
4767
4823
  }
4768
4824
  with(fn) {
4769
4825
  return fn(this);
@@ -4815,7 +4871,7 @@ var CollectionBase = class CollectionBase {
4815
4871
  } });
4816
4872
  }
4817
4873
  const columnName = polyInfo.discriminatorColumn;
4818
- const filter = BinaryExpr.eq(ColumnRef.of(this.tableName, columnName), LiteralExpr.of(variantInfo.value));
4874
+ const filter = BinaryExpr.eq(this.state.tables.root.column(columnName), paramRefForStorageColumn(this.contract, this.state.tables.root.storage, columnName, variantInfo.value));
4819
4875
  return this.#cloneWithRow({
4820
4876
  filters: [...this.state.filters, filter],
4821
4877
  variantName: variantInfo.modelName
@@ -4823,14 +4879,16 @@ var CollectionBase = class CollectionBase {
4823
4879
  }
4824
4880
  include(relationName, refineFn) {
4825
4881
  const relation = resolveIncludeRelation(this.contract, this.namespaceId, this.modelName, relationName, this.state.variantName);
4826
- let nestedState = emptyState();
4882
+ const child = createIncludeTables(this.contract, this.state.tables, relation);
4883
+ let nestedState = emptyState(child.tables);
4884
+ let adoptedScope = child.tables.scope;
4827
4885
  let scalarSelector;
4828
4886
  let combineBranches;
4829
4887
  if (refineFn) {
4830
4888
  const refined = refineFn(this.#createCollection(blindCast(relation.relatedModelName), {
4831
4889
  tableName: relation.relatedTableName,
4832
4890
  namespaceId: relation.relatedNamespaceId,
4833
- state: emptyState(),
4891
+ state: nestedState,
4834
4892
  includeRefinementMode: true
4835
4893
  }));
4836
4894
  if (isIncludeScalar(refined)) {
@@ -4838,6 +4896,7 @@ var CollectionBase = class CollectionBase {
4838
4896
  relation: relationName,
4839
4897
  kind: "scalar"
4840
4898
  } });
4899
+ adoptedScope = refined.state.tables.scope;
4841
4900
  scalarSelector = refined;
4842
4901
  nestedState = refined.state;
4843
4902
  } else if (isIncludeCombine(refined)) {
@@ -4846,49 +4905,49 @@ var CollectionBase = class CollectionBase {
4846
4905
  kind: "combine"
4847
4906
  } });
4848
4907
  combineBranches = refined.branches;
4849
- } else if (isCollectionStateCarrier(refined)) nestedState = refined.state;
4850
- else throw ormError("ORM.INCLUDE_INVALID", `include('${relationName}') refinement must return a collection, include scalar selector, or combine() descriptor`, { meta: { relation: relationName } });
4908
+ } else if (isCollectionStateCarrier(refined)) {
4909
+ adoptedScope = refined.state.tables.scope;
4910
+ nestedState = refined.state;
4911
+ } else throw ormError("ORM.INCLUDE_INVALID", `include('${relationName}') refinement must return a collection, include scalar selector, or combine() descriptor`, { meta: { relation: relationName } });
4851
4912
  }
4852
4913
  const includeExpr = {
4853
4914
  relationName,
4854
4915
  relatedModelName: relation.relatedModelName,
4855
4916
  relatedNamespaceId: relation.relatedNamespaceId,
4856
4917
  relatedTableName: relation.relatedTableName,
4857
- localTableName: relation.localTableName,
4918
+ ...ifDefined("localVariantName", relation.localVariantName),
4858
4919
  targetColumns: relation.targetColumns,
4859
4920
  localColumns: relation.localColumns,
4860
4921
  cardinality: relation.cardinality,
4861
4922
  ...ifDefined("through", relation.through),
4923
+ ...ifDefined("junction", child.junction),
4862
4924
  nested: nestedState,
4863
4925
  scalar: scalarSelector,
4864
4926
  combine: combineBranches
4865
4927
  };
4866
- return this.#cloneWithRow({ includes: [...this.state.includes, includeExpr] });
4928
+ return this.#cloneWithRow({
4929
+ tables: {
4930
+ ...this.state.tables,
4931
+ scope: adoptedScope
4932
+ },
4933
+ includes: [...this.state.includes, includeExpr]
4934
+ });
4867
4935
  }
4868
4936
  select(...fields) {
4869
4937
  const selectedFields = mapSelectedFieldsToColumns(this.contract, this.namespaceId, this.modelName, this.state.variantName, fields);
4870
4938
  return this.#cloneWithRow({ selectedFields });
4871
4939
  }
4872
4940
  orderBy(selection) {
4873
- const accessor = createModelAccessor(this.ctx.context, this.namespaceId, this.modelName, this.state.variantName);
4874
- const tools = this.#callbackTools();
4941
+ const tables = withScopeCopy(this.state.tables);
4942
+ const accessor = createModelAccessor(this.ctx.context, this.namespaceId, this.modelName, tables, this.state.variantName);
4943
+ const tools = this.#callbackTools(tables);
4875
4944
  const nextOrders = (Array.isArray(selection) ? selection : [selection]).map((selector) => selector(accessor, tools));
4876
4945
  const existing = this.state.orderBy ?? [];
4877
- return this.#cloneSelf({ orderBy: [...existing, ...nextOrders] });
4946
+ return this.#cloneSelf({
4947
+ tables,
4948
+ orderBy: [...existing, ...nextOrders]
4949
+ });
4878
4950
  }
4879
- /**
4880
- * Switch to grouped-aggregate mode. Returns a `GroupedCollection`
4881
- * whose `.aggregate(...)` terminal produces one row per group with
4882
- * the chosen key columns plus the requested aggregates.
4883
- *
4884
- * ```typescript
4885
- * const stats = await db.orm.Post
4886
- * .where({ published: true })
4887
- * .groupBy('userId')
4888
- * .aggregate((agg) => ({ count: agg.count(), totalViews: agg.sum('views') }));
4889
- * // [{ userId: 1, count: 3, totalViews: 120 }, ...]
4890
- * ```
4891
- */
4892
4951
  groupBy(...fields) {
4893
4952
  assertLockCompatible(this.state, "groupBy");
4894
4953
  const groupByColumns = mapFieldsToColumns(this.contract, this.namespaceId, this.modelName, fields);
@@ -5006,7 +5065,6 @@ var CollectionBase = class CollectionBase {
5006
5065
  return {
5007
5066
  context: this.ctx.context,
5008
5067
  state: this.state,
5009
- tableName: this.tableName,
5010
5068
  modelName: this.modelName,
5011
5069
  namespaceId: this.namespaceId
5012
5070
  };
@@ -5020,27 +5078,6 @@ var CollectionBase = class CollectionBase {
5020
5078
  async firstOrThrow(filter, configure) {
5021
5079
  return this.#forFirst(filter, configure, "firstOrThrow").#dispatch().firstOrThrow();
5022
5080
  }
5023
- /**
5024
- * Read terminal: run an aggregate query (count, sum, avg, min, max)
5025
- * built via the `AggregateBuilder` callback. Returns one object
5026
- * with the requested aggregate values keyed by the aliases supplied
5027
- * in the spec.
5028
- *
5029
- * ```typescript
5030
- * const stats = await db.orm.Post
5031
- * .where({ published: true })
5032
- * .aggregate((agg) => ({
5033
- * total: agg.count(),
5034
- * averageViews: agg.avg('views'),
5035
- * maxViews: agg.max('views'),
5036
- * }));
5037
- * // { total: 42, averageViews: 17.3, maxViews: 9001 }
5038
- * ```
5039
- *
5040
- * Accepts an optional `configure` callback that receives a
5041
- * `MetaBuilder<'read'>` for attaching typed annotations.
5042
- * Annotations are merged into the compiled plan's `meta.annotations`.
5043
- */
5044
5081
  async aggregate(fn, configure) {
5045
5082
  const description = this.#describeAggregate(fn, configure);
5046
5083
  return description.consume(queryPlanRows(this.ctx.runtime, description.plan));
@@ -5059,7 +5096,7 @@ var CollectionBase = class CollectionBase {
5059
5096
  alias
5060
5097
  } });
5061
5098
  const annotationsMap = this.#collectAnnotationsFromMeta(configure, "read", "aggregate");
5062
- const compiled = mergeAnnotations(compileAggregate(this.contract, this.ctx.context.aggregateDescriptors, this.namespaceId, this.tableName, this.state, aggregateSpec, this.modelName), annotationsMap);
5099
+ const compiled = mergeAnnotations(compileAggregate(this.contract, this.ctx.context.aggregateDescriptors, this.state, aggregateSpec, this.modelName), annotationsMap);
5063
5100
  const results = entries.map(([alias, selector]) => {
5064
5101
  const resolved = resolveAggregate({
5065
5102
  aggregates: this.ctx.context.aggregateDescriptors,
@@ -5136,7 +5173,7 @@ var CollectionBase = class CollectionBase {
5136
5173
  context: this.ctx.context,
5137
5174
  runtime: this.ctx.runtime,
5138
5175
  plans,
5139
- tableName: this.tableName,
5176
+ tables: this.state.tables,
5140
5177
  modelName: this.modelName,
5141
5178
  namespaceId: this.namespaceId,
5142
5179
  variantName: this.state.variantName,
@@ -5151,7 +5188,7 @@ var CollectionBase = class CollectionBase {
5151
5188
  context: this.ctx.context,
5152
5189
  runtime: this.ctx.runtime,
5153
5190
  compiled,
5154
- tableName: this.tableName,
5191
+ tables: this.state.tables,
5155
5192
  modelName: this.modelName,
5156
5193
  namespaceId: this.namespaceId,
5157
5194
  variantName: this.state.variantName,
@@ -5215,6 +5252,8 @@ var CollectionBase = class CollectionBase {
5215
5252
  const tableName = this.tableName;
5216
5253
  const modelName = this.modelName;
5217
5254
  const namespaceId = this.namespaceId;
5255
+ const tables = this.state.tables;
5256
+ const variantTable = requireVariantTable(tables, variant.modelName);
5218
5257
  const baseFieldColumns = new Set(Object.values(baseFieldToColumn));
5219
5258
  const variantFieldColumns = new Set(Object.values(variantFieldToColumn));
5220
5259
  const generator = async function* () {
@@ -5242,8 +5281,8 @@ var CollectionBase = class CollectionBase {
5242
5281
  phase: "mti-base"
5243
5282
  } });
5244
5283
  for (const pkColumn of pkColumns) variantRow[pkColumn] = baseCreated[pkColumn];
5245
- applyCreateDefaults(collectionCtx, namespaceId, variant.table, [variantRow], defaultValueCache);
5246
- const variantCreated = (await queryPlanRows(scope, compileInsertReturning(contract, namespaceId, variant.modelName, variant.table, [variantRow], void 0)).toArray())[0];
5284
+ applyCreateDefaults(collectionCtx, variantTable.storage.namespaceId, variantTable.storage.tableName, [variantRow], defaultValueCache);
5285
+ const variantCreated = (await queryPlanRows(scope, compileInsertReturning(contract, variantTable.storage.namespaceId, variant.modelName, variantTable.storage.tableName, [variantRow], void 0)).toArray())[0];
5247
5286
  if (!variantCreated) throw ormError("ORM.MUTATION_ROW_MISSING", `MTI variant INSERT for model "${modelName}" into "${variant.table}" did not return a row`, { meta: {
5248
5287
  operation: "create",
5249
5288
  model: modelName,
@@ -5253,9 +5292,9 @@ var CollectionBase = class CollectionBase {
5253
5292
  const prefixedVariant = {};
5254
5293
  for (const [col, val] of Object.entries(variantCreated)) {
5255
5294
  if (pkColumns.includes(col)) continue;
5256
- prefixedVariant[`${variant.table}__${col}`] = val;
5295
+ prefixedVariant[variantColumnLabel(variantTable, col)] = val;
5257
5296
  }
5258
- return mapPolymorphicRow(contract, namespaceId, modelName, polyInfo, {
5297
+ return mapPolymorphicRow(contract, namespaceId, modelName, polyInfo, tables, {
5259
5298
  ...baseCreated,
5260
5299
  ...prefixedVariant
5261
5300
  }, variant.modelName);
@@ -5350,7 +5389,7 @@ var CollectionBase = class CollectionBase {
5350
5389
  context: this.ctx.context,
5351
5390
  runtime: this.ctx.runtime,
5352
5391
  compiled,
5353
- tableName: this.tableName,
5392
+ tables: this.state.tables,
5354
5393
  modelName: this.modelName,
5355
5394
  namespaceId: this.namespaceId,
5356
5395
  variantName: this.state.variantName,
@@ -5383,6 +5422,7 @@ var CollectionBase = class CollectionBase {
5383
5422
  runtime: this.ctx.runtime,
5384
5423
  namespaceId: this.namespaceId,
5385
5424
  modelName: this.modelName,
5425
+ tables: this.state.tables,
5386
5426
  filters: this.state.filters,
5387
5427
  data: blindCast(data)
5388
5428
  });
@@ -5412,12 +5452,12 @@ var CollectionBase = class CollectionBase {
5412
5452
  }
5413
5453
  applyUpdateDefaults(this.ctx, this.namespaceId, this.tableName, mappedData);
5414
5454
  const { selectedForQuery: selectedForUpdate, hiddenColumns } = this.#augmentMutationSelection();
5415
- const compiled = mergeAnnotations(compileUpdateReturning(this.contract, this.namespaceId, this.modelName, this.tableName, mappedData, this.state.filters, selectedForUpdate), annotationsMap);
5455
+ const compiled = mergeAnnotations(compileUpdateReturning(this.contract, this.modelName, this.state.tables, mappedData, this.state.filters, selectedForUpdate), annotationsMap);
5416
5456
  return dispatchMutationRows({
5417
5457
  context: this.ctx.context,
5418
5458
  runtime: this.ctx.runtime,
5419
5459
  compiled,
5420
- tableName: this.tableName,
5460
+ tables: this.state.tables,
5421
5461
  modelName: this.modelName,
5422
5462
  namespaceId: this.namespaceId,
5423
5463
  variantName: this.state.variantName,
@@ -5434,7 +5474,7 @@ var CollectionBase = class CollectionBase {
5434
5474
  if (Object.keys(mappedData).length === 0) return 0;
5435
5475
  applyUpdateDefaults(this.ctx, this.namespaceId, this.tableName, mappedData);
5436
5476
  const annotationsMap = this.#collectAnnotationsFromMeta(configure, "write", "updateAndCount");
5437
- const compiled = mergeAnnotations(compileUpdateCount(this.contract, this.namespaceId, this.tableName, mappedData, this.state.filters, this.state.variantName, this.modelName), annotationsMap);
5477
+ const compiled = mergeAnnotations(compileUpdateCount(this.contract, this.state.tables, mappedData, this.state.filters, this.state.variantName), annotationsMap);
5438
5478
  return (await this.ctx.runtime.execute(compiled)).affectedRows;
5439
5479
  }
5440
5480
  async delete(configure) {
@@ -5464,12 +5504,12 @@ var CollectionBase = class CollectionBase {
5464
5504
  #executeDeleteReturning(annotationsMap) {
5465
5505
  if (this.state.includes.length > 0) return this.#executeDeleteReturningWithIncludes(annotationsMap);
5466
5506
  const { selectedForQuery: selectedForDelete, hiddenColumns } = this.#augmentMutationSelection();
5467
- const compiled = mergeAnnotations(compileDeleteReturning(this.contract, this.namespaceId, this.modelName, this.tableName, this.state.filters, selectedForDelete), annotationsMap);
5507
+ const compiled = mergeAnnotations(compileDeleteReturning(this.contract, this.modelName, this.state.tables, this.state.filters, selectedForDelete), annotationsMap);
5468
5508
  return dispatchMutationRows({
5469
5509
  context: this.ctx.context,
5470
5510
  runtime: this.ctx.runtime,
5471
5511
  compiled,
5472
- tableName: this.tableName,
5512
+ tables: this.state.tables,
5473
5513
  modelName: this.modelName,
5474
5514
  namespaceId: this.namespaceId,
5475
5515
  variantName: this.state.variantName,
@@ -5500,11 +5540,10 @@ var CollectionBase = class CollectionBase {
5500
5540
  context: collection.ctx.context,
5501
5541
  runtime: scope,
5502
5542
  state: collection.state,
5503
- tableName: collection.tableName,
5504
5543
  modelName: collection.modelName,
5505
5544
  namespaceId: collection.namespaceId
5506
5545
  }).toArray();
5507
- const deletePlan = mergeAnnotations(compileDeleteCount(collection.contract, collection.namespaceId, collection.tableName, collection.state.filters, collection.state.variantName, collection.modelName), annotationsMap);
5546
+ const deletePlan = mergeAnnotations(compileDeleteCount(collection.contract, collection.state.tables, collection.state.filters, collection.state.variantName), annotationsMap);
5508
5547
  await scope.execute(deletePlan);
5509
5548
  return rows;
5510
5549
  });
@@ -5516,7 +5555,7 @@ var CollectionBase = class CollectionBase {
5516
5555
  assertBulkWriteIgnoresNothing(this.state, this.modelName, "deleteAndCount");
5517
5556
  assertLockCompatible(this.state, "mutation");
5518
5557
  const annotationsMap = this.#collectAnnotationsFromMeta(configure, "write", "deleteAndCount");
5519
- const compiled = mergeAnnotations(compileDeleteCount(this.contract, this.namespaceId, this.tableName, this.state.filters, this.state.variantName, this.modelName), annotationsMap);
5558
+ const compiled = mergeAnnotations(compileDeleteCount(this.contract, this.state.tables, this.state.filters, this.state.variantName), annotationsMap);
5520
5559
  return (await this.ctx.runtime.execute(compiled)).affectedRows;
5521
5560
  }
5522
5561
  #buildUpsertConflictCriterion(createValues, conflictColumns) {
@@ -5579,16 +5618,16 @@ var CollectionBase = class CollectionBase {
5579
5618
  if (value === void 0) throw new InternalError(`Missing identity field "${fieldName}" while resolving single-row scope for model "${this.modelName}"`);
5580
5619
  criterion[fieldName] = value;
5581
5620
  }
5582
- return shorthandToWhereExpr(this.ctx.context, this.namespaceId, this.modelName, blindCast(criterion)) ?? null;
5621
+ return shorthandToWhereExpr(this.ctx.context, this.namespaceId, this.modelName, blindCast(criterion), this.state.tables.root) ?? null;
5583
5622
  }
5584
5623
  async #reloadMutationRowByIdentity(criterion) {
5585
5624
  return this.#reloadMutationRowByCriterion(criterion, "row identity");
5586
5625
  }
5587
5626
  async #reloadMutationRowByCriterion(criterion, criterionLabel) {
5588
- const whereExpr = shorthandToWhereExpr(this.ctx.context, this.namespaceId, this.modelName, blindCast(criterion));
5627
+ const whereExpr = shorthandToWhereExpr(this.ctx.context, this.namespaceId, this.modelName, blindCast(criterion), this.state.tables.root);
5589
5628
  if (!whereExpr) throw new InternalError(`Failed to build ${criterionLabel} filter for mutation result on model "${this.modelName}"`);
5590
5629
  const resultState = {
5591
- ...emptyState(),
5630
+ ...emptyState(this.state.tables),
5592
5631
  filters: [whereExpr],
5593
5632
  includes: this.state.includes,
5594
5633
  selectedFields: this.state.selectedFields,
@@ -5598,7 +5637,6 @@ var CollectionBase = class CollectionBase {
5598
5637
  context: this.ctx.context,
5599
5638
  runtime: this.ctx.runtime,
5600
5639
  state: resultState,
5601
- tableName: this.tableName,
5602
5640
  modelName: this.modelName,
5603
5641
  namespaceId: this.namespaceId
5604
5642
  }))[0] ?? null;
@@ -5614,7 +5652,7 @@ var CollectionBase = class CollectionBase {
5614
5652
  const waitPolicy = lockWaitPolicyOf(strength, options);
5615
5653
  if (waitPolicy !== void 0) assertLockCapability(this.contract, lockOptionCapabilities[waitPolicy], strength);
5616
5654
  const clause = LockingClause.of(strength, {
5617
- of: [this.tableName],
5655
+ of: [this.state.tables.root.alias],
5618
5656
  ...ifDefined("waitPolicy", waitPolicy)
5619
5657
  });
5620
5658
  return this.#cloneSelf({ locking: [...this.state.locking ?? [], clause] });
@@ -5672,7 +5710,6 @@ var CollectionBase = class CollectionBase {
5672
5710
  context: this.ctx.context,
5673
5711
  runtime: this.ctx.runtime,
5674
5712
  state: this.state,
5675
- tableName: this.tableName,
5676
5713
  modelName: this.modelName,
5677
5714
  namespaceId: this.namespaceId
5678
5715
  });
@@ -5839,6 +5876,6 @@ function createPreparedRowQuery(description, statement) {
5839
5876
  } });
5840
5877
  }
5841
5878
  //#endregion
5842
- export { Collection, GroupedCollection, all, and, createModelAccessor, createPreparedRowQuery, emptyState, not, or, orderByField, orm, prepareQuery };
5879
+ export { Collection, GroupedCollection, all, and, createCollectionTables, createModelAccessor, createPreparedRowQuery, emptyState, not, or, orderByField, orm, prepareQuery };
5843
5880
 
5844
5881
  //# sourceMappingURL=orm-client.mjs.map