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.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
- var BelongsToVirtualColumn = class extends VirtualColumn {
787
- constructor(schema, key, state) {
788
- super(schema);
789
- this.key = key;
790
- this.state = state;
791
- this.nestedUpdate = nestedUpdate$2(this.state);
792
- }
793
- create(q, ctx, items) {
794
- const queryForCreate = q;
795
- const { key, state: { query, primaryKeys, foreignKeys } } = this;
796
- let nestedCreateItems;
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
- if (queryForCreate.q.type === "upsert") _prependWithOnUpsertCreate(queryForCreate, setForeignKeys, createQuery);
834
- else _prependWith(queryForCreate, setForeignKeys, createQuery);
835
- }
836
- if (connect) connect.values.forEach((value, itemI) => {
837
- const as = getFreeAlias(queryForCreate.q.withShapes, "q");
838
- (queryForCreate.q.type === "upsert" ? _prependWithOnUpsertCreate : _prependWith)(queryForCreate, as, query.select(...primaryKeys).findBy(value));
839
- foreignKeys.map((foreignKey, i) => {
840
- connect.items[itemI][foreignKey] = new RawSql(selectCteColumnMustExistSql(i, as, primaryKeys[i]));
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
- if (connectOrCreate) connectOrCreate.values.forEach((value, itemI) => {
844
- const asFn = setForeignKeysFromCte(connectOrCreate.items[itemI], primaryKeys, foreignKeys);
845
- const selectPKeys = query.select(...primaryKeys);
846
- (queryForCreate.q.type === "upsert" ? _prependWithOnUpsertCreate : _prependWith)(queryForCreate, asFn, _orCreate(_queryWhere(selectPKeys, [value.where]), value.create));
847
- });
848
- }
849
- update(q, set) {
850
- const queryForUpdate = q;
851
- queryForUpdate.q.wrapInTransaction = true;
852
- const data = set[this.key];
853
- this.nestedUpdate(queryForUpdate, set, data);
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 getBelongsToRequired = (tableConfig, relatedTableConfig, relation) => {
857
- const { required } = relation.options;
858
- if (typeof required === "boolean") return required;
859
- if (relatedTableConfig.softDelete) return false;
860
- return relation.options.columns.every((key) => {
861
- return !tableConfig.columns.shape[key].data.isNullable;
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
- const setForeignKeysFromCte = (record, primaryKeys, foreignKeys, mustExist) => {
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.nestedInsert = nestedInsert$2(state);
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(self, ctx, items, rowIndexes, count) {
998
- const querySelf = self;
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(self, set) {
1118
- const querySelf = self;
1119
- const params = set[this.key];
1120
- throwIfQueryReturnsAllForNestedUpdate(querySelf, params);
1121
- const { primaryKeys, foreignKeys, query: relQuery } = this.state;
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 makeHasOneMethod = (tableConfig, table, relation, relationName, query) => {
1142
- const relPKeys = getPrimaryKeys(query);
1143
- if ("through" in relation.options) {
1144
- const { through, source, on } = relation.options;
1145
- if (on) _queryWhere(query, [on]);
1146
- const throughRelation = getThroughRelation(table, through);
1147
- const sourceRelation = getSourceRelation(throughRelation, source);
1148
- const sourceRelationQuery = sourceRelation.query.as(relationName);
1149
- const sourceQuery = sourceRelation.joinQuery(sourceRelationQuery, throughRelation.query);
1150
- const whereExistsCallback = () => sourceQuery;
1151
- const reverseJoin = (baseQuery, joiningQuery) => {
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
- addAutoForeignKey(tableConfig, query, table, primaryKeys, foreignKeys, relation.options);
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
- const len = primaryKeys.length;
1179
- const reversedOn = {};
1180
- for (let i = 0; i < len; i++) reversedOn[foreignKeys[i]] = primaryKeys[i];
1181
- const fromQuerySelect = [{ selectAs: reversedOn }];
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 joinHasRelation(joiningQuery, baseQuery, foreignKeys, primaryKeys, len);
977
+ return join(joiningQuery, baseQuery, foreignKeys, primaryKeys);
1184
978
  };
1185
979
  return {
1186
980
  returns: "one",
1187
- queryRelated: (params) => {
1188
- const values = {};
1189
- for (let i = 0; i < len; i++) values[foreignKeys[i]] = params[primaryKeys[i]];
1190
- return _queryDefaults(query.where(values), {
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 HasOneVirtualColumn(internalSchemaConfig, relationName, state),
1196
- joinQuery: joinQueryChainHOF(relPKeys, reverseJoin, (joiningQuery, baseQuery) => joinHasRelation(baseQuery, joiningQuery, primaryKeys, foreignKeys, len)),
1197
- reverseJoin,
1198
- modifyRelatedQuery(relationQuery) {
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
- var HasManyVirtualColumn = class extends VirtualColumn {
1243
- constructor(schema, key, state) {
1244
- super(schema);
1245
- this.key = key;
1246
- this.state = state;
1247
- this.nestedInsert = nestedInsert$1(state);
1248
- this.nestedUpdate = nestedUpdate$1(state);
1249
- this.setNulls = {};
1250
- for (const foreignKey of state.foreignKeys) this.setNulls[foreignKey] = null;
1251
- }
1252
- create(self, ctx, items, rowIndexes, count) {
1253
- const querySelf = self;
1254
- if (count <= querySelf.qb.internal.nestedCreateBatchMax) {
1255
- const { query: rel, primaryKeys, foreignKeys } = this.state;
1256
- let nestedCreateItems;
1257
- items.forEach((item, i) => {
1258
- const value = item[this.key];
1259
- if (value.create?.length) {
1260
- const nestedCreateItem = (nestedCreateItems ??= {}).create ??= {
1261
- indexes: [],
1262
- items: []
1263
- };
1264
- nestedCreateItem.indexes.push(rowIndexes[i]);
1265
- const data = value.create.map((obj) => {
1266
- const data = { ...obj };
1267
- for (const key of foreignKeys) data[key] = new RawSql("");
1268
- return data;
1269
- });
1270
- nestedCreateItem.items.push(data);
1271
- } else {
1272
- const kind = value.connect?.length ? "connect" : value.connectOrCreate?.length ? "connectOrCreate" : void 0;
1273
- if (kind) {
1274
- const nestedCreateItem = (nestedCreateItems ??= {})[kind] ??= {
1275
- indexes: [],
1276
- items: [],
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 (!nestedCreateItems) return;
1288
- let createAs;
1289
- let createWhereExists;
1290
- let createSelectAs;
1291
- let createAliasedPrimaryKeys;
1292
- let upsertCreateAs;
1293
- let connectAs;
1294
- let connectOrCreateAs;
1295
- const setUpsertCreatePlaceholders = () => {
1296
- if (!upsertCreateAs || !createAliasedPrimaryKeys) return;
1297
- const aliasedPrimaryKeys = createAliasedPrimaryKeys;
1298
- if (createWhereExists) createWhereExists._sql = `EXISTS (SELECT 1 FROM "${upsertCreateAs}")`;
1299
- if (createSelectAs) foreignKeys.forEach((key, keyI) => {
1300
- createSelectAs[key]._sql = selectCteColumnFromManySql(upsertCreateAs, aliasedPrimaryKeys[keyI], 0, 1);
1301
- });
1302
- if (connect) foreignKeys.forEach((key, keyI) => {
1303
- const primaryKey = aliasedPrimaryKeys[keyI];
1304
- for (let i = 0; i < connect.items.length; i++) connect.items[i][key]._sql = selectCteColumnFromManySql(upsertCreateAs, primaryKey, connect.indexes[i], count);
1305
- });
1306
- if (connectOrCreate) foreignKeys.forEach((key, keyI) => {
1307
- const primaryKey = aliasedPrimaryKeys[keyI];
1308
- for (let i = 0; i < connectOrCreate.items.length; i++) connectOrCreate.items[i][key]._sql = selectCteColumnFromManySql(upsertCreateAs, primaryKey, connectOrCreate.indexes[i], count);
1309
- });
1310
- };
1311
- _hookSelectColumns(querySelf, primaryKeys, (aliasedPrimaryKeys) => {
1312
- createAliasedPrimaryKeys = aliasedPrimaryKeys;
1313
- foreignKeys.forEach((key, keyI) => {
1314
- const primaryKey = aliasedPrimaryKeys[keyI];
1315
- if (create && createAs) for (let i = 0; i < create.items.length; i++) {
1316
- const sql = selectCteColumnFromManySql(createAs, primaryKey, create.indexes[i], count);
1317
- for (const item of create.items[i]) item[key]._sql = sql;
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
- const { create, connect, connectOrCreate } = nestedCreateItems;
1325
- if (create) {
1326
- let query;
1327
- if (querySelf.q.type === "upsert") {
1328
- createWhereExists = new RawSql("");
1329
- createSelectAs = {};
1330
- for (const key of foreignKeys) createSelectAs[key] = new RawSql("");
1331
- const sourceQuery = _queryWhere(_queryTake(_querySelect(_clone(rel.qb), [createSelectAs])), [createWhereExists]);
1332
- query = _queryInsertManyFrom(_clone(rel), sourceQuery, create.items.flat());
1333
- } else query = _queryInsertMany(_clone(rel), create.items.flat());
1334
- if (querySelf.q.type === "upsert") _appendQueryOnUpsertCreate(querySelf, query, (as) => {
1335
- upsertCreateAs = as;
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
- if (connectOrCreate) connectOrCreate.values.forEach((array, i) => {
1353
- const foreignKeyValues = connectOrCreate.items[i];
1354
- for (const value of array) {
1355
- const connectOrCreateWhereExists = querySelf.q.type === "upsert" ? new RawSql("") : void 0;
1356
- const connectOrCreateSelectAs = {};
1357
- if (connectOrCreateWhereExists) for (const key of foreignKeys) {
1358
- const value = foreignKeyValues[key];
1359
- value.result = { value: rel.qb.shape[key] };
1360
- connectOrCreateSelectAs[key] = value;
1361
- }
1362
- const query = _queryUpsert(rel.where(value.where), {
1363
- update: foreignKeyValues,
1364
- create: {
1365
- ...value.create,
1366
- ...foreignKeyValues
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
- } else hasRelationHandleCreate(querySelf, ctx, items, rowIndexes, this.key, this.state.primaryKeys, this.nestedInsert);
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
- const querySelf = self;
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 makeHasManyMethod = (tableConfig, table, relation, relationName, query) => {
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: "many",
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 HasManyVirtualColumn(internalSchemaConfig, relationName, state),
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 nestedUpdate$1 = ({ query: relQuery, primaryKeys, foreignKeys }) => {
1544
- const len = primaryKeys.length;
1545
- return (async (_, data, params) => {
1546
- const t = relQuery.clone();
1547
- if (params.create) {
1548
- const obj = {};
1549
- for (let i = 0; i < len; i++) obj[foreignKeys[i]] = data[0][primaryKeys[i]];
1550
- await t.insertMany(params.create.map((create) => ({
1551
- ...create,
1552
- ...obj
1553
- })));
1554
- }
1555
- if (params.add) {
1556
- 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");
1557
- const obj = {};
1558
- for (let i = 0; i < len; i++) obj[foreignKeys[i]] = data[0][primaryKeys[i]];
1559
- const relatedWheres = toArray(params.add);
1560
- const count = await _queryUpdate(t.where({ OR: relatedWheres }), obj);
1561
- if (count < relatedWheres.length) throw new OrchidOrmInternalError(relQuery, `Expected to find at least ${relatedWheres.length} record(s) based on \`add\` conditions, but found ${count}`);
1562
- }
1563
- if (params.disconnect || params.set) {
1564
- const obj = {};
1565
- for (const foreignKey of foreignKeys) obj[foreignKey] = null;
1566
- const setConditions = params.set && (Array.isArray(params.set) ? params.set.length : objectHasValues(params.set)) && (Array.isArray(params.set) ? { OR: params.set } : params.set);
1567
- let queryToDisconnect = getWhereForNestedUpdate(t, data, params.disconnect, primaryKeys, foreignKeys);
1568
- if (setConditions) queryToDisconnect = queryToDisconnect.whereNot(setConditions);
1569
- await _queryUpdate(queryToDisconnect, obj);
1570
- if (setConditions) {
1571
- const obj = {};
1572
- for (let i = 0; i < len; i++) obj[foreignKeys[i]] = data[0][primaryKeys[i]];
1573
- await _queryUpdate(t.where(setConditions), obj);
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 (params.delete || params.update) {
1577
- const q = getWhereForNestedUpdate(t, data, params.delete || params.update?.where, primaryKeys, foreignKeys);
1578
- if (params.delete) await _queryDelete(q);
1579
- else if (params.update) await _queryUpdate(q, params.update.data);
1580
- }
1581
- });
1582
- };
1583
- var HasAndBelongsToManyVirtualColumn = class extends VirtualColumn {
1584
- constructor(joinTable, schema, key, state) {
1585
- super(schema);
1586
- this.joinTable = joinTable;
1587
- this.key = key;
1588
- this.state = state;
1589
- this.nestedInsert = nestedInsert(state);
1590
- this.nestedUpdate = nestedUpdate(state);
1591
- }
1592
- create(q, ctx, items, rowIndexes) {
1593
- hasRelationHandleCreate(q, ctx, items, rowIndexes, this.key, this.state.primaryKeys, this.nestedInsert);
1594
- }
1595
- update(q, set) {
1596
- const querySelf = q;
1597
- const params = set[this.key];
1598
- hasRelationHandleUpdate(querySelf, set, this.key, this.state.primaryKeys, this.nestedUpdate);
1599
- if (params.upsert) {
1600
- throwIfQueryReturnsAllForNestedUpdate(querySelf, { upsert: params.upsert });
1601
- nestedUpdateUpsert(querySelf, this.state, params.upsert);
1602
- }
1603
- }
1604
- };
1605
- const selectCteColumnsSql = (cteAs, columns) => `(SELECT ${columns.map((c) => `"${cteAs}"."${c}"`).join(", ")} FROM "${cteAs}")`;
1606
- const selectCteColumnSql = (cteAs, column) => `(SELECT "${cteAs}"."${column}" FROM "${cteAs}")`;
1607
- const nestedUpdateUpsert = (querySelf, state, upsert) => {
1608
- const parentIdsSql = new RawSql("");
1609
- const parentValues = state.foreignKeys.map(() => new RawSql(""));
1610
- const relatedIdsSql = new RawSql("");
1611
- const relatedValues = state.throughPrimaryKeys.map(() => new RawSql(""));
1612
- let parentAs;
1613
- _hookSelectColumns(querySelf, state.primaryKeys, (aliasedPrimaryKeys) => {
1614
- parentIdsSql._sql = selectCteColumnsSql(parentAs, aliasedPrimaryKeys);
1615
- for (let i = 0; i < state.foreignKeys.length; i++) parentValues[i]._sql = selectCteColumnSql(parentAs, aliasedPrimaryKeys[i]);
1616
- });
1617
- const existingRelQuery = _queryWhereExists(_queryWhere(_clone(state.relatedTableQuery), [upsert.findBy]), state.joinTableQuery, [(q) => {
1618
- for (let i = 0; i < state.throughPrimaryKeys.length; i++) _queryJoinOn(q, [state.throughForeignKeysFull[i], state.throughPrimaryKeysFull[i]]);
1619
- return _queryWhereIn(q, true, state.foreignKeysFull, parentIdsSql);
1620
- }]);
1621
- const upsertQuery = _querySelect(_queryUpsert(existingRelQuery, {
1622
- update: upsert.update,
1623
- create: upsert.create || {}
1624
- }), state.throughPrimaryKeys);
1625
- const selectAs = {};
1626
- for (let i = 0; i < state.foreignKeys.length; i++) selectAs[state.foreignKeys[i]] = parentValues[i];
1627
- for (let i = 0; i < state.throughForeignKeys.length; i++) selectAs[state.throughForeignKeys[i]] = relatedValues[i];
1628
- const joinRows = _querySelect(_clone(state.queryBuilder), [selectAs]);
1629
- _queryWhere(joinRows, [relatedIdsSql]);
1630
- const joinQuery = state.joinTableQuery.insertForEachFrom(joinRows);
1631
- joinQuery.q.returnType = "void";
1632
- _appendQuery(querySelf, _appendQueryOnUpsertCreate(upsertQuery, joinQuery, (as) => {
1633
- relatedIdsSql._sql = `EXISTS (SELECT 1 FROM "${as}")`;
1634
- for (let i = 0; i < relatedValues.length; i++) relatedValues[i]._sql = selectCteColumnSql(as, state.throughPrimaryKeys[i]);
1635
- }), (as) => {
1636
- parentAs = as;
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
- const removeColumnName = (column) => {
1640
- if (!column.data.name) return column;
1641
- const cloned = Object.create(column);
1642
- cloned.data = {
1643
- ...column.data,
1644
- name: void 0
1645
- };
1646
- return cloned;
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 makeHasAndBelongsToManyMethod = (tableConfig, table, qb, relation, relationName, query, schema) => {
1649
- const { options } = relation;
1650
- const { snakeCase } = table.internal;
1651
- const primaryKeys = options.columns;
1652
- const originalForeignKeys = options.references;
1653
- const foreignKeys = snakeCase ? [...originalForeignKeys] : originalForeignKeys;
1654
- const joinTable = snakeCase && options.through.snakeCase !== false ? toSnakeCase(options.through.table) : options.through.table;
1655
- const originalThroughForeignKeys = options.through.columns;
1656
- const throughForeignKeys = snakeCase ? [...originalThroughForeignKeys] : originalThroughForeignKeys;
1657
- const throughPrimaryKeys = options.through.references;
1658
- const { on } = options;
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
- const foreignKeysFull = foreignKeys.map((key, i) => {
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
- queryBuilder: qb,
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 joinQuery = (joiningQuery, tableAs, foreignAs, joinedShapes) => {
1710
- const cloned = joiningQuery.clone();
1711
- cloned.q.joinedShapes = joinedShapes;
1712
- return _queryWhereExists(cloned, subQuery, [(q) => {
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
- const foreignAs = getQueryAs(joiningQuery);
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 q = query.whereExists(subQuery, (q) => {
1732
- q = q.clone();
1733
- const where = {};
1734
- for (let i = 0; i < len; i++) where[foreignKeysFull[i]] = params[primaryKeys[i]];
1735
- for (let i = 0; i < throughLen; i++) _queryJoinOn(q, [throughForeignKeysFull[i], throughPrimaryKeysFull[i]]);
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 HasAndBelongsToManyVirtualColumn(subQuery, internalSchemaConfig, relationName, state),
1741
- joinQuery: joinQueryChainHOF(getPrimaryKeys(query), reverseJoin, (joiningQuery, baseQuery) => joinQuery(joiningQuery, getQueryAs(baseQuery), getQueryAs(joiningQuery), {
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
- const ref = {};
1748
- _queryHookAfterCreate(relationQuery, [], async (result) => {
1749
- const baseQuery = ref.q.clone();
1750
- baseQuery.q.select = selectPrimaryKeysAsForeignKeys;
1751
- const data = result.map((resultRow) => {
1752
- const dataRow = {};
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();