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

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,
@@ -677,6 +677,108 @@ function mapCursorValuesToColumns(contract, namespaceId, modelName, cursorValues
677
677
  }
678
678
  return mappedCursor;
679
679
  }
680
+ const MAX_ALIAS_BYTES = 63;
681
+ const encoder = new TextEncoder();
682
+ function shortenToBytes(value, maxBytes) {
683
+ let shortened = "";
684
+ let bytes = 0;
685
+ for (const character of value) {
686
+ bytes += encoder.encode(character).length;
687
+ if (bytes > maxBytes) break;
688
+ shortened += character;
689
+ }
690
+ return shortened;
691
+ }
692
+ var TableScopeImpl = class TableScopeImpl {
693
+ #aliases;
694
+ constructor(aliases = []) {
695
+ this.#aliases = new Set(aliases);
696
+ }
697
+ alias(preferred) {
698
+ for (let n = 1;; n += 1) {
699
+ const suffix = n === 1 ? "" : `_${n}`;
700
+ const candidate = `${shortenToBytes(preferred, MAX_ALIAS_BYTES - suffix.length)}${suffix}`;
701
+ if (!this.#aliases.has(candidate)) {
702
+ this.#aliases.add(candidate);
703
+ return candidate;
704
+ }
705
+ }
706
+ }
707
+ aliasTable(storage) {
708
+ const alias = this.alias(storage.tableName);
709
+ const coordinate = Object.freeze({ ...storage });
710
+ return Object.freeze({
711
+ alias,
712
+ storage: coordinate,
713
+ column: (name) => ColumnRef.of(alias, name),
714
+ tableSource: (contract) => tableSourceForContract(contract, coordinate.namespaceId, coordinate.tableName, alias)
715
+ });
716
+ }
717
+ copy() {
718
+ return new TableScopeImpl(this.#aliases);
719
+ }
720
+ };
721
+ function createTableScope() {
722
+ return new TableScopeImpl();
723
+ }
724
+ function createModelTables(contract, scope, namespaceId, modelName, tableName) {
725
+ const root = scope.aliasTable({
726
+ namespaceId,
727
+ tableName
728
+ });
729
+ const variants = /* @__PURE__ */ new Map();
730
+ const mtiVariants = resolvePolymorphismInfo(contract, namespaceId, modelName)?.mtiVariants ?? [];
731
+ for (const variant of mtiVariants) variants.set(variant.modelName, scope.aliasTable({
732
+ namespaceId,
733
+ tableName: variant.table
734
+ }));
735
+ return {
736
+ scope,
737
+ root,
738
+ variants
739
+ };
740
+ }
741
+ function createCollectionTables(contract, namespaceId, modelName, tableName = resolveModelTableName(contract, namespaceId, modelName)) {
742
+ return createModelTables(contract, createTableScope(), namespaceId, modelName, tableName);
743
+ }
744
+ function createIncludeTables(contract, parent, relation) {
745
+ const scope = parent.scope.copy();
746
+ return {
747
+ tables: createModelTables(contract, scope, relation.relatedNamespaceId, relation.relatedModelName, relation.relatedTableName),
748
+ junction: relation.through === void 0 ? void 0 : scope.aliasTable({
749
+ namespaceId: relation.through.namespaceId,
750
+ tableName: relation.through.table
751
+ })
752
+ };
753
+ }
754
+ function createStatementTables(storage) {
755
+ const scope = createTableScope();
756
+ return {
757
+ scope,
758
+ root: scope.aliasTable(storage),
759
+ variants: /* @__PURE__ */ new Map()
760
+ };
761
+ }
762
+ function withScopeCopy(tables) {
763
+ return {
764
+ ...tables,
765
+ scope: tables.scope.copy()
766
+ };
767
+ }
768
+ function requireVariantTable(tables, variantModelName) {
769
+ const variantTable = tables.variants.get(variantModelName);
770
+ if (variantTable === void 0) throw new InternalError(`Collection state has no aliased table for variant "${variantModelName}"`);
771
+ return variantTable;
772
+ }
773
+ function tableAliases(tables) {
774
+ return new Map([tables.root, ...tables.variants.values()].map((table) => [table.alias, table.storage]));
775
+ }
776
+ function variantColumnLabelPrefix(variantTable) {
777
+ return `${variantTable.alias}__`;
778
+ }
779
+ function variantColumnLabel(variantTable, column) {
780
+ return `${variantColumnLabelPrefix(variantTable)}${column}`;
781
+ }
680
782
  function stripHiddenMappedFields(contract, namespaceId, modelName, mapped, hiddenColumns) {
681
783
  if (hiddenColumns.length === 0) return;
682
784
  const columnToField = getModelColumnFields(contract, namespaceId, modelName);
@@ -694,7 +796,7 @@ function createStorageRowMapper(contract, namespaceId, modelName) {
694
796
  }
695
797
  const mergedColumnToFieldCache = /* @__PURE__ */ new WeakMap();
696
798
  function getMergedColumnToFieldMap(contract, namespaceId, baseModelName, variantModelName, variantTable) {
697
- const cacheKey = `${namespaceId}:${baseModelName}:${variantModelName}:${variantTable ?? ""}`;
799
+ const cacheKey = `${namespaceId}:${baseModelName}:${variantModelName}:${variantTable?.alias ?? ""}`;
698
800
  let perContract = mergedColumnToFieldCache.get(contract);
699
801
  if (!perContract) {
700
802
  perContract = /* @__PURE__ */ new Map();
@@ -705,25 +807,27 @@ function getMergedColumnToFieldMap(contract, namespaceId, baseModelName, variant
705
807
  const baseMap = getModelColumnFields(contract, namespaceId, baseModelName);
706
808
  const variantMap = getOwnColumnFields(contract, namespaceId, variantModelName);
707
809
  const merged = { ...baseMap };
708
- for (const [col, field] of Object.entries(variantMap)) if (variantTable) merged[`${variantTable}__${col}`] = field;
810
+ for (const [col, field] of Object.entries(variantMap)) if (variantTable) merged[variantColumnLabel(variantTable, col)] = field;
709
811
  else merged[col] = field;
710
812
  perContract.set(cacheKey, merged);
711
813
  return merged;
712
814
  }
713
- function mapPolymorphicRow(contract, namespaceId, baseModelName, polyInfo, row, variantName) {
815
+ function variantTableOf(tables, variant) {
816
+ return variant.strategy === "mti" ? requireVariantTable(tables, variant.modelName) : void 0;
817
+ }
818
+ function mapPolymorphicRow(contract, namespaceId, baseModelName, polyInfo, tables, row, variantName) {
714
819
  const discriminatorValue = row[polyInfo.discriminatorColumn] ?? row["__prisma_polymorphic_discriminator"];
715
820
  const variant = variantName ? polyInfo.variants.get(variantName) : typeof discriminatorValue === "string" ? polyInfo.variantsByValue.get(discriminatorValue) : void 0;
716
821
  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));
822
+ return mapKnownColumnNames(row, getMergedColumnToFieldMap(contract, namespaceId, baseModelName, variant.modelName, variantTableOf(tables, variant)));
719
823
  }
720
- function createPolymorphicRowMapper(contract, namespaceId, baseModelName, polyInfo, variantName) {
824
+ function createPolymorphicRowMapper(contract, namespaceId, baseModelName, polyInfo, tables, variantName) {
721
825
  const baseMapper = captureColumnMapper(() => getModelColumnFields(contract, namespaceId, baseModelName));
722
826
  const mappersByValue = /* @__PURE__ */ new Map();
723
827
  let pinnedMapper = baseMapper;
724
828
  for (const [name, variant] of polyInfo.variants) {
725
829
  if (variantName && name !== variantName) continue;
726
- const mapper = captureColumnMapper(() => getMergedColumnToFieldMap(contract, namespaceId, baseModelName, variant.modelName, variant.strategy === "mti" ? variant.table : void 0));
830
+ const mapper = captureColumnMapper(() => getMergedColumnToFieldMap(contract, namespaceId, baseModelName, variant.modelName, variantTableOf(tables, variant)));
727
831
  if (variantName) pinnedMapper = mapper;
728
832
  for (const [value, candidate] of polyInfo.variantsByValue) if (candidate === variant) mappersByValue.set(value, mapper);
729
833
  }
@@ -872,43 +976,43 @@ function mergeAnnotations(plan, annotations) {
872
976
  })
873
977
  });
874
978
  }
875
- function namespaceCoordinateForSource(source) {
876
- return source.kind === "table-source" ? source.namespaceId : void 0;
979
+ function bindWhereExpr(contract, expr, aliases) {
980
+ return bindWhereExprInScope(contract, expr, aliases);
877
981
  }
878
- function bindWhereExpr(contract, expr, namespaceId) {
982
+ function bindWhereExprInScope(contract, expr, aliases) {
879
983
  return expr.accept({
880
984
  columnRef(expr) {
881
- return bindExpression(contract, expr);
985
+ return bindExpression(contract, expr, aliases);
882
986
  },
883
987
  identifierRef(expr) {
884
988
  return expr;
885
989
  },
886
990
  subquery(expr) {
887
- return bindExpression(contract, expr);
991
+ return bindExpression(contract, expr, aliases);
888
992
  },
889
993
  operation(expr) {
890
- return bindExpression(contract, expr);
994
+ return bindExpression(contract, expr, aliases);
891
995
  },
892
996
  aggregate(expr) {
893
- return bindExpression(contract, expr);
997
+ return bindExpression(contract, expr, aliases);
894
998
  },
895
999
  windowFunc(expr) {
896
- return bindExpression(contract, expr);
1000
+ return bindExpression(contract, expr, aliases);
897
1001
  },
898
1002
  functionCall(expr) {
899
- return bindExpression(contract, expr);
1003
+ return bindExpression(contract, expr, aliases);
900
1004
  },
901
1005
  cast(expr) {
902
- return bindExpression(contract, expr);
1006
+ return bindExpression(contract, expr, aliases);
903
1007
  },
904
1008
  case(expr) {
905
- return bindExpression(contract, expr);
1009
+ return bindExpression(contract, expr, aliases);
906
1010
  },
907
1011
  jsonObject(expr) {
908
- return bindExpression(contract, expr);
1012
+ return bindExpression(contract, expr, aliases);
909
1013
  },
910
1014
  jsonArrayAgg(expr) {
911
- return bindExpression(contract, expr);
1015
+ return bindExpression(contract, expr, aliases);
912
1016
  },
913
1017
  literal(expr) {
914
1018
  return expr;
@@ -920,81 +1024,92 @@ function bindWhereExpr(contract, expr, namespaceId) {
920
1024
  return expr;
921
1025
  },
922
1026
  list(expr) {
923
- return bindExpression(contract, expr);
1027
+ return bindExpression(contract, expr, aliases);
924
1028
  },
925
1029
  binary(expr) {
926
- const left = bindExpression(contract, expr.left);
1030
+ const left = bindExpression(contract, expr.left, aliases);
927
1031
  const bindingColumn = left.kind === "column-ref" ? left : void 0;
928
- return new BinaryExpr(expr.op, left, bindComparable(contract, expr.right, bindingColumn, namespaceId));
1032
+ return new BinaryExpr(expr.op, left, bindComparable(contract, expr.right, bindingColumn, aliases));
929
1033
  },
930
1034
  and(expr) {
931
- return AndExpr.of(expr.exprs.map((part) => bindWhereExpr(contract, part, namespaceId)));
1035
+ return AndExpr.of(expr.exprs.map((part) => bindWhereExprInScope(contract, part, aliases)));
932
1036
  },
933
1037
  or(expr) {
934
- return OrExpr.of(expr.exprs.map((part) => bindWhereExpr(contract, part, namespaceId)));
1038
+ return OrExpr.of(expr.exprs.map((part) => bindWhereExprInScope(contract, part, aliases)));
935
1039
  },
936
1040
  exists(expr) {
937
- return expr.notExists ? ExistsExpr.notExists(bindSelectAst(contract, expr.subquery)) : ExistsExpr.exists(bindSelectAst(contract, expr.subquery));
1041
+ return expr.notExists ? ExistsExpr.notExists(bindSelectAst(contract, expr.subquery, aliases)) : ExistsExpr.exists(bindSelectAst(contract, expr.subquery, aliases));
938
1042
  },
939
1043
  nullCheck(expr) {
940
- return expr.isNull ? NullCheckExpr.isNull(bindExpression(contract, expr.expr)) : NullCheckExpr.isNotNull(bindExpression(contract, expr.expr));
1044
+ return expr.isNull ? NullCheckExpr.isNull(bindExpression(contract, expr.expr, aliases)) : NullCheckExpr.isNotNull(bindExpression(contract, expr.expr, aliases));
941
1045
  },
942
1046
  not(expr) {
943
- return new NotExpr(bindWhereExpr(contract, expr.expr, namespaceId));
1047
+ return new NotExpr(bindWhereExprInScope(contract, expr.expr, aliases));
944
1048
  },
945
1049
  rawExpr(expr) {
946
1050
  return expr;
947
1051
  }
948
1052
  });
949
1053
  }
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
1054
+ function bindComparable(contract, comparable, bindingColumn, aliases) {
1055
+ 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);
1056
+ if (comparable.kind === "literal") return paramRefForAlias(contract, bindingColumn, comparable.value, aliases);
1057
+ if (comparable.kind === "list") return ListExpression.of(comparable.values.map((value) => value.kind === "literal" ? paramRefForAlias(contract, bindingColumn, value.value, aliases) : value));
1058
+ return bindExpression(contract, comparable, aliases);
1059
+ }
1060
+ function unknownColumn(alias, column) {
1061
+ return ormError("ORM.COLUMN_UNKNOWN", `Unknown column "${column}" in table "${alias}"`, { meta: {
1062
+ tableName: alias,
1063
+ column
961
1064
  } });
962
- const codec = codecRefForStorageColumn(contract.storage, resolved.namespaceId, columnRef.table, columnRef.column);
963
- return ParamRef.of(value, codec ? { codec } : void 0);
964
1065
  }
965
- function createExpressionBinder(contract) {
966
- return { select: (ast) => bindSelectAst(contract, ast) };
1066
+ function paramRefForAlias(contract, columnRef, value, aliases) {
1067
+ const coordinate = aliases.get(columnRef.table);
1068
+ if (coordinate === void 0) throw unknownColumn(columnRef.table, columnRef.column);
1069
+ return paramRefForTable(contract, coordinate, columnRef.table, columnRef.column, value);
1070
+ }
1071
+ function paramRefForTable(contract, coordinate, alias, column, value) {
1072
+ const resolved = resolveStorageTable(contract.storage, coordinate.tableName, coordinate.namespaceId);
1073
+ if (resolved === void 0 || !resolved.table.columns[column]) throw unknownColumn(alias, column);
1074
+ const codec = codecRefForStorageColumn(contract.storage, resolved.namespaceId, coordinate.tableName, column);
1075
+ return ParamRef.of(value, codec ? { codec } : void 0);
967
1076
  }
968
- function bindExpression(contract, expr) {
969
- return expr.rewrite(createExpressionBinder(contract));
1077
+ function paramRefForStorageColumn(contract, storage, column, value) {
1078
+ return paramRefForTable(contract, storage, storage.tableName, column, value);
970
1079
  }
971
- function bindProjectionExpr(contract, expr) {
972
- return expr.kind === "literal" ? expr : bindExpression(contract, expr);
1080
+ function bindExpression(contract, expr, aliases) {
1081
+ return expr.rewrite({ select: (ast) => bindSelectAst(contract, ast, aliases) });
973
1082
  }
974
- function bindOrderByItem(contract, orderItem) {
975
- return orderItem.withExpr(bindExpression(contract, orderItem.expr));
1083
+ function bindProjectionExpr(contract, expr, aliases) {
1084
+ return expr.kind === "literal" ? expr : bindExpression(contract, expr, aliases);
976
1085
  }
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);
1086
+ function bindJoin(contract, join, aliases) {
1087
+ 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
1088
  }
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));
1089
+ function bindFromSource(contract, source, aliases) {
1090
+ if (source.kind === "derived-table-source") return DerivedTableSource.as(source.alias, bindSelectAst(contract, source.query, aliases));
984
1091
  return source;
985
1092
  }
986
- function bindSelectAst(contract, ast) {
987
- const namespaceId = ast.from !== void 0 ? namespaceCoordinateForSource(ast.from) : void 0;
1093
+ function aliasesWithSources(outer, sources) {
1094
+ const aliases = new Map(outer);
1095
+ for (const source of sources) if (source.kind === "table-source") aliases.set(source.alias ?? source.name, {
1096
+ namespaceId: source.namespaceId,
1097
+ tableName: source.name
1098
+ });
1099
+ return aliases;
1100
+ }
1101
+ function bindSelectAst(contract, ast, outer) {
1102
+ const aliases = aliasesWithSources(outer, [...ast.from !== void 0 ? [ast.from] : [], ...(ast.joins ?? []).map((join) => join.source)]);
988
1103
  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)),
1104
+ ...ast.from !== void 0 ? { from: bindFromSource(contract, ast.from, outer) } : {},
1105
+ joins: ast.joins?.map((join) => bindJoin(contract, join, aliases)),
1106
+ projection: ast.projection.map((projection) => new ProjectionItem(projection.alias, bindProjectionExpr(contract, projection.expr, aliases), projection.codec)),
1107
+ where: ast.where ? bindWhereExprInScope(contract, ast.where, aliases) : void 0,
1108
+ orderBy: ast.orderBy?.map((orderItem) => orderItem.withExpr(bindExpression(contract, orderItem.expr, aliases))),
994
1109
  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,
1110
+ distinctOn: ast.distinctOn?.map((expr) => bindExpression(contract, expr, aliases)),
1111
+ groupBy: ast.groupBy?.map((expr) => bindExpression(contract, expr, aliases)),
1112
+ having: ast.having ? bindWhereExprInScope(contract, ast.having, aliases) : void 0,
998
1113
  limit: ast.limit,
999
1114
  offset: ast.offset,
1000
1115
  locking: ast.locking,
@@ -1006,14 +1121,14 @@ function combineWhereExprs(filters) {
1006
1121
  if (filters.length === 1) return filters[0];
1007
1122
  return AndExpr.of(filters);
1008
1123
  }
1009
- function createBoundaryExpr(tableName, entry) {
1010
- return new BinaryExpr(entry.direction === "asc" ? "gt" : "lt", ColumnRef.of(tableName, entry.column), LiteralExpr.of(entry.value));
1124
+ function createBoundaryExpr(contract, table, entry) {
1125
+ return new BinaryExpr(entry.direction === "asc" ? "gt" : "lt", table.column(entry.column), paramRefForStorageColumn(contract, table.storage, entry.column, entry.value));
1011
1126
  }
1012
- function buildLexicographicCursorWhere(tableName, entries) {
1127
+ function buildLexicographicCursorWhere(contract, table, entries) {
1013
1128
  const branches = entries.map((entry, index) => {
1014
1129
  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));
1130
+ for (const prefixEntry of entries.slice(0, index)) branchExprs.push(BinaryExpr.eq(table.column(prefixEntry.column), paramRefForStorageColumn(contract, table.storage, prefixEntry.column, prefixEntry.value)));
1131
+ branchExprs.push(createBoundaryExpr(contract, table, entry));
1017
1132
  if (branchExprs.length === 1) {
1018
1133
  const branch = branchExprs[0];
1019
1134
  assertDefined(branch, "cursor branch contains its boundary expression");
@@ -1028,7 +1143,7 @@ function buildLexicographicCursorWhere(tableName, entries) {
1028
1143
  }
1029
1144
  return OrExpr.of(branches);
1030
1145
  }
1031
- function buildCursorWhere(tableName, orderBy, cursor) {
1146
+ function buildCursorWhere(contract, table, orderBy, cursor) {
1032
1147
  if (!cursor || !orderBy || orderBy.length === 0) return;
1033
1148
  assertCursorCompatibleOrder(orderBy);
1034
1149
  const entries = [];
@@ -1044,28 +1159,12 @@ function buildCursorWhere(tableName, orderBy, cursor) {
1044
1159
  });
1045
1160
  }
1046
1161
  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
- };
1162
+ if (entries.length === 1 && firstEntry !== void 0) return createBoundaryExpr(contract, table, firstEntry);
1163
+ return buildLexicographicCursorWhere(contract, table, entries);
1060
1164
  }
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);
1165
+ function buildStateWhere(contract, state) {
1166
+ const cursorWhere = buildCursorWhere(contract, state.tables.root, state.orderBy, state.cursor);
1167
+ return combineWhereExprs(cursorWhere ? [...state.filters, cursorWhere] : state.filters);
1069
1168
  }
1070
1169
  /**
1071
1170
  * Wrap a base SELECT in a `ROW_NUMBER() OVER (PARTITION BY … ORDER BY …) = 1`
@@ -1098,32 +1197,33 @@ function wrapWithRowNumberDedup(options) {
1098
1197
  }
1099
1198
  /**
1100
1199
  * FROM source + WHERE for `state.distinct`: wraps in a `ROW_NUMBER`-ranked
1101
- * derived table aliased back to `tableName`, so callers need no rewriting.
1200
+ * derived table aliased back to the root alias, so callers need no rewriting.
1102
1201
  */
1103
- function buildDedupedTableSource(contract, namespaceId, tableName, state, where, wrapProjection, joins) {
1202
+ function buildDedupedTableSource(contract, state, where, wrapProjection, joins) {
1203
+ const { root } = state.tables;
1104
1204
  if (!hasEntries(state.distinct)) return {
1105
- source: tableSourceForContract(contract, namespaceId, tableName),
1205
+ source: root.tableSource(contract),
1106
1206
  where
1107
1207
  };
1108
- const distinctColumnRefs = state.distinct.map((column) => ColumnRef.of(tableName, column));
1208
+ const distinctColumnRefs = state.distinct.map((column) => root.column(column));
1109
1209
  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({
1210
+ let inner = SelectAst.from(root.tableSource(contract)).withProjection([...wrapProjection, ProjectionItem.of("__prisma_distinct_rn", WindowFuncExpr.rowNumber({
1111
1211
  partitionBy: distinctColumnRefs,
1112
1212
  orderBy: rankingOrderBy
1113
1213
  }))]);
1114
1214
  if (joins && joins.length > 0) inner = inner.withJoins(joins);
1115
1215
  if (where) inner = inner.withWhere(where);
1116
1216
  return {
1117
- source: DerivedTableSource.as(tableName, inner),
1118
- where: BinaryExpr.eq(ColumnRef.of(tableName, "__prisma_distinct_rn"), LiteralExpr.of(1))
1217
+ source: DerivedTableSource.as(root.alias, inner),
1218
+ where: BinaryExpr.eq(root.column("__prisma_distinct_rn"), LiteralExpr.of(1))
1119
1219
  };
1120
1220
  }
1121
- function buildPrimaryKeyJoinOn(leftTable, rightTable, primaryKeyColumns) {
1221
+ function buildPrimaryKeyJoinOn(left, right, primaryKeyColumns) {
1122
1222
  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))));
1223
+ if (primaryKeyColumns.length === 1 && firstColumn !== void 0) return EqColJoinOn.of(left.column(firstColumn), right.column(firstColumn));
1224
+ return AndExpr.of(primaryKeyColumns.map((column) => BinaryExpr.eq(left.column(column), right.column(column))));
1125
1225
  }
1126
- function buildMtiJoins(contract, namespaceId, polyInfo, variantName, selectedColumnsByTable) {
1226
+ function buildMtiJoins(contract, tables, polyInfo, variantName, selectedColumnsByVariant) {
1127
1227
  const joins = [];
1128
1228
  const projection = [];
1129
1229
  const variantsToJoin = variantName ? polyInfo.mtiVariants.filter((v) => v.modelName === variantName) : polyInfo.mtiVariants;
@@ -1131,19 +1231,19 @@ function buildMtiJoins(contract, namespaceId, polyInfo, variantName, selectedCol
1131
1231
  joins,
1132
1232
  projection
1133
1233
  };
1134
- const pkColumns = resolvePrimaryKeyColumns(contract, namespaceId, polyInfo.baseTable);
1234
+ const { root } = tables;
1235
+ const pkColumns = resolvePrimaryKeyColumns(contract, root.storage.namespaceId, root.storage.tableName);
1135
1236
  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);
1237
+ const variantTable = requireVariantTable(tables, variant.modelName);
1238
+ const joinOn = buildPrimaryKeyJoinOn(root, variantTable, pkColumns);
1239
+ joins.push(variantName ? JoinAst.inner(variantTable.tableSource(contract), joinOn) : JoinAst.left(variantTable.tableSource(contract), joinOn));
1240
+ const { namespaceId, tableName } = variantTable.storage;
1241
+ const variantColumns = getColumnsReadOnTable(contract, namespaceId, variant.modelName, tableName);
1242
+ const selectedVariantColumns = selectedColumnsByVariant?.get(variant.modelName);
1142
1243
  for (const col of variantColumns) {
1143
1244
  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)));
1245
+ if (selectedColumnsByVariant !== void 0 && selectedVariantColumns?.has(col) !== true) continue;
1246
+ projection.push(ProjectionItem.of(variantColumnLabel(variantTable, col), variantTable.column(col), codecRefForStorageColumn(contract.storage, namespaceId, tableName, col)));
1147
1247
  }
1148
1248
  }
1149
1249
  return {
@@ -1155,30 +1255,31 @@ function hasEntries(value) {
1155
1255
  return value !== void 0 && value.length > 0;
1156
1256
  }
1157
1257
  /**
1158
- * The rows an aggregate reduces over, one SELECT aliased to `tableName` — an
1258
+ * The rows an aggregate reduces over, one SELECT aliased to the root alias — an
1159
1259
  * aggregate has no outer level of its own, so where/joins/distinct/orderBy/
1160
1260
  * limit/offset all have to live in this one wrap.
1161
1261
  */
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);
1262
+ function buildAggregateInput(contract, state, modelName, projection) {
1263
+ const { root } = state.tables;
1264
+ const polyInfo = modelName ? resolvePolymorphismInfo(contract, root.storage.namespaceId, modelName) : void 0;
1265
+ const variantJoins = polyInfo && polyInfo.mtiVariants.length > 0 ? buildMtiJoins(contract, state.tables, polyInfo, state.variantName, void 0).joins : [];
1266
+ const where = buildStateWhere(contract, state);
1267
+ const hiddenOrders = hasEntries(state.distinct) ? projectExpressionOrders(root, state.orderBy) : void 0;
1268
+ const { source, where: effectiveWhere } = buildDedupedTableSource(contract, state, where, [...projection, ...hiddenOrders?.projection ?? []], variantJoins);
1168
1269
  let inner = SelectAst.from(source).withProjection(projection);
1169
1270
  if (!hasEntries(state.distinct) && variantJoins.length > 0) inner = inner.withJoins(variantJoins);
1170
1271
  if (effectiveWhere) inner = inner.withWhere(effectiveWhere);
1171
- if (hasEntries(state.distinctOn)) inner = inner.withDistinctOn(state.distinctOn.map((column) => ColumnRef.of(tableName, column)));
1272
+ if (hasEntries(state.distinctOn)) inner = inner.withDistinctOn(state.distinctOn.map((column) => root.column(column)));
1172
1273
  const orderBy = hiddenOrders?.orderBy ?? state.orderBy;
1173
1274
  if (hasEntries(orderBy)) inner = inner.withOrderBy(orderBy);
1174
1275
  if (state.limit !== void 0) inner = inner.withLimit(state.limit);
1175
1276
  if (state.offset !== void 0) inner = inner.withOffset(state.offset);
1176
- return { source: DerivedTableSource.as(tableName, inner) };
1277
+ return { source: DerivedTableSource.as(root.alias, inner) };
1177
1278
  }
1178
1279
  /**
1179
1280
  * 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
1281
  */
1181
- function projectExpressionOrders(tableName, orderBy) {
1282
+ function projectExpressionOrders(root, orderBy) {
1182
1283
  const projection = [];
1183
1284
  return {
1184
1285
  projection,
@@ -1186,7 +1287,7 @@ function projectExpressionOrders(tableName, orderBy) {
1186
1287
  if (item.expr.kind === "column-ref") return item;
1187
1288
  const alias = `__order_${index}`;
1188
1289
  projection.push(ProjectionItem.of(alias, item.expr));
1189
- return item.withExpr(ColumnRef.of(tableName, alias));
1290
+ return item.withExpr(root.column(alias));
1190
1291
  })
1191
1292
  };
1192
1293
  }
@@ -1199,8 +1300,9 @@ function predicateComparison(op, left, right) {
1199
1300
  function predicateExpression(value) {
1200
1301
  if (isExpression(value)) return value.buildAst();
1201
1302
  }
1202
- function emptyState() {
1303
+ function emptyState(tables) {
1203
1304
  return {
1305
+ tables,
1204
1306
  filters: [],
1205
1307
  includes: [],
1206
1308
  orderBy: void 0,
@@ -1300,7 +1402,8 @@ const COMPARISON_METHODS_META = {
1300
1402
  create: (left) => () => NullCheckExpr.isNotNull(left)
1301
1403
  }
1302
1404
  };
1303
- function toAggregateProjection(contract, aggregates, namespaceId, tableName, selector) {
1405
+ function toAggregateProjection(contract, aggregates, root, selector) {
1406
+ const { namespaceId, tableName } = root.storage;
1304
1407
  const { codec, input: inputCodec, lower } = resolveAggregate({
1305
1408
  aggregates,
1306
1409
  contract,
@@ -1309,7 +1412,7 @@ function toAggregateProjection(contract, aggregates, namespaceId, tableName, sel
1309
1412
  fn: selector.fn,
1310
1413
  column: selector.column
1311
1414
  });
1312
- const inputExpr = selector.column === void 0 ? void 0 : ColumnRef.of(tableName, selector.column);
1415
+ const inputExpr = selector.column === void 0 ? void 0 : root.column(selector.column);
1313
1416
  return {
1314
1417
  expr: lower !== void 0 ? lower({
1315
1418
  expr: inputExpr,
@@ -1383,14 +1486,16 @@ function validateGroupedHavingExpr(expr) {
1383
1486
  rawExpr: rejectHavingExpr
1384
1487
  });
1385
1488
  }
1386
- function aggregateInputColumns(tableName, entries, orderBy, groupByColumns = []) {
1489
+ function aggregateInputColumns(root, entries, orderBy, groupByColumns = []) {
1387
1490
  const columns = new Set(groupByColumns);
1388
1491
  for (const [, selector] of entries) if (selector.column !== void 0) columns.add(selector.column);
1389
1492
  for (const item of orderBy ?? []) if (item.expr.kind === "column-ref") columns.add(item.expr.column);
1390
1493
  if (columns.size === 0) return [ProjectionItem.of("__row", LiteralExpr.of(1))];
1391
- return Array.from(columns, (column) => ProjectionItem.of(column, ColumnRef.of(tableName, column)));
1494
+ return Array.from(columns, (column) => ProjectionItem.of(column, root.column(column)));
1392
1495
  }
1393
- function compileAggregate(contract, aggregates, namespaceId, tableName, state, aggregateSpec, modelName) {
1496
+ function compileAggregate(contract, aggregates, state, aggregateSpec, modelName) {
1497
+ const { root } = state.tables;
1498
+ const { namespaceId, tableName } = root.storage;
1394
1499
  const entries = Object.entries(aggregateSpec);
1395
1500
  if (entries.length === 0) throw ormError("ORM.AGGREGATE_SELECTOR_MISSING", "aggregate() requires at least one aggregation selector", { meta: {
1396
1501
  method: "aggregate",
@@ -1404,9 +1509,9 @@ function compileAggregate(contract, aggregates, namespaceId, tableName, state, a
1404
1509
  const hasPagination = state.limit !== void 0 || state.offset !== void 0;
1405
1510
  const hasDistinct = state.distinct !== void 0 && state.distinct.length > 0 || state.distinctOn !== void 0 && state.distinctOn.length > 0;
1406
1511
  if (hasPagination || hasDistinct) {
1407
- const { source } = buildAggregateInput(contract, namespaceId, tableName, state, modelName, aggregateInputColumns(tableName, entries, state.orderBy));
1512
+ const { source } = buildAggregateInput(contract, state, modelName, aggregateInputColumns(root, entries, state.orderBy));
1408
1513
  const projection = entries.map(([alias, selector]) => {
1409
- const { expr, codec } = toAggregateProjection(contract, aggregates, namespaceId, tableName, selector);
1514
+ const { expr, codec } = toAggregateProjection(contract, aggregates, root, selector);
1410
1515
  return ProjectionItem.of(alias, expr, codec);
1411
1516
  });
1412
1517
  const ast = SelectAst.from(source).withProjection(projection);
@@ -1414,19 +1519,21 @@ function compileAggregate(contract, aggregates, namespaceId, tableName, state, a
1414
1519
  return buildOrmQueryPlan(contract, ast, params);
1415
1520
  }
1416
1521
  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 });
1522
+ const variantJoins = polyInfo && polyInfo.mtiVariants.length > 0 ? buildMtiJoins(contract, state.tables, polyInfo, state.variantName, void 0).joins : [];
1523
+ const where = buildStateWhere(contract, state);
1419
1524
  const projection = entries.map(([alias, selector]) => {
1420
- const { expr, codec } = toAggregateProjection(contract, aggregates, namespaceId, tableName, selector);
1525
+ const { expr, codec } = toAggregateProjection(contract, aggregates, root, selector);
1421
1526
  return ProjectionItem.of(alias, expr, codec);
1422
1527
  });
1423
- let ast = SelectAst.from(tableSourceForContract(contract, namespaceId, tableName)).withProjection(projection);
1528
+ let ast = SelectAst.from(root.tableSource(contract)).withProjection(projection);
1424
1529
  if (variantJoins.length > 0) ast = ast.withJoins(variantJoins);
1425
1530
  if (where) ast = ast.withWhere(where);
1426
1531
  const { params } = deriveParamsFromAst(ast);
1427
1532
  return buildOrmQueryPlan(contract, ast, params);
1428
1533
  }
1429
- function compileGroupedAggregate(contract, aggregates, namespaceId, tableName, preGroupState, groupByColumns, aggregateSpec, havingExpr, modelName, postGroup = emptyGroupPagingState()) {
1534
+ function compileGroupedAggregate(contract, aggregates, preGroupState, groupByColumns, aggregateSpec, havingExpr, modelName, postGroup = emptyGroupPagingState()) {
1535
+ const { root } = preGroupState.tables;
1536
+ const { namespaceId, tableName } = root.storage;
1430
1537
  if (groupByColumns.length === 0) throw ormError("ORM.GROUP_BY_FIELD_MISSING", "groupBy() requires at least one field", { meta: {
1431
1538
  namespaceId,
1432
1539
  tableName
@@ -1441,8 +1548,8 @@ function compileGroupedAggregate(contract, aggregates, namespaceId, tableName, p
1441
1548
  assertDistinctOnCapability(contract, "distinctOn");
1442
1549
  assertDistinctOnCompatibleOrder(preGroupState.orderBy, preGroupState.distinctOn.length);
1443
1550
  }
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);
1551
+ const projection = [...groupByColumns.map((column) => ProjectionItem.of(column, root.column(column), codecRefForStorageColumn(contract.storage, namespaceId, tableName, column))), ...entries.map(([alias, selector]) => {
1552
+ const { expr, codec } = toAggregateProjection(contract, aggregates, root, selector);
1446
1553
  return ProjectionItem.of(alias, expr, codec);
1447
1554
  })];
1448
1555
  const hasPagination = preGroupState.limit !== void 0 || preGroupState.offset !== void 0;
@@ -1450,14 +1557,15 @@ function compileGroupedAggregate(contract, aggregates, namespaceId, tableName, p
1450
1557
  const needsInputSelect = hasPagination || hasDistinct;
1451
1558
  let ast;
1452
1559
  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)));
1560
+ const { source } = buildAggregateInput(contract, preGroupState, modelName, aggregateInputColumns(root, entries, preGroupState.orderBy, groupByColumns));
1561
+ ast = SelectAst.from(source).withProjection(projection).withGroupBy(groupByColumns.map((column) => root.column(column)));
1455
1562
  } else {
1456
1563
  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)));
1564
+ const { tables, variantName } = preGroupState;
1565
+ const variantJoins = polyInfo && polyInfo.mtiVariants.length > 0 ? buildMtiJoins(contract, tables, polyInfo, variantName, void 0).joins : [];
1566
+ ast = SelectAst.from(root.tableSource(contract)).withProjection(projection).withGroupBy(groupByColumns.map((column) => root.column(column)));
1459
1567
  if (variantJoins.length > 0) ast = ast.withJoins(variantJoins);
1460
- const where = buildStateWhere(contract, tableName, preGroupState, { namespaceId });
1568
+ const where = buildStateWhere(contract, preGroupState);
1461
1569
  if (where) ast = ast.withWhere(where);
1462
1570
  }
1463
1571
  if (havingExpr) ast = ast.withHaving(validateGroupedHavingExpr(havingExpr));
@@ -1467,8 +1575,15 @@ function compileGroupedAggregate(contract, aggregates, namespaceId, tableName, p
1467
1575
  const { params } = deriveParamsFromAst(ast);
1468
1576
  return buildOrmQueryPlan(contract, ast, params);
1469
1577
  }
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)));
1578
+ function aliasTarget(namespaceId, tableName) {
1579
+ return createTableScope().aliasTable({
1580
+ namespaceId,
1581
+ tableName
1582
+ });
1583
+ }
1584
+ function buildReturningColumns(contract, modelName, target, returningColumns) {
1585
+ const { namespaceId, tableName } = target.storage;
1586
+ 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
1587
  }
1473
1588
  function toParamAssignments(contract, namespaceId, tableName, values) {
1474
1589
  const assignments = {};
@@ -1519,20 +1634,22 @@ function normalizeInsertRows(contract, namespaceId, tableName, rows) {
1519
1634
  return normalizedRow;
1520
1635
  }) };
1521
1636
  }
1522
- function conflictSkipClause(tableName, conflictSkip) {
1637
+ function conflictSkipClause(target, conflictSkip) {
1523
1638
  if (!conflictSkip) return void 0;
1524
1639
  if (conflictSkip.columns.length === 0) return InsertOnConflict.doNothing();
1525
- return InsertOnConflict.on(conflictSkip.columns.map((column) => ColumnRef.of(tableName, column))).doNothing();
1640
+ return InsertOnConflict.on(conflictSkip.columns.map((column) => target.column(column))).doNothing();
1526
1641
  }
1527
1642
  function compileInsertReturning(contract, namespaceId, modelName, tableName, rows, returningColumns, conflictSkip) {
1643
+ const target = aliasTarget(namespaceId, tableName);
1528
1644
  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));
1645
+ const ast = InsertAst.into(target.tableSource(contract)).withRows(normalizedRows).withOnConflict(conflictSkipClause(target, conflictSkip)).withReturning(buildReturningColumns(contract, modelName, target, returningColumns));
1530
1646
  const { params } = deriveParamsFromAst(ast);
1531
1647
  return buildOrmQueryPlan(contract, ast, params);
1532
1648
  }
1533
1649
  function compileInsertCount(contract, namespaceId, tableName, rows, conflictSkip) {
1650
+ const target = aliasTarget(namespaceId, tableName);
1534
1651
  const { rows: normalizedRows } = normalizeInsertRows(contract, namespaceId, tableName, rows);
1535
- const ast = InsertAst.into(tableSourceForContract(contract, namespaceId, tableName)).withRows(normalizedRows).withOnConflict(conflictSkipClause(tableName, conflictSkip));
1652
+ const ast = InsertAst.into(target.tableSource(contract)).withRows(normalizedRows).withOnConflict(conflictSkipClause(target, conflictSkip));
1536
1653
  const { params } = deriveParamsFromAst(ast);
1537
1654
  return buildOrmQueryPlan(contract, ast, params);
1538
1655
  }
@@ -1541,29 +1658,14 @@ function stripUndefinedValues(row) {
1541
1658
  for (const [key, value] of Object.entries(row)) if (value !== void 0) result[key] = value;
1542
1659
  return result;
1543
1660
  }
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)]);
1661
+ function buildCountMutationWhere(contract, tables, filters, variantName) {
1662
+ const variantTable = variantName === void 0 ? void 0 : tables.variants.get(variantName);
1663
+ if (variantTable === void 0) return combineWhereExprs(filters);
1664
+ const { root } = tables;
1665
+ const pkColumns = resolvePrimaryKeyColumns(contract, root.storage.namespaceId, root.storage.tableName);
1666
+ const rootCopy = tables.scope.copy().aliasTable(root.storage);
1667
+ const where = combineWhereExprs([...pkColumns.map((column) => BinaryExpr.eq(rootCopy.column(column), root.column(column))), ...filters]);
1668
+ 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
1669
  if (where) subquery = subquery.withWhere(where);
1568
1670
  return ExistsExpr.exists(subquery);
1569
1671
  }
@@ -1602,37 +1704,44 @@ function compileInsertCountSplit(contract, namespaceId, tableName, rows, conflic
1602
1704
  function compileUpsertReturning(contract, namespaceId, modelName, tableName, createValues, updateValues, conflictColumns, returningColumns) {
1603
1705
  const createAssignments = toParamAssignments(contract, namespaceId, tableName, createValues);
1604
1706
  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));
1707
+ const target = aliasTarget(namespaceId, tableName);
1708
+ const conflictTarget = InsertOnConflict.on(conflictColumns.map((column) => target.column(column)));
1709
+ const onConflict = updateAssignments ? conflictTarget.doUpdateSet(updateAssignments.assignments) : conflictTarget.doNothing();
1710
+ const ast = InsertAst.into(target.tableSource(contract)).withRows([createAssignments.assignments]).withOnConflict(onConflict).withReturning(buildReturningColumns(contract, modelName, target, returningColumns));
1607
1711
  const { params } = deriveParamsFromAst(ast);
1608
1712
  return buildOrmQueryPlan(contract, ast, params);
1609
1713
  }
1610
- function compileUpdateReturning(contract, namespaceId, modelName, tableName, setValues, filters, returningColumns) {
1714
+ function compileUpdateReturning(contract, modelName, tables, setValues, filters, returningColumns) {
1715
+ const { root } = tables;
1716
+ const { namespaceId, tableName } = root.storage;
1611
1717
  const where = combineWhereExprs(filters);
1612
1718
  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));
1719
+ let ast = UpdateAst.table(root.tableSource(contract)).withSet(assignments).withReturning(buildReturningColumns(contract, modelName, root, returningColumns));
1614
1720
  if (where) ast = ast.withWhere(where);
1615
1721
  const { params } = deriveParamsFromAst(ast);
1616
1722
  return buildOrmQueryPlan(contract, ast, params);
1617
1723
  }
