orchid-orm 1.3.14 → 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/CHANGELOG.md +15 -0
- package/dist/index.d.ts +21 -23
- package/dist/index.esm.js +678 -450
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +677 -449
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
- package/src/relations/belongsTo.ts +289 -184
- package/src/relations/hasAndBelongsToMany.ts +283 -209
- package/src/relations/hasMany.ts +237 -166
- package/src/relations/hasOne.ts +205 -132
- package/src/relations/relations.ts +14 -8
- package/src/relations/utils.ts +151 -1
package/dist/index.esm.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { getColumnTypes,
|
|
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
|
-
|
|
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
|
-
|
|
58
|
-
|
|
59
|
-
|
|
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
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
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
|
-
|
|
93
|
-
|
|
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
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
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
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
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
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
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
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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(
|
|
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
|