orchid-orm 1.3.15 → 1.3.16

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.esm.js CHANGED
@@ -1,4 +1,4 @@
1
- import { getColumnTypes, isQueryReturnsAll, addQueryOn, getQueryAs, toSqlCacheKey, pushQueryValue, NotFoundError, relationQueryKey, Db, Adapter, anyShape, columnTypes, getClonedQueryData } from 'pqb';
1
+ import { getColumnTypes, addQueryOn, VirtualColumn, pushQueryValue, isQueryReturnsAll, getQueryAs, toSqlCacheKey, NotFoundError, relationQueryKey, Db, Adapter, anyShape, columnTypes, getClonedQueryData } from 'pqb';
2
2
 
3
3
  const createModel = (options) => {
4
4
  return class Model {
@@ -47,142 +47,195 @@ const createModel = (options) => {
47
47
  };
48
48
  };
49
49
 
50
- const makeBelongsToMethod = (relation, query) => {
50
+ class BelongsToVirtualColumn extends VirtualColumn {
51
+ constructor(key, state) {
52
+ super();
53
+ this.key = key;
54
+ this.state = state;
55
+ this.nestedInsert = nestedInsert$3(this.state);
56
+ this.nestedUpdate = nestedUpdate$3(this.state);
57
+ }
58
+ create(q, ctx, item, rowIndex) {
59
+ const {
60
+ key,
61
+ state: { foreignKey, primaryKey }
62
+ } = this;
63
+ let columnIndex = ctx.columns.get(foreignKey);
64
+ if (columnIndex === void 0) {
65
+ ctx.columns.set(foreignKey, columnIndex = ctx.columns.size);
66
+ }
67
+ const store = ctx;
68
+ if (!store.belongsTo)
69
+ store.belongsTo = {};
70
+ const values = [rowIndex, columnIndex, item[key]];
71
+ if (store.belongsTo[key]) {
72
+ store.belongsTo[key].push(values);
73
+ return;
74
+ }
75
+ const relationData = [values];
76
+ store.belongsTo[key] = relationData;
77
+ q.query.wrapInTransaction = true;
78
+ pushQueryValue(q, "beforeCreate", async (q2) => {
79
+ const inserted = await this.nestedInsert(
80
+ q2,
81
+ relationData.map(([, , data]) => data)
82
+ );
83
+ const { values: values2 } = q2.query;
84
+ relationData.forEach(([rowIndex2, columnIndex2], index) => {
85
+ values2[rowIndex2][columnIndex2] = inserted[index][primaryKey];
86
+ });
87
+ });
88
+ }
89
+ update(q, ctx, set) {
90
+ q.query.wrapInTransaction = true;
91
+ const data = set[this.key];
92
+ if (this.nestedUpdate(q, set, data, ctx)) {
93
+ ctx.willSetKeys = true;
94
+ }
95
+ }
96
+ }
97
+ const makeBelongsToMethod = (relation, relationName, query) => {
51
98
  const { primaryKey, foreignKey } = relation.options;
99
+ const state = { query, primaryKey, foreignKey };
52
100
  return {
53
101
  returns: "one",
54
102
  method: (params) => {
55
103
  return query.findBy({ [primaryKey]: params[foreignKey] });
56
104
  },
57
- nestedInsert: async (q, data) => {
58
- const connectOrCreate = data.filter(
59
- (item) => Boolean(item.connectOrCreate)
105
+ virtualColumn: new BelongsToVirtualColumn(relationName, state),
106
+ joinQuery(fromQuery, toQuery) {
107
+ return addQueryOn(toQuery, fromQuery, toQuery, primaryKey, foreignKey);
108
+ },
109
+ reverseJoin(fromQuery, toQuery) {
110
+ return addQueryOn(fromQuery, toQuery, fromQuery, foreignKey, primaryKey);
111
+ },
112
+ primaryKey
113
+ };
114
+ };
115
+ const nestedInsert$3 = ({ query, primaryKey }) => {
116
+ return async (q, data) => {
117
+ const connectOrCreate = data.filter(
118
+ (item) => Boolean(item.connectOrCreate)
119
+ );
120
+ const t = query.transacting(q);
121
+ let connectOrCreated;
122
+ if (connectOrCreate.length) {
123
+ connectOrCreated = await Promise.all(
124
+ connectOrCreate.map(
125
+ (item) => t.findBy(item.connectOrCreate.where)._takeOptional()
126
+ )
60
127
  );
61
- const t = query.transacting(q);
62
- let connectOrCreated;
63
- if (connectOrCreate.length) {
64
- connectOrCreated = await Promise.all(
65
- connectOrCreate.map(
66
- (item) => t.findBy(item.connectOrCreate.where)._takeOptional()
67
- )
68
- );
69
- } else {
70
- connectOrCreated = [];
71
- }
72
- let connectOrCreatedI = 0;
73
- const create = data.filter(
74
- (item) => {
75
- if (item.connectOrCreate) {
76
- return !connectOrCreated[connectOrCreatedI++];
77
- } else {
78
- return Boolean(item.create);
79
- }
128
+ } else {
129
+ connectOrCreated = [];
130
+ }
131
+ let connectOrCreatedI = 0;
132
+ const create = data.filter(
133
+ (item) => {
134
+ if (item.connectOrCreate) {
135
+ return !connectOrCreated[connectOrCreatedI++];
136
+ } else {
137
+ return Boolean(item.create);
80
138
  }
81
- );
82
- let created;
83
- if (create.length) {
84
- created = await t.select(primaryKey)._createMany(
85
- create.map(
86
- (item) => "create" in item ? item.create : item.connectOrCreate.create
87
- )
88
- );
89
- } else {
90
- created = [];
91
139
  }
92
- const connect = data.filter(
93
- (item) => Boolean(item.connect)
140
+ );
141
+ let created;
142
+ if (create.length) {
143
+ created = await t.select(primaryKey)._createMany(
144
+ create.map(
145
+ (item) => "create" in item ? item.create : item.connectOrCreate.create
146
+ )
94
147
  );
95
- let connected;
96
- if (connect.length) {
97
- connected = await Promise.all(
98
- connect.map((item) => t.findBy(item.connect)._take())
99
- );
100
- } else {
101
- connected = [];
102
- }
103
- let createdI = 0;
104
- let connectedI = 0;
105
- connectOrCreatedI = 0;
106
- return data.map(
107
- (item) => item.connectOrCreate ? connectOrCreated[connectOrCreatedI++] || created[createdI++] : item.connect ? connected[connectedI++] : created[createdI++]
148
+ } else {
149
+ created = [];
150
+ }
151
+ const connect = data.filter(
152
+ (item) => Boolean(item.connect)
153
+ );
154
+ let connected;
155
+ if (connect.length) {
156
+ connected = await Promise.all(
157
+ connect.map((item) => t.findBy(item.connect)._take())
108
158
  );
109
- },
110
- nestedUpdate: (q, update, params, state) => {
111
- var _a, _b;
112
- if (params.upsert && isQueryReturnsAll(q)) {
113
- throw new Error("`upsert` option is not allowed in a batch update");
114
- }
115
- let idForDelete;
116
- q._beforeUpdate(async (q2) => {
117
- if (params.disconnect) {
118
- update[foreignKey] = null;
119
- } else if (params.set) {
120
- if (primaryKey in params.set) {
121
- update[foreignKey] = params.set[primaryKey];
122
- } else {
123
- update[foreignKey] = await query.transacting(q2)._findBy(params.set)._get(primaryKey);
124
- }
125
- } else if (params.create) {
126
- update[foreignKey] = await query.transacting(q2)._get(primaryKey)._create(params.create);
127
- } else if (params.delete) {
128
- const selectQuery = q2.transacting(q2);
129
- selectQuery.query.type = void 0;
130
- idForDelete = await selectQuery._getOptional(foreignKey);
131
- update[foreignKey] = null;
132
- }
133
- });
134
- const { upsert } = params;
135
- if (upsert || params.update || params.delete) {
136
- if (!((_a = q.query.select) == null ? void 0 : _a.includes("*")) && !((_b = q.query.select) == null ? void 0 : _b.includes(foreignKey))) {
137
- q._select(foreignKey);
159
+ } else {
160
+ connected = [];
161
+ }
162
+ let createdI = 0;
163
+ let connectedI = 0;
164
+ connectOrCreatedI = 0;
165
+ return data.map(
166
+ (item) => item.connectOrCreate ? connectOrCreated[connectOrCreatedI++] || created[createdI++] : item.connect ? connected[connectedI++] : created[createdI++]
167
+ );
168
+ };
169
+ };
170
+ const nestedUpdate$3 = ({ query, primaryKey, foreignKey }) => {
171
+ return (q, update, params, state) => {
172
+ var _a, _b;
173
+ if (params.upsert && isQueryReturnsAll(q)) {
174
+ throw new Error("`upsert` option is not allowed in a batch update");
175
+ }
176
+ let idForDelete;
177
+ q._beforeUpdate(async (q2) => {
178
+ if (params.disconnect) {
179
+ update[foreignKey] = null;
180
+ } else if (params.set) {
181
+ if (primaryKey in params.set) {
182
+ update[foreignKey] = params.set[primaryKey];
183
+ } else {
184
+ update[foreignKey] = await query.transacting(q2)._findBy(params.set)._get(primaryKey);
138
185
  }
186
+ } else if (params.create) {
187
+ update[foreignKey] = await query.transacting(q2)._get(primaryKey)._create(params.create);
188
+ } else if (params.delete) {
189
+ const selectQuery = q2.transacting(q2);
190
+ selectQuery.query.type = void 0;
191
+ idForDelete = await selectQuery._getOptional(foreignKey);
192
+ update[foreignKey] = null;
139
193
  }
140
- if (upsert) {
141
- if (!state.updateLater) {
142
- state.updateLater = {};
143
- state.updateLaterPromises = [];
194
+ });
195
+ const { upsert } = params;
196
+ if (upsert || params.update || params.delete) {
197
+ if (!((_a = q.query.select) == null ? void 0 : _a.includes("*")) && !((_b = q.query.select) == null ? void 0 : _b.includes(foreignKey))) {
198
+ q._select(foreignKey);
199
+ }
200
+ }
201
+ if (upsert) {
202
+ if (!state.updateLater) {
203
+ state.updateLater = {};
204
+ state.updateLaterPromises = [];
205
+ }
206
+ const { handleResult } = q.query;
207
+ q.query.handleResult = async (q2, queryResult) => {
208
+ const data = await handleResult(q2, queryResult);
209
+ const id = data[0][foreignKey];
210
+ if (id !== null) {
211
+ await query.transacting(q2)._findBy({ [primaryKey]: id })._update(upsert.update);
212
+ } else {
213
+ state.updateLaterPromises.push(
214
+ query.transacting(q2)._select(primaryKey)._create(upsert.create).then((result) => {
215
+ state.updateLater[foreignKey] = result[primaryKey];
216
+ })
217
+ );
144
218
  }
145
- const { handleResult } = q.query;
146
- q.query.handleResult = async (q2, queryResult) => {
147
- const data = await handleResult(q2, queryResult);
148
- const id = data[0][foreignKey];
149
- if (id !== null) {
150
- await query.transacting(q2)._findBy({ [primaryKey]: id })._update(upsert.update);
151
- } else {
152
- state.updateLaterPromises.push(
153
- query.transacting(q2)._select(primaryKey)._create(upsert.create).then((result) => {
154
- state.updateLater[foreignKey] = result[primaryKey];
155
- })
156
- );
157
- }
158
- return data;
159
- };
160
- } else if (params.delete || params.update) {
161
- q._afterQuery(async (q2, data) => {
162
- const id = params.delete ? idForDelete : Array.isArray(data) ? data.length === 0 ? null : {
163
- in: data.map((item) => item[foreignKey]).filter((id2) => id2 !== null)
164
- } : data[foreignKey];
165
- if (id !== void 0 && id !== null) {
166
- const t = query.transacting(q2)._findBy({
167
- [primaryKey]: id
168
- });
169
- if (params.delete) {
170
- await t._delete();
171
- } else if (params.update) {
172
- await t._update(params.update);
173
- }
219
+ return data;
220
+ };
221
+ } else if (params.delete || params.update) {
222
+ q._afterQuery(async (q2, data) => {
223
+ const id = params.delete ? idForDelete : Array.isArray(data) ? data.length === 0 ? null : {
224
+ in: data.map((item) => item[foreignKey]).filter((id2) => id2 !== null)
225
+ } : data[foreignKey];
226
+ if (id !== void 0 && id !== null) {
227
+ const t = query.transacting(q2)._findBy({
228
+ [primaryKey]: id
229
+ });
230
+ if (params.delete) {
231
+ await t._delete();
232
+ } else if (params.update) {
233
+ await t._update(params.update);
174
234
  }
175
- });
176
- }
177
- return !params.update && !params.upsert;
178
- },
179
- joinQuery(fromQuery, toQuery) {
180
- return addQueryOn(toQuery, fromQuery, toQuery, primaryKey, foreignKey);
181
- },
182
- reverseJoin(fromQuery, toQuery) {
183
- return addQueryOn(fromQuery, toQuery, fromQuery, foreignKey, primaryKey);
184
- },
185
- primaryKey
235
+ }
236
+ });
237
+ }
238
+ return !params.update && !params.upsert;
186
239
  };
187
240
  };
188
241
 
@@ -192,6 +245,52 @@ const getThroughRelation = (model, through) => {
192
245
  const getSourceRelation = (throughRelation, source) => {
193
246
  return throughRelation.model.relations[source];
194
247
  };
248
+ const hasRelationHandleCreate = (q, ctx, item, rowIndex, key, primaryKey, nestedInsert) => {
249
+ const value = item[key];
250
+ if ((!value.create || Array.isArray(value.create) && value.create.length === 0) && (!value.connect || Array.isArray(value.connect) && value.connect.length === 0) && (!value.connectOrCreate || Array.isArray(value.connectOrCreate) && value.connectOrCreate.length === 0))
251
+ return;
252
+ const store = ctx;
253
+ if (!store.hasRelation)
254
+ store.hasRelation = {};
255
+ const values = [rowIndex, value];
256
+ if (store.hasRelation[key]) {
257
+ store.hasRelation[key].push(values);
258
+ return;
259
+ }
260
+ q.query.wrapInTransaction = true;
261
+ ctx.returnTypeAll = true;
262
+ ctx.requiredReturning[primaryKey] = true;
263
+ const relationData = [values];
264
+ store.hasRelation[key] = relationData;
265
+ pushQueryValue(q, "afterCreate", async (q2) => {
266
+ const { resultAll } = ctx;
267
+ return nestedInsert(
268
+ q2,
269
+ relationData.map(([rowIndex2, data]) => [
270
+ resultAll[rowIndex2],
271
+ data
272
+ ])
273
+ );
274
+ });
275
+ };
276
+ const hasRelationHandleUpdate = (q, ctx, set, key, primaryKey, nestedUpdate) => {
277
+ var _a, _b;
278
+ const value = set[key];
279
+ 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))
280
+ return;
281
+ if (!((_a = q.query.select) == null ? void 0 : _a.includes("*")) && !((_b = q.query.select) == null ? void 0 : _b.includes(primaryKey))) {
282
+ q._select(primaryKey);
283
+ }
284
+ q.query.wrapInTransaction = true;
285
+ ctx.returnTypeAll = true;
286
+ pushQueryValue(q, "afterUpdate", (q2) => {
287
+ return nestedUpdate(
288
+ q2,
289
+ ctx.resultAll,
290
+ value
291
+ );
292
+ });
293
+ };
195
294
 
196
295
  var __defProp$4 = Object.defineProperty;
197
296
  var __defProps$2 = Object.defineProperties;
@@ -212,6 +311,36 @@ var __spreadValues$4 = (a, b) => {
212
311
  return a;
213
312
  };
214
313
  var __spreadProps$2 = (a, b) => __defProps$2(a, __getOwnPropDescs$2(b));
314
+ class HasOneVirtualColumn extends VirtualColumn {
315
+ constructor(key, state) {
316
+ super();
317
+ this.key = key;
318
+ this.state = state;
319
+ this.nestedInsert = nestedInsert$2(state);
320
+ this.nestedUpdate = nestedUpdate$2(state);
321
+ }
322
+ create(q, ctx, item, rowIndex) {
323
+ hasRelationHandleCreate(
324
+ q,
325
+ ctx,
326
+ item,
327
+ rowIndex,
328
+ this.key,
329
+ this.state.primaryKey,
330
+ this.nestedInsert
331
+ );
332
+ }
333
+ update(q, ctx, set) {
334
+ hasRelationHandleUpdate(
335
+ q,
336
+ ctx,
337
+ set,
338
+ this.key,
339
+ this.state.primaryKey,
340
+ this.nestedUpdate
341
+ );
342
+ }
343
+ }
215
344
  const makeHasOneMethod = (model, relation, relationName, query) => {
216
345
  if (relation.options.required) {
217
346
  query._take();
@@ -233,8 +362,6 @@ const makeHasOneMethod = (model, relation, relationName, query) => {
233
362
  whereExistsCallback
234
363
  );
235
364
  },
236
- nestedInsert: void 0,
237
- nestedUpdate: void 0,
238
365
  joinQuery(fromQuery, toQuery) {
239
366
  return toQuery.whereExists(
240
367
  throughRelation.joinQuery(fromQuery, throughRelation.query),
@@ -263,6 +390,7 @@ const makeHasOneMethod = (model, relation, relationName, query) => {
263
390
  };
264
391
  }
265
392
  const { primaryKey, foreignKey } = relation.options;
393
+ const state = { query, primaryKey, foreignKey };
266
394
  const fromQuerySelect = [{ selectAs: { [foreignKey]: primaryKey } }];
267
395
  return {
268
396
  returns: "one",
@@ -270,75 +398,7 @@ const makeHasOneMethod = (model, relation, relationName, query) => {
270
398
  const values = { [foreignKey]: params[primaryKey] };
271
399
  return query.where(values)._defaults(values);
272
400
  },
273
- nestedInsert: async (q, data) => {
274
- const connect = data.filter(
275
- (item) => Boolean(item[1].connect || item[1].connectOrCreate)
276
- );
277
- const t = query.transacting(q);
278
- let connected;
279
- if (connect.length) {
280
- connected = await Promise.all(
281
- connect.map(([selfData, item]) => {
282
- const data2 = { [foreignKey]: selfData[primaryKey] };
283
- return "connect" in item ? t.where(item.connect)._updateOrThrow(data2) : t.where(item.connectOrCreate.where)._update(data2);
284
- })
285
- );
286
- } else {
287
- connected = [];
288
- }
289
- let connectedI = 0;
290
- const create = data.filter(
291
- (item) => {
292
- if (item[1].connectOrCreate) {
293
- return !connected[connectedI++];
294
- }
295
- return Boolean(item[1].create);
296
- }
297
- );
298
- if (create.length) {
299
- await t._count()._createMany(
300
- create.map(([selfData, item]) => __spreadValues$4({
301
- [foreignKey]: selfData[primaryKey]
302
- }, "create" in item ? item.create : item.connectOrCreate.create))
303
- );
304
- }
305
- },
306
- nestedUpdate: async (q, data, params) => {
307
- if ((params.set || params.create || params.upsert) && isQueryReturnsAll(q)) {
308
- const key = params.set ? "set" : params.create ? "create" : "upsert";
309
- throw new Error(`\`${key}\` option is not allowed in a batch update`);
310
- }
311
- const t = query.transacting(q);
312
- const ids = data.map((item) => item[primaryKey]);
313
- const currentRelationsQuery = t.where({
314
- [foreignKey]: { in: ids }
315
- });
316
- if (params.create || params.disconnect || params.set) {
317
- await currentRelationsQuery._update({ [foreignKey]: null });
318
- if (params.create) {
319
- await t._count()._create(__spreadProps$2(__spreadValues$4({}, params.create), {
320
- [foreignKey]: data[0][primaryKey]
321
- }));
322
- }
323
- if (params.set) {
324
- await t._where(params.set)._update({ [foreignKey]: data[0][primaryKey] });
325
- }
326
- } else if (params.update) {
327
- await currentRelationsQuery._update(params.update);
328
- } else if (params.delete) {
329
- await currentRelationsQuery._delete();
330
- } else if (params.upsert) {
331
- const { update, create } = params.upsert;
332
- const updatedIds = await currentRelationsQuery._pluck(foreignKey)._update(update);
333
- if (updatedIds.length < ids.length) {
334
- await t.createMany(
335
- ids.filter((id) => !updatedIds.includes(id)).map((id) => __spreadProps$2(__spreadValues$4({}, create), {
336
- [foreignKey]: id
337
- }))
338
- );
339
- }
340
- }
341
- },
401
+ virtualColumn: new HasOneVirtualColumn(relationName, state),
342
402
  joinQuery(fromQuery, toQuery) {
343
403
  return addQueryOn(toQuery, fromQuery, toQuery, foreignKey, primaryKey);
344
404
  },
@@ -355,6 +415,79 @@ const makeHasOneMethod = (model, relation, relationName, query) => {
355
415
  }
356
416
  };
357
417
  };
418
+ const nestedInsert$2 = ({ query, primaryKey, foreignKey }) => {
419
+ return async (q, data) => {
420
+ const connect = data.filter(
421
+ (item) => Boolean(item[1].connect || item[1].connectOrCreate)
422
+ );
423
+ const t = query.transacting(q);
424
+ let connected;
425
+ if (connect.length) {
426
+ connected = await Promise.all(
427
+ connect.map(([selfData, item]) => {
428
+ const data2 = { [foreignKey]: selfData[primaryKey] };
429
+ return "connect" in item ? t.where(item.connect)._updateOrThrow(data2) : t.where(item.connectOrCreate.where)._update(data2);
430
+ })
431
+ );
432
+ } else {
433
+ connected = [];
434
+ }
435
+ let connectedI = 0;
436
+ const create = data.filter(
437
+ (item) => {
438
+ if (item[1].connectOrCreate) {
439
+ return !connected[connectedI++];
440
+ }
441
+ return Boolean(item[1].create);
442
+ }
443
+ );
444
+ if (create.length) {
445
+ await t._count()._createMany(
446
+ create.map(([selfData, item]) => __spreadValues$4({
447
+ [foreignKey]: selfData[primaryKey]
448
+ }, "create" in item ? item.create : item.connectOrCreate.create))
449
+ );
450
+ }
451
+ };
452
+ };
453
+ const nestedUpdate$2 = ({ query, primaryKey, foreignKey }) => {
454
+ return async (q, data, params) => {
455
+ if ((params.set || params.create || params.upsert) && isQueryReturnsAll(q)) {
456
+ const key = params.set ? "set" : params.create ? "create" : "upsert";
457
+ throw new Error(`\`${key}\` option is not allowed in a batch update`);
458
+ }
459
+ const t = query.transacting(q);
460
+ const ids = data.map((item) => item[primaryKey]);
461
+ const currentRelationsQuery = t.where({
462
+ [foreignKey]: { in: ids }
463
+ });
464
+ if (params.create || params.disconnect || params.set) {
465
+ await currentRelationsQuery._update({ [foreignKey]: null });
466
+ if (params.create) {
467
+ await t._count()._create(__spreadProps$2(__spreadValues$4({}, params.create), {
468
+ [foreignKey]: data[0][primaryKey]
469
+ }));
470
+ }
471
+ if (params.set) {
472
+ await t._where(params.set)._update({ [foreignKey]: data[0][primaryKey] });
473
+ }
474
+ } else if (params.update) {
475
+ await currentRelationsQuery._update(params.update);
476
+ } else if (params.delete) {
477
+ await currentRelationsQuery._delete();
478
+ } else if (params.upsert) {
479
+ const { update, create } = params.upsert;
480
+ const updatedIds = await currentRelationsQuery._pluck(foreignKey)._update(update);
481
+ if (updatedIds.length < ids.length) {
482
+ await t.createMany(
483
+ ids.filter((id) => !updatedIds.includes(id)).map((id) => __spreadProps$2(__spreadValues$4({}, create), {
484
+ [foreignKey]: id
485
+ }))
486
+ );
487
+ }
488
+ }
489
+ };
490
+ };
358
491
 
359
492
  var __defProp$3 = Object.defineProperty;
360
493
  var __defProps$1 = Object.defineProperties;
@@ -375,6 +508,36 @@ var __spreadValues$3 = (a, b) => {
375
508
  return a;
376
509
  };
377
510
  var __spreadProps$1 = (a, b) => __defProps$1(a, __getOwnPropDescs$1(b));
511
+ class HasManyVirtualColumn extends VirtualColumn {
512
+ constructor(key, state) {
513
+ super();
514
+ this.key = key;
515
+ this.state = state;
516
+ this.nestedInsert = nestedInsert$1(state);
517
+ this.nestedUpdate = nestedUpdate$1(state);
518
+ }
519
+ create(q, ctx, item, rowIndex) {
520
+ hasRelationHandleCreate(
521
+ q,
522
+ ctx,
523
+ item,
524
+ rowIndex,
525
+ this.key,
526
+ this.state.primaryKey,
527
+ this.nestedInsert
528
+ );
529
+ }
530
+ update(q, ctx, set) {
531
+ hasRelationHandleUpdate(
532
+ q,
533
+ ctx,
534
+ set,
535
+ this.key,
536
+ this.state.primaryKey,
537
+ this.nestedUpdate
538
+ );
539
+ }
540
+ }
378
541
  const makeHasManyMethod = (model, relation, relationName, query) => {
379
542
  if ("through" in relation.options) {
380
543
  const { through, source } = relation.options;
@@ -395,8 +558,6 @@ const makeHasManyMethod = (model, relation, relationName, query) => {
395
558
  whereExistsCallback
396
559
  );
397
560
  },
398
- nestedInsert: void 0,
399
- nestedUpdate: void 0,
400
561
  joinQuery(fromQuery, toQuery) {
401
562
  return toQuery.whereExists(
402
563
  throughRelation.joinQuery(fromQuery, throughRelation.query),
@@ -425,6 +586,7 @@ const makeHasManyMethod = (model, relation, relationName, query) => {
425
586
  };
426
587
  }
427
588
  const { primaryKey, foreignKey } = relation.options;
589
+ const state = { query, primaryKey, foreignKey };
428
590
  const fromQuerySelect = [{ selectAs: { [foreignKey]: primaryKey } }];
429
591
  return {
430
592
  returns: "many",
@@ -432,117 +594,7 @@ const makeHasManyMethod = (model, relation, relationName, query) => {
432
594
  const values = { [foreignKey]: params[primaryKey] };
433
595
  return query.where(values)._defaults(values);
434
596
  },
435
- nestedInsert: async (q, data) => {
436
- const connect = data.filter(
437
- (item) => Boolean(item[1].connect)
438
- );
439
- const t = query.transacting(q);
440
- if (connect.length) {
441
- await Promise.all(
442
- connect.flatMap(
443
- ([selfData, { connect: connect2 }]) => t.or(...connect2)._updateOrThrow({ [foreignKey]: selfData[primaryKey] })
444
- )
445
- );
446
- }
447
- const connectOrCreate = data.filter(
448
- (item) => Boolean(item[1].connectOrCreate)
449
- );
450
- let connected;
451
- if (connectOrCreate.length) {
452
- connected = await Promise.all(
453
- connectOrCreate.flatMap(
454
- ([selfData, { connectOrCreate: connectOrCreate2 }]) => connectOrCreate2.map(
455
- (item) => t.where(item.where)._update({
456
- [foreignKey]: selfData[primaryKey]
457
- })
458
- )
459
- )
460
- );
461
- } else {
462
- connected = [];
463
- }
464
- let connectedI = 0;
465
- const create = data.filter(
466
- (item) => {
467
- if (item[1].connectOrCreate) {
468
- const length = item[1].connectOrCreate.length;
469
- connectedI += length;
470
- for (let i = length; i > 0; i--) {
471
- if (connected[connectedI - i] === 0)
472
- return true;
473
- }
474
- }
475
- return Boolean(item[1].create);
476
- }
477
- );
478
- connectedI = 0;
479
- if (create.length) {
480
- await t._createMany(
481
- create.flatMap(
482
- ([selfData, { create: create2 = [], connectOrCreate: connectOrCreate2 = [] }]) => {
483
- return [
484
- ...create2.map((item) => __spreadValues$3({
485
- [foreignKey]: selfData[primaryKey]
486
- }, item)),
487
- ...connectOrCreate2.filter(() => connected[connectedI++] === 0).map((item) => __spreadValues$3({
488
- [foreignKey]: selfData[primaryKey]
489
- }, item.create))
490
- ];
491
- }
492
- )
493
- );
494
- }
495
- },
496
- nestedUpdate: async (q, data, params) => {
497
- var _a;
498
- if ((params.set || params.create) && isQueryReturnsAll(q)) {
499
- const key = params.set ? "set" : "create";
500
- throw new Error(`\`${key}\` option is not allowed in a batch update`);
501
- }
502
- const t = query.transacting(q);
503
- if (params.create) {
504
- await t._count()._createMany(
505
- params.create.map((create) => __spreadProps$1(__spreadValues$3({}, create), {
506
- [foreignKey]: data[0][primaryKey]
507
- }))
508
- );
509
- delete t.query[toSqlCacheKey];
510
- }
511
- if (params.disconnect || params.set) {
512
- await t.where(
513
- getWhereForNestedUpdate(
514
- data,
515
- params.disconnect,
516
- primaryKey,
517
- foreignKey
518
- )
519
- )._update({ [foreignKey]: null });
520
- if (params.set) {
521
- delete t.query[toSqlCacheKey];
522
- await t.where(
523
- Array.isArray(params.set) ? {
524
- OR: params.set
525
- } : params.set
526
- )._update({ [foreignKey]: data[0][primaryKey] });
527
- }
528
- }
529
- if (params.delete || params.update) {
530
- delete t.query[toSqlCacheKey];
531
- const q2 = t._where(
532
- getWhereForNestedUpdate(
533
- data,
534
- params.delete || ((_a = params.update) == null ? void 0 : _a.where),
535
- primaryKey,
536
- foreignKey
537
- )
538
- );
539
- if (params.delete) {
540
- await q2._delete();
541
- } else if (params.update) {
542
- await q2._update(params.update.data);
543
- }
544
- }
545
- },
597
+ virtualColumn: new HasManyVirtualColumn(relationName, state),
546
598
  joinQuery(fromQuery, toQuery) {
547
599
  return addQueryOn(toQuery, fromQuery, toQuery, foreignKey, primaryKey);
548
600
  },
@@ -572,6 +624,119 @@ const getWhereForNestedUpdate = (data, params, primaryKey, foreignKey) => {
572
624
  }
573
625
  return where;
574
626
  };
627
+ const nestedInsert$1 = ({ query, primaryKey, foreignKey }) => {
628
+ return async (q, data) => {
629
+ const connect = data.filter(
630
+ (item) => Boolean(item[1].connect)
631
+ );
632
+ const t = query.transacting(q);
633
+ if (connect.length) {
634
+ await Promise.all(
635
+ connect.flatMap(
636
+ ([selfData, { connect: connect2 }]) => t.or(...connect2)._updateOrThrow({ [foreignKey]: selfData[primaryKey] })
637
+ )
638
+ );
639
+ }
640
+ const connectOrCreate = data.filter(
641
+ (item) => Boolean(item[1].connectOrCreate)
642
+ );
643
+ let connected;
644
+ if (connectOrCreate.length) {
645
+ connected = await Promise.all(
646
+ connectOrCreate.flatMap(
647
+ ([selfData, { connectOrCreate: connectOrCreate2 }]) => connectOrCreate2.map(
648
+ (item) => t.where(item.where)._update({
649
+ [foreignKey]: selfData[primaryKey]
650
+ })
651
+ )
652
+ )
653
+ );
654
+ } else {
655
+ connected = [];
656
+ }
657
+ let connectedI = 0;
658
+ const create = data.filter(
659
+ (item) => {
660
+ if (item[1].connectOrCreate) {
661
+ const length = item[1].connectOrCreate.length;
662
+ connectedI += length;
663
+ for (let i = length; i > 0; i--) {
664
+ if (connected[connectedI - i] === 0)
665
+ return true;
666
+ }
667
+ }
668
+ return Boolean(item[1].create);
669
+ }
670
+ );
671
+ connectedI = 0;
672
+ if (create.length) {
673
+ await t._createMany(
674
+ create.flatMap(([selfData, { create: create2 = [], connectOrCreate: connectOrCreate2 = [] }]) => {
675
+ return [
676
+ ...create2.map((item) => __spreadValues$3({
677
+ [foreignKey]: selfData[primaryKey]
678
+ }, item)),
679
+ ...connectOrCreate2.filter(() => connected[connectedI++] === 0).map((item) => __spreadValues$3({
680
+ [foreignKey]: selfData[primaryKey]
681
+ }, item.create))
682
+ ];
683
+ })
684
+ );
685
+ }
686
+ };
687
+ };
688
+ const nestedUpdate$1 = ({ query, primaryKey, foreignKey }) => {
689
+ return async (q, data, params) => {
690
+ var _a;
691
+ if ((params.set || params.create) && isQueryReturnsAll(q)) {
692
+ const key = params.set ? "set" : "create";
693
+ throw new Error(`\`${key}\` option is not allowed in a batch update`);
694
+ }
695
+ const t = query.transacting(q);
696
+ if (params.create) {
697
+ await t._count()._createMany(
698
+ params.create.map((create) => __spreadProps$1(__spreadValues$3({}, create), {
699
+ [foreignKey]: data[0][primaryKey]
700
+ }))
701
+ );
702
+ delete t.query[toSqlCacheKey];
703
+ }
704
+ if (params.disconnect || params.set) {
705
+ await t.where(
706
+ getWhereForNestedUpdate(
707
+ data,
708
+ params.disconnect,
709
+ primaryKey,
710
+ foreignKey
711
+ )
712
+ )._update({ [foreignKey]: null });
713
+ if (params.set) {
714
+ delete t.query[toSqlCacheKey];
715
+ await t.where(
716
+ Array.isArray(params.set) ? {
717
+ OR: params.set
718
+ } : params.set
719
+ )._update({ [foreignKey]: data[0][primaryKey] });
720
+ }
721
+ }
722
+ if (params.delete || params.update) {
723
+ delete t.query[toSqlCacheKey];
724
+ const q2 = t._where(
725
+ getWhereForNestedUpdate(
726
+ data,
727
+ params.delete || ((_a = params.update) == null ? void 0 : _a.where),
728
+ primaryKey,
729
+ foreignKey
730
+ )
731
+ );
732
+ if (params.delete) {
733
+ await q2._delete();
734
+ } else if (params.update) {
735
+ await q2._update(params.update.data);
736
+ }
737
+ }
738
+ };
739
+ };
575
740
 
576
741
  var __defProp$2 = Object.defineProperty;
577
742
  var __getOwnPropSymbols$2 = Object.getOwnPropertySymbols;
@@ -589,7 +754,37 @@ var __spreadValues$2 = (a, b) => {
589
754
  }
590
755
  return a;
591
756
  };
592
- const makeHasAndBelongsToManyMethod = (model, qb, relation, query) => {
757
+ class HasAndBelongsToManyVirtualColumn extends VirtualColumn {
758
+ constructor(key, state) {
759
+ super();
760
+ this.key = key;
761
+ this.state = state;
762
+ this.nestedInsert = nestedInsert(state);
763
+ this.nestedUpdate = nestedUpdate(state);
764
+ }
765
+ create(q, ctx, item, rowIndex) {
766
+ hasRelationHandleCreate(
767
+ q,
768
+ ctx,
769
+ item,
770
+ rowIndex,
771
+ this.key,
772
+ this.state.primaryKey,
773
+ this.nestedInsert
774
+ );
775
+ }
776
+ update(q, ctx, set) {
777
+ hasRelationHandleUpdate(
778
+ q,
779
+ ctx,
780
+ set,
781
+ this.key,
782
+ this.state.primaryKey,
783
+ this.nestedUpdate
784
+ );
785
+ }
786
+ }
787
+ const makeHasAndBelongsToManyMethod = (model, qb, relation, relationName, query) => {
593
788
  const {
594
789
  primaryKey: pk,
595
790
  foreignKey: fk,
@@ -615,7 +810,10 @@ const makeHasAndBelongsToManyMethod = (model, qb, relation, query) => {
615
810
  primaryKey: pk,
616
811
  foreignKey: fk,
617
812
  associationPrimaryKey: apk,
618
- associationForeignKey: afk
813
+ associationForeignKey: afk,
814
+ foreignKeyFull,
815
+ associationForeignKeyFull,
816
+ associationPrimaryKeyFull
619
817
  };
620
818
  return {
621
819
  returns: "many",
@@ -627,144 +825,7 @@ const makeHasAndBelongsToManyMethod = (model, qb, relation, query) => {
627
825
  })
628
826
  );
629
827
  },
630
- nestedInsert: async (q, data) => {
631
- const connect = data.filter(
632
- (item) => Boolean(item[1].connect)
633
- );
634
- const t = query.transacting(q);
635
- let connected;
636
- if (connect.length) {
637
- connected = await Promise.all(
638
- connect.flatMap(
639
- ([, { connect: connect2 }]) => connect2.map((item) => t.select(apk)._findBy(item)._take())
640
- )
641
- );
642
- } else {
643
- connected = [];
644
- }
645
- const connectOrCreate = data.filter(
646
- (item) => Boolean(item[1].connectOrCreate)
647
- );
648
- let connectOrCreated;
649
- if (connectOrCreate.length) {
650
- connectOrCreated = await Promise.all(
651
- connectOrCreate.flatMap(
652
- ([, { connectOrCreate: connectOrCreate2 }]) => connectOrCreate2.map(
653
- (item) => t.select(apk)._findBy(item.where)._takeOptional()
654
- )
655
- )
656
- );
657
- } else {
658
- connectOrCreated = [];
659
- }
660
- let connectOrCreateI = 0;
661
- const create = data.filter(
662
- (item) => {
663
- if (item[1].connectOrCreate) {
664
- const length = item[1].connectOrCreate.length;
665
- connectOrCreateI += length;
666
- for (let i = length; i > 0; i--) {
667
- if (!connectOrCreated[connectOrCreateI - i])
668
- return true;
669
- }
670
- }
671
- return Boolean(item[1].create);
672
- }
673
- );
674
- connectOrCreateI = 0;
675
- let created;
676
- if (create.length) {
677
- created = await t.select(apk)._createMany(
678
- create.flatMap(([, { create: create2 = [], connectOrCreate: connectOrCreate2 = [] }]) => [
679
- ...create2,
680
- ...connectOrCreate2.filter(() => !connectOrCreated[connectOrCreateI++]).map((item) => item.create)
681
- ])
682
- );
683
- } else {
684
- created = [];
685
- }
686
- const allKeys = data;
687
- let createI = 0;
688
- let connectI = 0;
689
- connectOrCreateI = 0;
690
- data.forEach(([, data2], index) => {
691
- if (data2.create || data2.connectOrCreate) {
692
- if (data2.create) {
693
- const len = data2.create.length;
694
- allKeys[index][1] = created.slice(createI, createI + len);
695
- createI += len;
696
- }
697
- if (data2.connectOrCreate) {
698
- const arr = [];
699
- allKeys[index][1] = arr;
700
- const len = data2.connectOrCreate.length;
701
- for (let i = 0; i < len; i++) {
702
- const item = connectOrCreated[connectOrCreateI++];
703
- if (item) {
704
- arr.push(item);
705
- } else {
706
- arr.push(created[createI++]);
707
- }
708
- }
709
- }
710
- }
711
- if (data2.connect) {
712
- const len = data2.connect.length;
713
- allKeys[index][1] = connected.slice(connectI, connectI + len);
714
- connectI += len;
715
- }
716
- });
717
- await subQuery.transacting(q)._count()._createMany(
718
- allKeys.flatMap(([selfData, relationKeys]) => {
719
- const selfKey = selfData[pk];
720
- return relationKeys.map((relationData) => ({
721
- [fk]: selfKey,
722
- [afk]: relationData[apk]
723
- }));
724
- })
725
- );
726
- },
727
- nestedUpdate: async (q, data, params) => {
728
- if (params.create) {
729
- const ids = await query.transacting(q)._pluck(apk)._createMany(params.create);
730
- await subQuery.transacting(q)._createMany(
731
- data.flatMap(
732
- (item) => ids.map((id) => ({
733
- [fk]: item[pk],
734
- [afk]: id
735
- }))
736
- )
737
- );
738
- }
739
- if (params.update) {
740
- await query.transacting(q)._whereExists(
741
- subQuery,
742
- (q2) => q2._on(associationForeignKeyFull, associationPrimaryKeyFull)._where({
743
- IN: {
744
- columns: [foreignKeyFull],
745
- values: [data.map((item) => item[pk])]
746
- }
747
- })
748
- )._where(
749
- Array.isArray(params.update.where) ? { OR: params.update.where } : params.update.where
750
- )._update(params.update.data);
751
- }
752
- if (params.disconnect) {
753
- await queryJoinTable(state, q, data, params.disconnect)._delete();
754
- }
755
- if (params.delete) {
756
- const j = queryJoinTable(state, q, data, params.delete);
757
- const ids = await j._pluck(afk)._delete();
758
- await queryRelatedTable(query, q, { [apk]: { in: ids } })._delete();
759
- }
760
- if (params.set) {
761
- const j = queryJoinTable(state, q, data);
762
- await j._delete();
763
- delete j.query[toSqlCacheKey];
764
- const ids = await queryRelatedTable(query, q, params.set)._pluck(apk);
765
- await insertToJoinTable(state, j, data, ids);
766
- }
767
- },
828
+ virtualColumn: new HasAndBelongsToManyVirtualColumn(relationName, state),
768
829
  joinQuery(fromQuery, toQuery) {
769
830
  return toQuery.whereExists(
770
831
  subQuery,
@@ -830,6 +891,166 @@ const insertToJoinTable = (state, joinTableTransaction, data, ids) => {
830
891
  )
831
892
  );
832
893
  };
894
+ const nestedInsert = ({
895
+ relatedTableQuery,
896
+ joinTableQuery,
897
+ primaryKey,
898
+ foreignKey,
899
+ associationPrimaryKey,
900
+ associationForeignKey
901
+ }) => {
902
+ return async (q, data) => {
903
+ const connect = data.filter(
904
+ (item) => Boolean(item[1].connect)
905
+ );
906
+ const t = relatedTableQuery.transacting(q);
907
+ let connected;
908
+ if (connect.length) {
909
+ connected = await Promise.all(
910
+ connect.flatMap(
911
+ ([, { connect: connect2 }]) => connect2.map(
912
+ (item) => t.select(associationPrimaryKey)._findBy(item)._take()
913
+ )
914
+ )
915
+ );
916
+ } else {
917
+ connected = [];
918
+ }
919
+ const connectOrCreate = data.filter(
920
+ (item) => Boolean(item[1].connectOrCreate)
921
+ );
922
+ let connectOrCreated;
923
+ if (connectOrCreate.length) {
924
+ connectOrCreated = await Promise.all(
925
+ connectOrCreate.flatMap(
926
+ ([, { connectOrCreate: connectOrCreate2 }]) => connectOrCreate2.map(
927
+ (item) => t.select(associationPrimaryKey)._findBy(item.where)._takeOptional()
928
+ )
929
+ )
930
+ );
931
+ } else {
932
+ connectOrCreated = [];
933
+ }
934
+ let connectOrCreateI = 0;
935
+ const create = data.filter(
936
+ (item) => {
937
+ if (item[1].connectOrCreate) {
938
+ const length = item[1].connectOrCreate.length;
939
+ connectOrCreateI += length;
940
+ for (let i = length; i > 0; i--) {
941
+ if (!connectOrCreated[connectOrCreateI - i])
942
+ return true;
943
+ }
944
+ }
945
+ return Boolean(item[1].create);
946
+ }
947
+ );
948
+ connectOrCreateI = 0;
949
+ let created;
950
+ if (create.length) {
951
+ created = await t.select(associationPrimaryKey)._createMany(
952
+ create.flatMap(([, { create: create2 = [], connectOrCreate: connectOrCreate2 = [] }]) => [
953
+ ...create2,
954
+ ...connectOrCreate2.filter(() => !connectOrCreated[connectOrCreateI++]).map((item) => item.create)
955
+ ])
956
+ );
957
+ } else {
958
+ created = [];
959
+ }
960
+ const allKeys = data;
961
+ let createI = 0;
962
+ let connectI = 0;
963
+ connectOrCreateI = 0;
964
+ data.forEach(([, data2], index) => {
965
+ if (data2.create || data2.connectOrCreate) {
966
+ if (data2.create) {
967
+ const len = data2.create.length;
968
+ allKeys[index][1] = created.slice(createI, createI + len);
969
+ createI += len;
970
+ }
971
+ if (data2.connectOrCreate) {
972
+ const arr = [];
973
+ allKeys[index][1] = arr;
974
+ const len = data2.connectOrCreate.length;
975
+ for (let i = 0; i < len; i++) {
976
+ const item = connectOrCreated[connectOrCreateI++];
977
+ if (item) {
978
+ arr.push(item);
979
+ } else {
980
+ arr.push(created[createI++]);
981
+ }
982
+ }
983
+ }
984
+ }
985
+ if (data2.connect) {
986
+ const len = data2.connect.length;
987
+ allKeys[index][1] = connected.slice(connectI, connectI + len);
988
+ connectI += len;
989
+ }
990
+ });
991
+ await joinTableQuery.transacting(q)._count()._createMany(
992
+ allKeys.flatMap(([selfData, relationKeys]) => {
993
+ const selfKey = selfData[primaryKey];
994
+ return relationKeys.map((relationData) => ({
995
+ [foreignKey]: selfKey,
996
+ [associationForeignKey]: relationData[associationPrimaryKey]
997
+ }));
998
+ })
999
+ );
1000
+ };
1001
+ };
1002
+ const nestedUpdate = (state) => {
1003
+ return async (q, data, params) => {
1004
+ if (params.create) {
1005
+ const ids = await state.relatedTableQuery.transacting(q)._pluck(state.associationPrimaryKey)._createMany(params.create);
1006
+ await state.joinTableQuery.transacting(q)._createMany(
1007
+ data.flatMap(
1008
+ (item) => ids.map((id) => ({
1009
+ [state.foreignKey]: item[state.primaryKey],
1010
+ [state.associationForeignKey]: id
1011
+ }))
1012
+ )
1013
+ );
1014
+ }
1015
+ if (params.update) {
1016
+ await state.relatedTableQuery.transacting(q)._whereExists(
1017
+ state.joinTableQuery,
1018
+ (q2) => q2._on(
1019
+ state.associationForeignKeyFull,
1020
+ state.associationPrimaryKeyFull
1021
+ )._where({
1022
+ IN: {
1023
+ columns: [state.foreignKeyFull],
1024
+ values: [data.map((item) => item[state.primaryKey])]
1025
+ }
1026
+ })
1027
+ )._where(
1028
+ Array.isArray(params.update.where) ? { OR: params.update.where } : params.update.where
1029
+ )._update(params.update.data);
1030
+ }
1031
+ if (params.disconnect) {
1032
+ await queryJoinTable(state, q, data, params.disconnect)._delete();
1033
+ }
1034
+ if (params.delete) {
1035
+ const j = queryJoinTable(state, q, data, params.delete);
1036
+ const ids = await j._pluck(state.associationForeignKey)._delete();
1037
+ await queryRelatedTable(state.relatedTableQuery, q, {
1038
+ [state.associationPrimaryKey]: { in: ids }
1039
+ })._delete();
1040
+ }
1041
+ if (params.set) {
1042
+ const j = queryJoinTable(state, q, data);
1043
+ await j._delete();
1044
+ delete j.query[toSqlCacheKey];
1045
+ const ids = await queryRelatedTable(
1046
+ state.relatedTableQuery,
1047
+ q,
1048
+ params.set
1049
+ )._pluck(state.associationPrimaryKey);
1050
+ await insertToJoinTable(state, j, data, ids);
1051
+ }
1052
+ };
1053
+ };
833
1054
 
834
1055
  const applyRelations = (qb, models, result) => {
835
1056
  const modelsEntries = Object.entries(models);
@@ -928,27 +1149,34 @@ const applyRelation = (qb, { relationName, relation, dbModel, otherDbModel }, de
928
1149
  const { type } = relation;
929
1150
  let data;
930
1151
  if (type === "belongsTo") {
931
- data = makeBelongsToMethod(relation, query);
1152
+ data = makeBelongsToMethod(relation, relationName, query);
932
1153
  } else if (type === "hasOne") {
933
1154
  data = makeHasOneMethod(dbModel, relation, relationName, query);
934
1155
  } else if (type === "hasMany") {
935
1156
  data = makeHasManyMethod(dbModel, relation, relationName, query);
936
1157
  } else if (type === "hasAndBelongsToMany") {
937
- data = makeHasAndBelongsToManyMethod(dbModel, qb, relation, query);
1158
+ data = makeHasAndBelongsToManyMethod(
1159
+ dbModel,
1160
+ qb,
1161
+ relation,
1162
+ relationName,
1163
+ query
1164
+ );
938
1165
  } else {
939
1166
  throw new Error(`Unknown relation type ${type}`);
940
1167
  }
941
1168
  if (data.returns === "one") {
942
1169
  query._take();
943
1170
  }
1171
+ if (data.virtualColumn) {
1172
+ dbModel.shape[relationName] = data.virtualColumn;
1173
+ }
944
1174
  makeRelationQuery(dbModel, definedAs, relationName, data);
945
1175
  dbModel.relations[relationName] = {
946
1176
  type,
947
1177
  key: relationName,
948
1178
  model: otherDbModel,
949
1179
  query,
950
- nestedInsert: data.nestedInsert,
951
- nestedUpdate: data.nestedUpdate,
952
1180
  joinQuery: data.joinQuery,
953
1181
  primaryKey: data.primaryKey,
954
1182
  options: relation.options