1618
- function compileUpdateCount(contract, namespaceId, tableName, setValues, filters, variantName, modelName) {
1619
- const where = buildCountMutationWhere(contract, namespaceId, tableName, filters, variantName, modelName);
1724
+ function compileUpdateCount(contract, tables, setValues, filters, variantName) {
1725
+ const { root } = tables;
1726
+ const { namespaceId, tableName } = root.storage;
1727
+ const where = buildCountMutationWhere(contract, tables, filters, variantName);
1620
1728
  const { assignments } = toParamAssignments(contract, namespaceId, tableName, setValues);
1621
- let ast = UpdateAst.table(tableSourceForContract(contract, namespaceId, tableName)).withSet(assignments);
1729
+ let ast = UpdateAst.table(root.tableSource(contract)).withSet(assignments);
1622
1730
  if (where) ast = ast.withWhere(where);
1623
1731
  const { params } = deriveParamsFromAst(ast);
1624
1732
  return buildOrmQueryPlan(contract, ast, params);
1625
1733
  }
1626
- function compileDeleteReturning(contract, namespaceId, modelName, tableName, filters, returningColumns) {
1734
+ function compileDeleteReturning(contract, modelName, tables, filters, returningColumns) {
1735
+ const { root } = tables;
1627
1736
  const where = combineWhereExprs(filters);
1628
- let ast = DeleteAst.from(tableSourceForContract(contract, namespaceId, tableName)).withReturning(buildReturningColumns(contract, namespaceId, modelName, tableName, returningColumns));
1737
+ let ast = DeleteAst.from(root.tableSource(contract)).withReturning(buildReturningColumns(contract, modelName, root, returningColumns));
1629
1738
  if (where) ast = ast.withWhere(where);
1630
1739
  const { params } = deriveParamsFromAst(ast);
1631
1740
  return buildOrmQueryPlan(contract, ast, params);
1632
1741
  }
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));
1742
+ function compileDeleteCount(contract, tables, filters, variantName) {
1743
+ const where = buildCountMutationWhere(contract, tables, filters, variantName);
1744
+ let ast = DeleteAst.from(tables.root.tableSource(contract));
1636
1745
  if (where) ast = ast.withWhere(where);
1637
1746
  const { params } = deriveParamsFromAst(ast);
1638
1747
  return buildOrmQueryPlan(contract, ast, params);
@@ -1706,8 +1815,9 @@ function jsonEntryProjection(value, identity) {
1706
1815
  if (identity.document === true) return new JsonDocumentProjection(value);
1707
1816
  return new NativeJsonValueProjection(value);
1708
1817
  }
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)));
1818
+ function buildProjection(contract, modelName, table, selectedFields, projectedThrough) {
1819
+ const { namespaceId, tableName } = table.storage;
1820
+ 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
1821
  }
