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