orchid-orm 1.77.1 → 1.77.2
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/index.d.ts +6 -6
- package/dist/index.js +753 -727
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +753 -727
- package/dist/index.mjs.map +1 -1
- package/package.json +7 -7
package/dist/index.mjs
CHANGED
|
@@ -712,6 +712,20 @@ const selectCteColumnFromManySql = (cteAs, column, rowIndex, count) => {
|
|
|
712
712
|
}
|
|
713
713
|
return sql + ")";
|
|
714
714
|
};
|
|
715
|
+
const selectCteColumnMustExistSql = (i, cteAs, column) => {
|
|
716
|
+
const selectColumn = selectCteColumnSql$1(cteAs, column);
|
|
717
|
+
return i === 0 ? `CASE WHEN (SELECT count(*) FROM "${cteAs}") = 0 AND (SELECT 'not-found')::int = 0 THEN NULL ELSE ${selectColumn} END` : selectColumn;
|
|
718
|
+
};
|
|
719
|
+
const setForeignKeysFromCte = (record, primaryKeys, foreignKeys, mustExist) => {
|
|
720
|
+
for (const key of foreignKeys) record[key] = new RawSql("");
|
|
721
|
+
return (as) => {
|
|
722
|
+
foreignKeys.forEach(mustExist ? (foreignKey, i) => {
|
|
723
|
+
record[foreignKey]._sql = selectCteColumnMustExistSql(i, as, primaryKeys[i]);
|
|
724
|
+
} : (foreignKey, i) => {
|
|
725
|
+
record[foreignKey]._sql = selectCteColumnSql$1(as, primaryKeys[i]);
|
|
726
|
+
});
|
|
727
|
+
};
|
|
728
|
+
};
|
|
715
729
|
const joinQueryChainHOF = (relPKeys, reverseJoin, joinQuery) => (joiningQuery, baseQuery) => {
|
|
716
730
|
const jq = joiningQuery;
|
|
717
731
|
const chain = jq.q.relChain;
|
|
@@ -783,122 +797,61 @@ const wrapQuery = (joiningQuery, result, item) => {
|
|
|
783
797
|
result.q.returnsOne = true;
|
|
784
798
|
return result.wrap(outer);
|
|
785
799
|
};
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
items.forEach((item) => {
|
|
798
|
-
const value = item[key];
|
|
799
|
-
const kind = value.create ? "create" : value.connect ? "connect" : "connectOrCreate";
|
|
800
|
-
if (kind) {
|
|
801
|
-
const nestedCreateItem = (nestedCreateItems ??= {})[kind] ??= {
|
|
802
|
-
items: [],
|
|
803
|
-
values: []
|
|
804
|
-
};
|
|
805
|
-
nestedCreateItem.items.push(item);
|
|
806
|
-
nestedCreateItem.values.push(value[kind]);
|
|
807
|
-
if (kind !== "connect") for (const key of foreignKeys) item[key] = new RawSql("");
|
|
808
|
-
}
|
|
809
|
-
});
|
|
810
|
-
if (!nestedCreateItems) return;
|
|
811
|
-
for (const key of foreignKeys) if (!ctx.columns.has(key)) ctx.columns.set(key, ctx.columns.size);
|
|
812
|
-
const { create, connect, connectOrCreate } = nestedCreateItems;
|
|
813
|
-
if (create) {
|
|
814
|
-
const selectPKeys = query.select(...primaryKeys);
|
|
815
|
-
let createQuery;
|
|
816
|
-
if (queryForCreate.q.type === "upsert") {
|
|
817
|
-
const createWhereNotExists = new RawSql("");
|
|
818
|
-
_onUpsertUpdate(queryForCreate, (as) => {
|
|
819
|
-
createWhereNotExists._sql = `NOT EXISTS (SELECT 1 FROM "${as}")`;
|
|
820
|
-
});
|
|
821
|
-
const sourceQuery = _queryWhere(_queryTake(_querySelect(_clone(query.qb), [{}])), [createWhereNotExists]);
|
|
822
|
-
createQuery = _queryInsertManyFrom(selectPKeys, sourceQuery, create.values);
|
|
823
|
-
} else createQuery = _queryInsertMany(selectPKeys, create.values);
|
|
824
|
-
const setForeignKeys = (as) => {
|
|
825
|
-
const count = create.items.length;
|
|
826
|
-
foreignKeys.forEach((foreignKey, i) => {
|
|
827
|
-
const primaryKey = primaryKeys[i];
|
|
828
|
-
create.items.forEach((item, i) => {
|
|
829
|
-
item[foreignKey]._sql = selectCteColumnFromManySql(as, primaryKey, i, count);
|
|
830
|
-
});
|
|
831
|
-
});
|
|
800
|
+
const belongsToCreate = (key, state, q, ctx, items) => {
|
|
801
|
+
const queryForCreate = q;
|
|
802
|
+
const { query, primaryKeys, foreignKeys } = state;
|
|
803
|
+
let nestedCreateItems;
|
|
804
|
+
items.forEach((item) => {
|
|
805
|
+
const value = item[key];
|
|
806
|
+
const kind = value.create ? "create" : value.connect ? "connect" : "connectOrCreate";
|
|
807
|
+
if (kind) {
|
|
808
|
+
const nestedCreateItem = (nestedCreateItems ??= {})[kind] ??= {
|
|
809
|
+
items: [],
|
|
810
|
+
values: []
|
|
832
811
|
};
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
812
|
+
nestedCreateItem.items.push(item);
|
|
813
|
+
nestedCreateItem.values.push(value[kind]);
|
|
814
|
+
if (kind !== "connect") for (const key of foreignKeys) item[key] = new RawSql("");
|
|
815
|
+
}
|
|
816
|
+
});
|
|
817
|
+
if (!nestedCreateItems) return;
|
|
818
|
+
for (const key of foreignKeys) if (!ctx.columns.has(key)) ctx.columns.set(key, ctx.columns.size);
|
|
819
|
+
const { create, connect, connectOrCreate } = nestedCreateItems;
|
|
820
|
+
if (create) {
|
|
821
|
+
const selectPKeys = query.select(...primaryKeys);
|
|
822
|
+
let createQuery;
|
|
823
|
+
if (queryForCreate.q.type === "upsert") {
|
|
824
|
+
const createWhereNotExists = new RawSql("");
|
|
825
|
+
_onUpsertUpdate(queryForCreate, (as) => {
|
|
826
|
+
createWhereNotExists._sql = `NOT EXISTS (SELECT 1 FROM "${as}")`;
|
|
841
827
|
});
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
828
|
+
const sourceQuery = _queryWhere(_queryTake(_querySelect(_clone(query.qb), [{}])), [createWhereNotExists]);
|
|
829
|
+
createQuery = _queryInsertManyFrom(selectPKeys, sourceQuery, create.values);
|
|
830
|
+
} else createQuery = _queryInsertMany(selectPKeys, create.values);
|
|
831
|
+
const setForeignKeys = (as) => {
|
|
832
|
+
const count = create.items.length;
|
|
833
|
+
foreignKeys.forEach((foreignKey, i) => {
|
|
834
|
+
const primaryKey = primaryKeys[i];
|
|
835
|
+
create.items.forEach((item, i) => {
|
|
836
|
+
item[foreignKey]._sql = selectCteColumnFromManySql(as, primaryKey, i, count);
|
|
837
|
+
});
|
|
838
|
+
});
|
|
839
|
+
};
|
|
840
|
+
if (queryForCreate.q.type === "upsert") _prependWithOnUpsertCreate(queryForCreate, setForeignKeys, createQuery);
|
|
841
|
+
else _prependWith(queryForCreate, setForeignKeys, createQuery);
|
|
854
842
|
}
|
|
855
|
-
|
|
856
|
-
const
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
843
|
+
if (connect) connect.values.forEach((value, itemI) => {
|
|
844
|
+
const as = getFreeAlias(queryForCreate.q.withShapes, "q");
|
|
845
|
+
(queryForCreate.q.type === "upsert" ? _prependWithOnUpsertCreate : _prependWith)(queryForCreate, as, query.select(...primaryKeys).findBy(value));
|
|
846
|
+
foreignKeys.map((foreignKey, i) => {
|
|
847
|
+
connect.items[itemI][foreignKey] = new RawSql(selectCteColumnMustExistSql(i, as, primaryKeys[i]));
|
|
848
|
+
});
|
|
849
|
+
});
|
|
850
|
+
if (connectOrCreate) connectOrCreate.values.forEach((value, itemI) => {
|
|
851
|
+
const asFn = setForeignKeysFromCte(connectOrCreate.items[itemI], primaryKeys, foreignKeys);
|
|
852
|
+
const selectPKeys = query.select(...primaryKeys);
|
|
853
|
+
(queryForCreate.q.type === "upsert" ? _prependWithOnUpsertCreate : _prependWith)(queryForCreate, asFn, _orCreate(_queryWhere(selectPKeys, [value.where]), value.create));
|
|
862
854
|
});
|
|
863
|
-
};
|
|
864
|
-
const makeBelongsToMethod = (tableConfig, table, relation, relationName, query) => {
|
|
865
|
-
const primaryKeys = relation.options.references;
|
|
866
|
-
const foreignKeys = relation.options.columns;
|
|
867
|
-
const { on } = relation.options;
|
|
868
|
-
if (on) {
|
|
869
|
-
_queryWhere(query, [on]);
|
|
870
|
-
_queryDefaults(query, on);
|
|
871
|
-
}
|
|
872
|
-
const len = primaryKeys.length;
|
|
873
|
-
const state = {
|
|
874
|
-
query,
|
|
875
|
-
primaryKeys,
|
|
876
|
-
foreignKeys,
|
|
877
|
-
len,
|
|
878
|
-
on
|
|
879
|
-
};
|
|
880
|
-
addAutoForeignKey(tableConfig, table, query, primaryKeys, foreignKeys, relation.options);
|
|
881
|
-
const join = (baseQuery, joiningQuery, primaryKeys, foreignKeys) => {
|
|
882
|
-
const baseAs = getQueryAs(baseQuery);
|
|
883
|
-
const q = joiningQuery.clone();
|
|
884
|
-
setQueryObjectValueImmutable(q, "joinedShapes", baseAs, baseQuery.q.selectShape);
|
|
885
|
-
for (let i = 0; i < len; i++) pushQueryOnForOuter(q, baseQuery, joiningQuery, primaryKeys[i], `${baseAs}.${foreignKeys[i]}`);
|
|
886
|
-
return q;
|
|
887
|
-
};
|
|
888
|
-
const reverseJoin = (baseQuery, joiningQuery) => {
|
|
889
|
-
return join(joiningQuery, baseQuery, foreignKeys, primaryKeys);
|
|
890
|
-
};
|
|
891
|
-
return {
|
|
892
|
-
returns: "one",
|
|
893
|
-
queryRelated(params) {
|
|
894
|
-
const obj = {};
|
|
895
|
-
for (let i = 0; i < len; i++) obj[primaryKeys[i]] = params[foreignKeys[i]];
|
|
896
|
-
return query.where(obj);
|
|
897
|
-
},
|
|
898
|
-
virtualColumn: new BelongsToVirtualColumn(internalSchemaConfig, relationName, state),
|
|
899
|
-
joinQuery: joinQueryChainHOF(getPrimaryKeys(query), reverseJoin, (joiningQuery, baseQuery) => join(baseQuery, joiningQuery, primaryKeys, foreignKeys)),
|
|
900
|
-
reverseJoin
|
|
901
|
-
};
|
|
902
855
|
};
|
|
903
856
|
const nestedUpdate$2 = ({ query, primaryKeys, foreignKeys, len }) => {
|
|
904
857
|
return ((self, update, params) => {
|
|
@@ -971,240 +924,69 @@ const makeSelectIdsQuery = (self, foreignKeys) => {
|
|
|
971
924
|
selectIdsQuery.q.or = self.q.or;
|
|
972
925
|
return selectIdsQuery;
|
|
973
926
|
};
|
|
974
|
-
|
|
975
|
-
for (const key of foreignKeys) record[key] = new RawSql("");
|
|
976
|
-
return (as) => {
|
|
977
|
-
foreignKeys.forEach(mustExist ? (foreignKey, i) => {
|
|
978
|
-
record[foreignKey]._sql = selectCteColumnMustExistSql(i, as, primaryKeys[i]);
|
|
979
|
-
} : (foreignKey, i) => {
|
|
980
|
-
record[foreignKey]._sql = selectCteColumnSql$1(as, primaryKeys[i]);
|
|
981
|
-
});
|
|
982
|
-
};
|
|
983
|
-
};
|
|
984
|
-
const selectCteColumnMustExistSql = (i, cteAs, column) => {
|
|
985
|
-
const selectColumn = selectCteColumnSql$1(cteAs, column);
|
|
986
|
-
return i === 0 ? `CASE WHEN (SELECT count(*) FROM "${cteAs}") = 0 AND (SELECT 'not-found')::int = 0 THEN NULL ELSE ${selectColumn} END` : selectColumn;
|
|
987
|
-
};
|
|
988
|
-
var HasOneVirtualColumn = class extends VirtualColumn {
|
|
927
|
+
var BelongsToVirtualColumn = class extends VirtualColumn {
|
|
989
928
|
constructor(schema, key, state) {
|
|
990
929
|
super(schema);
|
|
991
930
|
this.key = key;
|
|
992
931
|
this.state = state;
|
|
993
|
-
this.
|
|
994
|
-
this.setNulls = {};
|
|
995
|
-
for (const foreignKey of state.foreignKeys) this.setNulls[foreignKey] = null;
|
|
932
|
+
this.nestedUpdate = nestedUpdate$2(this.state);
|
|
996
933
|
}
|
|
997
|
-
create(
|
|
998
|
-
|
|
999
|
-
if (count <= querySelf.qb.internal.nestedCreateBatchMax) {
|
|
1000
|
-
const { query: rel, primaryKeys, foreignKeys } = this.state;
|
|
1001
|
-
let nestedCreateItems;
|
|
1002
|
-
items.forEach((item, i) => {
|
|
1003
|
-
const value = item[this.key];
|
|
1004
|
-
const kind = value.create ? "create" : value.connect ? "connect" : "connectOrCreate";
|
|
1005
|
-
if (kind) {
|
|
1006
|
-
const nestedCreateItem = (nestedCreateItems ??= {})[kind] ??= {
|
|
1007
|
-
indexes: [],
|
|
1008
|
-
items: [],
|
|
1009
|
-
values: []
|
|
1010
|
-
};
|
|
1011
|
-
nestedCreateItem.indexes.push(rowIndexes[i]);
|
|
1012
|
-
nestedCreateItem.values.push(value[kind]);
|
|
1013
|
-
const data = value.create ? { ...value.create } : {};
|
|
1014
|
-
for (const key of foreignKeys) data[key] = new RawSql("");
|
|
1015
|
-
nestedCreateItem.items.push(data);
|
|
1016
|
-
}
|
|
1017
|
-
});
|
|
1018
|
-
if (!nestedCreateItems) return;
|
|
1019
|
-
let createAs;
|
|
1020
|
-
let createWhereExists;
|
|
1021
|
-
let createSelectAs;
|
|
1022
|
-
let createAliasedPrimaryKeys;
|
|
1023
|
-
let upsertCreateAs;
|
|
1024
|
-
let connectAs;
|
|
1025
|
-
let connectOrCreateAs;
|
|
1026
|
-
const setUpsertCreatePlaceholders = () => {
|
|
1027
|
-
if (!upsertCreateAs || !createAliasedPrimaryKeys) return;
|
|
1028
|
-
const aliasedPrimaryKeys = createAliasedPrimaryKeys;
|
|
1029
|
-
if (createWhereExists) createWhereExists._sql = `EXISTS (SELECT 1 FROM "${upsertCreateAs}")`;
|
|
1030
|
-
if (createSelectAs) foreignKeys.forEach((key, keyI) => {
|
|
1031
|
-
createSelectAs[key]._sql = selectCteColumnFromManySql(upsertCreateAs, aliasedPrimaryKeys[keyI], 0, 1);
|
|
1032
|
-
});
|
|
1033
|
-
if (connect) foreignKeys.forEach((key, keyI) => {
|
|
1034
|
-
const primaryKey = aliasedPrimaryKeys[keyI];
|
|
1035
|
-
for (let i = 0; i < connect.items.length; i++) connect.items[i][key]._sql = selectCteColumnFromManySql(upsertCreateAs, primaryKey, connect.indexes[i], count);
|
|
1036
|
-
});
|
|
1037
|
-
if (connectOrCreate) foreignKeys.forEach((key, keyI) => {
|
|
1038
|
-
const primaryKey = aliasedPrimaryKeys[keyI];
|
|
1039
|
-
for (let i = 0; i < connectOrCreate.items.length; i++) connectOrCreate.items[i][key]._sql = selectCteColumnFromManySql(upsertCreateAs, primaryKey, connectOrCreate.indexes[i], count);
|
|
1040
|
-
});
|
|
1041
|
-
};
|
|
1042
|
-
_hookSelectColumns(querySelf, primaryKeys, (aliasedPrimaryKeys) => {
|
|
1043
|
-
createAliasedPrimaryKeys = aliasedPrimaryKeys;
|
|
1044
|
-
foreignKeys.forEach((key, keyI) => {
|
|
1045
|
-
const primaryKey = aliasedPrimaryKeys[keyI];
|
|
1046
|
-
if (create && createAs) for (let i = 0; i < create.items.length; i++) create.items[i][key]._sql = selectCteColumnFromManySql(createAs, primaryKey, create.indexes[i], count);
|
|
1047
|
-
if (connect && connectAs) for (let i = 0; i < connect.items.length; i++) connect.items[i][key]._sql = selectCteColumnFromManySql(connectAs, primaryKey, connect.indexes[i], count);
|
|
1048
|
-
if (connectOrCreate && connectOrCreateAs) for (let i = 0; i < connectOrCreate.items.length; i++) connectOrCreate.items[i][key]._sql = selectCteColumnFromManySql(connectOrCreateAs, primaryKey, connectOrCreate.indexes[i], count);
|
|
1049
|
-
});
|
|
1050
|
-
setUpsertCreatePlaceholders();
|
|
1051
|
-
});
|
|
1052
|
-
const { create, connect, connectOrCreate } = nestedCreateItems;
|
|
1053
|
-
if (create) {
|
|
1054
|
-
let query;
|
|
1055
|
-
if (querySelf.q.type === "upsert") {
|
|
1056
|
-
createWhereExists = new RawSql("");
|
|
1057
|
-
createSelectAs = {};
|
|
1058
|
-
for (const key of foreignKeys) createSelectAs[key] = new RawSql("");
|
|
1059
|
-
const sourceQuery = _queryWhere(_queryTake(_querySelect(_clone(rel.qb), [createSelectAs])), [createWhereExists]);
|
|
1060
|
-
query = _queryInsertManyFrom(_clone(rel), sourceQuery, create.items);
|
|
1061
|
-
} else query = _queryInsertMany(_clone(rel), create.items);
|
|
1062
|
-
if (querySelf.q.type === "upsert") _appendQueryOnUpsertCreate(querySelf, query, (as) => {
|
|
1063
|
-
upsertCreateAs = as;
|
|
1064
|
-
setUpsertCreatePlaceholders();
|
|
1065
|
-
});
|
|
1066
|
-
else _appendQuery(querySelf, query, (as) => createAs = as);
|
|
1067
|
-
}
|
|
1068
|
-
if (connect) connect.values.forEach((value, i) => {
|
|
1069
|
-
const connectWhereExists = querySelf.q.type === "upsert" ? new RawSql("") : void 0;
|
|
1070
|
-
const query = _queryUpdateOrThrow(rel.where(value), connect.items[i]);
|
|
1071
|
-
if (connectWhereExists) _queryWhere(query, [connectWhereExists]);
|
|
1072
|
-
query.q.ensureCount = 1;
|
|
1073
|
-
(querySelf.q.type === "upsert" ? _appendQueryOnUpsertCreate : _appendQuery)(querySelf, query, (as) => {
|
|
1074
|
-
upsertCreateAs = as;
|
|
1075
|
-
setUpsertCreatePlaceholders();
|
|
1076
|
-
connectAs = as;
|
|
1077
|
-
if (connectWhereExists) connectWhereExists._sql = `EXISTS (SELECT 1 FROM "${as}")`;
|
|
1078
|
-
});
|
|
1079
|
-
});
|
|
1080
|
-
if (connectOrCreate) connectOrCreate.values.forEach((value, i) => {
|
|
1081
|
-
const foreignKeyValues = connectOrCreate.items[i];
|
|
1082
|
-
const connectOrCreateWhereExists = querySelf.q.type === "upsert" ? new RawSql("") : void 0;
|
|
1083
|
-
const connectOrCreateSelectAs = {};
|
|
1084
|
-
if (connectOrCreateWhereExists) for (const key of foreignKeys) {
|
|
1085
|
-
const value = foreignKeyValues[key];
|
|
1086
|
-
value.result = { value: rel.qb.shape[key] };
|
|
1087
|
-
connectOrCreateSelectAs[key] = value;
|
|
1088
|
-
}
|
|
1089
|
-
const query = _queryUpsert(rel.where(value.where), {
|
|
1090
|
-
update: foreignKeyValues,
|
|
1091
|
-
create: {
|
|
1092
|
-
...value.create,
|
|
1093
|
-
...foreignKeyValues
|
|
1094
|
-
}
|
|
1095
|
-
});
|
|
1096
|
-
if (connectOrCreateWhereExists) {
|
|
1097
|
-
_queryWhere(query, [connectOrCreateWhereExists]);
|
|
1098
|
-
const guardQuery = _queryWhere(_queryTake(_querySelect(_clone(rel.qb), [{ one: new RawSql("1") }])), [connectOrCreateWhereExists]);
|
|
1099
|
-
const sourceQuery = _querySelect(_clone(rel.qb).from(guardQuery), [connectOrCreateSelectAs]);
|
|
1100
|
-
const q = query.q;
|
|
1101
|
-
const columns = q.columns || [];
|
|
1102
|
-
const foreignKeysSet = new Set(foreignKeys);
|
|
1103
|
-
q.columns = [...foreignKeys, ...columns.filter((column) => !foreignKeysSet.has(column))];
|
|
1104
|
-
q.values = q.values.map((row) => row.filter((_, i) => !foreignKeysSet.has(columns[i])));
|
|
1105
|
-
q.queryColumnsCount = foreignKeys.length;
|
|
1106
|
-
q.insertFrom = prepareSubQueryForSql(query, sourceQuery);
|
|
1107
|
-
}
|
|
1108
|
-
(querySelf.q.type === "upsert" ? _appendQueryOnUpsertCreate : _appendQuery)(querySelf, query, (as) => {
|
|
1109
|
-
upsertCreateAs = as;
|
|
1110
|
-
setUpsertCreatePlaceholders();
|
|
1111
|
-
connectOrCreateAs = as;
|
|
1112
|
-
if (connectOrCreateWhereExists) connectOrCreateWhereExists._sql = `EXISTS (SELECT 1 FROM "${as}")`;
|
|
1113
|
-
});
|
|
1114
|
-
});
|
|
1115
|
-
} else hasRelationHandleCreate(querySelf, ctx, items, rowIndexes, this.key, this.state.primaryKeys, this.nestedInsert);
|
|
934
|
+
create(q, ctx, items) {
|
|
935
|
+
belongsToCreate(this.key, this.state, q, ctx, items);
|
|
1116
936
|
}
|
|
1117
|
-
update(
|
|
1118
|
-
const
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
if (params.create || params.update || params.upsert || params.disconnect || params.set || params.delete) {
|
|
1123
|
-
const ids = makeNestedUpdateRelationIds(querySelf, relQuery, primaryKeys, foreignKeys);
|
|
1124
|
-
const nullifyOrDeleteQuery = params.update ? _queryUpdate(ids.existingRelQuery, params.update) : params.upsert ? _queryUpsert(ids.existingRelQuery, makeNestedUpdateUpsertData(params.upsert, ids.setIds)) : params.delete ? _queryDelete(ids.existingRelQuery) : _queryUpdate(ids.existingRelQuery, this.setNulls);
|
|
1125
|
-
nullifyOrDeleteQuery.q.returnType = "void";
|
|
1126
|
-
_appendQuery(querySelf, nullifyOrDeleteQuery, ids.setAppendedAs);
|
|
1127
|
-
if (params.create) {
|
|
1128
|
-
const createQuery = _queryInsert(_clone(relQuery), {
|
|
1129
|
-
...params.create,
|
|
1130
|
-
...ids.setIds
|
|
1131
|
-
});
|
|
1132
|
-
_appendQuery(querySelf, createQuery, noop);
|
|
1133
|
-
} else if (params.set) {
|
|
1134
|
-
const setQuery = _queryUpdate(_queryWhere(_clone(relQuery), [params.set]), ids.setIds);
|
|
1135
|
-
setQuery.q.returnType = "void";
|
|
1136
|
-
_appendQuery(querySelf, setQuery, noop);
|
|
1137
|
-
}
|
|
1138
|
-
}
|
|
937
|
+
update(q, set) {
|
|
938
|
+
const queryForUpdate = q;
|
|
939
|
+
queryForUpdate.q.wrapInTransaction = true;
|
|
940
|
+
const data = set[this.key];
|
|
941
|
+
this.nestedUpdate(queryForUpdate, set, data);
|
|
1139
942
|
}
|
|
1140
943
|
};
|
|
1141
|
-
const
|
|
1142
|
-
const
|
|
1143
|
-
if ("
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
return joinHasThrough(baseQuery, baseQuery, joiningQuery, throughRelation, sourceRelation);
|
|
1153
|
-
};
|
|
1154
|
-
return {
|
|
1155
|
-
returns: "one",
|
|
1156
|
-
queryRelated: (params) => {
|
|
1157
|
-
const throughQuery = table.queryRelated(through, params);
|
|
1158
|
-
return query.whereExists(throughQuery, whereExistsCallback);
|
|
1159
|
-
},
|
|
1160
|
-
joinQuery: joinQueryChainHOF(relPKeys, reverseJoin, (joiningQuery, baseQuery) => joinHasThrough(joiningQuery, baseQuery, joiningQuery, throughRelation, sourceRelation)),
|
|
1161
|
-
reverseJoin
|
|
1162
|
-
};
|
|
1163
|
-
}
|
|
1164
|
-
const primaryKeys = relation.options.columns;
|
|
1165
|
-
const foreignKeys = relation.options.references;
|
|
944
|
+
const getBelongsToRequired = (tableConfig, relatedTableConfig, relation) => {
|
|
945
|
+
const { required } = relation.options;
|
|
946
|
+
if (typeof required === "boolean") return required;
|
|
947
|
+
if (relatedTableConfig.softDelete) return false;
|
|
948
|
+
return relation.options.columns.every((key) => {
|
|
949
|
+
return !tableConfig.columns.shape[key].data.isNullable;
|
|
950
|
+
});
|
|
951
|
+
};
|
|
952
|
+
const makeBelongsToMethod = (tableConfig, table, relation, relationName, query) => {
|
|
953
|
+
const primaryKeys = relation.options.references;
|
|
954
|
+
const foreignKeys = relation.options.columns;
|
|
1166
955
|
const { on } = relation.options;
|
|
1167
956
|
if (on) {
|
|
1168
957
|
_queryWhere(query, [on]);
|
|
1169
958
|
_queryDefaults(query, on);
|
|
1170
959
|
}
|
|
1171
|
-
|
|
960
|
+
const len = primaryKeys.length;
|
|
1172
961
|
const state = {
|
|
1173
962
|
query,
|
|
1174
963
|
primaryKeys,
|
|
1175
964
|
foreignKeys,
|
|
965
|
+
len,
|
|
1176
966
|
on
|
|
1177
967
|
};
|
|
1178
|
-
|
|
1179
|
-
const
|
|
1180
|
-
|
|
1181
|
-
|
|
968
|
+
addAutoForeignKey(tableConfig, table, query, primaryKeys, foreignKeys, relation.options);
|
|
969
|
+
const join = (baseQuery, joiningQuery, primaryKeys, foreignKeys) => {
|
|
970
|
+
const baseAs = getQueryAs(baseQuery);
|
|
971
|
+
const q = joiningQuery.clone();
|
|
972
|
+
setQueryObjectValueImmutable(q, "joinedShapes", baseAs, baseQuery.q.selectShape);
|
|
973
|
+
for (let i = 0; i < len; i++) pushQueryOnForOuter(q, baseQuery, joiningQuery, primaryKeys[i], `${baseAs}.${foreignKeys[i]}`);
|
|
974
|
+
return q;
|
|
975
|
+
};
|
|
1182
976
|
const reverseJoin = (baseQuery, joiningQuery) => {
|
|
1183
|
-
return
|
|
977
|
+
return join(joiningQuery, baseQuery, foreignKeys, primaryKeys);
|
|
1184
978
|
};
|
|
1185
979
|
return {
|
|
1186
980
|
returns: "one",
|
|
1187
|
-
queryRelated
|
|
1188
|
-
const
|
|
1189
|
-
for (let i = 0; i < len; i++)
|
|
1190
|
-
return
|
|
1191
|
-
...on,
|
|
1192
|
-
...values
|
|
1193
|
-
});
|
|
981
|
+
queryRelated(params) {
|
|
982
|
+
const obj = {};
|
|
983
|
+
for (let i = 0; i < len; i++) obj[primaryKeys[i]] = params[foreignKeys[i]];
|
|
984
|
+
return query.where(obj);
|
|
1194
985
|
},
|
|
1195
|
-
virtualColumn: new
|
|
1196
|
-
joinQuery: joinQueryChainHOF(
|
|
1197
|
-
reverseJoin
|
|
1198
|
-
|
|
1199
|
-
return (query) => {
|
|
1200
|
-
const baseQuery = query.clone();
|
|
1201
|
-
baseQuery.q.select = fromQuerySelect;
|
|
1202
|
-
const q = relationQuery.q;
|
|
1203
|
-
q.insertFrom = prepareSubQueryForSql(q, baseQuery);
|
|
1204
|
-
q.values = [];
|
|
1205
|
-
};
|
|
1206
|
-
}
|
|
1207
|
-
};
|
|
986
|
+
virtualColumn: new BelongsToVirtualColumn(internalSchemaConfig, relationName, state),
|
|
987
|
+
joinQuery: joinQueryChainHOF(getPrimaryKeys(query), reverseJoin, (joiningQuery, baseQuery) => join(baseQuery, joiningQuery, primaryKeys, foreignKeys)),
|
|
988
|
+
reverseJoin
|
|
989
|
+
};
|
|
1208
990
|
};
|
|
1209
991
|
const nestedInsert$2 = ({ query, primaryKeys, foreignKeys }) => {
|
|
1210
992
|
return (async (_, data) => {
|
|
@@ -1239,192 +1021,189 @@ const nestedInsert$2 = ({ query, primaryKeys, foreignKeys }) => {
|
|
|
1239
1021
|
}
|
|
1240
1022
|
});
|
|
1241
1023
|
};
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
const
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
values: []
|
|
1278
|
-
};
|
|
1279
|
-
nestedCreateItem.indexes.push(rowIndexes[i]);
|
|
1280
|
-
nestedCreateItem.values.push(value[kind]);
|
|
1281
|
-
const data = {};
|
|
1282
|
-
for (const key of foreignKeys) data[key] = new RawSql("");
|
|
1283
|
-
nestedCreateItem.items.push(data);
|
|
1284
|
-
}
|
|
1285
|
-
}
|
|
1024
|
+
const hasOneCreate = (key, state, nestedInsertFn, self, ctx, items, rowIndexes, count) => {
|
|
1025
|
+
const querySelf = self;
|
|
1026
|
+
if (count <= querySelf.qb.internal.nestedCreateBatchMax) {
|
|
1027
|
+
const { query: rel, primaryKeys, foreignKeys } = state;
|
|
1028
|
+
let nestedCreateItems;
|
|
1029
|
+
items.forEach((item, i) => {
|
|
1030
|
+
const value = item[key];
|
|
1031
|
+
const kind = value.create ? "create" : value.connect ? "connect" : "connectOrCreate";
|
|
1032
|
+
if (kind) {
|
|
1033
|
+
const nestedCreateItem = (nestedCreateItems ??= {})[kind] ??= {
|
|
1034
|
+
indexes: [],
|
|
1035
|
+
items: [],
|
|
1036
|
+
values: []
|
|
1037
|
+
};
|
|
1038
|
+
nestedCreateItem.indexes.push(rowIndexes[i]);
|
|
1039
|
+
nestedCreateItem.values.push(value[kind]);
|
|
1040
|
+
const data = value.create ? { ...value.create } : {};
|
|
1041
|
+
for (const key of foreignKeys) data[key] = new RawSql("");
|
|
1042
|
+
nestedCreateItem.items.push(data);
|
|
1043
|
+
}
|
|
1044
|
+
});
|
|
1045
|
+
if (!nestedCreateItems) return;
|
|
1046
|
+
let createAs;
|
|
1047
|
+
let createWhereExists;
|
|
1048
|
+
let createSelectAs;
|
|
1049
|
+
let createAliasedPrimaryKeys;
|
|
1050
|
+
let upsertCreateAs;
|
|
1051
|
+
let connectAs;
|
|
1052
|
+
let connectOrCreateAs;
|
|
1053
|
+
const setUpsertCreatePlaceholders = () => {
|
|
1054
|
+
if (!upsertCreateAs || !createAliasedPrimaryKeys) return;
|
|
1055
|
+
const aliasedPrimaryKeys = createAliasedPrimaryKeys;
|
|
1056
|
+
if (createWhereExists) createWhereExists._sql = `EXISTS (SELECT 1 FROM "${upsertCreateAs}")`;
|
|
1057
|
+
if (createSelectAs) foreignKeys.forEach((key, keyI) => {
|
|
1058
|
+
createSelectAs[key]._sql = selectCteColumnFromManySql(upsertCreateAs, aliasedPrimaryKeys[keyI], 0, 1);
|
|
1286
1059
|
});
|
|
1287
|
-
if (
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
if (
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
}
|
|
1319
|
-
if (connect && connectAs) for (let i = 0; i < connect.items.length; i++) connect.items[i][key]._sql = selectCteColumnFromManySql(connectAs, primaryKey, connect.indexes[i], count);
|
|
1320
|
-
if (connectOrCreate && connectOrCreateAs) for (let i = 0; i < connectOrCreate.items.length; i++) connectOrCreate.items[i][key]._sql = selectCteColumnFromManySql(connectOrCreateAs, primaryKey, connectOrCreate.indexes[i], count);
|
|
1321
|
-
});
|
|
1060
|
+
if (connect) foreignKeys.forEach((key, keyI) => {
|
|
1061
|
+
const primaryKey = aliasedPrimaryKeys[keyI];
|
|
1062
|
+
for (let i = 0; i < connect.items.length; i++) connect.items[i][key]._sql = selectCteColumnFromManySql(upsertCreateAs, primaryKey, connect.indexes[i], count);
|
|
1063
|
+
});
|
|
1064
|
+
if (connectOrCreate) foreignKeys.forEach((key, keyI) => {
|
|
1065
|
+
const primaryKey = aliasedPrimaryKeys[keyI];
|
|
1066
|
+
for (let i = 0; i < connectOrCreate.items.length; i++) connectOrCreate.items[i][key]._sql = selectCteColumnFromManySql(upsertCreateAs, primaryKey, connectOrCreate.indexes[i], count);
|
|
1067
|
+
});
|
|
1068
|
+
};
|
|
1069
|
+
_hookSelectColumns(querySelf, primaryKeys, (aliasedPrimaryKeys) => {
|
|
1070
|
+
createAliasedPrimaryKeys = aliasedPrimaryKeys;
|
|
1071
|
+
foreignKeys.forEach((key, keyI) => {
|
|
1072
|
+
const primaryKey = aliasedPrimaryKeys[keyI];
|
|
1073
|
+
if (create && createAs) for (let i = 0; i < create.items.length; i++) create.items[i][key]._sql = selectCteColumnFromManySql(createAs, primaryKey, create.indexes[i], count);
|
|
1074
|
+
if (connect && connectAs) for (let i = 0; i < connect.items.length; i++) connect.items[i][key]._sql = selectCteColumnFromManySql(connectAs, primaryKey, connect.indexes[i], count);
|
|
1075
|
+
if (connectOrCreate && connectOrCreateAs) for (let i = 0; i < connectOrCreate.items.length; i++) connectOrCreate.items[i][key]._sql = selectCteColumnFromManySql(connectOrCreateAs, primaryKey, connectOrCreate.indexes[i], count);
|
|
1076
|
+
});
|
|
1077
|
+
setUpsertCreatePlaceholders();
|
|
1078
|
+
});
|
|
1079
|
+
const { create, connect, connectOrCreate } = nestedCreateItems;
|
|
1080
|
+
if (create) {
|
|
1081
|
+
let query;
|
|
1082
|
+
if (querySelf.q.type === "upsert") {
|
|
1083
|
+
createWhereExists = new RawSql("");
|
|
1084
|
+
createSelectAs = {};
|
|
1085
|
+
for (const key of foreignKeys) createSelectAs[key] = new RawSql("");
|
|
1086
|
+
const sourceQuery = _queryWhere(_queryTake(_querySelect(_clone(rel.qb), [createSelectAs])), [createWhereExists]);
|
|
1087
|
+
query = _queryInsertManyFrom(_clone(rel), sourceQuery, create.items);
|
|
1088
|
+
} else query = _queryInsertMany(_clone(rel), create.items);
|
|
1089
|
+
if (querySelf.q.type === "upsert") _appendQueryOnUpsertCreate(querySelf, query, (as) => {
|
|
1090
|
+
upsertCreateAs = as;
|
|
1322
1091
|
setUpsertCreatePlaceholders();
|
|
1323
1092
|
});
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
setUpsertCreatePlaceholders();
|
|
1337
|
-
});
|
|
1338
|
-
else _appendQuery(querySelf, query, (as) => createAs = as);
|
|
1339
|
-
}
|
|
1340
|
-
if (connect) connect.values.forEach((value, i) => {
|
|
1341
|
-
const connectWhereExists = querySelf.q.type === "upsert" ? new RawSql("") : void 0;
|
|
1342
|
-
const query = _queryUpdateOrThrow(rel.whereOneOf(...value), connect.items[i]);
|
|
1343
|
-
if (connectWhereExists) _queryWhere(query, [connectWhereExists]);
|
|
1344
|
-
query.q.ensureCount = value.length;
|
|
1345
|
-
(querySelf.q.type === "upsert" ? _appendQueryOnUpsertCreate : _appendQuery)(querySelf, query, (as) => {
|
|
1346
|
-
upsertCreateAs = as;
|
|
1347
|
-
setUpsertCreatePlaceholders();
|
|
1348
|
-
connectAs = as;
|
|
1349
|
-
if (connectWhereExists) connectWhereExists._sql = `EXISTS (SELECT 1 FROM "${as}")`;
|
|
1350
|
-
});
|
|
1093
|
+
else _appendQuery(querySelf, query, (as) => createAs = as);
|
|
1094
|
+
}
|
|
1095
|
+
if (connect) connect.values.forEach((value, i) => {
|
|
1096
|
+
const connectWhereExists = querySelf.q.type === "upsert" ? new RawSql("") : void 0;
|
|
1097
|
+
const query = _queryUpdateOrThrow(rel.where(value), connect.items[i]);
|
|
1098
|
+
if (connectWhereExists) _queryWhere(query, [connectWhereExists]);
|
|
1099
|
+
query.q.ensureCount = 1;
|
|
1100
|
+
(querySelf.q.type === "upsert" ? _appendQueryOnUpsertCreate : _appendQuery)(querySelf, query, (as) => {
|
|
1101
|
+
upsertCreateAs = as;
|
|
1102
|
+
setUpsertCreatePlaceholders();
|
|
1103
|
+
connectAs = as;
|
|
1104
|
+
if (connectWhereExists) connectWhereExists._sql = `EXISTS (SELECT 1 FROM "${as}")`;
|
|
1351
1105
|
});
|
|
1352
|
-
|
|
1353
|
-
|
|
1354
|
-
|
|
1355
|
-
|
|
1356
|
-
|
|
1357
|
-
|
|
1358
|
-
|
|
1359
|
-
|
|
1360
|
-
|
|
1361
|
-
|
|
1362
|
-
|
|
1363
|
-
|
|
1364
|
-
|
|
1365
|
-
|
|
1366
|
-
|
|
1367
|
-
}
|
|
1368
|
-
});
|
|
1369
|
-
if (connectOrCreateWhereExists) {
|
|
1370
|
-
_queryWhere(query, [connectOrCreateWhereExists]);
|
|
1371
|
-
const guardQuery = _queryWhere(_queryTake(_querySelect(_clone(rel.qb), [{ one: new RawSql("1") }])), [connectOrCreateWhereExists]);
|
|
1372
|
-
const sourceQuery = _querySelect(_clone(rel.qb).from(guardQuery), [connectOrCreateSelectAs]);
|
|
1373
|
-
const q = query.q;
|
|
1374
|
-
const columns = q.columns || [];
|
|
1375
|
-
const foreignKeysSet = new Set(foreignKeys);
|
|
1376
|
-
q.columns = [...foreignKeys, ...columns.filter((column) => !foreignKeysSet.has(column))];
|
|
1377
|
-
q.values = q.values.map((row) => row.filter((_, i) => !foreignKeysSet.has(columns[i])));
|
|
1378
|
-
q.queryColumnsCount = foreignKeys.length;
|
|
1379
|
-
q.insertFrom = prepareSubQueryForSql(query, sourceQuery);
|
|
1380
|
-
}
|
|
1381
|
-
(querySelf.q.type === "upsert" ? _appendQueryOnUpsertCreate : _appendQuery)(querySelf, query, (as) => {
|
|
1382
|
-
upsertCreateAs = as;
|
|
1383
|
-
setUpsertCreatePlaceholders();
|
|
1384
|
-
connectOrCreateAs = as;
|
|
1385
|
-
if (connectOrCreateWhereExists) connectOrCreateWhereExists._sql = `EXISTS (SELECT 1 FROM "${as}")`;
|
|
1386
|
-
});
|
|
1106
|
+
});
|
|
1107
|
+
if (connectOrCreate) connectOrCreate.values.forEach((value, i) => {
|
|
1108
|
+
const foreignKeyValues = connectOrCreate.items[i];
|
|
1109
|
+
const connectOrCreateWhereExists = querySelf.q.type === "upsert" ? new RawSql("") : void 0;
|
|
1110
|
+
const connectOrCreateSelectAs = {};
|
|
1111
|
+
if (connectOrCreateWhereExists) for (const key of foreignKeys) {
|
|
1112
|
+
const value = foreignKeyValues[key];
|
|
1113
|
+
value.result = { value: rel.qb.shape[key] };
|
|
1114
|
+
connectOrCreateSelectAs[key] = value;
|
|
1115
|
+
}
|
|
1116
|
+
const query = _queryUpsert(rel.where(value.where), {
|
|
1117
|
+
update: foreignKeyValues,
|
|
1118
|
+
create: {
|
|
1119
|
+
...value.create,
|
|
1120
|
+
...foreignKeyValues
|
|
1387
1121
|
}
|
|
1388
1122
|
});
|
|
1389
|
-
|
|
1123
|
+
if (connectOrCreateWhereExists) {
|
|
1124
|
+
_queryWhere(query, [connectOrCreateWhereExists]);
|
|
1125
|
+
const guardQuery = _queryWhere(_queryTake(_querySelect(_clone(rel.qb), [{ one: new RawSql("1") }])), [connectOrCreateWhereExists]);
|
|
1126
|
+
const sourceQuery = _querySelect(_clone(rel.qb).from(guardQuery), [connectOrCreateSelectAs]);
|
|
1127
|
+
const q = query.q;
|
|
1128
|
+
const columns = q.columns || [];
|
|
1129
|
+
const foreignKeysSet = new Set(foreignKeys);
|
|
1130
|
+
q.columns = [...foreignKeys, ...columns.filter((column) => !foreignKeysSet.has(column))];
|
|
1131
|
+
q.values = q.values.map((row) => row.filter((_, i) => !foreignKeysSet.has(columns[i])));
|
|
1132
|
+
q.queryColumnsCount = foreignKeys.length;
|
|
1133
|
+
q.insertFrom = prepareSubQueryForSql(query, sourceQuery);
|
|
1134
|
+
}
|
|
1135
|
+
(querySelf.q.type === "upsert" ? _appendQueryOnUpsertCreate : _appendQuery)(querySelf, query, (as) => {
|
|
1136
|
+
upsertCreateAs = as;
|
|
1137
|
+
setUpsertCreatePlaceholders();
|
|
1138
|
+
connectOrCreateAs = as;
|
|
1139
|
+
if (connectOrCreateWhereExists) connectOrCreateWhereExists._sql = `EXISTS (SELECT 1 FROM "${as}")`;
|
|
1140
|
+
});
|
|
1141
|
+
});
|
|
1142
|
+
} else hasRelationHandleCreate(querySelf, ctx, items, rowIndexes, key, state.primaryKeys, nestedInsertFn);
|
|
1143
|
+
};
|
|
1144
|
+
const hasOneThrough = (table, options, relationName, query, relPKeys) => {
|
|
1145
|
+
const { through, source, on } = options;
|
|
1146
|
+
if (on) _queryWhere(query, [on]);
|
|
1147
|
+
const throughRelation = getThroughRelation(table, through);
|
|
1148
|
+
const sourceRelation = getSourceRelation(throughRelation, source);
|
|
1149
|
+
const sourceRelationQuery = sourceRelation.query.as(relationName);
|
|
1150
|
+
const sourceQuery = sourceRelation.joinQuery(sourceRelationQuery, throughRelation.query);
|
|
1151
|
+
const whereExistsCallback = () => sourceQuery;
|
|
1152
|
+
const reverseJoin = (baseQuery, joiningQuery) => {
|
|
1153
|
+
return joinHasThrough(baseQuery, baseQuery, joiningQuery, throughRelation, sourceRelation);
|
|
1154
|
+
};
|
|
1155
|
+
return {
|
|
1156
|
+
returns: "one",
|
|
1157
|
+
queryRelated: (params) => {
|
|
1158
|
+
const throughQuery = table.queryRelated(through, params);
|
|
1159
|
+
return query.whereExists(throughQuery, whereExistsCallback);
|
|
1160
|
+
},
|
|
1161
|
+
joinQuery: joinQueryChainHOF(relPKeys, reverseJoin, (joiningQuery, baseQuery) => joinHasThrough(joiningQuery, baseQuery, joiningQuery, throughRelation, sourceRelation)),
|
|
1162
|
+
reverseJoin
|
|
1163
|
+
};
|
|
1164
|
+
};
|
|
1165
|
+
const hasOneUpdate = (key, state, self, set) => {
|
|
1166
|
+
const querySelf = self;
|
|
1167
|
+
const params = set[key];
|
|
1168
|
+
throwIfQueryReturnsAllForNestedUpdate(querySelf, params);
|
|
1169
|
+
const { primaryKeys, foreignKeys, query: relQuery } = state;
|
|
1170
|
+
if (params.create || params.update || params.upsert || params.disconnect || params.set || params.delete) {
|
|
1171
|
+
const ids = makeNestedUpdateRelationIds(querySelf, relQuery, primaryKeys, foreignKeys);
|
|
1172
|
+
const setNulls = {};
|
|
1173
|
+
for (const foreignKey of foreignKeys) setNulls[foreignKey] = null;
|
|
1174
|
+
const nullifyOrDeleteQuery = params.update ? _queryUpdate(ids.existingRelQuery, params.update) : params.upsert ? _queryUpsert(ids.existingRelQuery, makeNestedUpdateUpsertData(params.upsert, ids.setIds)) : params.delete ? _queryDelete(ids.existingRelQuery) : _queryUpdate(ids.existingRelQuery, setNulls);
|
|
1175
|
+
nullifyOrDeleteQuery.q.returnType = "void";
|
|
1176
|
+
_appendQuery(querySelf, nullifyOrDeleteQuery, ids.setAppendedAs);
|
|
1177
|
+
if (params.create) {
|
|
1178
|
+
const createQuery = _queryInsert(_clone(relQuery), {
|
|
1179
|
+
...params.create,
|
|
1180
|
+
...ids.setIds
|
|
1181
|
+
});
|
|
1182
|
+
_appendQuery(querySelf, createQuery, noop);
|
|
1183
|
+
} else if (params.set) {
|
|
1184
|
+
const setQuery = _queryUpdate(_queryWhere(_clone(relQuery), [params.set]), ids.setIds);
|
|
1185
|
+
setQuery.q.returnType = "void";
|
|
1186
|
+
_appendQuery(querySelf, setQuery, noop);
|
|
1187
|
+
}
|
|
1188
|
+
}
|
|
1189
|
+
};
|
|
1190
|
+
var HasOneVirtualColumn = class extends VirtualColumn {
|
|
1191
|
+
constructor(schema, key, state) {
|
|
1192
|
+
super(schema);
|
|
1193
|
+
this.key = key;
|
|
1194
|
+
this.state = state;
|
|
1195
|
+
this.nestedInsert = nestedInsert$2(state);
|
|
1196
|
+
}
|
|
1197
|
+
create(self, ctx, items, rowIndexes, count) {
|
|
1198
|
+
hasOneCreate(this.key, this.state, this.nestedInsert, self, ctx, items, rowIndexes, count);
|
|
1390
1199
|
}
|
|
1391
1200
|
update(self, set) {
|
|
1392
|
-
|
|
1393
|
-
const params = set[this.key];
|
|
1394
|
-
throwIfQueryReturnsAllForNestedUpdate(querySelf, params);
|
|
1395
|
-
hasRelationHandleUpdate(querySelf, set, this.key, this.state.primaryKeys, this.nestedUpdate);
|
|
1396
|
-
if (params.upsert) {
|
|
1397
|
-
const { primaryKeys, foreignKeys, query: relQuery } = this.state;
|
|
1398
|
-
const ids = makeNestedUpdateRelationIds(querySelf, relQuery, primaryKeys, foreignKeys);
|
|
1399
|
-
const appendedQuery = _queryUpsert(ids.existingRelQuery, makeNestedUpdateUpsertData(params.upsert, ids.setIds));
|
|
1400
|
-
appendedQuery.q.returnType = "void";
|
|
1401
|
-
_appendQuery(querySelf, appendedQuery, ids.setAppendedAs);
|
|
1402
|
-
}
|
|
1201
|
+
hasOneUpdate(this.key, this.state, self, set);
|
|
1403
1202
|
}
|
|
1404
1203
|
};
|
|
1405
|
-
const
|
|
1204
|
+
const makeHasOneMethod = (tableConfig, table, relation, relationName, query) => {
|
|
1406
1205
|
const relPKeys = getPrimaryKeys(query);
|
|
1407
|
-
if ("through" in relation.options)
|
|
1408
|
-
const { through, source, on } = relation.options;
|
|
1409
|
-
if (on) _queryWhere(query, [on]);
|
|
1410
|
-
const throughRelation = getThroughRelation(table, through);
|
|
1411
|
-
const sourceRelation = getSourceRelation(throughRelation, source);
|
|
1412
|
-
const sourceRelationQuery = sourceRelation.query.as(relationName);
|
|
1413
|
-
const sourceQuery = sourceRelation.joinQuery(sourceRelationQuery, throughRelation.query);
|
|
1414
|
-
const whereExistsCallback = () => sourceQuery;
|
|
1415
|
-
const reverseJoin = (baseQuery, joiningQuery) => {
|
|
1416
|
-
return joinHasThrough(baseQuery, baseQuery, joiningQuery, throughRelation, sourceRelation);
|
|
1417
|
-
};
|
|
1418
|
-
return {
|
|
1419
|
-
returns: "many",
|
|
1420
|
-
queryRelated: (params) => {
|
|
1421
|
-
const throughQuery = table.queryRelated(through, params);
|
|
1422
|
-
return query.whereExists(throughQuery, whereExistsCallback);
|
|
1423
|
-
},
|
|
1424
|
-
joinQuery: joinQueryChainHOF(relPKeys, reverseJoin, (joiningQuery, baseQuery) => joinHasThrough(joiningQuery, baseQuery, joiningQuery, throughRelation, sourceRelation)),
|
|
1425
|
-
reverseJoin
|
|
1426
|
-
};
|
|
1427
|
-
}
|
|
1206
|
+
if ("through" in relation.options) return hasOneThrough(table, relation.options, relationName, query, relPKeys);
|
|
1428
1207
|
const primaryKeys = relation.options.columns;
|
|
1429
1208
|
const foreignKeys = relation.options.references;
|
|
1430
1209
|
const { on } = relation.options;
|
|
@@ -1447,7 +1226,7 @@ const makeHasManyMethod = (tableConfig, table, relation, relationName, query) =>
|
|
|
1447
1226
|
return joinHasRelation(joiningQuery, baseQuery, foreignKeys, primaryKeys, len);
|
|
1448
1227
|
};
|
|
1449
1228
|
return {
|
|
1450
|
-
returns: "
|
|
1229
|
+
returns: "one",
|
|
1451
1230
|
queryRelated: (params) => {
|
|
1452
1231
|
const values = {};
|
|
1453
1232
|
for (let i = 0; i < len; i++) values[foreignKeys[i]] = params[primaryKeys[i]];
|
|
@@ -1456,7 +1235,7 @@ const makeHasManyMethod = (tableConfig, table, relation, relationName, query) =>
|
|
|
1456
1235
|
...values
|
|
1457
1236
|
});
|
|
1458
1237
|
},
|
|
1459
|
-
virtualColumn: new
|
|
1238
|
+
virtualColumn: new HasOneVirtualColumn(internalSchemaConfig, relationName, state),
|
|
1460
1239
|
joinQuery: joinQueryChainHOF(relPKeys, reverseJoin, (joiningQuery, baseQuery) => joinHasRelation(baseQuery, joiningQuery, primaryKeys, foreignKeys, len)),
|
|
1461
1240
|
reverseJoin,
|
|
1462
1241
|
modifyRelatedQuery(relationQuery) {
|
|
@@ -1479,6 +1258,81 @@ const getWhereForNestedUpdate = (t, data, params, primaryKeys, foreignKeys) => {
|
|
|
1479
1258
|
OR: params ? toArray(params) : void 0
|
|
1480
1259
|
});
|
|
1481
1260
|
};
|
|
1261
|
+
const nestedUpdate$1 = ({ query: relQuery, primaryKeys, foreignKeys }) => {
|
|
1262
|
+
const len = primaryKeys.length;
|
|
1263
|
+
return (async (_, data, params) => {
|
|
1264
|
+
const t = relQuery.clone();
|
|
1265
|
+
if (params.create) {
|
|
1266
|
+
const obj = {};
|
|
1267
|
+
for (let i = 0; i < len; i++) obj[foreignKeys[i]] = data[0][primaryKeys[i]];
|
|
1268
|
+
await t.insertMany(params.create.map((create) => ({
|
|
1269
|
+
...create,
|
|
1270
|
+
...obj
|
|
1271
|
+
})));
|
|
1272
|
+
}
|
|
1273
|
+
if (params.add) {
|
|
1274
|
+
if (data.length > 1) throw new OrchidOrmInternalError(relQuery, "`connect` is not available when updating multiple records, it is only applicable for a single record update");
|
|
1275
|
+
const obj = {};
|
|
1276
|
+
for (let i = 0; i < len; i++) obj[foreignKeys[i]] = data[0][primaryKeys[i]];
|
|
1277
|
+
const relatedWheres = toArray(params.add);
|
|
1278
|
+
const count = await _queryUpdate(t.where({ OR: relatedWheres }), obj);
|
|
1279
|
+
if (count < relatedWheres.length) throw new OrchidOrmInternalError(relQuery, `Expected to find at least ${relatedWheres.length} record(s) based on \`add\` conditions, but found ${count}`);
|
|
1280
|
+
}
|
|
1281
|
+
if (params.disconnect || params.set) {
|
|
1282
|
+
const obj = {};
|
|
1283
|
+
for (const foreignKey of foreignKeys) obj[foreignKey] = null;
|
|
1284
|
+
const setConditions = params.set && (Array.isArray(params.set) ? params.set.length : objectHasValues(params.set)) && (Array.isArray(params.set) ? { OR: params.set } : params.set);
|
|
1285
|
+
let queryToDisconnect = getWhereForNestedUpdate(t, data, params.disconnect, primaryKeys, foreignKeys);
|
|
1286
|
+
if (setConditions) queryToDisconnect = queryToDisconnect.whereNot(setConditions);
|
|
1287
|
+
await _queryUpdate(queryToDisconnect, obj);
|
|
1288
|
+
if (setConditions) {
|
|
1289
|
+
const obj = {};
|
|
1290
|
+
for (let i = 0; i < len; i++) obj[foreignKeys[i]] = data[0][primaryKeys[i]];
|
|
1291
|
+
await _queryUpdate(t.where(setConditions), obj);
|
|
1292
|
+
}
|
|
1293
|
+
}
|
|
1294
|
+
if (params.delete || params.update) {
|
|
1295
|
+
const q = getWhereForNestedUpdate(t, data, params.delete || params.update?.where, primaryKeys, foreignKeys);
|
|
1296
|
+
if (params.delete) await _queryDelete(q);
|
|
1297
|
+
else if (params.update) await _queryUpdate(q, params.update.data);
|
|
1298
|
+
}
|
|
1299
|
+
});
|
|
1300
|
+
};
|
|
1301
|
+
const hasManyUpdate = (key, state, nestedUpdateFn, self, set) => {
|
|
1302
|
+
const querySelf = self;
|
|
1303
|
+
const params = set[key];
|
|
1304
|
+
throwIfQueryReturnsAllForNestedUpdate(querySelf, params);
|
|
1305
|
+
hasRelationHandleUpdate(querySelf, set, key, state.primaryKeys, nestedUpdateFn);
|
|
1306
|
+
if (params.upsert) {
|
|
1307
|
+
const { primaryKeys, foreignKeys, query: relQuery } = state;
|
|
1308
|
+
const ids = makeNestedUpdateRelationIds(querySelf, relQuery, primaryKeys, foreignKeys);
|
|
1309
|
+
const appendedQuery = _queryUpsert(ids.existingRelQuery, makeNestedUpdateUpsertData(params.upsert, ids.setIds));
|
|
1310
|
+
appendedQuery.q.returnType = "void";
|
|
1311
|
+
_appendQuery(querySelf, appendedQuery, ids.setAppendedAs);
|
|
1312
|
+
}
|
|
1313
|
+
};
|
|
1314
|
+
const makeHasManyThroughMethod = ({ table, query, relation, relationName, relPKeys }) => {
|
|
1315
|
+
if (!("through" in relation.options)) return;
|
|
1316
|
+
const { through, source, on } = relation.options;
|
|
1317
|
+
if (on) _queryWhere(query, [on]);
|
|
1318
|
+
const throughRelation = getThroughRelation(table, through);
|
|
1319
|
+
const sourceRelation = getSourceRelation(throughRelation, source);
|
|
1320
|
+
const sourceRelationQuery = sourceRelation.query.as(relationName);
|
|
1321
|
+
const sourceQuery = sourceRelation.joinQuery(sourceRelationQuery, throughRelation.query);
|
|
1322
|
+
const whereExistsCallback = () => sourceQuery;
|
|
1323
|
+
const reverseJoin = (baseQuery, joiningQuery) => {
|
|
1324
|
+
return joinHasThrough(baseQuery, baseQuery, joiningQuery, throughRelation, sourceRelation);
|
|
1325
|
+
};
|
|
1326
|
+
return {
|
|
1327
|
+
returns: "many",
|
|
1328
|
+
queryRelated: (params) => {
|
|
1329
|
+
const throughQuery = table.queryRelated(through, params);
|
|
1330
|
+
return query.whereExists(throughQuery, whereExistsCallback);
|
|
1331
|
+
},
|
|
1332
|
+
joinQuery: joinQueryChainHOF(relPKeys, reverseJoin, (joiningQuery, baseQuery) => joinHasThrough(joiningQuery, baseQuery, joiningQuery, throughRelation, sourceRelation)),
|
|
1333
|
+
reverseJoin
|
|
1334
|
+
};
|
|
1335
|
+
};
|
|
1482
1336
|
const nestedInsert$1 = ({ query, primaryKeys, foreignKeys }) => {
|
|
1483
1337
|
const len = primaryKeys.length;
|
|
1484
1338
|
return (async (_, data) => {
|
|
@@ -1540,258 +1394,218 @@ const nestedInsert$1 = ({ query, primaryKeys, foreignKeys }) => {
|
|
|
1540
1394
|
}
|
|
1541
1395
|
});
|
|
1542
1396
|
};
|
|
1543
|
-
const
|
|
1544
|
-
const
|
|
1545
|
-
|
|
1546
|
-
const
|
|
1547
|
-
|
|
1548
|
-
|
|
1549
|
-
|
|
1550
|
-
|
|
1551
|
-
|
|
1552
|
-
|
|
1553
|
-
|
|
1554
|
-
|
|
1555
|
-
|
|
1556
|
-
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
|
|
1561
|
-
|
|
1562
|
-
|
|
1563
|
-
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
-
|
|
1568
|
-
|
|
1569
|
-
|
|
1570
|
-
|
|
1571
|
-
|
|
1572
|
-
|
|
1573
|
-
|
|
1397
|
+
const hasManyCreate = (key, state, nestedInsertFn, self, ctx, items, rowIndexes, count) => {
|
|
1398
|
+
const querySelf = self;
|
|
1399
|
+
if (count <= querySelf.qb.internal.nestedCreateBatchMax) {
|
|
1400
|
+
const { query: rel, primaryKeys, foreignKeys } = state;
|
|
1401
|
+
let nestedCreateItems;
|
|
1402
|
+
items.forEach((item, i) => {
|
|
1403
|
+
const value = item[key];
|
|
1404
|
+
if (value.create?.length) {
|
|
1405
|
+
const nestedCreateItem = (nestedCreateItems ??= {}).create ??= {
|
|
1406
|
+
indexes: [],
|
|
1407
|
+
items: []
|
|
1408
|
+
};
|
|
1409
|
+
nestedCreateItem.indexes.push(rowIndexes[i]);
|
|
1410
|
+
const data = value.create.map((obj) => {
|
|
1411
|
+
const data = { ...obj };
|
|
1412
|
+
for (const key of foreignKeys) data[key] = new RawSql("");
|
|
1413
|
+
return data;
|
|
1414
|
+
});
|
|
1415
|
+
nestedCreateItem.items.push(data);
|
|
1416
|
+
} else {
|
|
1417
|
+
const kind = value.connect?.length ? "connect" : value.connectOrCreate?.length ? "connectOrCreate" : void 0;
|
|
1418
|
+
if (kind) {
|
|
1419
|
+
const nestedCreateItem = (nestedCreateItems ??= {})[kind] ??= {
|
|
1420
|
+
indexes: [],
|
|
1421
|
+
items: [],
|
|
1422
|
+
values: []
|
|
1423
|
+
};
|
|
1424
|
+
nestedCreateItem.indexes.push(rowIndexes[i]);
|
|
1425
|
+
nestedCreateItem.values.push(value[kind]);
|
|
1426
|
+
const data = {};
|
|
1427
|
+
for (const key of foreignKeys) data[key] = new RawSql("");
|
|
1428
|
+
nestedCreateItem.items.push(data);
|
|
1429
|
+
}
|
|
1574
1430
|
}
|
|
1575
|
-
}
|
|
1576
|
-
if (
|
|
1577
|
-
|
|
1578
|
-
|
|
1579
|
-
|
|
1580
|
-
|
|
1581
|
-
|
|
1582
|
-
|
|
1583
|
-
|
|
1584
|
-
|
|
1585
|
-
|
|
1586
|
-
|
|
1587
|
-
|
|
1588
|
-
|
|
1589
|
-
|
|
1590
|
-
|
|
1591
|
-
|
|
1592
|
-
|
|
1593
|
-
|
|
1594
|
-
|
|
1595
|
-
|
|
1596
|
-
|
|
1597
|
-
|
|
1598
|
-
|
|
1599
|
-
|
|
1600
|
-
|
|
1601
|
-
|
|
1602
|
-
|
|
1603
|
-
|
|
1604
|
-
|
|
1605
|
-
const
|
|
1606
|
-
const
|
|
1607
|
-
|
|
1608
|
-
|
|
1609
|
-
|
|
1610
|
-
|
|
1611
|
-
|
|
1612
|
-
|
|
1613
|
-
|
|
1614
|
-
|
|
1615
|
-
|
|
1616
|
-
|
|
1617
|
-
|
|
1618
|
-
|
|
1619
|
-
|
|
1620
|
-
|
|
1621
|
-
|
|
1622
|
-
|
|
1623
|
-
|
|
1624
|
-
|
|
1625
|
-
|
|
1626
|
-
|
|
1627
|
-
|
|
1628
|
-
|
|
1629
|
-
|
|
1630
|
-
|
|
1631
|
-
|
|
1632
|
-
|
|
1633
|
-
|
|
1634
|
-
|
|
1635
|
-
|
|
1636
|
-
|
|
1637
|
-
|
|
1431
|
+
});
|
|
1432
|
+
if (!nestedCreateItems) return;
|
|
1433
|
+
let createAs;
|
|
1434
|
+
let createWhereExists;
|
|
1435
|
+
let createSelectAs;
|
|
1436
|
+
let createAliasedPrimaryKeys;
|
|
1437
|
+
let upsertCreateAs;
|
|
1438
|
+
let connectAs;
|
|
1439
|
+
let connectOrCreateAs;
|
|
1440
|
+
const setUpsertCreatePlaceholders = () => {
|
|
1441
|
+
if (!upsertCreateAs || !createAliasedPrimaryKeys) return;
|
|
1442
|
+
const aliasedPrimaryKeys = createAliasedPrimaryKeys;
|
|
1443
|
+
if (createWhereExists) createWhereExists._sql = `EXISTS (SELECT 1 FROM "${upsertCreateAs}")`;
|
|
1444
|
+
if (createSelectAs) foreignKeys.forEach((key, keyI) => {
|
|
1445
|
+
createSelectAs[key]._sql = selectCteColumnFromManySql(upsertCreateAs, aliasedPrimaryKeys[keyI], 0, 1);
|
|
1446
|
+
});
|
|
1447
|
+
if (connect) foreignKeys.forEach((key, keyI) => {
|
|
1448
|
+
const primaryKey = aliasedPrimaryKeys[keyI];
|
|
1449
|
+
for (let i = 0; i < connect.items.length; i++) connect.items[i][key]._sql = selectCteColumnFromManySql(upsertCreateAs, primaryKey, connect.indexes[i], count);
|
|
1450
|
+
});
|
|
1451
|
+
if (connectOrCreate) foreignKeys.forEach((key, keyI) => {
|
|
1452
|
+
const primaryKey = aliasedPrimaryKeys[keyI];
|
|
1453
|
+
for (let i = 0; i < connectOrCreate.items.length; i++) connectOrCreate.items[i][key]._sql = selectCteColumnFromManySql(upsertCreateAs, primaryKey, connectOrCreate.indexes[i], count);
|
|
1454
|
+
});
|
|
1455
|
+
};
|
|
1456
|
+
_hookSelectColumns(querySelf, primaryKeys, (aliasedPrimaryKeys) => {
|
|
1457
|
+
createAliasedPrimaryKeys = aliasedPrimaryKeys;
|
|
1458
|
+
foreignKeys.forEach((key, keyI) => {
|
|
1459
|
+
const primaryKey = aliasedPrimaryKeys[keyI];
|
|
1460
|
+
if (create && createAs) for (let i = 0; i < create.items.length; i++) {
|
|
1461
|
+
const sql = selectCteColumnFromManySql(createAs, primaryKey, create.indexes[i], count);
|
|
1462
|
+
for (const item of create.items[i]) item[key]._sql = sql;
|
|
1463
|
+
}
|
|
1464
|
+
if (connect && connectAs) for (let i = 0; i < connect.items.length; i++) connect.items[i][key]._sql = selectCteColumnFromManySql(connectAs, primaryKey, connect.indexes[i], count);
|
|
1465
|
+
if (connectOrCreate && connectOrCreateAs) for (let i = 0; i < connectOrCreate.items.length; i++) connectOrCreate.items[i][key]._sql = selectCteColumnFromManySql(connectOrCreateAs, primaryKey, connectOrCreate.indexes[i], count);
|
|
1466
|
+
});
|
|
1467
|
+
setUpsertCreatePlaceholders();
|
|
1468
|
+
});
|
|
1469
|
+
const { create, connect, connectOrCreate } = nestedCreateItems;
|
|
1470
|
+
if (create) {
|
|
1471
|
+
let query;
|
|
1472
|
+
if (querySelf.q.type === "upsert") {
|
|
1473
|
+
createWhereExists = new RawSql("");
|
|
1474
|
+
createSelectAs = {};
|
|
1475
|
+
for (const key of foreignKeys) createSelectAs[key] = new RawSql("");
|
|
1476
|
+
const sourceQuery = _queryWhere(_queryTake(_querySelect(_clone(rel.qb), [createSelectAs])), [createWhereExists]);
|
|
1477
|
+
query = _queryInsertManyFrom(_clone(rel), sourceQuery, create.items.flat());
|
|
1478
|
+
} else query = _queryInsertMany(_clone(rel), create.items.flat());
|
|
1479
|
+
if (querySelf.q.type === "upsert") _appendQueryOnUpsertCreate(querySelf, query, (as) => {
|
|
1480
|
+
upsertCreateAs = as;
|
|
1481
|
+
setUpsertCreatePlaceholders();
|
|
1482
|
+
});
|
|
1483
|
+
else _appendQuery(querySelf, query, (as) => createAs = as);
|
|
1484
|
+
}
|
|
1485
|
+
if (connect) connect.values.forEach((value, i) => {
|
|
1486
|
+
const connectWhereExists = querySelf.q.type === "upsert" ? new RawSql("") : void 0;
|
|
1487
|
+
const query = _queryUpdateOrThrow(rel.whereOneOf(...value), connect.items[i]);
|
|
1488
|
+
if (connectWhereExists) _queryWhere(query, [connectWhereExists]);
|
|
1489
|
+
query.q.ensureCount = value.length;
|
|
1490
|
+
(querySelf.q.type === "upsert" ? _appendQueryOnUpsertCreate : _appendQuery)(querySelf, query, (as) => {
|
|
1491
|
+
upsertCreateAs = as;
|
|
1492
|
+
setUpsertCreatePlaceholders();
|
|
1493
|
+
connectAs = as;
|
|
1494
|
+
if (connectWhereExists) connectWhereExists._sql = `EXISTS (SELECT 1 FROM "${as}")`;
|
|
1495
|
+
});
|
|
1496
|
+
});
|
|
1497
|
+
if (connectOrCreate) connectOrCreate.values.forEach((array, i) => {
|
|
1498
|
+
const foreignKeyValues = connectOrCreate.items[i];
|
|
1499
|
+
for (const value of array) {
|
|
1500
|
+
const connectOrCreateWhereExists = querySelf.q.type === "upsert" ? new RawSql("") : void 0;
|
|
1501
|
+
const connectOrCreateSelectAs = {};
|
|
1502
|
+
if (connectOrCreateWhereExists) for (const key of foreignKeys) {
|
|
1503
|
+
const value = foreignKeyValues[key];
|
|
1504
|
+
value.result = { value: rel.qb.shape[key] };
|
|
1505
|
+
connectOrCreateSelectAs[key] = value;
|
|
1506
|
+
}
|
|
1507
|
+
const query = _queryUpsert(rel.where(value.where), {
|
|
1508
|
+
update: foreignKeyValues,
|
|
1509
|
+
create: {
|
|
1510
|
+
...value.create,
|
|
1511
|
+
...foreignKeyValues
|
|
1512
|
+
}
|
|
1513
|
+
});
|
|
1514
|
+
if (connectOrCreateWhereExists) {
|
|
1515
|
+
_queryWhere(query, [connectOrCreateWhereExists]);
|
|
1516
|
+
const guardQuery = _queryWhere(_queryTake(_querySelect(_clone(rel.qb), [{ one: new RawSql("1") }])), [connectOrCreateWhereExists]);
|
|
1517
|
+
const sourceQuery = _querySelect(_clone(rel.qb).from(guardQuery), [connectOrCreateSelectAs]);
|
|
1518
|
+
const q = query.q;
|
|
1519
|
+
const columns = q.columns || [];
|
|
1520
|
+
const foreignKeysSet = new Set(foreignKeys);
|
|
1521
|
+
q.columns = [...foreignKeys, ...columns.filter((column) => !foreignKeysSet.has(column))];
|
|
1522
|
+
q.values = q.values.map((row) => row.filter((_, i) => !foreignKeysSet.has(columns[i])));
|
|
1523
|
+
q.queryColumnsCount = foreignKeys.length;
|
|
1524
|
+
q.insertFrom = prepareSubQueryForSql(query, sourceQuery);
|
|
1525
|
+
}
|
|
1526
|
+
(querySelf.q.type === "upsert" ? _appendQueryOnUpsertCreate : _appendQuery)(querySelf, query, (as) => {
|
|
1527
|
+
upsertCreateAs = as;
|
|
1528
|
+
setUpsertCreatePlaceholders();
|
|
1529
|
+
connectOrCreateAs = as;
|
|
1530
|
+
if (connectOrCreateWhereExists) connectOrCreateWhereExists._sql = `EXISTS (SELECT 1 FROM "${as}")`;
|
|
1531
|
+
});
|
|
1532
|
+
}
|
|
1533
|
+
});
|
|
1534
|
+
} else hasRelationHandleCreate(querySelf, ctx, items, rowIndexes, key, state.primaryKeys, nestedInsertFn);
|
|
1638
1535
|
};
|
|
1639
|
-
|
|
1640
|
-
|
|
1641
|
-
|
|
1642
|
-
|
|
1643
|
-
|
|
1644
|
-
|
|
1645
|
-
|
|
1646
|
-
|
|
1536
|
+
var HasManyVirtualColumn = class extends VirtualColumn {
|
|
1537
|
+
constructor(schema, key, state) {
|
|
1538
|
+
super(schema);
|
|
1539
|
+
this.key = key;
|
|
1540
|
+
this.state = state;
|
|
1541
|
+
this.nestedInsert = nestedInsert$1(state);
|
|
1542
|
+
this.nestedUpdate = nestedUpdate$1(state);
|
|
1543
|
+
this.setNulls = {};
|
|
1544
|
+
for (const foreignKey of state.foreignKeys) this.setNulls[foreignKey] = null;
|
|
1545
|
+
}
|
|
1546
|
+
create(self, ctx, items, rowIndexes, count) {
|
|
1547
|
+
hasManyCreate(this.key, this.state, this.nestedInsert, self, ctx, items, rowIndexes, count);
|
|
1548
|
+
}
|
|
1549
|
+
update(self, set) {
|
|
1550
|
+
hasManyUpdate(this.key, this.state, this.nestedUpdate, self, set);
|
|
1551
|
+
}
|
|
1647
1552
|
};
|
|
1648
|
-
const
|
|
1649
|
-
const
|
|
1650
|
-
const
|
|
1651
|
-
|
|
1652
|
-
|
|
1653
|
-
|
|
1654
|
-
|
|
1655
|
-
|
|
1656
|
-
|
|
1657
|
-
|
|
1658
|
-
const
|
|
1553
|
+
const makeHasManyMethod = (tableConfig, table, relation, relationName, query) => {
|
|
1554
|
+
const relPKeys = getPrimaryKeys(query);
|
|
1555
|
+
const throughResult = makeHasManyThroughMethod({
|
|
1556
|
+
table,
|
|
1557
|
+
query,
|
|
1558
|
+
relation,
|
|
1559
|
+
relationName,
|
|
1560
|
+
relPKeys
|
|
1561
|
+
});
|
|
1562
|
+
if (throughResult) return throughResult;
|
|
1563
|
+
const opts = relation.options;
|
|
1564
|
+
const primaryKeys = opts.columns;
|
|
1565
|
+
const foreignKeys = opts.references;
|
|
1566
|
+
const { on } = opts;
|
|
1659
1567
|
if (on) {
|
|
1660
1568
|
_queryWhere(query, [on]);
|
|
1661
1569
|
_queryDefaults(query, on);
|
|
1662
1570
|
}
|
|
1663
|
-
|
|
1664
|
-
if (snakeCase) key = foreignKeys[i] = toSnakeCase(key);
|
|
1665
|
-
return `${joinTable}.${key}`;
|
|
1666
|
-
});
|
|
1667
|
-
const throughForeignKeysFull = throughForeignKeys.map((key, i) => {
|
|
1668
|
-
if (snakeCase) key = throughForeignKeys[i] = toSnakeCase(key);
|
|
1669
|
-
return `${joinTable}.${key}`;
|
|
1670
|
-
});
|
|
1671
|
-
const foreignTable = getQueryAs(query);
|
|
1672
|
-
const throughPrimaryKeysFull = throughPrimaryKeys.map((key) => `${foreignTable}.${key}`);
|
|
1673
|
-
const len = primaryKeys.length;
|
|
1674
|
-
const throughLen = throughPrimaryKeys.length;
|
|
1675
|
-
const baseQuery = Object.create(qb.baseQuery);
|
|
1676
|
-
baseQuery.baseQuery = baseQuery;
|
|
1677
|
-
baseQuery.table = joinTable;
|
|
1678
|
-
const shape = {};
|
|
1679
|
-
const primaryKeysShape = {};
|
|
1680
|
-
for (let i = 0; i < len; i++) {
|
|
1681
|
-
const pk = primaryKeys[i];
|
|
1682
|
-
shape[foreignKeys[i]] = removeColumnName(table.shape[pk]);
|
|
1683
|
-
primaryKeysShape[pk] = table.shape[pk];
|
|
1684
|
-
}
|
|
1685
|
-
for (let i = 0; i < throughLen; i++) shape[throughForeignKeys[i]] = removeColumnName(query.shape[throughPrimaryKeys[i]]);
|
|
1686
|
-
baseQuery.shape = shape;
|
|
1687
|
-
baseQuery.q = {
|
|
1688
|
-
...baseQuery.q,
|
|
1689
|
-
schema: options.through.schema || schema,
|
|
1690
|
-
shape: baseQuery.shape
|
|
1691
|
-
};
|
|
1692
|
-
const subQuery = Object.create(baseQuery);
|
|
1693
|
-
addAutoForeignKey(tableConfig, subQuery, table, primaryKeys, foreignKeys, relation.options, originalForeignKeys);
|
|
1694
|
-
addAutoForeignKey(tableConfig, subQuery, query, throughPrimaryKeys, throughForeignKeys, relation.options.through, originalThroughForeignKeys);
|
|
1571
|
+
addAutoForeignKey(tableConfig, query, table, primaryKeys, foreignKeys, opts);
|
|
1695
1572
|
const state = {
|
|
1696
|
-
|
|
1697
|
-
relatedTableQuery: query,
|
|
1698
|
-
joinTableQuery: subQuery,
|
|
1573
|
+
query,
|
|
1699
1574
|
primaryKeys,
|
|
1700
1575
|
foreignKeys,
|
|
1701
|
-
throughForeignKeys,
|
|
1702
|
-
throughPrimaryKeys,
|
|
1703
|
-
foreignKeysFull,
|
|
1704
|
-
throughForeignKeysFull,
|
|
1705
|
-
throughPrimaryKeysFull,
|
|
1706
|
-
primaryKeysShape,
|
|
1707
1576
|
on
|
|
1708
1577
|
};
|
|
1709
|
-
const
|
|
1710
|
-
|
|
1711
|
-
|
|
1712
|
-
|
|
1713
|
-
for (let i = 0; i < throughLen; i++) _queryJoinOn(q, [throughForeignKeysFull[i], `${foreignAs}.${throughPrimaryKeys[i]}`]);
|
|
1714
|
-
for (let i = 0; i < len; i++) _queryJoinOn(q, [foreignKeysFull[i], `${tableAs}.${primaryKeys[i]}`]);
|
|
1715
|
-
return q;
|
|
1716
|
-
}]);
|
|
1717
|
-
};
|
|
1718
|
-
const obj = {};
|
|
1719
|
-
for (let i = 0; i < len; i++) obj[foreignKeys[i]] = primaryKeys[i];
|
|
1720
|
-
const selectPrimaryKeysAsForeignKeys = [{ selectAs: obj }];
|
|
1578
|
+
const len = primaryKeys.length;
|
|
1579
|
+
const reversedOn = {};
|
|
1580
|
+
for (let i = 0; i < len; i++) reversedOn[foreignKeys[i]] = primaryKeys[i];
|
|
1581
|
+
const fromQuerySelect = [{ selectAs: reversedOn }];
|
|
1721
1582
|
const reverseJoin = (baseQuery, joiningQuery) => {
|
|
1722
|
-
|
|
1723
|
-
return joinQuery(baseQuery, getQueryAs(baseQuery), foreignAs, {
|
|
1724
|
-
...baseQuery.q.joinedShapes,
|
|
1725
|
-
[foreignAs]: joiningQuery.q.selectShape
|
|
1726
|
-
});
|
|
1583
|
+
return joinHasRelation(joiningQuery, baseQuery, foreignKeys, primaryKeys, len);
|
|
1727
1584
|
};
|
|
1728
1585
|
return {
|
|
1729
1586
|
returns: "many",
|
|
1730
|
-
queryRelated(params) {
|
|
1731
|
-
const
|
|
1732
|
-
|
|
1733
|
-
|
|
1734
|
-
|
|
1735
|
-
|
|
1736
|
-
return _queryWhere(q, [where]);
|
|
1587
|
+
queryRelated: (params) => {
|
|
1588
|
+
const values = {};
|
|
1589
|
+
for (let i = 0; i < len; i++) values[foreignKeys[i]] = params[primaryKeys[i]];
|
|
1590
|
+
return _queryDefaults(query.where(values), {
|
|
1591
|
+
...on,
|
|
1592
|
+
...values
|
|
1737
1593
|
});
|
|
1738
|
-
return on ? _queryDefaults(q, on) : q;
|
|
1739
1594
|
},
|
|
1740
|
-
virtualColumn: new
|
|
1741
|
-
joinQuery: joinQueryChainHOF(
|
|
1742
|
-
...joiningQuery.q.joinedShapes,
|
|
1743
|
-
[baseQuery.q.as || baseQuery.table]: baseQuery.q.selectShape
|
|
1744
|
-
})),
|
|
1595
|
+
virtualColumn: new HasManyVirtualColumn(internalSchemaConfig, relationName, state),
|
|
1596
|
+
joinQuery: joinQueryChainHOF(relPKeys, reverseJoin, (joiningQuery, baseQuery) => joinHasRelation(baseQuery, joiningQuery, primaryKeys, foreignKeys, len)),
|
|
1745
1597
|
reverseJoin,
|
|
1746
1598
|
modifyRelatedQuery(relationQuery) {
|
|
1747
|
-
|
|
1748
|
-
|
|
1749
|
-
|
|
1750
|
-
|
|
1751
|
-
|
|
1752
|
-
|
|
1753
|
-
for (let i = 0; i < throughLen; i++) dataRow[throughForeignKeys[i]] = resultRow[throughPrimaryKeys[i]];
|
|
1754
|
-
return dataRow;
|
|
1755
|
-
});
|
|
1756
|
-
if (await _queryCreateManyFrom(subQuery.count(), baseQuery, data) === 0) throw new NotFoundError(baseQuery);
|
|
1757
|
-
});
|
|
1758
|
-
return (q) => {
|
|
1759
|
-
ref.q = q;
|
|
1599
|
+
return (query) => {
|
|
1600
|
+
const baseQuery = query.clone();
|
|
1601
|
+
baseQuery.q.select = fromQuerySelect;
|
|
1602
|
+
const q = relationQuery.q;
|
|
1603
|
+
q.insertFrom = prepareSubQueryForSql(q, baseQuery);
|
|
1604
|
+
q.values = [];
|
|
1760
1605
|
};
|
|
1761
1606
|
}
|
|
1762
1607
|
};
|
|
1763
1608
|
};
|
|
1764
|
-
const queryJoinTable = (state, data, conditions) => {
|
|
1765
|
-
const t = state.joinTableQuery.where({ IN: {
|
|
1766
|
-
columns: state.foreignKeys,
|
|
1767
|
-
values: data.map((item) => state.primaryKeys.map((key) => item[key]))
|
|
1768
|
-
} });
|
|
1769
|
-
if (conditions) _queryWhere(t, [{ IN: {
|
|
1770
|
-
columns: state.throughForeignKeys,
|
|
1771
|
-
values: _querySelect(state.relatedTableQuery.where(conditionsToWhereArg(conditions)), state.throughPrimaryKeys)
|
|
1772
|
-
} }]);
|
|
1773
|
-
if (state.on) _queryWhereExists(t, state.relatedTableQuery, [(q) => {
|
|
1774
|
-
for (let i = 0; i < state.throughPrimaryKeys.length; i++) _queryJoinOn(q, [state.throughPrimaryKeysFull[i], state.throughForeignKeysFull[i]]);
|
|
1775
|
-
return q;
|
|
1776
|
-
}]);
|
|
1777
|
-
return t;
|
|
1778
|
-
};
|
|
1779
|
-
const conditionsToWhereArg = (conditions) => Array.isArray(conditions) ? { OR: conditions } : conditions;
|
|
1780
|
-
const insertToJoinTable = (state, joinTableTransaction, data, idsRows) => {
|
|
1781
|
-
const len = state.primaryKeys.length;
|
|
1782
|
-
const throughLen = state.throughPrimaryKeys.length;
|
|
1783
|
-
const records = [];
|
|
1784
|
-
for (const item of data) {
|
|
1785
|
-
const obj = {};
|
|
1786
|
-
for (let i = 0; i < len; i++) obj[state.foreignKeys[i]] = item[state.primaryKeys[i]];
|
|
1787
|
-
for (const ids of idsRows) {
|
|
1788
|
-
const record = { ...obj };
|
|
1789
|
-
for (let i = 0; i < throughLen; i++) record[state.throughForeignKeys[i]] = ids[i];
|
|
1790
|
-
records.push(record);
|
|
1791
|
-
}
|
|
1792
|
-
}
|
|
1793
|
-
return joinTableTransaction.insertMany(records);
|
|
1794
|
-
};
|
|
1795
1609
|
const nestedInsert = ({ relatedTableQuery, joinTableQuery, primaryKeys, foreignKeys, throughPrimaryKeys, throughForeignKeys }) => {
|
|
1796
1610
|
const len = primaryKeys.length;
|
|
1797
1611
|
const throughLen = primaryKeys.length;
|
|
@@ -1877,6 +1691,71 @@ const nestedInsert = ({ relatedTableQuery, joinTableQuery, primaryKeys, foreignK
|
|
|
1877
1691
|
await joinTableQuery.insertMany(records);
|
|
1878
1692
|
});
|
|
1879
1693
|
};
|
|
1694
|
+
const selectCteColumnsSql = (cteAs, columns) => `(SELECT ${columns.map((c) => `"${cteAs}"."${c}"`).join(", ")} FROM "${cteAs}")`;
|
|
1695
|
+
const selectCteColumnSql = (cteAs, column) => `(SELECT "${cteAs}"."${column}" FROM "${cteAs}")`;
|
|
1696
|
+
const conditionsToWhereArg = (conditions) => Array.isArray(conditions) ? { OR: conditions } : conditions;
|
|
1697
|
+
const queryJoinTable = (state, data, conditions) => {
|
|
1698
|
+
const t = state.joinTableQuery.where({ IN: {
|
|
1699
|
+
columns: state.foreignKeys,
|
|
1700
|
+
values: data.map((item) => state.primaryKeys.map((key) => item[key]))
|
|
1701
|
+
} });
|
|
1702
|
+
if (conditions) _queryWhere(t, [{ IN: {
|
|
1703
|
+
columns: state.throughForeignKeys,
|
|
1704
|
+
values: _querySelect(state.relatedTableQuery.where(conditionsToWhereArg(conditions)), state.throughPrimaryKeys)
|
|
1705
|
+
} }]);
|
|
1706
|
+
if (state.on) _queryWhereExists(t, state.relatedTableQuery, [(q) => {
|
|
1707
|
+
for (let i = 0; i < state.throughPrimaryKeys.length; i++) _queryJoinOn(q, [state.throughPrimaryKeysFull[i], state.throughForeignKeysFull[i]]);
|
|
1708
|
+
return q;
|
|
1709
|
+
}]);
|
|
1710
|
+
return t;
|
|
1711
|
+
};
|
|
1712
|
+
const insertToJoinTable = (state, joinTableTransaction, data, idsRows) => {
|
|
1713
|
+
const len = state.primaryKeys.length;
|
|
1714
|
+
const throughLen = state.throughPrimaryKeys.length;
|
|
1715
|
+
const records = [];
|
|
1716
|
+
for (const item of data) {
|
|
1717
|
+
const obj = {};
|
|
1718
|
+
for (let i = 0; i < len; i++) obj[state.foreignKeys[i]] = item[state.primaryKeys[i]];
|
|
1719
|
+
for (const ids of idsRows) {
|
|
1720
|
+
const record = { ...obj };
|
|
1721
|
+
for (let i = 0; i < throughLen; i++) record[state.throughForeignKeys[i]] = ids[i];
|
|
1722
|
+
records.push(record);
|
|
1723
|
+
}
|
|
1724
|
+
}
|
|
1725
|
+
return joinTableTransaction.insertMany(records);
|
|
1726
|
+
};
|
|
1727
|
+
const nestedUpdateUpsert = (querySelf, state, upsert) => {
|
|
1728
|
+
const parentIdsSql = new RawSql("");
|
|
1729
|
+
const parentValues = state.foreignKeys.map(() => new RawSql(""));
|
|
1730
|
+
const relatedIdsSql = new RawSql("");
|
|
1731
|
+
const relatedValues = state.throughPrimaryKeys.map(() => new RawSql(""));
|
|
1732
|
+
let parentAs;
|
|
1733
|
+
_hookSelectColumns(querySelf, state.primaryKeys, (aliasedPrimaryKeys) => {
|
|
1734
|
+
parentIdsSql._sql = selectCteColumnsSql(parentAs, aliasedPrimaryKeys);
|
|
1735
|
+
for (let i = 0; i < state.foreignKeys.length; i++) parentValues[i]._sql = selectCteColumnSql(parentAs, aliasedPrimaryKeys[i]);
|
|
1736
|
+
});
|
|
1737
|
+
const existingRelQuery = _queryWhereExists(_queryWhere(_clone(state.relatedTableQuery), [upsert.findBy]), state.joinTableQuery, [(q) => {
|
|
1738
|
+
for (let i = 0; i < state.throughPrimaryKeys.length; i++) _queryJoinOn(q, [state.throughForeignKeysFull[i], state.throughPrimaryKeysFull[i]]);
|
|
1739
|
+
return _queryWhereIn(q, true, state.foreignKeysFull, parentIdsSql);
|
|
1740
|
+
}]);
|
|
1741
|
+
const upsertQuery = _querySelect(_queryUpsert(existingRelQuery, {
|
|
1742
|
+
update: upsert.update,
|
|
1743
|
+
create: upsert.create || {}
|
|
1744
|
+
}), state.throughPrimaryKeys);
|
|
1745
|
+
const selectAs = {};
|
|
1746
|
+
for (let i = 0; i < state.foreignKeys.length; i++) selectAs[state.foreignKeys[i]] = parentValues[i];
|
|
1747
|
+
for (let i = 0; i < state.throughForeignKeys.length; i++) selectAs[state.throughForeignKeys[i]] = relatedValues[i];
|
|
1748
|
+
const joinRows = _querySelect(_clone(state.queryBuilder), [selectAs]);
|
|
1749
|
+
_queryWhere(joinRows, [relatedIdsSql]);
|
|
1750
|
+
const joinQuery = state.joinTableQuery.insertForEachFrom(joinRows);
|
|
1751
|
+
joinQuery.q.returnType = "void";
|
|
1752
|
+
_appendQuery(querySelf, _appendQueryOnUpsertCreate(upsertQuery, joinQuery, (as) => {
|
|
1753
|
+
relatedIdsSql._sql = `EXISTS (SELECT 1 FROM "${as}")`;
|
|
1754
|
+
for (let i = 0; i < relatedValues.length; i++) relatedValues[i]._sql = selectCteColumnSql(as, state.throughPrimaryKeys[i]);
|
|
1755
|
+
}), (as) => {
|
|
1756
|
+
parentAs = as;
|
|
1757
|
+
});
|
|
1758
|
+
};
|
|
1880
1759
|
const nestedUpdate = (state) => {
|
|
1881
1760
|
const len = state.primaryKeys.length;
|
|
1882
1761
|
const throughLen = state.throughPrimaryKeys.length;
|
|
@@ -1938,6 +1817,153 @@ const nestedUpdate = (state) => {
|
|
|
1938
1817
|
}
|
|
1939
1818
|
});
|
|
1940
1819
|
};
|
|
1820
|
+
var HasAndBelongsToManyVirtualColumn = class extends VirtualColumn {
|
|
1821
|
+
constructor(joinTable, schema, key, state) {
|
|
1822
|
+
super(schema);
|
|
1823
|
+
this.joinTable = joinTable;
|
|
1824
|
+
this.key = key;
|
|
1825
|
+
this.state = state;
|
|
1826
|
+
this.nestedInsert = nestedInsert(state);
|
|
1827
|
+
this.nestedUpdate = nestedUpdate(state);
|
|
1828
|
+
}
|
|
1829
|
+
create(q, ctx, items, rowIndexes) {
|
|
1830
|
+
hasRelationHandleCreate(q, ctx, items, rowIndexes, this.key, this.state.primaryKeys, this.nestedInsert);
|
|
1831
|
+
}
|
|
1832
|
+
update(q, set) {
|
|
1833
|
+
const querySelf = q;
|
|
1834
|
+
const params = set[this.key];
|
|
1835
|
+
hasRelationHandleUpdate(querySelf, set, this.key, this.state.primaryKeys, this.nestedUpdate);
|
|
1836
|
+
if (params.upsert) {
|
|
1837
|
+
throwIfQueryReturnsAllForNestedUpdate(querySelf, { upsert: params.upsert });
|
|
1838
|
+
nestedUpdateUpsert(querySelf, this.state, params.upsert);
|
|
1839
|
+
}
|
|
1840
|
+
}
|
|
1841
|
+
};
|
|
1842
|
+
const removeColumnName = (column) => {
|
|
1843
|
+
if (!column.data.name) return column;
|
|
1844
|
+
const cloned = Object.create(column);
|
|
1845
|
+
cloned.data = {
|
|
1846
|
+
...column.data,
|
|
1847
|
+
name: void 0
|
|
1848
|
+
};
|
|
1849
|
+
return cloned;
|
|
1850
|
+
};
|
|
1851
|
+
const makeHasAndBelongsToManyMethod = (tableConfig, table, qb, relation, relationName, query, schema) => {
|
|
1852
|
+
const { options } = relation;
|
|
1853
|
+
const { snakeCase } = table.internal;
|
|
1854
|
+
const primaryKeys = options.columns;
|
|
1855
|
+
const originalForeignKeys = options.references;
|
|
1856
|
+
const foreignKeys = snakeCase ? [...originalForeignKeys] : originalForeignKeys;
|
|
1857
|
+
const joinTable = snakeCase && options.through.snakeCase !== false ? toSnakeCase(options.through.table) : options.through.table;
|
|
1858
|
+
const originalThroughForeignKeys = options.through.columns;
|
|
1859
|
+
const throughForeignKeys = snakeCase ? [...originalThroughForeignKeys] : originalThroughForeignKeys;
|
|
1860
|
+
const throughPrimaryKeys = options.through.references;
|
|
1861
|
+
const { on } = options;
|
|
1862
|
+
if (on) {
|
|
1863
|
+
_queryWhere(query, [on]);
|
|
1864
|
+
_queryDefaults(query, on);
|
|
1865
|
+
}
|
|
1866
|
+
const foreignKeysFull = foreignKeys.map((key, i) => {
|
|
1867
|
+
if (snakeCase) key = foreignKeys[i] = toSnakeCase(key);
|
|
1868
|
+
return `${joinTable}.${key}`;
|
|
1869
|
+
});
|
|
1870
|
+
const throughForeignKeysFull = throughForeignKeys.map((key, i) => {
|
|
1871
|
+
if (snakeCase) key = throughForeignKeys[i] = toSnakeCase(key);
|
|
1872
|
+
return `${joinTable}.${key}`;
|
|
1873
|
+
});
|
|
1874
|
+
const foreignTable = getQueryAs(query);
|
|
1875
|
+
const throughPrimaryKeysFull = throughPrimaryKeys.map((key) => `${foreignTable}.${key}`);
|
|
1876
|
+
const len = primaryKeys.length;
|
|
1877
|
+
const throughLen = throughPrimaryKeys.length;
|
|
1878
|
+
const baseQuery = Object.create(qb.baseQuery);
|
|
1879
|
+
baseQuery.baseQuery = baseQuery;
|
|
1880
|
+
baseQuery.table = joinTable;
|
|
1881
|
+
const shape = {};
|
|
1882
|
+
const primaryKeysShape = {};
|
|
1883
|
+
for (let i = 0; i < len; i++) {
|
|
1884
|
+
const pk = primaryKeys[i];
|
|
1885
|
+
shape[foreignKeys[i]] = removeColumnName(table.shape[pk]);
|
|
1886
|
+
primaryKeysShape[pk] = table.shape[pk];
|
|
1887
|
+
}
|
|
1888
|
+
for (let i = 0; i < throughLen; i++) shape[throughForeignKeys[i]] = removeColumnName(query.shape[throughPrimaryKeys[i]]);
|
|
1889
|
+
baseQuery.shape = shape;
|
|
1890
|
+
baseQuery.q = {
|
|
1891
|
+
...baseQuery.q,
|
|
1892
|
+
schema: options.through.schema || schema,
|
|
1893
|
+
shape: baseQuery.shape
|
|
1894
|
+
};
|
|
1895
|
+
const subQuery = Object.create(baseQuery);
|
|
1896
|
+
addAutoForeignKey(tableConfig, subQuery, table, primaryKeys, foreignKeys, relation.options, originalForeignKeys);
|
|
1897
|
+
addAutoForeignKey(tableConfig, subQuery, query, throughPrimaryKeys, throughForeignKeys, relation.options.through, originalThroughForeignKeys);
|
|
1898
|
+
const state = {
|
|
1899
|
+
queryBuilder: qb,
|
|
1900
|
+
relatedTableQuery: query,
|
|
1901
|
+
joinTableQuery: subQuery,
|
|
1902
|
+
primaryKeys,
|
|
1903
|
+
foreignKeys,
|
|
1904
|
+
throughForeignKeys,
|
|
1905
|
+
throughPrimaryKeys,
|
|
1906
|
+
foreignKeysFull,
|
|
1907
|
+
throughForeignKeysFull,
|
|
1908
|
+
throughPrimaryKeysFull,
|
|
1909
|
+
primaryKeysShape,
|
|
1910
|
+
on
|
|
1911
|
+
};
|
|
1912
|
+
const joinQuery = (joiningQuery, tableAs, foreignAs, joinedShapes) => {
|
|
1913
|
+
const cloned = joiningQuery.clone();
|
|
1914
|
+
cloned.q.joinedShapes = joinedShapes;
|
|
1915
|
+
return _queryWhereExists(cloned, subQuery, [(q) => {
|
|
1916
|
+
for (let i = 0; i < throughLen; i++) _queryJoinOn(q, [throughForeignKeysFull[i], `${foreignAs}.${throughPrimaryKeys[i]}`]);
|
|
1917
|
+
for (let i = 0; i < len; i++) _queryJoinOn(q, [foreignKeysFull[i], `${tableAs}.${primaryKeys[i]}`]);
|
|
1918
|
+
return q;
|
|
1919
|
+
}]);
|
|
1920
|
+
};
|
|
1921
|
+
const obj = {};
|
|
1922
|
+
for (let i = 0; i < len; i++) obj[foreignKeys[i]] = primaryKeys[i];
|
|
1923
|
+
const selectPrimaryKeysAsForeignKeys = [{ selectAs: obj }];
|
|
1924
|
+
const reverseJoin = (baseQuery, joiningQuery) => {
|
|
1925
|
+
const foreignAs = getQueryAs(joiningQuery);
|
|
1926
|
+
return joinQuery(baseQuery, getQueryAs(baseQuery), foreignAs, {
|
|
1927
|
+
...baseQuery.q.joinedShapes,
|
|
1928
|
+
[foreignAs]: joiningQuery.q.selectShape
|
|
1929
|
+
});
|
|
1930
|
+
};
|
|
1931
|
+
return {
|
|
1932
|
+
returns: "many",
|
|
1933
|
+
queryRelated(params) {
|
|
1934
|
+
const q = query.whereExists(subQuery, (q) => {
|
|
1935
|
+
q = q.clone();
|
|
1936
|
+
const where = {};
|
|
1937
|
+
for (let i = 0; i < len; i++) where[foreignKeysFull[i]] = params[primaryKeys[i]];
|
|
1938
|
+
for (let i = 0; i < throughLen; i++) _queryJoinOn(q, [throughForeignKeysFull[i], throughPrimaryKeysFull[i]]);
|
|
1939
|
+
return _queryWhere(q, [where]);
|
|
1940
|
+
});
|
|
1941
|
+
return on ? _queryDefaults(q, on) : q;
|
|
1942
|
+
},
|
|
1943
|
+
virtualColumn: new HasAndBelongsToManyVirtualColumn(subQuery, internalSchemaConfig, relationName, state),
|
|
1944
|
+
joinQuery: joinQueryChainHOF(getPrimaryKeys(query), reverseJoin, (joiningQuery, baseQuery) => joinQuery(joiningQuery, getQueryAs(baseQuery), getQueryAs(joiningQuery), {
|
|
1945
|
+
...joiningQuery.q.joinedShapes,
|
|
1946
|
+
[baseQuery.q.as || baseQuery.table]: baseQuery.q.selectShape
|
|
1947
|
+
})),
|
|
1948
|
+
reverseJoin,
|
|
1949
|
+
modifyRelatedQuery(relationQuery) {
|
|
1950
|
+
const ref = {};
|
|
1951
|
+
_queryHookAfterCreate(relationQuery, [], async (result) => {
|
|
1952
|
+
const baseQuery = ref.q.clone();
|
|
1953
|
+
baseQuery.q.select = selectPrimaryKeysAsForeignKeys;
|
|
1954
|
+
const data = result.map((resultRow) => {
|
|
1955
|
+
const dataRow = {};
|
|
1956
|
+
for (let i = 0; i < throughLen; i++) dataRow[throughForeignKeys[i]] = resultRow[throughPrimaryKeys[i]];
|
|
1957
|
+
return dataRow;
|
|
1958
|
+
});
|
|
1959
|
+
if (await _queryCreateManyFrom(subQuery.count(), baseQuery, data) === 0) throw new NotFoundError(baseQuery);
|
|
1960
|
+
});
|
|
1961
|
+
return (q) => {
|
|
1962
|
+
ref.q = q;
|
|
1963
|
+
};
|
|
1964
|
+
}
|
|
1965
|
+
};
|
|
1966
|
+
};
|
|
1941
1967
|
const applyRelations = (qb, tables, result, schema) => {
|
|
1942
1968
|
const tableEntries = Object.entries(tables);
|
|
1943
1969
|
const delayedRelations = /* @__PURE__ */ new Map();
|