1712
1822
  function appendUnique(values, value) {
1713
1823
  if (!values.includes(value)) values.push(value);
@@ -1715,7 +1825,7 @@ function appendUnique(values, value) {
1715
1825
  function resolvePolymorphicProjectionSelection(contract, namespaceId, modelName, polyInfo, state) {
1716
1826
  if (state.selectedFields === void 0) return {
1717
1827
  baseSelectedFields: void 0,
1718
- selectedMtiColumnsByTable: void 0,
1828
+ selectedMtiColumnsByVariant: void 0,
1719
1829
  needsHiddenDiscriminator: false
1720
1830
  };
1721
1831
  const baseColumnToField = getModelColumnFields(contract, namespaceId, modelName);
@@ -1724,7 +1834,7 @@ function resolvePolymorphicProjectionSelection(contract, namespaceId, modelName,
1724
1834
  columnToField: getOwnColumnFields(contract, namespaceId, variant.modelName)
1725
1835
  }));
1726
1836
  const baseSelectedFields = [];
1727
- const selectedMtiColumnsByTable = /* @__PURE__ */ new Map();
1837
+ const selectedMtiColumnsByVariant = /* @__PURE__ */ new Map();
1728
1838
  let hasVariantOwnedSelection = false;
1729
1839
  for (const column of state.selectedFields) {
1730
1840
  const isBaseColumn = Object.hasOwn(baseColumnToField, column);
@@ -1738,10 +1848,10 @@ function resolvePolymorphicProjectionSelection(contract, namespaceId, modelName,
1738
1848
  appendUnique(baseSelectedFields, column);
1739
1849
  continue;
1740
1850
  }
1741
- let selectedColumns = selectedMtiColumnsByTable.get(variant.table);
1851
+ let selectedColumns = selectedMtiColumnsByVariant.get(variant.modelName);
1742
1852
  if (selectedColumns === void 0) {
1743
1853
  selectedColumns = /* @__PURE__ */ new Set();
1744
- selectedMtiColumnsByTable.set(variant.table, selectedColumns);
1854
+ selectedMtiColumnsByVariant.set(variant.modelName, selectedColumns);
1745
1855
  }
1746
1856
  selectedColumns.add(column);
1747
1857
  }
@@ -1749,13 +1859,13 @@ function resolvePolymorphicProjectionSelection(contract, namespaceId, modelName,
1749
1859
  }
1750
1860
  return {
1751
1861
  baseSelectedFields,
1752
- selectedMtiColumnsByTable,
1862
+ selectedMtiColumnsByVariant,
1753
1863
  needsHiddenDiscriminator: state.variantName === void 0 && hasVariantOwnedSelection && !baseSelectedFields.includes(polyInfo.discriminatorColumn)
1754
1864
  };
1755
1865
  }
