orchid-orm 1.40.1 → 1.40.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 CHANGED
@@ -114,6 +114,7 @@ interface HasManyInfo<T extends RelationConfigSelf, Name extends string, Rel ext
114
114
  data: UpdateData<Q>;
115
115
  };
116
116
  set?: MaybeArray<WhereArg<Q>>;
117
+ add?: MaybeArray<WhereArg<Q>>;
117
118
  create?: CreateData<T['relations'][Name]['options'] extends RelationThroughOptions ? Q : AddQueryDefaults<Q, HasOnePopulate<T, Name>>>[];
118
119
  };
119
120
  }
@@ -332,6 +333,7 @@ interface HasAndBelongsToManyInfo<T extends RelationConfigSelf, Name extends str
332
333
  dataForUpdate: {
333
334
  disconnect?: MaybeArray<WhereArg<Q>>;
334
335
  set?: MaybeArray<WhereArg<Q>>;
336
+ add?: MaybeArray<WhereArg<Q>>;
335
337
  delete?: MaybeArray<WhereArg<Q>>;
336
338
  update?: {
337
339
  where: MaybeArray<WhereArg<Q>>;
@@ -342,6 +344,7 @@ interface HasAndBelongsToManyInfo<T extends RelationConfigSelf, Name extends str
342
344
  dataForUpdateOne: {
343
345
  disconnect?: MaybeArray<WhereArg<Q>>;
344
346
  set?: MaybeArray<WhereArg<Q>>;
347
+ add?: MaybeArray<WhereArg<Q>>;
345
348
  delete?: MaybeArray<WhereArg<Q>>;
346
349
  update?: {
347
350
  where: MaybeArray<WhereArg<Q>>;
package/dist/index.js CHANGED
@@ -181,7 +181,7 @@ const hasRelationHandleCreate = (q, ctx, item, rowIndex, key, primaryKeys, neste
181
181
  };
182
182
  const hasRelationHandleUpdate = (q, set, key, primaryKeys, nestedUpdate) => {
183
183
  const value = set[key];
184
- if (!value.set && !("upsert" in value) && (!value.disconnect || Array.isArray(value.disconnect) && value.disconnect.length === 0) && (!value.delete || Array.isArray(value.delete) && value.delete.length === 0) && (!value.update || Array.isArray(value.update.where) && value.update.where.length === 0) && (!value.create || Array.isArray(value.create) && value.create.length === 0))
184
+ if (!value.set && !("upsert" in value) && (!value.add || Array.isArray(value.add) && value.add.length === 0) && (!value.disconnect || Array.isArray(value.disconnect) && value.disconnect.length === 0) && (!value.delete || Array.isArray(value.delete) && value.delete.length === 0) && (!value.update || Array.isArray(value.update.where) && value.update.where.length === 0) && (!value.create || Array.isArray(value.create) && value.create.length === 0))
185
185
  return;
186
186
  selectIfNotSelected(q, primaryKeys);
187
187
  q.q.wrapInTransaction = true;
@@ -1131,6 +1131,29 @@ const nestedUpdate$1 = ({ query, primaryKeys, foreignKeys }) => {
1131
1131
  );
1132
1132
  delete t.q.sqlCache;
1133
1133
  }
1134
+ if (params.add) {
1135
+ if (data.length > 1) {
1136
+ throw new pqb.OrchidOrmInternalError(
1137
+ query,
1138
+ "`connect` is not available when updating multiple records, it is only applicable for a single record update"
1139
+ );
1140
+ }
1141
+ const obj = {};
1142
+ for (let i = 0; i < len; i++) {
1143
+ obj[foreignKeys[i]] = data[0][primaryKeys[i]];
1144
+ }
1145
+ const relatedWheres = orchidCore.toArray(params.add);
1146
+ const count = await pqb._queryUpdate(
1147
+ t.orWhere(...relatedWheres),
1148
+ obj
1149
+ );
1150
+ if (count < relatedWheres.length) {
1151
+ throw new pqb.OrchidOrmInternalError(
1152
+ query,
1153
+ `Expected to find at least ${relatedWheres.length} record(s) based on \`add\` conditions, but found ${count}`
1154
+ );
1155
+ }
1156
+ }
1134
1157
  if (params.disconnect || params.set) {
1135
1158
  const obj = {};
1136
1159
  for (const foreignKey of foreignKeys) {
@@ -1242,10 +1265,11 @@ const makeHasAndBelongsToManyMethod = (tableConfig, table, qb, relation, relatio
1242
1265
  baseQuery.baseQuery = baseQuery;
1243
1266
  baseQuery.table = joinTable;
1244
1267
  const shape = {};
1268
+ const primaryKeysShape = {};
1245
1269
  for (let i = 0; i < len; i++) {
1246
- shape[foreignKeys[i]] = removeColumnName(
1247
- table.shape[primaryKeys[i]]
1248
- );
1270
+ const pk = primaryKeys[i];
1271
+ shape[foreignKeys[i]] = removeColumnName(table.shape[pk]);
1272
+ primaryKeysShape[pk] = table.shape[pk];
1249
1273
  }
1250
1274
  for (let i = 0; i < throughLen; i++) {
1251
1275
  shape[throughForeignKeys[i]] = removeColumnName(
@@ -1283,7 +1307,8 @@ const makeHasAndBelongsToManyMethod = (tableConfig, table, qb, relation, relatio
1283
1307
  throughPrimaryKeys,
1284
1308
  foreignKeysFull,
1285
1309
  throughForeignKeysFull,
1286
- throughPrimaryKeysFull
1310
+ throughPrimaryKeysFull,
1311
+ primaryKeysShape
1287
1312
  };
1288
1313
  const joinQuery = (joiningQuery, tableAs, foreignAs, joinedShapes) => {
1289
1314
  const cloned = joiningQuery.clone();
@@ -1580,7 +1605,7 @@ const nestedInsert = ({
1580
1605
  const nestedUpdate = (state) => {
1581
1606
  const len = state.primaryKeys.length;
1582
1607
  const throughLen = state.throughPrimaryKeys.length;
1583
- return async (_, data, params) => {
1608
+ return async (query, data, params) => {
1584
1609
  if (params.create) {
1585
1610
  const idsRows = await pqb._queryCreateMany(
1586
1611
  pqb._queryRows(state.relatedTableQuery.select(...state.throughPrimaryKeys)),
@@ -1628,6 +1653,58 @@ const nestedUpdate = (state) => {
1628
1653
  params.update.data
1629
1654
  );
1630
1655
  }
1656
+ if (params.add) {
1657
+ const as = query.table;
1658
+ const relatedWheres = orchidCore.toArray(params.add);
1659
+ const joinTableColumns = [
1660
+ ...state.foreignKeys,
1661
+ ...state.throughForeignKeys
1662
+ ];
1663
+ try {
1664
+ const count = await state.joinTableQuery.insertManyFrom(
1665
+ pqb._querySelect(
1666
+ state.relatedTableQuery.orWhere(...relatedWheres),
1667
+ [
1668
+ Object.fromEntries([
1669
+ ...state.primaryKeys.map((key, i) => [
1670
+ state.foreignKeys[i],
1671
+ as + "." + (state.primaryKeysShape[key].data.name || key)
1672
+ ]),
1673
+ ...state.throughForeignKeys.map((key, i) => [
1674
+ key,
1675
+ state.throughPrimaryKeys[i]
1676
+ ])
1677
+ ])
1678
+ ]
1679
+ ).joinData(
1680
+ as,
1681
+ () => Object.fromEntries(
1682
+ state.primaryKeys.map((key) => [
1683
+ key,
1684
+ state.primaryKeysShape[key]
1685
+ ])
1686
+ ),
1687
+ data.map((x) => orchidCore.pick(x, state.primaryKeys))
1688
+ )
1689
+ ).onConflict(joinTableColumns).merge([state.foreignKeys[0]]);
1690
+ if (count < data.length * relatedWheres.length) {
1691
+ throw new pqb.OrchidOrmInternalError(
1692
+ query,
1693
+ `Expected to find at least ${relatedWheres.length} record(s) based on \`connect\` conditions, but found ${count / data.length}`
1694
+ );
1695
+ }
1696
+ } catch (err) {
1697
+ if (err.code === "42P10") {
1698
+ throw new pqb.OrchidOrmInternalError(
1699
+ query,
1700
+ `"${state.joinTableQuery.table}" must have a primary key or a unique index on columns (${joinTableColumns.join(
1701
+ ", "
1702
+ )}) for this kind of query.`
1703
+ );
1704
+ }
1705
+ throw err;
1706
+ }
1707
+ }
1631
1708
  if (params.disconnect) {
1632
1709
  await pqb._queryDelete(
1633
1710
  queryJoinTable(state, data, params.disconnect)