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