1756
- function buildHiddenDiscriminatorProjection(contract, namespaceId, polyInfo, tableRef, needed) {
1866
+ function buildHiddenDiscriminatorProjection(contract, table, polyInfo, needed) {
1757
1867
  if (!needed) return [];
1758
- return [ProjectionItem.of(POLYMORPHIC_DISCRIMINATOR_ALIAS, ColumnRef.of(tableRef, polyInfo.discriminatorColumn), codecRefForStorageColumn(contract.storage, namespaceId, polyInfo.baseTable, polyInfo.discriminatorColumn))];
1868
+ return [ProjectionItem.of(POLYMORPHIC_DISCRIMINATOR_ALIAS, table.column(polyInfo.discriminatorColumn), codecRefForStorageColumn(contract.storage, table.storage.namespaceId, table.storage.tableName, polyInfo.discriminatorColumn))];
1759
1869
  }
1760
1870
  function buildIncludeOrderArtifacts(relationName, rowAlias, childOrderBy) {
1761
1871
  if (!childOrderBy || childOrderBy.length === 0) return {
@@ -1777,41 +1887,34 @@ function buildIncludeOrderArtifacts(relationName, rowAlias, childOrderBy) {
1777
1887
  function localColumnsForRowInclude(include) {
1778
1888
  return include.through?.parentLocalColumns ?? include.localColumns;
1779
1889
  }
1780
- function buildIncludeJoinExpr(include, childTableRef, parentLocalRefs) {
1890
+ function buildIncludeJoinExpr(include, child, parentLocalRefs) {
1781
1891
  invariant(parentLocalRefs.length === include.targetColumns.length, `Include '${include.relationName}' has mismatched join column counts: ${parentLocalRefs.length} local, ${include.targetColumns.length} target`);
1782
1892
  const joinExprs = include.targetColumns.map((targetColumn, i) => {
1783
1893
  const parentLocalRef = parentLocalRefs[i];
1784
1894
  assertDefined(parentLocalRef, `Include '${include.relationName}': no local column at ${i}`);
1785
- return BinaryExpr.eq(ColumnRef.of(childTableRef, targetColumn), parentLocalRef);
1895
+ return BinaryExpr.eq(child.column(targetColumn), parentLocalRef);
1786
1896
  });
1787
1897
  const [firstExpr] = joinExprs;
1788
1898
  assertDefined(firstExpr, `Include '${include.relationName}' has no join columns`);
1789
1899
  return joinExprs.length === 1 ? firstExpr : AndExpr.of(joinExprs);
1790
1900
  }
1791
- function resolveParentLocalRefs(parentSource, include, localColumns) {
1901
+ function localTable(tables, include) {
1902
+ return include.localVariantName === void 0 ? tables.root : requireVariantTable(tables, include.localVariantName);
1903
+ }
1904
+ function resolveParentLocalRefs(parent, include, localColumns) {
1905
+ const local = localTable(parent.tables, include);
1906
+ const { projectedThrough } = parent;
1792
1907
  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);
1908
+ if (projectedThrough === void 0) return local.column(column);
1909
+ return ColumnRef.of(projectedThrough, local === parent.tables.root ? column : variantColumnLabel(local, column));
1796
1910
  });
1797
1911
  }
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
- };
1912
+ function requireJunction(include) {
1913
+ if (include.junction === void 0) throw new InternalError(`Include '${include.relationName}' goes through a junction table but carries no aliased table for it`);
1914
+ return include.junction;
1804
1915
  }
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);
1916
+ function buildNestedIncludeProjections(contract, aggregates, scope, parent, includes) {
1917
+ return includes.map((nested) => buildCorrelatedIncludeProjection(contract, aggregates, scope, parent, nested).projection);
1815
1918
  }
1816
1919
  /**
1817
1920
  * The aliases a level's nested includes contribute. Each such subquery
@@ -1829,13 +1932,8 @@ function documentAliasesOf(nestedProjections) {
1829
1932
  * variant-specific columns live on the base table and reach the row through
1830
1933
  * the ordinary base-column projection (`buildProjection`); only the MTI
1831
1934
  * 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
1935
  */
1838
- function buildChildPolymorphismJoinsAndProjection(contract, include, childTableAlias, childTableRef) {
1936
+ function buildChildPolymorphismJoinsAndProjection(contract, include) {
1839
1937
  const polyInfo = resolvePolymorphismInfo(contract, include.relatedNamespaceId, include.relatedModelName);
1840
1938
  if (!polyInfo) return {
1841
1939
  joins: [],
@@ -1844,35 +1942,25 @@ function buildChildPolymorphismJoinsAndProjection(contract, include, childTableA
1844
1942
  baseSelectedFields: include.nested.selectedFields
1845
1943
  };
1846
1944
  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);
1945
+ const { joins, projection } = buildMtiJoins(contract, include.nested.tables, polyInfo, include.nested.variantName, selection.selectedMtiColumnsByVariant);
1856
1946
  return {
1857
- joins: joins.map((join) => join.rewrite(remapper)),
1947
+ joins,
1858
1948
  projection,
1859
- hiddenProjection,
1949
+ hiddenProjection: buildHiddenDiscriminatorProjection(contract, include.nested.tables.root, polyInfo, selection.needsHiddenDiscriminator),
1860
1950
  baseSelectedFields: selection.baseSelectedFields
1861
1951
  };
1862
1952
  }
1863
1953
  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
1954
  const aliases = /* @__PURE__ */ new Set();
1868
1955
  const projection = [];
1869
1956
  for (const nested of include.nested.includes) {
1870
- if (!mtiTables.has(nested.localTableName)) continue;
1957
+ if (nested.localVariantName === void 0) continue;
1958
+ const variantTable = requireVariantTable(include.nested.tables, nested.localVariantName);
1871
1959
  for (const column of localColumnsForRowInclude(nested)) {
1872
- const alias = `${nested.localTableName}__${column}`;
1960
+ const alias = variantColumnLabel(variantTable, column);
1873
1961
  if (aliases.has(alias)) continue;
1874
1962
  aliases.add(alias);
1875
- projection.push(ProjectionItem.of(alias, ColumnRef.of(nested.localTableName, column), codecRefForStorageColumn(contract.storage, include.relatedNamespaceId, nested.localTableName, column)));
1963
+ projection.push(ProjectionItem.of(alias, variantTable.column(column), codecRefForStorageColumn(contract.storage, variantTable.storage.namespaceId, variantTable.storage.tableName, column)));
1876
1964
  }
1877
1965
  }
1878
1966
  return projection;
@@ -1892,61 +1980,54 @@ function mergeProjectionByAlias(projection, additional) {
1892
1980
  * (AND-ed across all column pairs for composite keys). The junction JOIN
1893
1981
  * connects child rows to the junction via the child columns.
1894
1982
  */
1895
- function buildManyToManyJunctionArtifacts(parentLocalRefs, childTableRef, through) {
1896
- const { table: junctionTable, parentColumns, childColumns, targetColumns, namespaceId } = through;
1983
+ function buildManyToManyJunctionArtifacts(contract, parentLocalRefs, child, junction, through) {
1984
+ const { table: junctionTable, parentColumns, childColumns, targetColumns } = through;
1897
1985
  invariant(childColumns.length === targetColumns.length, `M:N junction '${junctionTable}': childColumns (${childColumns.length}) and targetColumns (${targetColumns.length}) must have equal length`);
1898
1986
  invariant(parentColumns.length === parentLocalRefs.length, `M:N junction '${junctionTable}': parentColumns (${parentColumns.length}) and parentLocalColumns (${parentLocalRefs.length}) must have equal length`);
1899
1987
  const joinOnPairs = childColumns.map((junctionCol, i) => {
1900
1988
  const targetCol = targetColumns[i];
1901
1989
  assertDefined(targetCol, `M:N junction '${junctionTable}': missing target column at index ${i}`);
1902
- return BinaryExpr.eq(ColumnRef.of(junctionTable, junctionCol), ColumnRef.of(childTableRef, targetCol));
1990
+ return BinaryExpr.eq(junction.column(junctionCol), child.column(targetCol));
1903
1991
  });
1904
1992
  const firstJoinPair = joinOnPairs[0];
1905
1993
  const joinOn = joinOnPairs.length === 1 && firstJoinPair ? firstJoinPair : AndExpr.of(joinOnPairs);
1906
1994
  const correlationPairs = parentColumns.map((junctionCol, i) => {
1907
1995
  const parentLocalRef = parentLocalRefs[i];
1908
1996
  assertDefined(parentLocalRef, `M:N junction '${junctionTable}': missing parent-local column ref at index ${i}`);
1909
- return BinaryExpr.eq(ColumnRef.of(junctionTable, junctionCol), parentLocalRef);
1997
+ return BinaryExpr.eq(junction.column(junctionCol), parentLocalRef);
1910
1998
  });
1911
1999
  const firstCorrelationPair = correlationPairs[0];
1912
2000
  return {
1913
2001
  whereExpr: correlationPairs.length === 1 && firstCorrelationPair ? firstCorrelationPair : AndExpr.of(correlationPairs),
1914
- junctionJoin: JoinAst.inner(TableSource.named(junctionTable, void 0, namespaceId), joinOn, false)
2002
+ junctionJoin: JoinAst.inner(junction.tableSource(contract), joinOn, false)
1915
2003
  };
1916
2004
  }
1917
- function buildIncludeChildRowsSelect(contract, aggregates, parentSource, include) {
2005
+ function buildIncludeChildRowsSelect(contract, aggregates, scope, parent, include) {
1918
2006
  const childState = include.nested;
1919
2007
  if (childState.distinctOn !== void 0 && childState.distinctOn.length > 0) {
1920
2008
  assertDistinctOnCapability(contract, "distinctOn");
1921
2009
  assertDistinctOnCompatibleOrder(childState.orderBy, childState.distinctOn.length);
1922
2010
  }
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
- });
2011
+ const child = childState.tables.root;
2012
+ const parentLocalRefs = resolveParentLocalRefs(parent, include, localColumnsForRowInclude(include));
2013
+ const rowsAlias = scope.alias(`${include.relationName}__rows`);
2014
+ const { childOrderBy, hiddenOrderProjection, aggregateOrderBy } = buildIncludeOrderArtifacts(include.relationName, rowsAlias, childState.orderBy);
2015
+ const childWhere = buildStateWhere(contract, childState);
1934
2016
  let whereExpr;
1935
2017
  let junctionJoins = [];
1936
2018
  if (include.through !== void 0) {
1937
- const artifacts = buildManyToManyJunctionArtifacts(parentLocalRefs, childTableRef, include.through);
2019
+ const artifacts = buildManyToManyJunctionArtifacts(contract, parentLocalRefs, child, requireJunction(include), include.through);
1938
2020
  whereExpr = childWhere ? AndExpr.of([artifacts.whereExpr, childWhere]) : artifacts.whereExpr;
1939
2021
  junctionJoins = [artifacts.junctionJoin];
1940
2022
  } else {
1941
- const joinExpr = buildIncludeJoinExpr(include, childTableRef, parentLocalRefs);
2023
+ const joinExpr = buildIncludeJoinExpr(include, child, parentLocalRefs);
1942
2024
  whereExpr = childWhere ? AndExpr.of([joinExpr, childWhere]) : joinExpr;
1943
2025
  }
1944
2026
  if (childState.distinct !== void 0 && childState.distinct.length > 0 && childState.includes.length > 0) return buildDistinctNonLeafChildRowsSelect({
1945
2027
  contract,
1946
2028
  aggregates,
2029
+ scope,
1947
2030
  include,
1948
- childTableAlias,
1949
- childTableRef,
1950
2031
  rowsAlias,
1951
2032
  childOrderBy,
1952
2033
  hiddenOrderProjection,
@@ -1954,30 +2035,26 @@ function buildIncludeChildRowsSelect(contract, aggregates, parentSource, include
1954
2035
  whereExpr,
1955
2036
  junctionJoins
1956
2037
  });
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);
2038
+ const polyJoinsAndProjection = buildChildPolymorphismJoinsAndProjection(contract, include);
2039
+ const scalarProjection = buildProjection(contract, addressedModelName(include.relatedModelName, include.nested.variantName), child, polyJoinsAndProjection.baseSelectedFields);
2040
+ const nestedProjections = buildNestedIncludeProjections(contract, aggregates, scope, { tables: childState.tables }, childState.includes);
1964
2041
  const childProjection = [
1965
2042
  ...scalarProjection,
1966
2043
  ...polyJoinsAndProjection.projection,
1967
2044
  ...polyJoinsAndProjection.hiddenProjection,
1968
2045
  ...nestedProjections
1969
2046
  ];
1970
- let childRows = SelectAst.from(tableSourceForContract(contract, include.relatedNamespaceId, include.relatedTableName, childTableAlias)).withProjection([...childProjection, ...hiddenOrderProjection]).withWhere(whereExpr);
2047
+ let childRows = SelectAst.from(child.tableSource(contract)).withProjection([...childProjection, ...hiddenOrderProjection]).withWhere(whereExpr);
1971
2048
  if (polyJoinsAndProjection.joins.length > 0) childRows = childRows.withJoins([...polyJoinsAndProjection.joins]);
1972
2049
  if (junctionJoins.length > 0) childRows = childRows.withJoins(junctionJoins);
1973
2050
  if (childState.distinctOn && childState.distinctOn.length > 0) {
1974
- childRows = childRows.withDistinctOn(childState.distinctOn.map((column) => ColumnRef.of(childTableRef, column)));
2051
+ childRows = childRows.withDistinctOn(childState.distinctOn.map((column) => child.column(column)));
1975
2052
  if (childOrderBy) childRows = childRows.withOrderBy(childOrderBy);
1976
2053
  } else if (childState.distinct && childState.distinct.length > 0) {
1977
- const rankedAlias = `${include.relationName}__distinct`;
2054
+ const rankedAlias = scope.alias(`${include.relationName}__distinct`);
1978
2055
  childRows = wrapWithRowNumberDedup({
1979
2056
  base: childRows,
1980
- distinctColumnRefs: childState.distinct.map((column) => ColumnRef.of(childTableRef, column)),
2057
+ distinctColumnRefs: childState.distinct.map((column) => child.column(column)),
1981
2058
  rankingOrderBy: childOrderBy ?? [],
1982
2059
  rankedAlias
1983
2060
  });
@@ -1994,21 +2071,22 @@ function buildIncludeChildRowsSelect(contract, aggregates, parentSource, include
1994
2071
  };
1995
2072
  }
1996
2073
  function buildDistinctNonLeafChildRowsSelect(options) {
1997
- const { contract, aggregates, include, childTableAlias, childTableRef, rowsAlias, childOrderBy, hiddenOrderProjection, aggregateOrderBy, whereExpr, junctionJoins } = options;
2074
+ const { contract, aggregates, scope, include, rowsAlias, childOrderBy, hiddenOrderProjection, aggregateOrderBy, whereExpr, junctionJoins } = options;
1998
2075
  const childState = include.nested;
1999
- const grandchildJoinColumns = Array.from(new Set(childState.includes.flatMap((nested) => nested.localTableName === include.relatedTableName ? localColumnsForRowInclude(nested) : [])));
2076
+ const child = childState.tables.root;
2077
+ const grandchildJoinColumns = Array.from(new Set(childState.includes.flatMap((nested) => nested.localVariantName === void 0 ? localColumnsForRowInclude(nested) : [])));
2000
2078
  const { selectedForQuery } = augmentSelectionForJoinColumns(childState.selectedFields, grandchildJoinColumns);
2001
- const visiblePolyProjection = buildChildPolymorphismJoinsAndProjection(contract, include, childTableAlias, childTableRef);
2079
+ const visiblePolyProjection = buildChildPolymorphismJoinsAndProjection(contract, include);
2002
2080
  const queryPolyProjection = buildChildPolymorphismJoinsAndProjection(contract, {
2003
2081
  ...include,
2004
2082
  nested: {
2005
2083
  ...childState,
2006
2084
  selectedFields: selectedForQuery
2007
2085
  }
2008
- }, childTableAlias, childTableRef);
2009
- const innerScalarProjection = buildProjection(contract, include.relatedNamespaceId, addressedModelName(include.relatedModelName, include.nested.variantName), include.relatedTableName, queryPolyProjection.baseSelectedFields, childTableRef);
2086
+ });
2087
+ const innerScalarProjection = buildProjection(contract, addressedModelName(include.relatedModelName, include.nested.variantName), child, queryPolyProjection.baseSelectedFields);
2010
2088
  const innerMtiProjection = mergeProjectionByAlias(queryPolyProjection.projection, buildRequiredMtiJoinKeyProjection(contract, include));
2011
- let baseInner = SelectAst.from(tableSourceForContract(contract, include.relatedNamespaceId, include.relatedTableName, childTableAlias)).withProjection([
2089
+ let baseInner = SelectAst.from(child.tableSource(contract)).withProjection([
2012
2090
  ...innerScalarProjection,
2013
2091
  ...innerMtiProjection,
2014
2092
  ...queryPolyProjection.hiddenProjection,
@@ -2018,22 +2096,21 @@ function buildDistinctNonLeafChildRowsSelect(options) {
2018
2096
  if (distinctExtraJoins.length > 0) baseInner = baseInner.withJoins(distinctExtraJoins);
2019
2097
  const distinctColumns = childState.distinct;
2020
2098
  if (distinctColumns === void 0 || distinctColumns.length === 0) throw new InternalError("buildDistinctNonLeafChildRowsSelect requires a non-empty `distinct` selection");
2021
- const rankedAlias = `${include.relationName}__ranked`;
2099
+ const rankedAlias = scope.alias(`${include.relationName}__ranked`);
2022
2100
  let innerSelect = wrapWithRowNumberDedup({
2023
2101
  base: baseInner,
2024
- distinctColumnRefs: distinctColumns.map((column) => ColumnRef.of(childTableRef, column)),
2102
+ distinctColumnRefs: distinctColumns.map((column) => child.column(column)),
2025
2103
  rankingOrderBy: childOrderBy ?? [],
2026
2104
  rankedAlias
2027
2105
  });
2028
2106
  if (childOrderBy) innerSelect = innerSelect.withOrderBy(childOrderBy.map((item, index) => item.withExpr(ColumnRef.of(rankedAlias, `${include.relationName}__order_${index}`))));
2029
2107
  if (childState.limit !== void 0) innerSelect = innerSelect.withLimit(childState.limit);
2030
2108
  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
2109
+ const distinctAlias = scope.alias(`${include.relationName}__distinct`);
2110
+ const outerScalarProjection = buildProjection(contract, addressedModelName(include.relatedModelName, include.nested.variantName), child, visiblePolyProjection.baseSelectedFields, distinctAlias);
2111
+ const outerNestedProjections = buildNestedIncludeProjections(contract, aggregates, scope, {
2112
+ tables: childState.tables,
2113
+ projectedThrough: distinctAlias
2037
2114
  }, childState.includes);
2038
2115
  const outerPolyProjection = visiblePolyProjection.projection.map((proj) => ProjectionItem.of(proj.alias, ColumnRef.of(distinctAlias, proj.alias), proj.codec));
2039
2116
  const outerHiddenProjection = visiblePolyProjection.hiddenProjection.map((proj) => ProjectionItem.of(proj.alias, ColumnRef.of(distinctAlias, proj.alias), proj.codec));
@@ -2078,7 +2155,7 @@ function buildDistinctNonLeafChildRowsSelect(options) {
2078
2155
  * `distinct`) is dropped at the SQL level since reordering does not
2079
2156
  * change which rows are aggregated.
2080
2157
  */
2081
- function buildIncludeChildScalarSelect(contract, aggregates, parentSource, include, scalar) {
2158
+ function buildIncludeChildScalarSelect(contract, aggregates, scope, parent, include, scalar) {
2082
2159
  const { codec: resultCodec, input: inputCodec, lower: resultLowering } = resolveAggregate({
2083
2160
  aggregates,
2084
2161
  contract,
@@ -2087,65 +2164,58 @@ function buildIncludeChildScalarSelect(contract, aggregates, parentSource, inclu
2087
2164
  fn: scalar.fn,
2088
2165
  column: scalar.column
2089
2166
  });
2090
- const parentLocalRefs = resolveParentLocalRefs(parentSource, include, localColumnsForRowInclude(include));
2091
- const childSource = resolveChildTableSource(include, parentLocalRefs);
2092
- const childTableAlias = childSource.alias;
2093
- const childTableRef = childSource.tableRef;
2167
+ const parentLocalRefs = resolveParentLocalRefs(parent, include, localColumnsForRowInclude(include));
2094
2168
  const state = scalar.state;
2169
+ const child = state.tables.root;
2095
2170
  if (state.distinctOn !== void 0 && state.distinctOn.length > 0) {
2096
2171
  assertDistinctOnCapability(contract, "distinctOn");
2097
2172
  assertDistinctOnCompatibleOrder(state.orderBy, state.distinctOn.length);
2098
2173
  }
2099
- const childWhere = buildStateWhere(contract, childTableRef, state, {
2100
- filterTableName: include.relatedTableName,
2101
- namespaceId: include.relatedNamespaceId
2102
- });
2174
+ const childWhere = buildStateWhere(contract, state);
2103
2175
  let whereExpr;
2104
2176
  let junctionJoins = [];
2105
2177
  if (include.through !== void 0) {
2106
- const artifacts = buildManyToManyJunctionArtifacts(parentLocalRefs, childTableRef, include.through);
2178
+ const artifacts = buildManyToManyJunctionArtifacts(contract, parentLocalRefs, child, requireJunction(include), include.through);
2107
2179
  whereExpr = childWhere ? AndExpr.of([artifacts.whereExpr, childWhere]) : artifacts.whereExpr;
2108
2180
  junctionJoins = [artifacts.junctionJoin];
2109
2181
  } else {
2110
- const joinExpr = buildIncludeJoinExpr(include, childTableRef, parentLocalRefs);
2182
+ const joinExpr = buildIncludeJoinExpr(include, child, parentLocalRefs);
2111
2183
  whereExpr = childWhere ? AndExpr.of([joinExpr, childWhere]) : joinExpr;
2112
2184
  }
2113
- const remappedOrderBy = childTableAlias && state.orderBy ? state.orderBy.map((item) => item.rewrite(createTableRefRemapper$1(include.relatedTableName, childTableRef))) : state.orderBy;
2114
2185
  const hasPagination = state.limit !== void 0 || state.offset !== void 0;
2115
2186
  const hasDistinct = state.distinct !== void 0 && state.distinct.length > 0 || state.distinctOn !== void 0 && state.distinctOn.length > 0;
2116
2187
  if (!(hasPagination || hasDistinct)) {
2117
- const aggregateExpr = buildIncludeAggregateExpr(scalar, childTableRef, resultLowering, inputCodec);
2188
+ const aggregateExpr = buildIncludeAggregateExpr(scalar, scalar.column === void 0 ? void 0 : child.column(scalar.column), resultLowering, inputCodec);
2118
2189
  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);
2190
+ let select = SelectAst.from(child.tableSource(contract)).withProjection([ProjectionItem.of(include.relationName, jsonObjectExpr)]).withWhere(whereExpr);
2120
2191
  if (junctionJoins.length > 0) select = select.withJoins(junctionJoins);
2121
2192
  return select;
2122
2193
  }
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);
2194
+ const innerAlias = scope.alias(`${include.relationName}__scalar`);
2195
+ 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)) : [];
2196
+ const innerProjection = [...scalar.column !== void 0 ? [ProjectionItem.of(scalar.column, child.column(scalar.column))] : [ProjectionItem.of("__row", LiteralExpr.of(1))], ...hiddenOrderProjection];
2197
+ let inner = SelectAst.from(child.tableSource(contract)).withProjection(innerProjection).withWhere(whereExpr);
2127
2198
  if (junctionJoins.length > 0) inner = inner.withJoins(junctionJoins);
2128
2199
  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);
2200
+ inner = inner.withDistinctOn(state.distinctOn.map((column) => child.column(column)));
2201
+ if (state.orderBy !== void 0 && state.orderBy.length > 0) inner = inner.withOrderBy(state.orderBy);
2131
2202
  } else if (state.distinct !== void 0 && state.distinct.length > 0) {
2132
- const rankedAlias = `${include.relationName}__scalar_distinct`;
2203
+ const rankedAlias = scope.alias(`${include.relationName}__scalar_distinct`);
2133
2204
  inner = wrapWithRowNumberDedup({
2134
2205
  base: inner,
2135
- distinctColumnRefs: state.distinct.map((column) => ColumnRef.of(childTableRef, column)),
2136
- rankingOrderBy: remappedOrderBy ?? [],
2206
+ distinctColumnRefs: state.distinct.map((column) => child.column(column)),
2207
+ rankingOrderBy: state.orderBy ?? [],
2137
2208
  rankedAlias
2138
2209
  });
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);
2210
+ 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}`))));
2211
+ } else if (state.orderBy !== void 0 && state.orderBy.length > 0) inner = inner.withOrderBy(state.orderBy);
2141
2212
  if (state.limit !== void 0) inner = inner.withLimit(state.limit);
2142
2213
  if (state.offset !== void 0) inner = inner.withOffset(state.offset);
2143
- const outerAggregateExpr = buildIncludeAggregateExpr(scalar, innerAlias, resultLowering, inputCodec);
2214
+ const outerAggregateExpr = buildIncludeAggregateExpr(scalar, scalar.column === void 0 ? void 0 : ColumnRef.of(innerAlias, scalar.column), resultLowering, inputCodec);
2144
2215
  const outerJsonObjectExpr = JsonObjectExpr.fromEntries([JsonObjectExpr.entry("value", jsonEntryProjection(outerAggregateExpr, { codec: resultCodec }))]);
2145
2216
  return SelectAst.from(DerivedTableSource.as(innerAlias, inner)).withProjection([ProjectionItem.of(include.relationName, outerJsonObjectExpr)]);
2146
2217
  }
2147
- function buildIncludeAggregateExpr(scalar, childTableRef, lower, inputCodec) {
2148
- const expr = scalar.column === void 0 ? void 0 : ColumnRef.of(childTableRef, scalar.column);
2218
+ function buildIncludeAggregateExpr(scalar, expr, lower, inputCodec) {
2149
2219
  if (lower !== void 0) return lower({
2150
2220
  expr,
2151
2221
  inputCodec
@@ -2171,13 +2241,13 @@ function buildIncludeAggregateExpr(scalar, childTableRef, lower, inputCodec) {
2171
2241
  * branch fan out naturally because the row builder is invoked with
2172
2242
  * a synthetic IncludeExpr whose `nested` is the branch's state.
2173
2243
  */
2174
- function buildIncludeChildCombineSelect(contract, aggregates, parentSource, include, branches) {
2244
+ function buildIncludeChildCombineSelect(contract, aggregates, scope, parent, include, branches) {
2175
2245
  const branchEntries = Object.entries(branches);
2176
2246
  if (branchEntries.length === 0) throw ormError("ORM.INCLUDE_INVALID", `combine() include "${include.relationName}" has no branches`, { meta: { relation: include.relationName } });
2177
2247
  const compiledBranches = branchEntries.map(([name, branch]) => ({
2178
2248
  name,
2179
- alias: `${include.relationName}__combine__${name}`,
2180
- select: buildIncludeChildCombineBranchSelect(contract, aggregates, parentSource, include, branch)
2249
+ alias: scope.alias(`${include.relationName}__combine__${name}`),
2250
+ select: buildIncludeChildCombineBranchSelect(contract, aggregates, scope, parent, include, branch)
2181
2251
  }));
2182
2252
  const jsonObjectExpr = JsonObjectExpr.fromEntries(compiledBranches.map((branch) => JsonObjectExpr.entry(branch.name, jsonEntryProjection(ColumnRef.of(branch.alias, include.relationName), { document: true }))));
2183
2253
  const [firstBranch, ...restBranches] = compiledBranches;
@@ -2191,9 +2261,9 @@ function buildIncludeChildCombineSelect(contract, aggregates, parentSource, incl
2191
2261
  * relation name. Dispatches to the standalone scalar / row builders
2192
2262
  * with the branch's state spliced into a synthetic IncludeExpr.
2193
2263
  */
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, {
2264
+ function buildIncludeChildCombineBranchSelect(contract, aggregates, scope, parent, include, branch) {
2265
+ if (branch.kind === "scalar") return buildIncludeChildScalarSelect(contract, aggregates, scope, parent, include, branch.selector);
2266
+ return buildIncludeChildRowsAggregateSelect(contract, aggregates, scope, parent, {
2197
2267
  ...include,
2198
2268
  nested: branch.state,
2199
2269
  scalar: void 0,
@@ -2206,103 +2276,98 @@ function buildIncludeChildCombineBranchSelect(contract, aggregates, parentSource
2206
2276
  * name. Used by both the standalone row correlated-subquery path and
2207
2277
  * by combine's row branches.
2208
2278
  */
2209
- function buildIncludeChildRowsAggregateSelect(contract, aggregates, parentSource, include) {
2210
- const { childRows, childProjection, documentAliases, rowsAlias, aggregateOrderBy } = buildIncludeChildRowsSelect(contract, aggregates, parentSource, include);
2279
+ function buildIncludeChildRowsAggregateSelect(contract, aggregates, scope, parent, include) {
2280
+ const { childRows, childProjection, documentAliases, rowsAlias, aggregateOrderBy } = buildIncludeChildRowsSelect(contract, aggregates, scope, parent, include);
2211
2281
  const jsonObjectExpr = JsonObjectExpr.fromEntries(childProjection.map((item) => JsonObjectExpr.entry(item.alias, jsonEntryProjection(ColumnRef.of(rowsAlias, item.alias), {
2212
2282
  codec: item.codec,
2213
2283
  document: documentAliases.has(item.alias)
2214
2284
  }))));
2215
2285
  return SelectAst.from(DerivedTableSource.as(rowsAlias, childRows)).withProjection([ProjectionItem.of(include.relationName, JsonArrayAggExpr.of(jsonEntryProjection(jsonObjectExpr, { document: true }), "emptyArray", aggregateOrderBy))]);
2216
2286
  }
2217
- function buildCorrelatedIncludeProjection(contract, aggregates, parentSource, include) {
2287
+ function buildCorrelatedIncludeProjection(contract, aggregates, scope, parent, include) {
2218
2288
  if (include.scalar) {
2219
- const scalarSelect = buildIncludeChildScalarSelect(contract, aggregates, parentSource, include, include.scalar);
2289
+ const scalarSelect = buildIncludeChildScalarSelect(contract, aggregates, scope, parent, include, include.scalar);
2220
2290
  return { projection: ProjectionItem.of(include.relationName, SubqueryExpr.of(scalarSelect)) };
2221
2291
  }
2222
2292
  if (include.combine) {
2223
- const combineSelect = buildIncludeChildCombineSelect(contract, aggregates, parentSource, include, include.combine);
2293
+ const combineSelect = buildIncludeChildCombineSelect(contract, aggregates, scope, parent, include, include.combine);
2224
2294
  return { projection: ProjectionItem.of(include.relationName, SubqueryExpr.of(combineSelect)) };
2225
2295
  }
2226
- const aggregateQuery = buildIncludeChildRowsAggregateSelect(contract, aggregates, parentSource, include);
2296
+ const aggregateQuery = buildIncludeChildRowsAggregateSelect(contract, aggregates, scope, parent, include);
2227
2297
  return { projection: ProjectionItem.of(include.relationName, SubqueryExpr.of(aggregateQuery)) };
2228
2298
  }
2229
- function buildSelectAst(contract, modelName, tableName, state, options) {
2230
- const namespaceId = options.namespaceId;
2299
+ function buildSelectAst(contract, modelName, state, options) {
2300
+ const { root } = state.tables;
2301
+ const { namespaceId, tableName } = root.storage;
2231
2302
  if (state.distinctOn !== void 0 && state.distinctOn.length > 0) {
2232
2303
  assertDistinctOnCapability(contract, "distinctOn");
2233
2304
  assertDistinctOnCompatibleOrder(state.orderBy, state.distinctOn.length);
2234
2305
  }
2235
2306
  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))));
2307
+ const projection = [...buildProjection(contract, addressed, root, state.selectedFields), ...options.includeProjection ?? []];
2308
+ 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
2309
  let ast = SelectAst.from(fromSource).withProjection(projection);
2239
2310
  if (effectiveWhere) ast = ast.withWhere(effectiveWhere);
2240
2311
  if (state.orderBy) ast = ast.withOrderBy(state.orderBy);
2241
2312
  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)));
2313
+ if (state.distinctOn && state.distinctOn.length > 0) ast = ast.withDistinctOn(state.distinctOn.map((column) => root.column(column)));
2243
2314
  if (state.limit !== void 0) ast = ast.withLimit(state.limit);
2244
2315
  if (state.offset !== void 0) ast = ast.withOffset(state.offset);
2245
2316
  if (options.joins && options.joins.length > 0) ast = ast.withJoins(options.joins);
2246
2317
  if (state.locking !== void 0) ast = ast.withLocking(state.locking);
2247
2318
  return ast;
2248
2319
  }
2249
- function compileSelect(contract, namespaceId, modelName, tableName, state) {
2320
+ function buildRootPolymorphism(contract, state, modelName) {
2321
+ const { root } = state.tables;
2322
+ const { namespaceId } = root.storage;
2323
+ const polyInfo = resolvePolymorphismInfo(contract, namespaceId, modelName);
2324
+ if (!polyInfo) return {
2325
+ projectionState: state,
2326
+ joins: [],
2327
+ projection: []
2328
+ };
2329
+ const selection = resolvePolymorphicProjectionSelection(contract, namespaceId, modelName, polyInfo, state);
2330
+ const mtiArtifacts = polyInfo.mtiVariants.length > 0 ? buildMtiJoins(contract, state.tables, polyInfo, state.variantName, selection.selectedMtiColumnsByVariant) : void 0;
2331
+ return {
2332
+ projectionState: {
2333
+ ...state,
2334
+ selectedFields: selection.baseSelectedFields
2335
+ },
2336
+ joins: mtiArtifacts?.joins ?? [],
2337
+ projection: [...mtiArtifacts?.projection ?? [], ...buildHiddenDiscriminatorProjection(contract, root, polyInfo, selection.needsHiddenDiscriminator)]
2338
+ };
2339
+ }
2340
+ function compileSelect(contract, modelName, state) {
2250
2341
  assertLockCompatible(state);
2251
2342
  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,
2343
+ const polymorphism = buildRootPolymorphism(contract, state, modelName);
2344
+ const ast = buildSelectAst(contract, modelName, {
2345
+ ...polymorphism.projectionState,
2262
2346
  includes: []
2263
2347
  }, {
2264
- joins: mtiArtifacts?.joins ?? [],
2265
- includeProjection: [...mtiArtifacts?.projection ?? [], ...hiddenProjection],
2266
- namespaceId
2348
+ joins: polymorphism.joins,
2349
+ includeProjection: polymorphism.projection
2267
2350
  });
2268
2351
  const { params } = deriveParamsFromAst(ast);
2269
2352
  return buildOrmQueryPlan(contract, ast, params, state.annotations);
2270
2353
  }
2271
- function compileSelectWithIncludes(contract, aggregates, namespaceId, modelName, tableName, state) {
2354
+ function compileSelectWithIncludes(contract, aggregates, modelName, state) {
2272
2355
  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
- };
2356
+ const topLevelWhere = buildStateWhere(contract, state);
2357
+ const polymorphism = buildRootPolymorphism(contract, state, modelName);
2358
+ const includeProjection = [...polymorphism.projection];
2359
+ const scope = state.tables.scope.copy();
2360
+ const parent = { tables: state.tables };
2295
2361
  for (const include of state.includes) {
2296
- const artifact = buildCorrelatedIncludeProjection(contract, aggregates, parentSource, include);
2362
+ const artifact = buildCorrelatedIncludeProjection(contract, aggregates, scope, parent, include);
2297
2363
  includeProjection.push(artifact.projection);
2298
2364
  }
2299
- const ast = buildSelectAst(contract, modelName, tableName, {
2300
- ...projectionState,
2365
+ const ast = buildSelectAst(contract, modelName, {
2366
+ ...polymorphism.projectionState,
2301
2367
  includes: []
2302
2368
  }, {
2303
- joins: includeJoins,
2369
+ joins: polymorphism.joins,
2304
2370
  includeProjection,
2305
- namespaceId,
2306
2371
  ...ifDefined("where", topLevelWhere)
2307
2372
  });
2308
2373
  const { params } = deriveParamsFromAst(ast);
@@ -2318,19 +2383,19 @@ function describeCollectionRows(options) {
2318
2383
  };
2319
2384
  }
2320
2385
  function describeExecutionRows(options) {
2321
- const { context, state, tableName, modelName, namespaceId } = options;
2386
+ const { context, state, modelName, namespaceId } = options;
2322
2387
  const { contract } = context;
2323
2388
  const polyInfo = resolvePolymorphismInfo(contract, namespaceId, modelName);
2324
2389
  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));
2390
+ const compiled = compileSelect(contract, modelName, state);
2391
+ const mapper = polyInfo ? (rawRow) => blindCast(mapPolymorphicRow(contract, namespaceId, modelName, polyInfo, state.tables, rawRow, state.variantName)) : (rawRow) => blindCast(mapStorageRowToModelFields(contract, namespaceId, modelName, rawRow));
2327
2392
  return {
2328
2393
  plan: compiled,
2329
2394
  consume: (rows) => mapResultRows(rows, mapper)
2330
2395
  };
2331
2396
  }
2332
2397
  return {
2333
- plan: compileSelectWithIncludes(contract, context.aggregateDescriptors, namespaceId, modelName, tableName, state),
2398
+ plan: compileSelectWithIncludes(contract, context.aggregateDescriptors, modelName, state),
2334
2399
  consume: (rows) => consumeIncludeRows(context, state, namespaceId, modelName, rows)
2335
2400
  };
2336
2401
  }
@@ -2344,16 +2409,16 @@ function deferResolution(resolve) {
2344
2409
  };
2345
2410
  }
2346
2411
  }
2347
- function createPreparedMapper(contract, namespaceId, modelName, variantName) {
2412
+ function createPreparedMapper(contract, namespaceId, modelName, state) {
2348
2413
  const resolved = deferResolution(() => {
2349
2414
  const polyInfo = resolvePolymorphismInfo(contract, namespaceId, modelName);
2350
- return polyInfo ? createPolymorphicRowMapper(contract, namespaceId, modelName, polyInfo, variantName) : createStorageRowMapper(contract, namespaceId, modelName);
2415
+ return polyInfo ? createPolymorphicRowMapper(contract, namespaceId, modelName, polyInfo, state.tables, state.variantName) : createStorageRowMapper(contract, namespaceId, modelName);
2351
2416
  });
2352
2417
  return (row) => resolved()(row);
2353
2418
  }
2354
2419
  function createPreparedRowsConsumer(options) {
2355
2420
  const { context, state, namespaceId, modelName } = options;
2356
- const mapRow = createPreparedMapper(context.contract, namespaceId, modelName, state.variantName);
2421
+ const mapRow = createPreparedMapper(context.contract, namespaceId, modelName, state);
2357
2422
  const includes = state.includes.map((include) => createPreparedIncludeConsumer(context, include));
2358
2423
  const castRow = (row) => blindCast(row);
2359
2424
  if (includes.length === 0) return (rows) => mapResultRows(rows, (row) => castRow(mapRow(row)));
@@ -2393,12 +2458,15 @@ function createPreparedIncludeConsumer(context, include) {
2393
2458
  }
2394
2459
  };
2395
2460
  }
2396
- const mapRow = createPreparedMapper(contract, include.relatedNamespaceId, include.relatedModelName, include.nested.variantName);
2461
+ const mapRow = createPreparedMapper(contract, include.relatedNamespaceId, include.relatedModelName, include.nested);
2397
2462
  const bindings = deferResolution(() => {
2398
2463
  const namespace = include.relatedNamespaceId;
2399
2464
  const keys = new Set(getColumnsReadOnTable(contract, namespace, addressedModelName(include.relatedModelName, include.nested.variantName), include.relatedTableName));
2400
2465
  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}`);
2466
+ for (const variant of polyInfo?.mtiVariants ?? []) {
2467
+ const variantTable = requireVariantTable(include.nested.tables, variant.modelName);
2468
+ for (const column of getColumnsReadOnTable(contract, variantTable.storage.namespaceId, variant.modelName, variantTable.storage.tableName)) keys.add(variantColumnLabel(variantTable, column));
2469
+ }
2402
2470
  return new Map([...keys].map((key) => [key, deferResolution(() => resolveIncludedColumnBinding(contract, context, include, key))]));
2403
2471
  });
2404
2472
  const bindingFor = (key) => bindings().get(key)?.() ?? null;
@@ -2482,11 +2550,10 @@ function describeCollectionFirstOrThrow(options) {
2482
2550
  };
2483
2551
  }
2484
2552
  function dispatchCollectionRows(options) {
2485
- const { context, runtime, state, tableName, modelName, namespaceId } = options;
2553
+ const { context, runtime, state, modelName, namespaceId } = options;
2486
2554
  const descriptionOptions = {
2487
2555
  context,
2488
2556
  state,
2489
- tableName,
2490
2557
  modelName,
2491
2558
  namespaceId
2492
2559
  };
@@ -2510,7 +2577,7 @@ function consumeIncludeRows(context, state, namespaceId, modelName, rows) {
2510
2577
  const parentRows = parentRowsRaw.map((row) => {
2511
2578
  return {
2512
2579
  raw: row,
2513
- mapped: polyInfo ? mapPolymorphicRow(contract, namespaceId, modelName, polyInfo, row, state.variantName) : mapStorageRowToModelFields(contract, namespaceId, modelName, row)
2580
+ mapped: polyInfo ? mapPolymorphicRow(contract, namespaceId, modelName, polyInfo, state.tables, row, state.variantName) : mapStorageRowToModelFields(contract, namespaceId, modelName, row)
2514
2581
  };
2515
2582
  });
2516
2583
  const bindings = /* @__PURE__ */ new WeakMap();
@@ -2538,26 +2605,26 @@ function consumeIncludeRows(context, state, namespaceId, modelName, rows) {
2538
2605
  * its snapshot before issuing the DELETE (see `collection.ts`).
2539
2606
  */
2540
2607
  function reloadMutationRowsByIdentities(options) {
2541
- const { context, runtime, tableName, modelName, namespaceId, identityRows, selectedFields, includes } = options;
2608
+ const { context, runtime, tables, modelName, namespaceId, identityRows, selectedFields, includes } = options;
2542
2609
  const { contract } = context;
2610
+ const { tableName } = tables.root.storage;
2543
2611
  if (identityRows.length === 0) return emptyResult();
2544
2612
  const identityColumns = resolveRowIdentityColumns(contract, namespaceId, tableName);
2545
2613
  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
2614
  model: modelName,
2547
2615
  table: tableName
2548
2616
  } });
2549
- const identityFilter = buildIdentityInFilter(contract, namespaceId, tableName, identityColumns, identityRows);
2617
+ const identityFilter = buildIdentityInFilter(contract, tables.root, identityColumns, identityRows);
2550
2618
  if (!identityFilter) return emptyResult();
2551
2619
  return dispatchCollectionRows({
2552
2620
  context,
2553
2621
  runtime,
2554
2622
  state: {
2555
- ...emptyState(),
2623
+ ...emptyState(tables),
2556
2624
  filters: [identityFilter],
2557
2625
  selectedFields,
2558
2626
  includes
2559
2627
  },
2560
- tableName,
2561
2628
  modelName,
2562
2629
  namespaceId
2563
2630
  });
@@ -2565,16 +2632,17 @@ function reloadMutationRowsByIdentities(options) {
2565
2632
  function emptyResult() {
2566
2633
  return new AsyncIterableResult((async function* () {})());
2567
2634
  }
2568
- function buildIdentityInFilter(contract, namespaceId, tableName, identityColumns, identityRows) {
2635
+ function buildIdentityInFilter(contract, table, identityColumns, identityRows) {
2636
+ const { storage } = table;
2569
2637
  const [singleColumn, ...rest] = identityColumns;
2570
2638
  if (singleColumn !== void 0 && rest.length === 0) {
2571
2639
  const values = identityRows.map((row) => row[singleColumn]).filter((value) => value !== void 0);
2572
2640
  if (values.length === 0) return;
2573
- return bindWhereExpr(contract, BinaryExpr.in(ColumnRef.of(tableName, singleColumn), ListExpression.fromValues(values)), namespaceId);
2641
+ return BinaryExpr.in(table.column(singleColumn), ListExpression.of(values.map((value) => paramRefForStorageColumn(contract, storage, singleColumn, value))));
2574
2642
  }
2575
2643
  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);
2644
+ const tuples = identityRows.map((row) => AndExpr.of(identityColumns.map((column) => BinaryExpr.eq(table.column(column), paramRefForStorageColumn(contract, storage, column, row[column])))));
2645
+ return OrExpr.of(tuples);
2578
2646
  }
2579
2647
  /**
2580
2648
  * Decode a single-query include payload from a parent row's raw cell
@@ -2602,7 +2670,7 @@ function decodeIncludePayload(contract, context, include, raw, bindings) {
2602
2670
  if (include.combine) return decodeCombineIncludePayload(contract, context, include, include.combine, raw, bindings);
2603
2671
  const rawChildren = parseIncludedRows(include, raw);
2604
2672
  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);
2673
+ 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
2674
  let columns = bindings.get(include);
2607
2675
  if (!columns) {
2608
2676
  columns = /* @__PURE__ */ new Map();
@@ -2646,17 +2714,18 @@ function decodeIncludedStorageRow(row, bindingFor) {
2646
2714
  function resolveIncludedColumnBinding(contract, context, include, key) {
2647
2715
  const ref = resolveIncludedColumnRef(contract, include, key);
2648
2716
  if (!ref) return null;
2649
- const codec = context.contractCodecs.forColumn(include.relatedNamespaceId, ref.table, ref.column);
2717
+ const codec = context.contractCodecs.forColumn(ref.namespaceId, ref.table, ref.column);
2650
2718
  if (!codec) return null;
2651
2719
  return {
2652
2720
  ref,
2653
2721
  codec,
2654
- codecId: context.codecDescriptors.codecRefForColumn(include.relatedNamespaceId, ref.table, ref.column)?.codecId ?? ref.storageColumn.codecId
2722
+ codecId: context.codecDescriptors.codecRefForColumn(ref.namespaceId, ref.table, ref.column)?.codecId ?? ref.storageColumn.codecId
2655
2723
  };
2656
2724
  }
2657
2725
  function resolveIncludedColumnRef(contract, include, key) {
2658
2726
  const baseColumn = resolveColumn(contract, include.relatedNamespaceId, include.relatedTableName, key);
2659
2727
  if (baseColumn) return {
2728
+ namespaceId: include.relatedNamespaceId,
2660
2729
  table: include.relatedTableName,
2661
2730
  column: key,
2662
2731
  storageColumn: baseColumn
@@ -2664,12 +2733,15 @@ function resolveIncludedColumnRef(contract, include, key) {
2664
2733
  const polyInfo = resolvePolymorphismInfo(contract, include.relatedNamespaceId, include.relatedModelName);
2665
2734
  if (!polyInfo) return;
2666
2735
  for (const variant of polyInfo.mtiVariants) {
2667
- const prefix = `${variant.table}__`;
2736
+ const variantTable = requireVariantTable(include.nested.tables, variant.modelName);
2737
+ const prefix = variantColumnLabelPrefix(variantTable);
2668
2738
  if (!key.startsWith(prefix)) continue;
2669
2739
  const column = key.slice(prefix.length);
2670
- const variantColumn = resolveColumn(contract, include.relatedNamespaceId, variant.table, column);
2740
+ const { namespaceId, tableName } = variantTable.storage;
2741
+ const variantColumn = resolveColumn(contract, namespaceId, tableName, column);
2671
2742
  if (variantColumn) return {
2672
- table: variant.table,
2743
+ namespaceId,
2744
+ table: tableName,
2673
2745
  column,
2674
2746
  storageColumn: variantColumn
2675
2747
  };
@@ -2830,14 +2902,14 @@ function parseIncludePayload(value) {
2830
2902
  return [];
2831
2903
  }
2832
2904
  }
2833
- function createMutationRowMapper(contract, namespaceId, modelName, variantName) {
2905
+ function createMutationRowMapper(contract, namespaceId, modelName, tables, variantName) {
2834
2906
  const polyInfo = resolvePolymorphismInfo(contract, namespaceId, modelName);
2835
- return polyInfo ? (row) => mapPolymorphicRow(contract, namespaceId, modelName, polyInfo, row, variantName) : (row) => mapStorageRowToModelFields(contract, namespaceId, modelName, row);
2907
+ return polyInfo ? (row) => mapPolymorphicRow(contract, namespaceId, modelName, polyInfo, tables, row, variantName) : (row) => mapStorageRowToModelFields(contract, namespaceId, modelName, row);
2836
2908
  }
2837
2909
  function dispatchMutationRows(options) {
2838
- const { context, runtime, compiled, tableName, modelName, namespaceId, variantName, includes, selectedFields, hiddenColumns, mapRow } = options;
2910
+ const { context, runtime, compiled, tables, modelName, namespaceId, variantName, includes, selectedFields, hiddenColumns, mapRow } = options;
2839
2911
  const { contract } = context;
2840
- const mapStorageRow = createMutationRowMapper(contract, namespaceId, modelName, variantName);
2912
+ const mapStorageRow = createMutationRowMapper(contract, namespaceId, modelName, tables, variantName);
2841
2913
  if (includes.length === 0) return mapResultRows(queryPlanRows(runtime, compiled), (rawRow) => {
2842
2914
  const mapped = mapStorageRow(rawRow);
2843
2915
  if (hiddenColumns.length > 0) stripHiddenMappedFields(contract, namespaceId, modelName, mapped, hiddenColumns);
@@ -2848,7 +2920,7 @@ function dispatchMutationRows(options) {
2848
2920
  yield* reloadMutationRowsByIdentities({
2849
2921
  context,
2850
2922
  runtime,
2851
- tableName,
2923
+ tables,
2852
2924
  modelName,
2853
2925
  namespaceId,
2854
2926
  identityRows,
@@ -2859,9 +2931,9 @@ function dispatchMutationRows(options) {
2859
2931
  return new AsyncIterableResult(generator());
2860
2932
  }
2861
2933
  function dispatchSplitMutationRows(options) {
2862
- const { context, runtime, plans, tableName, modelName, namespaceId, variantName, includes, selectedFields, hiddenColumns, mapRow } = options;
2934
+ const { context, runtime, plans, tables, modelName, namespaceId, variantName, includes, selectedFields, hiddenColumns, mapRow } = options;
2863
2935
  const { contract } = context;
2864
- const mapStorageRow = createMutationRowMapper(contract, namespaceId, modelName, variantName);
2936
+ const mapStorageRow = createMutationRowMapper(contract, namespaceId, modelName, tables, variantName);
2865
2937
  const generator = async function* () {
2866
2938
  if (includes.length > 0) {
2867
2939
  const identityRows = [];
@@ -2869,7 +2941,7 @@ function dispatchSplitMutationRows(options) {
2869
2941
  yield* reloadMutationRowsByIdentities({
2870
2942
  context,
2871
2943
  runtime,
2872
- tableName,
2944
+ tables,
2873
2945
  modelName,
2874
2946
  namespaceId,
2875
2947
  identityRows,
@@ -2887,9 +2959,9 @@ function dispatchSplitMutationRows(options) {
2887
2959
  return new AsyncIterableResult(generator());
2888
2960
  }
2889
2961
  async function executeMutationReturningSingleRow(options) {
2890
- const { context, runtime, compiled, tableName, modelName, namespaceId, variantName, includes, selectedFields, hiddenColumns, mapRow, operation, onMissingRowMessage } = options;
2962
+ const { context, runtime, compiled, tables, modelName, namespaceId, variantName, includes, selectedFields, hiddenColumns, mapRow, operation, onMissingRowMessage } = options;
2891
2963
  const { contract } = context;
2892
- const mapStorageRow = createMutationRowMapper(contract, namespaceId, modelName, variantName);
2964
+ const mapStorageRow = createMutationRowMapper(contract, namespaceId, modelName, tables, variantName);
2893
2965
  if (includes.length === 0) {
2894
2966
  const first = (await queryPlanRows(runtime, compiled).toArray())[0];
2895
2967
  if (!first) return null;
@@ -2902,7 +2974,7 @@ async function executeMutationReturningSingleRow(options) {
2902
2974
  for await (const row of reloadMutationRowsByIdentities({
2903
2975
  context,
2904
2976
  runtime,
2905
- tableName,
2977
+ tables,
2906
2978
  modelName,
2907
2979
  namespaceId,
2908
2980
  identityRows,
@@ -2912,7 +2984,7 @@ async function executeMutationReturningSingleRow(options) {
2912
2984
  throw ormError("ORM.MUTATION_ROW_MISSING", onMissingRowMessage, { meta: {
2913
2985
  operation,
2914
2986
  model: modelName,
2915
- tableName
2987
+ tableName: tables.root.storage.tableName
2916
2988
  } });
2917
2989
  }
2918
2990
  /** The filter expression of a condition: a condition from `fns` becomes its AST. */
@@ -2938,20 +3010,20 @@ function not(expr) {
2938
3010
  function all() {
2939
3011
  return AndExpr.true();
2940
3012
  }
2941
- function shorthandToWhereExpr(context, namespaceId, modelName, filters) {
3013
+ function shorthandToWhereExpr(context, namespaceId, modelName, filters, table) {
2942
3014
  const contract = context.contract;
2943
- const tableName = resolveModelTableName(contract, namespaceId, modelName);
2944
3015
  const fieldColumns = getModelFieldColumns(contract, namespaceId, modelName);
2945
3016
  const exprs = [];
2946
3017
  for (const [fieldName, value] of Object.entries(filters)) {
2947
3018
  if (value === void 0) continue;
2948
- const left = ColumnRef.of(tableName, columnOfCallerField(contract, namespaceId, fieldColumns, modelName, fieldName));
3019
+ const columnName = columnOfCallerField(contract, namespaceId, fieldColumns, modelName, fieldName);
3020
+ const left = table.column(columnName);
2949
3021
  if (value === null) {
2950
3022
  exprs.push(NullCheckExpr.isNull(left));
2951
3023
  continue;
2952
3024
  }
2953
3025
  assertFieldHasEqualityTrait(context, namespaceId, modelName, fieldName);
2954
- exprs.push(predicateComparison("eq", left, predicateExpression(value) ?? LiteralExpr.of(value)));
3026
+ exprs.push(predicateComparison("eq", left, predicateExpression(value) ?? paramRefForStorageColumn(contract, table.storage, columnName, value)));
2955
3027
  }
2956
3028
  if (exprs.length === 0) return;
2957
3029
  return exprs.length === 1 ? exprs[0] : and(...exprs);
@@ -3419,103 +3491,21 @@ function createCallbackTools(context, indexes) {
3419
3491
  function hasThrough$1(relation) {
3420
3492
  return relation.through !== void 0;
3421
3493
  }
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));
3494
+ function createModelAccessor(context, namespaceId, modelName, tables, variantName) {
3495
+ return createModelAccessorInScope(context, namespaceId, modelName, variantName, tables.scope, tables.root, variantName === void 0 ? void 0 : tables.variants.get(variantName));
3505
3496
  }
3506
3497
  /**
3507
3498
  * 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
3499
  */
3509
- function createModelCallbackTools(context, namespaceId, modelName) {
3510
- const tableName = resolveModelTableName(context.contract, namespaceId, modelName);
3511
- return callbackToolsFor(context, namespaceId, modelName, ModelAccessorScope.root(namespaceId, tableName));
3500
+ function createModelCallbackTools(context, modelName, tables) {
3501
+ return callbackToolsFor(context, modelName, tables.root);
3512
3502
  }
3513
- function callbackToolsFor(context, namespaceId, modelName, scope) {
3514
- return createCallbackTools(context, () => indexReferencesOf(context, namespaceId, modelName, scope.current));
3503
+ function callbackToolsFor(context, modelName, aliasedTable) {
3504
+ return createCallbackTools(context, () => indexReferencesOf(context, modelName, aliasedTable));
3515
3505
  }
3516
- function indexReferencesOf(context, namespaceId, modelName, binding) {
3506
+ function indexReferencesOf(context, modelName, aliasedTable) {
3517
3507
  const { contract } = context;
3518
- const tableName = resolveModelTableName(contract, namespaceId, modelName);
3508
+ const { namespaceId, tableName } = aliasedTable.storage;
3519
3509
  const resolved = resolveTableForContract(contract, namespaceId, tableName);
3520
3510
  if (!resolved) throw new InternalError(`Model "${modelName}" is stored in table "${tableName}", which the contract does not have`);
3521
3511
  const { table } = resolved;
@@ -3532,22 +3522,21 @@ function indexReferencesOf(context, namespaceId, modelName, binding) {
3532
3522
  nullable: column.nullable,
3533
3523
  ...ifDefined("codec", codecRefForStorageColumn(contract.storage, namespaceId, tableName, columnName))
3534
3524
  },
3535
- buildAst: () => binding.column(columnName)
3525
+ buildAst: () => aliasedTable.column(columnName)
3536
3526
  };
3537
3527
  }
3538
3528
  });
3539
3529
  }
3540
- function createModelAccessorInScope(context, namespaceId, modelName, variantName, scope) {
3530
+ function createModelAccessorInScope(context, namespaceId, modelName, variantName, scope, table, variantTable) {
3541
3531
  const contract = context.contract;
3542
3532
  const fieldColumns = getModelAndVariantFieldColumns(contract, namespaceId, modelName, variantName);
3543
- const tableName = resolveModelTableName(contract, namespaceId, modelName);
3544
3533
  const modelRelations = resolveModelRelations(contract, namespaceId, modelName);
3545
3534
  const variantFieldColumns = variantName ? resolveVariantFieldColumns(contract, namespaceId, modelName, variantName) : {};
3546
3535
  const variantCoordinates = variantName ? {
3547
3536
  name: variantName,
3548
- relations: resolveModelRelations(contract, namespaceId, variantName),
3549
- tableName: resolvePolymorphismInfo(contract, namespaceId, modelName)?.variants.get(variantName)?.table ?? tableName
3537
+ relations: resolveModelRelations(contract, namespaceId, variantName)
3550
3538
  } : void 0;
3539
+ const variantFieldTable = variantTable ?? table;
3551
3540
  const opsByCodecId = /* @__PURE__ */ new Map();
3552
3541
  function registerOp(codecId, op) {
3553
3542
  let existing = opsByCodecId.get(codecId);
@@ -3571,27 +3560,27 @@ function createModelAccessorInScope(context, namespaceId, modelName, variantName
3571
3560
  if (typeof prop !== "string") return;
3572
3561
  if (variantCoordinates && Object.hasOwn(variantCoordinates.relations, prop)) {
3573
3562
  const variantRelation = variantCoordinates.relations[prop];
3574
- if (variantRelation) return createRelationFilterAccessor(context, namespaceId, variantCoordinates.name, scope.forJoinedSource(namespaceId, variantCoordinates.tableName), variantRelation);
3563
+ if (variantRelation) return createRelationFilterAccessor(context, namespaceId, variantCoordinates.name, scope, variantFieldTable, variantRelation);
3575
3564
  }
3576
3565
  const relation = Object.hasOwn(modelRelations, prop) ? modelRelations[prop] : void 0;
3577
- if (relation) return createRelationFilterAccessor(context, namespaceId, modelName, scope, relation);
3566
+ if (relation) return createRelationFilterAccessor(context, namespaceId, modelName, scope, table, relation);
3578
3567
  const variantField = Object.hasOwn(variantFieldColumns, prop) ? variantFieldColumns[prop] : void 0;
3579
3568
  if (variantField === void 0 && !Object.hasOwn(fieldColumns, prop)) {
3580
3569
  if (isProbedByRuntime(prop)) return probedValue(target, prop);
3581
3570
  }
3582
- const resolvedTable = variantField?.table ?? tableName;
3583
- const fieldBinding = scope.forJoinedSource(namespaceId, resolvedTable).current;
3571
+ const fieldTable = variantField ? variantFieldTable : table;
3572
+ const fieldStorage = fieldTable.storage;
3584
3573
  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`);
3574
+ const column = resolveColumn(contract, fieldStorage.namespaceId, fieldStorage.tableName, columnName);
3575
+ if (!column) throw new InternalError(`Field "${modelName}.${prop}" maps column "${columnName}", which table "${fieldStorage.tableName}" does not have`);
3587
3576
  const traits = codecTraits(context, column.codecId);
3588
3577
  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);
3578
+ const codec = codecRefForStorageColumn(contract.storage, fieldStorage.namespaceId, fieldStorage.tableName, columnName);
3579
+ return createScalarFieldAccessor(fieldTable, columnName, column.codecId, column.nullable, codec, traits, operations, context);
3591
3580
  } }));
3592
3581
  }
3593
- function createScalarFieldAccessor(tableBinding, columnName, codecId, nullable, codec, traits, operations, context) {
3594
- const column = tableBinding.column(columnName);
3582
+ function createScalarFieldAccessor(table, columnName, codecId, nullable, codec, traits, operations, context) {
3583
+ const column = table.column(columnName);
3595
3584
  const comparisonEntries = [];
3596
3585
  for (const [name, meta] of Object.entries(COMPARISON_METHODS_META)) {
3597
3586
  if (meta.traits.some((t) => !traits.includes(t))) continue;
@@ -3631,13 +3620,13 @@ const RELATION_ACCESSOR_METHOD_NAMES = /* @__PURE__ */ new Set([
3631
3620
  "none",
3632
3621
  "count"
3633
3622
  ]);
3634
- function createRelationFilterAccessor(context, parentNamespaceId, parentModelName, parentScope, relation) {
3623
+ function createRelationFilterAccessor(context, parentNamespaceId, parentModelName, scope, parentTable, relation) {
3635
3624
  const relatedTableName = resolveModelTableName(context.contract, relation.toNamespace, relation.to);
3636
- const correlate = () => correlateRelatedRows(context, parentNamespaceId, parentModelName, parentScope, relatedTableName, relation);
3625
+ const correlate = () => correlateRelatedRows(context, parentNamespaceId, parentModelName, scope, parentTable, relatedTableName, relation);
3637
3626
  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)
3627
+ some: (predicate) => buildExistsExpr(context, relation, scope, correlate(), "some", predicate),
3628
+ every: (predicate) => buildExistsExpr(context, relation, scope, correlate(), "every", predicate),
3629
+ none: (predicate) => buildExistsExpr(context, relation, scope, correlate(), "none", predicate)
3641
3630
  };
3642
3631
  if (isToOneCardinality(relation.cardinality)) return new Proxy(filters, { get(target, prop) {
3643
3632
  if (typeof prop !== "string") return void 0;
@@ -3648,7 +3637,7 @@ function createRelationFilterAccessor(context, parentNamespaceId, parentModelNam
3648
3637
  } });
3649
3638
  return {
3650
3639
  ...filters,
3651
- count: (predicate) => createOrderable(() => buildRelationCountExpr(context, relation, correlate(), predicate))
3640
+ count: (predicate) => createOrderable(() => buildRelationCountExpr(context, relation, scope, correlate(), predicate))
3652
3641
  };
3653
3642
  }
3654
3643
  /**
@@ -3672,39 +3661,45 @@ function relatedOrderableField(context, relation, relatedTableName, correlate, f
3672
3661
  if (!column || !hasTrait(context, column.codecId, "order")) return void 0;
3673
3662
  return createOrderable(() => {
3674
3663
  const rows = correlate();
3675
- return SubqueryExpr.of(rows.source.withProjection([ProjectionItem.of(columnName, rows.childScope.current.column(columnName))]).withWhere(rows.correlation));
3664
+ return SubqueryExpr.of(rows.source.withProjection([ProjectionItem.of(columnName, rows.child.column(columnName))]).withWhere(rows.correlation));
3676
3665
  });
3677
3666
  }
3678
- function buildRelationCountExpr(context, relation, rows, predicate) {
3679
- const childWhere = toRelationWhereExpr(context, relation.toNamespace, relation.to, predicate, rows.childScope);
3667
+ function buildRelationCountExpr(context, relation, scope, rows, predicate) {
3668
+ const childWhere = toRelationWhereExpr(context, relation.toNamespace, relation.to, predicate, scope, rows.child);
3680
3669
  return SubqueryExpr.of(rows.source.withProjection([ProjectionItem.of("count", plainAggregateExpr("count", void 0))]).withWhere(childWhere ? and(rows.correlation, childWhere) : rows.correlation));
3681
3670
  }
3682
- function correlateRelatedRows(context, parentNamespaceId, parentModelName, parentScope, relatedTableName, relation) {
3671
+ function correlateRelatedRows(context, parentNamespaceId, parentModelName, scope, parentTable, relatedTableName, relation) {
3672
+ const child = scope.aliasTable({
3673
+ namespaceId: relation.toNamespace,
3674
+ tableName: relatedTableName
3675
+ });
3683
3676
  if (hasThrough$1(relation)) {
3684
3677
  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);
3678
+ const junction = scope.aliasTable({
3679
+ namespaceId: through.namespaceId,
3680
+ tableName: through.table
3681
+ });
3682
+ const junctionJoinOn = buildPairedColumnExprs(junction, through.childColumns, child, through.targetColumns);
3687
3683
  const parentLocalColumns = relation.on.localFields.map((field) => columnOfContractField(context.contract, parentNamespaceId, parentModelName, field));
3688
3684
  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),
3685
+ child,
3686
+ source: SelectAst.from(child.tableSource(context.contract)).withJoins([JoinAst.inner(junction.tableSource(context.contract), junctionJoinOn)]),
3687
+ correlation: buildPairedColumnExprs(junction, through.parentColumns, parentTable, parentLocalColumns),
3692
3688
  keyColumn: firstJoinColumn(through.targetColumns, "targetColumns")
3693
3689
  };
3694
3690
  }
3695
- const childScope = parentScope.forRelation(relation.toNamespace, relatedTableName);
3696
3691
  return {
3697
- childScope,
3698
- source: SelectAst.from(childScope.current.tableSource(context.contract)),
3699
- correlation: buildJoinWhere(context.contract, parentNamespaceId, parentModelName, parentScope.current, childScope.current, relation),
3692
+ child,
3693
+ source: SelectAst.from(child.tableSource(context.contract)),
3694
+ correlation: buildJoinWhere(context.contract, parentNamespaceId, parentModelName, parentTable, child, relation),
3700
3695
  keyColumn: firstJoinColumn(resolveRelationTargetColumns(context.contract, relation), "targetFields")
3701
3696
  };
3702
3697
  }
3703
- function buildExistsExpr(context, relation, rows, mode, predicate) {
3704
- const childWhere = toRelationWhereExpr(context, relation.toNamespace, relation.to, predicate, rows.childScope);
3698
+ function buildExistsExpr(context, relation, scope, rows, mode, predicate) {
3699
+ const childWhere = toRelationWhereExpr(context, relation.toNamespace, relation.to, predicate, scope, rows.child);
3705
3700
  const filterPlan = planRelationFilterMode(rows.correlation, childWhere, mode);
3706
3701
  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);
3702
+ const subquery = rows.source.withProjection([ProjectionItem.of("_exists", rows.child.column(rows.keyColumn))]).withWhere(filterPlan.where);
3708
3703
  return filterPlan.notExists ? ExistsExpr.notExists(subquery) : ExistsExpr.exists(subquery);
3709
3704
  }
3710
3705
  function planRelationFilterMode(joinWhere, childWhere, mode) {
@@ -3745,10 +3740,10 @@ function buildPairedColumnExprs(leftTable, leftColumns, rightTable, rightColumns
3745
3740
  if (exprs.length === 1 && exprs[0]) return exprs[0];
3746
3741
  return and(...exprs);
3747
3742
  }
3748
- function toRelationWhereExpr(context, relatedNamespaceId, relatedModelName, predicate, scope) {
3743
+ function toRelationWhereExpr(context, relatedNamespaceId, relatedModelName, predicate, scope, table) {
3749
3744
  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)));
3745
+ const accessor = createModelAccessorInScope(context, relatedNamespaceId, relatedModelName, void 0, scope, table, void 0);
3746
+ if (typeof predicate === "function") return conditionExpr(predicate(accessor, callbackToolsFor(context, relatedModelName, table)));
3752
3747
  assertModelFieldNames(context.contract, relatedNamespaceId, relatedModelName, predicate);
3753
3748
  const exprs = [];
3754
3749
  for (const [fieldName, value] of Object.entries(predicate)) {
@@ -3824,7 +3819,7 @@ var GroupedCollection = class GroupedCollection {
3824
3819
  }));
3825
3820
  }
3826
3821
  having(predicate) {
3827
- const havingExpr = predicate(createHavingBuilder(this.contract, this.ctx.context.aggregateDescriptors, this.namespaceId, this.modelName, this.tableName));
3822
+ const havingExpr = predicate(createHavingBuilder(this.contract, this.ctx.context.aggregateDescriptors, this.namespaceId, this.modelName, this.preGroupState.tables.root));
3828
3823
  return this.#clone({ havingFilters: [...this.havingFilters, havingExpr] });
3829
3824
  }
3830
3825
  /**
@@ -3839,12 +3834,19 @@ var GroupedCollection = class GroupedCollection {
3839
3834
  method: "orderBy",
3840
3835
  model: this.modelName
3841
3836
  } });
3842
- const accessor = createModelAccessor(this.ctx.context, this.namespaceId, this.modelName);
3837
+ const tables = withScopeCopy(this.preGroupState.tables);
3838
+ const accessor = createModelAccessor(this.ctx.context, this.namespaceId, this.modelName, tables);
3843
3839
  const nextOrders = selectors.map((selector) => selector(accessor));
3844
- return this.#clone({ postGroup: {
3845
- ...this.postGroup,
3846
- orderBy: [...this.postGroup.orderBy, ...nextOrders]
3847
- } });
3840
+ return this.#clone({
3841
+ preGroupState: {
3842
+ ...this.preGroupState,
3843
+ tables
3844
+ },
3845
+ postGroup: {
3846
+ ...this.postGroup,
3847
+ orderBy: [...this.postGroup.orderBy, ...nextOrders]
3848
+ }
3849
+ });
3848
3850
  }
3849
3851
  /**
3850
3852
  * Apply `LIMIT n` to the grouped rows. Replaces any previous post-group
@@ -3900,7 +3902,7 @@ var GroupedCollection = class GroupedCollection {
3900
3902
  configure(meta);
3901
3903
  if (meta.annotations.size > 0) annotationsMap = meta.annotations;
3902
3904
  }
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);
3905
+ const compiled = mergeAnnotations(compileGroupedAggregate(this.contract, this.ctx.context.aggregateDescriptors, this.preGroupState, this.groupByColumns, aggregateSpec, combineWhereExprs(this.havingFilters), this.modelName, this.postGroup), annotationsMap);
3904
3906
  const mapRow = createStorageRowMapper(this.contract, this.namespaceId, this.modelName);
3905
3907
  return {
3906
3908
  plan: compiled,
@@ -3924,7 +3926,8 @@ var GroupedCollection = class GroupedCollection {
3924
3926
  * refused. The typed surface already excludes it; the runtime refusal covers
3925
3927
  * dynamic invocation.
3926
3928
  */
3927
- function createHavingBuilder(contract, aggregates, namespaceId, modelName, tableName) {
3929
+ function createHavingBuilder(contract, aggregates, namespaceId, modelName, root) {
3930
+ const { tableName } = root.storage;
3928
3931
  const fieldColumns = getModelFieldColumns(contract, namespaceId, modelName);
3929
3932
  const builder = {};
3930
3933
  for (const operation of aggregateOperationNames(aggregates)) builder[operation] = (field) => {
@@ -3934,7 +3937,7 @@ function createHavingBuilder(contract, aggregates, namespaceId, modelName, table
3934
3937
  meta: { operation }
3935
3938
  });
3936
3939
  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({
3940
+ return createHavingComparisonMethods(new AggregateExpr(operation, column === void 0 ? void 0 : root.column(column)), () => resolveAggregate({
3938
3941
  aggregates,
3939
3942
  contract,
3940
3943
  namespaceId,
@@ -4054,7 +4057,7 @@ async function executeNestedCreateMutation(options) {
4054
4057
  return withMutationScope(options.runtime, async (scope) => createGraph(scope, options.context, options.namespaceId, options.modelName, options.data));
4055
4058
  }
4056
4059
  async function executeNestedUpdateMutation(options) {
4057
- return withMutationScope(options.runtime, async (scope) => updateFirstGraph(scope, options.context, options.namespaceId, options.modelName, options.filters, options.data));
4060
+ return withMutationScope(options.runtime, async (scope) => updateFirstGraph(scope, options.context, options.namespaceId, options.modelName, options.tables, options.filters, options.data));
4058
4061
  }
4059
4062
  function buildRowIdentityFilterFromRow(contract, namespaceId, modelName, row) {
4060
4063
  const tableName = resolveModelTableName(contract, namespaceId, modelName);
@@ -4125,9 +4128,9 @@ async function createGraph(scope, context, namespaceId, modelName, input) {
4125
4128
  for (const relationMutation of junctionOwned) await applyJunctionOwnedMutation(scope, context, namespaceId, modelName, parentRow, relationMutation.relation, relationMutation.mutation);
4126
4129
  return parentRow;
4127
4130
  }
4128
- async function updateFirstGraph(scope, context, namespaceId, modelName, filters, input) {
4131
+ async function updateFirstGraph(scope, context, namespaceId, modelName, tables, filters, input) {
4129
4132
  const contract = context.contract;
4130
- const existingRow = await findFirstByFilters(scope, contract, namespaceId, modelName, filters);
4133
+ const existingRow = await findFirstByFilters(scope, contract, namespaceId, modelName, tables, filters);
4131
4134
  if (!existingRow) return null;
4132
4135
  const parsed = parseMutationInput(contract, namespaceId, modelName, input);
4133
4136
  const { parentOwned, childOwned, junctionOwned } = partitionByOwnership(parsed.relationMutations);
@@ -4145,9 +4148,9 @@ async function updateFirstGraph(scope, context, namespaceId, modelName, filters,
4145
4148
  values: mappedUpdateData
4146
4149
  });
4147
4150
  for (const def of appliedUpdateDefaults) mappedUpdateData[def.field] = def.value;
4148
- const identityWhere = shorthandToWhereExpr(context, namespaceId, modelName, castAs(buildRowIdentityFilterFromRow(contract, namespaceId, modelName, existingRow)));
4151
+ const identityWhere = shorthandToWhereExpr(context, namespaceId, modelName, castAs(buildRowIdentityFilterFromRow(contract, namespaceId, modelName, existingRow)), tables.root);
4149
4152
  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];
4153
+ const updatedRaw = (await queryPlanRows(scope, compileUpdateReturning(contract, modelName, tables, mappedUpdateData, [identityWhere], void 0)).toArray())[0];
4151
4154
  if (updatedRaw) parentRow = mapStorageRowToModelFields(contract, namespaceId, modelName, updatedRaw);
4152
4155
  }
4153
4156
  for (const relationMutation of childOwned) await applyChildOwnedMutation(scope, context, namespaceId, modelName, parentRow, relationMutation.relation, relationMutation.mutation);
@@ -4266,7 +4269,8 @@ async function applyChildOwnedMutation(scope, context, parentNamespaceId, parent
4266
4269
  }
4267
4270
  if (mutation.kind === "connect") {
4268
4271
  for (const criterion of mutation.criteria) {
4269
- const criterionWhere = shorthandToWhereExpr(context, relation.relatedNamespaceId, relation.relatedModelName, castAs(criterion));
4272
+ const related = createRelatedTables(relation);
4273
+ const criterionWhere = shorthandToWhereExpr(context, relation.relatedNamespaceId, relation.relatedModelName, castAs(criterion), related.root);
4270
4274
  if (!criterionWhere) throw ormError("ORM.RELATION_MUTATION_INVALID", `connect() nested mutation for relation "${relation.relationName}" requires non-empty criterion`, { meta: {
4271
4275
  kind: "connect",
4272
4276
  relation: relation.relationName,
@@ -4274,26 +4278,26 @@ async function applyChildOwnedMutation(scope, context, parentNamespaceId, parent
4274
4278
  } });
4275
4279
  const setValues = {};
4276
4280
  for (const [childColumn, parentValue] of parentValues.entries()) setValues[childColumn] = parentValue;
4277
- await executeUpdateCount(scope, contract, relation.relatedNamespaceId, relation.relatedTableName, setValues, [criterionWhere]);
4281
+ await executeUpdateCount(scope, contract, related, setValues, [criterionWhere]);
4278
4282
  }
4279
4283
  return;
4280
4284
  }
4281
4285
  const setValues = {};
4282
4286
  for (const childColumn of parentValues.keys()) setValues[childColumn] = null;
4283
4287
  if (!mutation.criteria || mutation.criteria.length === 0) {
4284
- const parentJoinWhere = buildChildJoinWhere(relation, parentValues);
4285
- await executeUpdateCount(scope, contract, relation.relatedNamespaceId, relation.relatedTableName, setValues, [parentJoinWhere]);
4288
+ const related = createRelatedTables(relation);
4289
+ await executeUpdateCount(scope, contract, related, setValues, [buildChildJoinWhere(contract, related.root, parentValues)]);
4286
4290
  return;
4287
4291
  }
4288
4292
  for (const criterion of mutation.criteria) {
4289
- const criterionWhere = shorthandToWhereExpr(context, relation.relatedNamespaceId, relation.relatedModelName, castAs(criterion));
4293
+ const related = createRelatedTables(relation);
4294
+ const criterionWhere = shorthandToWhereExpr(context, relation.relatedNamespaceId, relation.relatedModelName, castAs(criterion), related.root);
4290
4295
  if (!criterionWhere) throw ormError("ORM.RELATION_MUTATION_INVALID", `disconnect() nested mutation for relation "${relation.relationName}" requires non-empty criterion`, { meta: {
4291
4296
  kind: "disconnect",
4292
4297
  relation: relation.relationName,
4293
4298
  problem: "empty-criterion"
4294
4299
  } });
4295
- const parentJoinWhere = buildChildJoinWhere(relation, parentValues);
4296
- await executeUpdateCount(scope, contract, relation.relatedNamespaceId, relation.relatedTableName, setValues, [and(parentJoinWhere, criterionWhere)]);
4300
+ await executeUpdateCount(scope, contract, related, setValues, [and(buildChildJoinWhere(contract, related.root, parentValues), criterionWhere)]);
4297
4301
  }
4298
4302
  }
4299
4303
  async function applyJunctionOwnedMutation(scope, context, parentNamespaceId, parentModelName, parentRow, relation, mutation) {
@@ -4432,11 +4436,15 @@ async function deleteJunctionLink(scope, context, relation, parentPkValues, targ
4432
4436
  const junctionRow = {};
4433
4437
  for (const [column, value] of parentPkValues.entries()) writeJunctionColumn(junctionRow, through, column, value, relation.relationName);
4434
4438
  for (const [column, value] of targetPkValues.entries()) writeJunctionColumn(junctionRow, through, column, value, relation.relationName);
4439
+ const junction = createStatementTables({
4440
+ namespaceId: through.namespaceId,
4441
+ tableName: through.table
4442
+ });
4435
4443
  const exprs = [];
4436
- for (const [column, value] of Object.entries(junctionRow)) exprs.push(BinaryExpr.eq(ColumnRef.of(through.table, column), LiteralExpr.of(value)));
4444
+ 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
4445
  const first = exprs[0];
4438
4446
  const where = exprs.length === 1 && first !== void 0 ? first : and(...exprs);
4439
- const compiled = compileDeleteCount(context.contract, through.namespaceId, through.table, [where]);
4447
+ const compiled = compileDeleteCount(context.contract, junction, [where]);
4440
4448
  await scope.execute(compiled);
4441
4449
  }
4442
4450
  function readParentColumnValues(contract, parentNamespaceId, parentModelName, relation, parentRow) {
@@ -4452,9 +4460,15 @@ function readParentColumnValues(contract, parentNamespaceId, parentModelName, re
4452
4460
  }
4453
4461
  return values;
4454
4462
  }
4455
- function buildChildJoinWhere(relation, childValues) {
4463
+ function createRelatedTables(relation) {
4464
+ return createStatementTables({
4465
+ namespaceId: relation.relatedNamespaceId,
4466
+ tableName: relation.relatedTableName
4467
+ });
4468
+ }
4469
+ function buildChildJoinWhere(contract, related, childValues) {
4456
4470
  const exprs = [];
4457
- for (const [childColumn, parentValue] of childValues.entries()) exprs.push(BinaryExpr.eq(ColumnRef.of(relation.relatedTableName, childColumn), LiteralExpr.of(parentValue)));
4471
+ for (const [childColumn, parentValue] of childValues.entries()) exprs.push(BinaryExpr.eq(related.column(childColumn), paramRefForStorageColumn(contract, related.storage, childColumn, parentValue)));
4458
4472
  const first = exprs[0];
4459
4473
  if (exprs.length === 1 && first !== void 0) return first;
4460
4474
  return and(...exprs);
@@ -4480,31 +4494,35 @@ async function insertSingleRow(scope, context, namespaceId, modelName, data) {
4480
4494
  }
4481
4495
  async function findRowByCriterion(scope, context, namespaceId, modelName, criterion) {
4482
4496
  const contract = context.contract;
4483
- const whereExpr = shorthandToWhereExpr(context, namespaceId, modelName, castAs(criterion));
4497
+ const tables = createStatementTables({
4498
+ namespaceId,
4499
+ tableName: resolveModelTableName(contract, namespaceId, modelName)
4500
+ });
4501
+ const whereExpr = shorthandToWhereExpr(context, namespaceId, modelName, castAs(criterion), tables.root);
4484
4502
  if (!whereExpr) throw ormError("ORM.RELATION_MUTATION_INVALID", `Nested connect for model "${modelName}" requires non-empty criterion`, { meta: {
4485
4503
  kind: "connect",
4486
4504
  model: modelName,
4487
4505
  problem: "empty-criterion"
4488
4506
  } });
4489
- const firstRow = (await queryPlanRows(scope, compileSelect(contract, namespaceId, modelName, resolveModelTableName(contract, namespaceId, modelName), {
4490
- ...emptyState(),
4507
+ const firstRow = (await queryPlanRows(scope, compileSelect(contract, modelName, {
4508
+ ...emptyState(tables),
4491
4509
  filters: [whereExpr],
4492
4510
  limit: 1
4493
4511
  })).toArray())[0];
4494
4512
  if (!firstRow) return null;
4495
4513
  return mapStorageRowToModelFields(contract, namespaceId, modelName, firstRow);
4496
4514
  }
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(),
4515
+ async function findFirstByFilters(scope, contract, namespaceId, modelName, tables, filters) {
4516
+ const firstRow = (await queryPlanRows(scope, compileSelect(contract, modelName, {
4517
+ ...emptyState(tables),
4500
4518
  filters,
4501
4519
  limit: 1
4502
4520
  })).toArray())[0];
4503
4521
  if (!firstRow) return null;
4504
4522
  return mapStorageRowToModelFields(contract, namespaceId, modelName, firstRow);
4505
4523
  }
4506
- async function executeUpdateCount(scope, contract, namespaceId, tableName, setValues, filters) {
4507
- const compiled = compileUpdateCount(contract, namespaceId, tableName, setValues, filters);
4524
+ async function executeUpdateCount(scope, contract, tables, setValues, filters) {
4525
+ const compiled = compileUpdateCount(contract, tables, setValues, filters);
4508
4526
  await scope.execute(compiled);
4509
4527
  }
4510
4528
  const relationDefsCache = /* @__PURE__ */ new WeakMap();
@@ -4544,9 +4562,9 @@ function toFieldName(contract, namespaceId, modelName, columnName) {
4544
4562
  function normalizeWhereArg(arg, options) {
4545
4563
  if (arg === void 0) return;
4546
4564
  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;
4565
+ const expr = isToWhereExpr(arg) ? arg.toWhereExpr() : arg;
4566
+ if (!options) return expr;
4567
+ return bindWhereExpr(options.contract, expr, options.tables);
4550
4568
  }
4551
4569
  function isToWhereExpr(arg) {
4552
4570
  return typeof arg === "object" && arg !== null && "toWhereExpr" in arg && !isWhereExpr(arg);
@@ -4707,7 +4725,7 @@ var CollectionBase = class CollectionBase {
4707
4725
  this.modelName = modelName;
4708
4726
  this.namespaceId = options.namespaceId;
4709
4727
  this.tableName = options.tableName ?? resolveModelTableName(this.contract, options.namespaceId, modelName);
4710
- this.state = options.state ?? emptyState();
4728
+ this.state = options.state ?? emptyState(createCollectionTables(this.contract, options.namespaceId, modelName, this.tableName));
4711
4729
  this.registry = options.registry ?? /* @__PURE__ */ new Map();
4712
4730
  this.includeRefinementMode = options.includeRefinementMode ?? false;
4713
4731
  this.#installAggregateReducers();
@@ -4755,15 +4773,19 @@ var CollectionBase = class CollectionBase {
4755
4773
  return createIncludeScalar(operation, this.state, column);
4756
4774
  }
4757
4775
  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), {
4776
+ const tables = withScopeCopy(this.state.tables);
4777
+ 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
4778
  contract: this.contract,
4760
- namespaceId: this.namespaceId
4779
+ tables: tableAliases(tables)
4761
4780
  });
4762
4781
  if (!filter) return blindCast(this);
4763
- return this.#cloneSelf({ filters: [...this.state.filters, filter] });
4782
+ return this.#cloneSelf({
4783
+ tables,
4784
+ filters: [...this.state.filters, filter]
4785
+ });
4764
4786
  }
4765
- #callbackTools() {
4766
- return createModelCallbackTools(this.ctx.context, this.namespaceId, this.modelName);
4787
+ #callbackTools(tables) {
4788
+ return createModelCallbackTools(this.ctx.context, this.modelName, tables);
4767
4789
  }
4768
4790
  with(fn) {
4769
4791
  return fn(this);
@@ -4815,7 +4837,7 @@ var CollectionBase = class CollectionBase {
4815
4837
  } });
4816
4838
  }
4817
4839
  const columnName = polyInfo.discriminatorColumn;
4818
- const filter = BinaryExpr.eq(ColumnRef.of(this.tableName, columnName), LiteralExpr.of(variantInfo.value));
4840
+ const filter = BinaryExpr.eq(this.state.tables.root.column(columnName), paramRefForStorageColumn(this.contract, this.state.tables.root.storage, columnName, variantInfo.value));
4819
4841
  return this.#cloneWithRow({
4820
4842
  filters: [...this.state.filters, filter],
4821
4843
  variantName: variantInfo.modelName
@@ -4823,14 +4845,16 @@ var CollectionBase = class CollectionBase {
4823
4845
  }
4824
4846
  include(relationName, refineFn) {
4825
4847
  const relation = resolveIncludeRelation(this.contract, this.namespaceId, this.modelName, relationName, this.state.variantName);
4826
- let nestedState = emptyState();
4848
+ const child = createIncludeTables(this.contract, this.state.tables, relation);
4849
+ let nestedState = emptyState(child.tables);
4850
+ let adoptedScope = child.tables.scope;
4827
4851
  let scalarSelector;
4828
4852
  let combineBranches;
4829
4853
  if (refineFn) {
4830
4854
  const refined = refineFn(this.#createCollection(blindCast(relation.relatedModelName), {
4831
4855
  tableName: relation.relatedTableName,
4832
4856
  namespaceId: relation.relatedNamespaceId,
4833
- state: emptyState(),
4857
+ state: nestedState,
4834
4858
  includeRefinementMode: true
4835
4859
  }));
4836
4860
  if (isIncludeScalar(refined)) {
@@ -4838,6 +4862,7 @@ var CollectionBase = class CollectionBase {
4838
4862
  relation: relationName,
4839
4863
  kind: "scalar"
4840
4864
  } });
4865
+ adoptedScope = refined.state.tables.scope;
4841
4866
  scalarSelector = refined;
4842
4867
  nestedState = refined.state;
4843
4868
  } else if (isIncludeCombine(refined)) {
@@ -4846,35 +4871,48 @@ var CollectionBase = class CollectionBase {
4846
4871
  kind: "combine"
4847
4872
  } });
4848
4873
  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 } });
4874
+ } else if (isCollectionStateCarrier(refined)) {
4875
+ adoptedScope = refined.state.tables.scope;
4876
+ nestedState = refined.state;
4877
+ } else throw ormError("ORM.INCLUDE_INVALID", `include('${relationName}') refinement must return a collection, include scalar selector, or combine() descriptor`, { meta: { relation: relationName } });
4851
4878
  }
4852
4879
  const includeExpr = {
4853
4880
  relationName,
4854
4881
  relatedModelName: relation.relatedModelName,
4855
4882
  relatedNamespaceId: relation.relatedNamespaceId,
4856
4883
  relatedTableName: relation.relatedTableName,
4857
- localTableName: relation.localTableName,
4884
+ ...ifDefined("localVariantName", relation.localVariantName),
4858
4885
  targetColumns: relation.targetColumns,
4859
4886
  localColumns: relation.localColumns,
4860
4887
  cardinality: relation.cardinality,
4861
4888
  ...ifDefined("through", relation.through),
4889
+ ...ifDefined("junction", child.junction),
4862
4890
  nested: nestedState,
4863
4891
  scalar: scalarSelector,
4864
4892
  combine: combineBranches
4865
4893
  };
4866
- return this.#cloneWithRow({ includes: [...this.state.includes, includeExpr] });
4894
+ return this.#cloneWithRow({
4895
+ tables: {
4896
+ ...this.state.tables,
4897
+ scope: adoptedScope
4898
+ },
4899
+ includes: [...this.state.includes, includeExpr]
4900
+ });
4867
4901
  }
4868
4902
  select(...fields) {
4869
4903
  const selectedFields = mapSelectedFieldsToColumns(this.contract, this.namespaceId, this.modelName, this.state.variantName, fields);
4870
4904
  return this.#cloneWithRow({ selectedFields });
4871
4905
  }
4872
4906
  orderBy(selection) {
4873
- const accessor = createModelAccessor(this.ctx.context, this.namespaceId, this.modelName, this.state.variantName);
4874
- const tools = this.#callbackTools();
4907
+ const tables = withScopeCopy(this.state.tables);
4908
+ const accessor = createModelAccessor(this.ctx.context, this.namespaceId, this.modelName, tables, this.state.variantName);
4909
+ const tools = this.#callbackTools(tables);
4875
4910
  const nextOrders = (Array.isArray(selection) ? selection : [selection]).map((selector) => selector(accessor, tools));
4876
4911
  const existing = this.state.orderBy ?? [];
4877
- return this.#cloneSelf({ orderBy: [...existing, ...nextOrders] });
4912
+ return this.#cloneSelf({
4913
+ tables,
4914
+ orderBy: [...existing, ...nextOrders]
4915
+ });
4878
4916
  }
4879
4917
  /**
4880
4918
  * Switch to grouped-aggregate mode. Returns a `GroupedCollection`
@@ -5006,7 +5044,6 @@ var CollectionBase = class CollectionBase {
5006
5044
  return {
5007
5045
  context: this.ctx.context,
5008
5046
  state: this.state,
5009
- tableName: this.tableName,
5010
5047
  modelName: this.modelName,
5011
5048
  namespaceId: this.namespaceId
5012
5049
  };
@@ -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