orchid-orm 1.67.1 → 1.68.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +642 -682
- package/dist/index.js +1398 -2304
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1391 -2298
- package/dist/index.mjs.map +1 -1
- package/dist/migrations/index.d.ts +14 -13
- package/dist/migrations/index.js +2379 -3597
- package/dist/migrations/index.js.map +1 -1
- package/dist/migrations/index.mjs +2345 -3586
- package/dist/migrations/index.mjs.map +1 -1
- package/dist/migrations/node-postgres.d.ts +13 -14
- package/dist/migrations/node-postgres.js +12 -3795
- package/dist/migrations/node-postgres.js.map +1 -1
- package/dist/migrations/node-postgres.mjs +4 -3785
- package/dist/migrations/node-postgres.mjs.map +1 -1
- package/dist/migrations/postgres-js.d.ts +13 -14
- package/dist/migrations/postgres-js.js +12 -3795
- package/dist/migrations/postgres-js.js.map +1 -1
- package/dist/migrations/postgres-js.mjs +4 -3785
- package/dist/migrations/postgres-js.mjs.map +1 -1
- package/dist/node-postgres.d.ts +10 -10
- package/dist/node-postgres.js +17 -21
- package/dist/node-postgres.js.map +1 -1
- package/dist/node-postgres.mjs +14 -17
- package/dist/node-postgres.mjs.map +1 -1
- package/dist/postgres-js.d.ts +11 -14
- package/dist/postgres-js.js +16 -17
- package/dist/postgres-js.js.map +1 -1
- package/dist/postgres-js.mjs +13 -13
- package/dist/postgres-js.mjs.map +1 -1
- package/package.json +62 -27
package/dist/index.mjs
CHANGED
|
@@ -1,2386 +1,1479 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
function
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
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
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
options
|
|
140
|
-
};
|
|
141
|
-
}
|
|
142
|
-
}, _a.nowSQL = nowSQL, _a.exportAs = exportAs, _a.columnTypes = columnTypes, _a.sql = _createDbSqlMethod(columnTypes), _a);
|
|
143
|
-
applyMixins(base, [QueryHooks]);
|
|
144
|
-
base.prototype.types = columnTypes;
|
|
145
|
-
base.prototype.snakeCase = snakeCase;
|
|
146
|
-
base.prototype.language = language;
|
|
147
|
-
base.prototype.autoForeignKeys = autoForeignKeys === true ? {} : autoForeignKeys || void 0;
|
|
148
|
-
return base;
|
|
1
|
+
import { DynamicRawSQL, QueryHooks, RawSql, VirtualColumn, _appendQuery, _clone, _createDbSqlMethod, _hookSelectColumns, _initQueryBuilder, _orCreate, _prependWith, _queryCreate, _queryCreateMany, _queryCreateManyFrom, _queryDefaults, _queryDelete, _queryFindBy, _queryFindByOptional, _queryHookAfterCreate, _queryHookAfterUpdate, _queryInsert, _queryInsertMany, _queryJoinOn, _queryRows, _querySelect, _queryTake, _queryTakeOptional, _queryUpdate, _queryUpdateOrThrow, _queryUpsert, _queryWhere, _queryWhereExists, _queryWhereIn, applyMixins, cloneQueryBaseUnscoped, defaultSchemaConfig, emptyArray, emptyObject, getCallerFilePath, getClonedQueryData, getColumnTypes, getFreeAlias, getPrimaryKeys, getQueryAs, getShapeFromSelect, getStackTrace, isExpression, isQueryReturnsAll, makeColumnTypes, noop, objectHasValues, parseTableData, pick, prepareSubQueryForSql, pushQueryOnForOuter, setQueryObjectValueImmutable, snakeCaseKey, toArray, toSnakeCase } from "pqb/internal";
|
|
2
|
+
import { Db, NotFoundError, OrchidOrmInternalError } from "pqb";
|
|
3
|
+
import { AsyncLocalStorage } from "node:async_hooks";
|
|
4
|
+
export * from "pqb";
|
|
5
|
+
function createBaseTable({ schemaConfig = defaultSchemaConfig, columnTypes: columnTypesArg, snakeCase, filePath: filePathArg, nowSQL, exportAs = "BaseTable", language, autoForeignKeys } = {}) {
|
|
6
|
+
const columnTypes = typeof columnTypesArg === "function" ? columnTypesArg(makeColumnTypes(schemaConfig)) : columnTypesArg || makeColumnTypes(schemaConfig);
|
|
7
|
+
const filePathOrStack = filePathArg || getStackTrace();
|
|
8
|
+
let filePath;
|
|
9
|
+
const defaultColumns = {
|
|
10
|
+
shape: emptyObject,
|
|
11
|
+
data: emptyArray
|
|
12
|
+
};
|
|
13
|
+
const instances = /* @__PURE__ */ new WeakMap();
|
|
14
|
+
const base = class BaseTable {
|
|
15
|
+
constructor() {
|
|
16
|
+
this.columns = defaultColumns;
|
|
17
|
+
this.snakeCase = snakeCase;
|
|
18
|
+
this.types = columnTypes;
|
|
19
|
+
this.q = {};
|
|
20
|
+
this.language = language;
|
|
21
|
+
}
|
|
22
|
+
static {
|
|
23
|
+
this.nowSQL = nowSQL;
|
|
24
|
+
}
|
|
25
|
+
static {
|
|
26
|
+
this.exportAs = exportAs;
|
|
27
|
+
}
|
|
28
|
+
static {
|
|
29
|
+
this.columnTypes = columnTypes;
|
|
30
|
+
}
|
|
31
|
+
static {
|
|
32
|
+
this.sql = _createDbSqlMethod(columnTypes);
|
|
33
|
+
}
|
|
34
|
+
static inputSchema() {
|
|
35
|
+
this.instance();
|
|
36
|
+
return this._inputSchema === void 0 ? this._inputSchema = schemaConfig.inputSchema.call(this) : this._inputSchema;
|
|
37
|
+
}
|
|
38
|
+
static outputSchema() {
|
|
39
|
+
this.instance();
|
|
40
|
+
return this._outputSchema === void 0 ? this._outputSchema = schemaConfig.outputSchema.call(this) : this._outputSchema;
|
|
41
|
+
}
|
|
42
|
+
static querySchema() {
|
|
43
|
+
this.instance();
|
|
44
|
+
return this._querySchema === void 0 ? this._querySchema = schemaConfig.querySchema.call(this) : this._querySchema;
|
|
45
|
+
}
|
|
46
|
+
static createSchema() {
|
|
47
|
+
this.instance();
|
|
48
|
+
return this._createSchema === void 0 ? this._createSchema = schemaConfig.createSchema.call(this) : this._createSchema;
|
|
49
|
+
}
|
|
50
|
+
static updateSchema() {
|
|
51
|
+
this.instance();
|
|
52
|
+
return this._updateSchema === void 0 ? this._updateSchema = schemaConfig.updateSchema.call(this) : this._updateSchema;
|
|
53
|
+
}
|
|
54
|
+
static pkeySchema() {
|
|
55
|
+
this.instance();
|
|
56
|
+
return this._pkeySchema === void 0 ? this._pkeySchema = schemaConfig.pkeySchema.call(this) : this._pkeySchema;
|
|
57
|
+
}
|
|
58
|
+
static getFilePath() {
|
|
59
|
+
if (filePath) return filePath;
|
|
60
|
+
if (typeof filePathOrStack === "string") return filePath = filePathOrStack;
|
|
61
|
+
filePath = getCallerFilePath(filePathOrStack);
|
|
62
|
+
if (filePath) return filePath;
|
|
63
|
+
throw new Error(`Failed to determine file path of a base table. Please set the \`filePath\` option of \`createBaseTable\` manually.`);
|
|
64
|
+
}
|
|
65
|
+
static instance() {
|
|
66
|
+
let instance = instances.get(this);
|
|
67
|
+
if (!instance) {
|
|
68
|
+
instance = new this();
|
|
69
|
+
instances.set(this, instance);
|
|
70
|
+
}
|
|
71
|
+
return instance;
|
|
72
|
+
}
|
|
73
|
+
clone() {
|
|
74
|
+
return this;
|
|
75
|
+
}
|
|
76
|
+
getFilePath() {
|
|
77
|
+
if (this.filePath) return this.filePath;
|
|
78
|
+
if (typeof filePathOrStack === "string") return this.filePath = filePathOrStack;
|
|
79
|
+
const filePath = getCallerFilePath(filePathOrStack);
|
|
80
|
+
if (filePath) return this.filePath = filePath;
|
|
81
|
+
throw new Error(`Failed to determine file path for table ${this.constructor.name}. Please set \`filePath\` property manually`);
|
|
82
|
+
}
|
|
83
|
+
setColumns(fn, dataFn) {
|
|
84
|
+
columnTypes[snakeCaseKey] = this.snakeCase;
|
|
85
|
+
const shape = getColumnTypes(columnTypes, fn, nowSQL, this.language);
|
|
86
|
+
const tableData = parseTableData(dataFn);
|
|
87
|
+
if (this.snakeCase) for (const key in shape) {
|
|
88
|
+
const column = shape[key];
|
|
89
|
+
if (column.data.name) continue;
|
|
90
|
+
const snakeName = toSnakeCase(key);
|
|
91
|
+
if (snakeName !== key) column.data.name = snakeName;
|
|
92
|
+
}
|
|
93
|
+
return this.constructor.prototype.columns = {
|
|
94
|
+
shape,
|
|
95
|
+
data: tableData
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
setComputed(computed) {
|
|
99
|
+
return computed;
|
|
100
|
+
}
|
|
101
|
+
setScopes(scopes) {
|
|
102
|
+
return scopes;
|
|
103
|
+
}
|
|
104
|
+
belongsTo(fn, options) {
|
|
105
|
+
return {
|
|
106
|
+
type: "belongsTo",
|
|
107
|
+
fn,
|
|
108
|
+
options
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
hasOne(fn, options) {
|
|
112
|
+
return {
|
|
113
|
+
type: "hasOne",
|
|
114
|
+
fn,
|
|
115
|
+
options
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
hasMany(fn, options) {
|
|
119
|
+
return {
|
|
120
|
+
type: "hasMany",
|
|
121
|
+
fn,
|
|
122
|
+
options
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
hasAndBelongsToMany(fn, options) {
|
|
126
|
+
return {
|
|
127
|
+
type: "hasAndBelongsToMany",
|
|
128
|
+
fn,
|
|
129
|
+
options
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
};
|
|
133
|
+
applyMixins(base, [QueryHooks]);
|
|
134
|
+
base.prototype.types = columnTypes;
|
|
135
|
+
base.prototype.snakeCase = snakeCase;
|
|
136
|
+
base.prototype.language = language;
|
|
137
|
+
base.prototype.autoForeignKeys = autoForeignKeys === true ? {} : autoForeignKeys || void 0;
|
|
138
|
+
return base;
|
|
149
139
|
}
|
|
150
|
-
|
|
151
140
|
const getThroughRelation = (table, through) => {
|
|
152
|
-
|
|
141
|
+
return table.relations[through];
|
|
153
142
|
};
|
|
154
143
|
const getSourceRelation = (throughRelation, source) => {
|
|
155
|
-
|
|
144
|
+
return throughRelation.query.relations[source];
|
|
156
145
|
};
|
|
157
146
|
const hasRelationHandleCreate = (q, ctx, items, rowIndexes, key, primaryKeys, nestedInsert) => {
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
q,
|
|
174
|
-
primaryKeys,
|
|
175
|
-
(rows, q2) => nestedInsert(
|
|
176
|
-
q2,
|
|
177
|
-
relationData.map(([rowIndex, data]) => [
|
|
178
|
-
rows[rowIndex],
|
|
179
|
-
data
|
|
180
|
-
])
|
|
181
|
-
)
|
|
182
|
-
);
|
|
183
|
-
});
|
|
147
|
+
q.q.wrapInTransaction = true;
|
|
148
|
+
items.forEach((item, i) => {
|
|
149
|
+
const value = item[key];
|
|
150
|
+
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)) return;
|
|
151
|
+
const store = ctx;
|
|
152
|
+
if (!store.hasRelation) store.hasRelation = {};
|
|
153
|
+
const values = [rowIndexes[i], value];
|
|
154
|
+
if (store.hasRelation[key]) {
|
|
155
|
+
store.hasRelation[key].push(values);
|
|
156
|
+
return;
|
|
157
|
+
}
|
|
158
|
+
const relationData = [values];
|
|
159
|
+
store.hasRelation[key] = relationData;
|
|
160
|
+
_queryHookAfterCreate(q, primaryKeys, (rows, q) => nestedInsert(q, relationData.map(([rowIndex, data]) => [rows[rowIndex], data])));
|
|
161
|
+
});
|
|
184
162
|
};
|
|
185
163
|
const hasRelationHandleUpdate = (q, set, key, primaryKeys, nestedUpdate) => {
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
q2,
|
|
193
|
-
rows,
|
|
194
|
-
value
|
|
195
|
-
);
|
|
196
|
-
});
|
|
164
|
+
const value = set[key];
|
|
165
|
+
if (!value.set && !("upsert" in value) && (!value.add || Array.isArray(value.add) && value.add.length === 0) && (!value.disconnect || Array.isArray(value.disconnect) && value.disconnect.length === 0) && (!value.delete || Array.isArray(value.delete) && value.delete.length === 0) && (!value.update || Array.isArray(value.update.where) && value.update.where.length === 0) && (!value.create || Array.isArray(value.create) && value.create.length === 0)) return;
|
|
166
|
+
q.q.wrapInTransaction = true;
|
|
167
|
+
_queryHookAfterUpdate(q, primaryKeys, (rows, q) => {
|
|
168
|
+
return nestedUpdate(q, rows, value);
|
|
169
|
+
});
|
|
197
170
|
};
|
|
198
171
|
function joinHasThrough(q, baseQuery, joiningQuery, throughRelation, sourceRelation) {
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
),
|
|
204
|
-
() => {
|
|
205
|
-
const as = getQueryAs(joiningQuery);
|
|
206
|
-
return sourceRelation.joinQuery(
|
|
207
|
-
sourceRelation.query.as(as),
|
|
208
|
-
throughRelation.query
|
|
209
|
-
);
|
|
210
|
-
}
|
|
211
|
-
);
|
|
172
|
+
return q.whereExists(throughRelation.joinQuery(throughRelation.query, baseQuery), (() => {
|
|
173
|
+
const as = getQueryAs(joiningQuery);
|
|
174
|
+
return sourceRelation.joinQuery(sourceRelation.query.as(as), throughRelation.query);
|
|
175
|
+
}));
|
|
212
176
|
}
|
|
213
177
|
function joinHasRelation(baseQuery, joiningQuery, primaryKeys, foreignKeys, len) {
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
q,
|
|
220
|
-
baseQuery,
|
|
221
|
-
joiningQuery,
|
|
222
|
-
foreignKeys[i],
|
|
223
|
-
`${baseAs}.${primaryKeys[i]}`
|
|
224
|
-
);
|
|
225
|
-
}
|
|
226
|
-
return q;
|
|
178
|
+
const baseAs = getQueryAs(baseQuery);
|
|
179
|
+
const q = joiningQuery.clone();
|
|
180
|
+
setQueryObjectValueImmutable(q, "joinedShapes", baseAs, baseQuery.q.shape);
|
|
181
|
+
for (let i = 0; i < len; i++) pushQueryOnForOuter(q, baseQuery, joiningQuery, foreignKeys[i], `${baseAs}.${primaryKeys[i]}`);
|
|
182
|
+
return q;
|
|
227
183
|
}
|
|
228
184
|
const addAutoForeignKey = (tableConfig, from, to, primaryKeys, foreignKeys, options, originalForeignKeys) => {
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
references: {
|
|
267
|
-
columns: originalForeignKeys || foreignKeys,
|
|
268
|
-
fnOrTable: toTable,
|
|
269
|
-
foreignColumns: primaryKeys,
|
|
270
|
-
options: fkeyOptions
|
|
271
|
-
},
|
|
272
|
-
dropMode: fkeyOptions.dropMode
|
|
273
|
-
});
|
|
185
|
+
const toTable = to.table;
|
|
186
|
+
let fkeyOptions = options.foreignKey !== void 0 ? options.foreignKey : tableConfig.autoForeignKeys;
|
|
187
|
+
if (!fkeyOptions) return;
|
|
188
|
+
if (fkeyOptions === true) fkeyOptions = tableConfig.autoForeignKeys || emptyObject;
|
|
189
|
+
if (foreignKeys.length === 1) {
|
|
190
|
+
const column = from.shape[foreignKeys[0]];
|
|
191
|
+
if (column.data.foreignKeys) {
|
|
192
|
+
const pkey = primaryKeys[0];
|
|
193
|
+
for (const fkey of column.data.foreignKeys) {
|
|
194
|
+
let fkeyTable;
|
|
195
|
+
let fkeyColumn = fkey.foreignColumns[0];
|
|
196
|
+
if (typeof fkey.fnOrTable === "string") {
|
|
197
|
+
fkeyTable = fkey.fnOrTable;
|
|
198
|
+
fkeyColumn = getColumnKeyFromDbName(to, fkeyColumn);
|
|
199
|
+
} else fkeyTable = fkey.fnOrTable().instance().table;
|
|
200
|
+
if (toTable === fkeyTable && pkey === fkeyColumn) return;
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
const { constraints } = from.internal.tableData;
|
|
205
|
+
if (constraints) {
|
|
206
|
+
const sortedPkeys = [...primaryKeys].sort();
|
|
207
|
+
const sortedFkeys = [...foreignKeys].sort();
|
|
208
|
+
for (const { references: refs } of constraints) {
|
|
209
|
+
if (!refs) continue;
|
|
210
|
+
if (refs.columns.length === sortedFkeys.length && refs.columns.every((column, i) => column === sortedFkeys[i]) && refs.foreignColumns.length === sortedPkeys.length && (typeof refs.fnOrTable === "string" ? refs.fnOrTable === toTable && refs.foreignColumns.every((column, i) => getColumnKeyFromDbName(to, column) === sortedPkeys[i]) : refs.fnOrTable().instance().table === toTable && refs.foreignColumns.every((column, i) => column === sortedPkeys[i]))) return;
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
(from.internal.tableData.constraints ??= []).push({
|
|
214
|
+
references: {
|
|
215
|
+
columns: originalForeignKeys || foreignKeys,
|
|
216
|
+
fnOrTable: toTable,
|
|
217
|
+
foreignColumns: primaryKeys,
|
|
218
|
+
options: fkeyOptions
|
|
219
|
+
},
|
|
220
|
+
dropMode: fkeyOptions.dropMode
|
|
221
|
+
});
|
|
274
222
|
};
|
|
275
223
|
const getColumnKeyFromDbName = (query, name) => {
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
return k;
|
|
279
|
-
}
|
|
280
|
-
}
|
|
281
|
-
return name;
|
|
224
|
+
for (const k in query.shape) if (query.shape[k].data.name === name) return k;
|
|
225
|
+
return name;
|
|
282
226
|
};
|
|
283
227
|
const selectCteColumnsSql = (cteAs, columns) => `(SELECT ${columns.map((c) => `"${cteAs}"."${c}"`).join(", ")} FROM "${cteAs}")`;
|
|
284
228
|
const selectCteColumnSql = (cteAs, column) => `(SELECT "${cteAs}"."${column}" FROM "${cteAs}")`;
|
|
285
229
|
const selectCteColumnFromManySql = (cteAs, column, rowIndex, count) => {
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
230
|
+
let sql = `(SELECT "${cteAs}"."${column}" FROM "${cteAs}"`;
|
|
231
|
+
if (count > 1) {
|
|
232
|
+
sql += ` LIMIT 1`;
|
|
233
|
+
if (rowIndex) sql += ` OFFSET ${rowIndex}`;
|
|
234
|
+
}
|
|
235
|
+
return sql + ")";
|
|
292
236
|
};
|
|
293
|
-
|
|
294
237
|
const joinQueryChainHOF = (relPKeys, reverseJoin, joinQuery) => (joiningQuery, baseQuery) => {
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
}
|
|
338
|
-
}
|
|
339
|
-
return true;
|
|
340
|
-
}
|
|
341
|
-
});
|
|
342
|
-
}
|
|
343
|
-
}
|
|
344
|
-
if (useWhereExist) {
|
|
345
|
-
return jq.where({
|
|
346
|
-
EXISTS: { q: reverseJoin(query, jq) }
|
|
347
|
-
});
|
|
348
|
-
}
|
|
349
|
-
const result = jq.join(
|
|
350
|
-
{ _internalJoin: reverseJoin(query, jq) },
|
|
351
|
-
void 0
|
|
352
|
-
);
|
|
353
|
-
if (!query.q.chainMultiple) {
|
|
354
|
-
return result;
|
|
355
|
-
}
|
|
356
|
-
const item = selectRowNumber(result, relPKeys);
|
|
357
|
-
combineOrdering(result, query);
|
|
358
|
-
if (!result.q.select) result.q.select = ["*"];
|
|
359
|
-
return wrapQuery(jq, result, item);
|
|
238
|
+
const jq = joiningQuery;
|
|
239
|
+
const chain = jq.q.relChain;
|
|
240
|
+
if (!chain || chain.length === 1) return joinQuery(jq, baseQuery);
|
|
241
|
+
const last = chain[chain.length - 1];
|
|
242
|
+
const query = chain[chain.length - 2].rel.joinQuery(last.query, baseQuery);
|
|
243
|
+
let useWhereExist = true;
|
|
244
|
+
if (jq.q.returnType !== "value" && jq.q.returnType !== "valueOrThrow") {
|
|
245
|
+
let tablePrefix;
|
|
246
|
+
if (jq.q.order) {
|
|
247
|
+
const prefix = tablePrefix = getQueryAs(jq) + ".";
|
|
248
|
+
useWhereExist = jq.q.order.every((o) => {
|
|
249
|
+
if (typeof o === "string") return isOwnColumn(prefix, o);
|
|
250
|
+
else if (isExpression(o)) return false;
|
|
251
|
+
else {
|
|
252
|
+
for (const key in o) if (!isOwnColumn(prefix, key)) return false;
|
|
253
|
+
return true;
|
|
254
|
+
}
|
|
255
|
+
});
|
|
256
|
+
}
|
|
257
|
+
if (useWhereExist && jq.q.select) {
|
|
258
|
+
const prefix = tablePrefix || getQueryAs(jq) + ".";
|
|
259
|
+
useWhereExist = jq.q.select.every((s) => {
|
|
260
|
+
if (typeof s === "string") return isOwnColumn(prefix, s);
|
|
261
|
+
else if (isExpression(s)) return false;
|
|
262
|
+
else if (!s) return false;
|
|
263
|
+
else {
|
|
264
|
+
for (const key in s.selectAs) {
|
|
265
|
+
const value = s.selectAs[key];
|
|
266
|
+
if (typeof value !== "string" || !isOwnColumn(prefix, value)) return false;
|
|
267
|
+
}
|
|
268
|
+
return true;
|
|
269
|
+
}
|
|
270
|
+
});
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
if (useWhereExist) return jq.where({ EXISTS: { q: reverseJoin(query, jq) } });
|
|
274
|
+
const result = jq.join({ _internalJoin: reverseJoin(query, jq) }, void 0);
|
|
275
|
+
if (!query.q.chainMultiple) return result;
|
|
276
|
+
const item = selectRowNumber(result, relPKeys);
|
|
277
|
+
combineOrdering(result, query);
|
|
278
|
+
if (!result.q.select) result.q.select = ["*"];
|
|
279
|
+
return wrapQuery(jq, result, item);
|
|
360
280
|
};
|
|
361
281
|
const isOwnColumn = (prefix, column) => !column.includes(".") || column.startsWith(prefix);
|
|
362
282
|
const selectRowNumber = (result, relPKeys) => {
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
(key) => `${as}."${result.shape[key]?.data.name || key}"`
|
|
369
|
-
);
|
|
370
|
-
const item = {
|
|
371
|
-
select: {
|
|
372
|
-
sql: `row_number() OVER (PARTITION BY ${partitionColumns.join(", ")})`
|
|
373
|
-
}
|
|
374
|
-
};
|
|
375
|
-
hookSelect.set("r", item);
|
|
376
|
-
return item;
|
|
283
|
+
const hookSelect = result.q.hookSelect = new Map(result.q.hookSelect && [...result.q.hookSelect]);
|
|
284
|
+
const as = `"${getQueryAs(result)}"`;
|
|
285
|
+
const item = { select: { sql: `row_number() OVER (PARTITION BY ${relPKeys.map((key) => `${as}."${result.shape[key]?.data.name || key}"`).join(", ")})` } };
|
|
286
|
+
hookSelect.set("r", item);
|
|
287
|
+
return item;
|
|
377
288
|
};
|
|
378
289
|
const combineOrdering = (result, joined) => {
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
);
|
|
387
|
-
const arr = result.q.order;
|
|
388
|
-
result.q.order = arr ? [...add, ...arr] : add;
|
|
389
|
-
}
|
|
290
|
+
const { order } = joined.q;
|
|
291
|
+
if (order) {
|
|
292
|
+
const as = getQueryAs(joined);
|
|
293
|
+
const add = order.map((o) => typeof o === "string" ? `${as}.${o}` : isExpression(o) ? o : Object.fromEntries(Object.entries(o).map(([key, value]) => [`${as}.${key}`, value])));
|
|
294
|
+
const arr = result.q.order;
|
|
295
|
+
result.q.order = arr ? [...add, ...arr] : add;
|
|
296
|
+
}
|
|
390
297
|
};
|
|
391
298
|
const wrapQuery = (joiningQuery, result, item) => {
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
299
|
+
const outer = cloneQueryBaseUnscoped(joiningQuery).clone();
|
|
300
|
+
outer.q.and = [new DynamicRawSQL(() => new RawSql(`${item.as || "r"} = 1`))];
|
|
301
|
+
outer.q.useFromLimitOffset = true;
|
|
302
|
+
outer.shape = getShapeFromSelect(result, true);
|
|
303
|
+
outer.q.select = Object.keys(outer.shape);
|
|
304
|
+
outer.q.returnType = result.q.returnType;
|
|
305
|
+
result.q.returnsOne = true;
|
|
306
|
+
return result.wrap(outer);
|
|
307
|
+
};
|
|
308
|
+
var BelongsToVirtualColumn = class extends VirtualColumn {
|
|
309
|
+
constructor(schema, key, state) {
|
|
310
|
+
super(schema);
|
|
311
|
+
this.key = key;
|
|
312
|
+
this.state = state;
|
|
313
|
+
this.nestedUpdate = nestedUpdate$2(this.state);
|
|
314
|
+
}
|
|
315
|
+
create(q, ctx, items) {
|
|
316
|
+
const { key, state: { query, primaryKeys, foreignKeys } } = this;
|
|
317
|
+
let nestedCreateItems;
|
|
318
|
+
items.forEach((item) => {
|
|
319
|
+
const value = item[key];
|
|
320
|
+
const kind = value.create ? "create" : value.connect ? "connect" : "connectOrCreate";
|
|
321
|
+
if (kind) {
|
|
322
|
+
const nestedCreateItem = (nestedCreateItems ??= {})[kind] ??= {
|
|
323
|
+
items: [],
|
|
324
|
+
values: []
|
|
325
|
+
};
|
|
326
|
+
nestedCreateItem.items.push(item);
|
|
327
|
+
nestedCreateItem.values.push(value[kind]);
|
|
328
|
+
if (kind !== "connect") for (const key of foreignKeys) item[key] = new RawSql("");
|
|
329
|
+
}
|
|
330
|
+
});
|
|
331
|
+
if (!nestedCreateItems) return;
|
|
332
|
+
for (const key of foreignKeys) if (!ctx.columns.has(key)) ctx.columns.set(key, ctx.columns.size);
|
|
333
|
+
const { create, connect, connectOrCreate } = nestedCreateItems;
|
|
334
|
+
if (create) _prependWith(q, (as) => {
|
|
335
|
+
const count = create.items.length;
|
|
336
|
+
foreignKeys.forEach((foreignKey, i) => {
|
|
337
|
+
const primaryKey = primaryKeys[i];
|
|
338
|
+
create.items.forEach((item, i) => {
|
|
339
|
+
item[foreignKey]._sql = selectCteColumnFromManySql(as, primaryKey, i, count);
|
|
340
|
+
});
|
|
341
|
+
});
|
|
342
|
+
}, _queryInsertMany(query.select(...primaryKeys), create.values));
|
|
343
|
+
if (connect) connect.values.forEach((value, itemI) => {
|
|
344
|
+
const as = getFreeAlias(q.q.withShapes, "q");
|
|
345
|
+
_prependWith(q, as, query.select(...primaryKeys).findBy(value));
|
|
346
|
+
foreignKeys.map((foreignKey, i) => {
|
|
347
|
+
connect.items[itemI][foreignKey] = new RawSql(selectCteColumnMustExistSql(i, as, primaryKeys[i]));
|
|
348
|
+
});
|
|
349
|
+
});
|
|
350
|
+
if (connectOrCreate) connectOrCreate.values.forEach((value, itemI) => {
|
|
351
|
+
_prependWith(q, setForeignKeysFromCte(connectOrCreate.items[itemI], primaryKeys, foreignKeys), _orCreate(_queryWhere(query.select(...primaryKeys), [value.where]), value.create));
|
|
352
|
+
});
|
|
353
|
+
}
|
|
354
|
+
update(q, set) {
|
|
355
|
+
q.q.wrapInTransaction = true;
|
|
356
|
+
const data = set[this.key];
|
|
357
|
+
this.nestedUpdate(q, set, data);
|
|
358
|
+
}
|
|
401
359
|
};
|
|
402
|
-
|
|
403
|
-
class BelongsToVirtualColumn extends VirtualColumn {
|
|
404
|
-
constructor(schema, key, state) {
|
|
405
|
-
super(schema);
|
|
406
|
-
this.key = key;
|
|
407
|
-
this.state = state;
|
|
408
|
-
this.nestedUpdate = nestedUpdate$2(this.state);
|
|
409
|
-
}
|
|
410
|
-
create(q, ctx, items) {
|
|
411
|
-
const {
|
|
412
|
-
key,
|
|
413
|
-
state: { query, primaryKeys, foreignKeys }
|
|
414
|
-
} = this;
|
|
415
|
-
let nestedCreateItems;
|
|
416
|
-
items.forEach((item) => {
|
|
417
|
-
var _a;
|
|
418
|
-
const value = item[key];
|
|
419
|
-
const kind = value.create ? "create" : value.connect ? "connect" : "connectOrCreate";
|
|
420
|
-
{
|
|
421
|
-
const nestedCreateItem = (_a = nestedCreateItems ?? (nestedCreateItems = {}))[kind] ?? (_a[kind] = {
|
|
422
|
-
items: [],
|
|
423
|
-
values: []
|
|
424
|
-
});
|
|
425
|
-
nestedCreateItem.items.push(item);
|
|
426
|
-
nestedCreateItem.values.push(value[kind]);
|
|
427
|
-
if (kind !== "connect") {
|
|
428
|
-
for (const key2 of foreignKeys) {
|
|
429
|
-
item[key2] = new RawSql("");
|
|
430
|
-
}
|
|
431
|
-
}
|
|
432
|
-
}
|
|
433
|
-
});
|
|
434
|
-
if (!nestedCreateItems) {
|
|
435
|
-
return;
|
|
436
|
-
}
|
|
437
|
-
for (const key2 of foreignKeys) {
|
|
438
|
-
if (!ctx.columns.has(key2)) {
|
|
439
|
-
ctx.columns.set(key2, ctx.columns.size);
|
|
440
|
-
}
|
|
441
|
-
}
|
|
442
|
-
const { create, connect, connectOrCreate } = nestedCreateItems;
|
|
443
|
-
if (create) {
|
|
444
|
-
const selectPKeys = query.select(...primaryKeys);
|
|
445
|
-
_prependWith(
|
|
446
|
-
q,
|
|
447
|
-
(as) => {
|
|
448
|
-
const count = create.items.length;
|
|
449
|
-
foreignKeys.forEach((foreignKey, i) => {
|
|
450
|
-
const primaryKey = primaryKeys[i];
|
|
451
|
-
create.items.forEach((item, i2) => {
|
|
452
|
-
item[foreignKey]._sql = selectCteColumnFromManySql(
|
|
453
|
-
as,
|
|
454
|
-
primaryKey,
|
|
455
|
-
i2,
|
|
456
|
-
count
|
|
457
|
-
);
|
|
458
|
-
});
|
|
459
|
-
});
|
|
460
|
-
},
|
|
461
|
-
_queryInsertMany(selectPKeys, create.values)
|
|
462
|
-
);
|
|
463
|
-
}
|
|
464
|
-
if (connect) {
|
|
465
|
-
connect.values.forEach((value, itemI) => {
|
|
466
|
-
const as = getFreeAlias(q.q.withShapes, "q");
|
|
467
|
-
_prependWith(q, as, query.select(...primaryKeys).findBy(value));
|
|
468
|
-
foreignKeys.map((foreignKey, i) => {
|
|
469
|
-
connect.items[itemI][foreignKey] = new RawSql(
|
|
470
|
-
selectCteColumnMustExistSql(i, as, primaryKeys[i])
|
|
471
|
-
);
|
|
472
|
-
});
|
|
473
|
-
});
|
|
474
|
-
}
|
|
475
|
-
if (connectOrCreate) {
|
|
476
|
-
connectOrCreate.values.forEach((value, itemI) => {
|
|
477
|
-
const asFn = setForeignKeysFromCte(
|
|
478
|
-
connectOrCreate.items[itemI],
|
|
479
|
-
primaryKeys,
|
|
480
|
-
foreignKeys
|
|
481
|
-
);
|
|
482
|
-
const selectPKeys = query.select(...primaryKeys);
|
|
483
|
-
_prependWith(
|
|
484
|
-
q,
|
|
485
|
-
asFn,
|
|
486
|
-
_orCreate(
|
|
487
|
-
_queryWhere(selectPKeys, [value.where]),
|
|
488
|
-
value.create
|
|
489
|
-
)
|
|
490
|
-
);
|
|
491
|
-
});
|
|
492
|
-
}
|
|
493
|
-
}
|
|
494
|
-
update(q, set) {
|
|
495
|
-
q.q.wrapInTransaction = true;
|
|
496
|
-
const data = set[this.key];
|
|
497
|
-
this.nestedUpdate(q, set, data);
|
|
498
|
-
}
|
|
499
|
-
}
|
|
500
360
|
const makeBelongsToMethod = (tableConfig, table, relation, relationName, query) => {
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
primaryKeys
|
|
539
|
-
);
|
|
540
|
-
};
|
|
541
|
-
return {
|
|
542
|
-
returns: "one",
|
|
543
|
-
queryRelated(params) {
|
|
544
|
-
const obj = {};
|
|
545
|
-
for (let i = 0; i < len; i++) {
|
|
546
|
-
obj[primaryKeys[i]] = params[foreignKeys[i]];
|
|
547
|
-
}
|
|
548
|
-
return query.where(obj);
|
|
549
|
-
},
|
|
550
|
-
virtualColumn: new BelongsToVirtualColumn(
|
|
551
|
-
defaultSchemaConfig,
|
|
552
|
-
relationName,
|
|
553
|
-
state
|
|
554
|
-
),
|
|
555
|
-
joinQuery: joinQueryChainHOF(
|
|
556
|
-
getPrimaryKeys(query),
|
|
557
|
-
reverseJoin,
|
|
558
|
-
(joiningQuery, baseQuery) => join(
|
|
559
|
-
baseQuery,
|
|
560
|
-
joiningQuery,
|
|
561
|
-
primaryKeys,
|
|
562
|
-
foreignKeys
|
|
563
|
-
)
|
|
564
|
-
),
|
|
565
|
-
reverseJoin
|
|
566
|
-
};
|
|
361
|
+
const primaryKeys = relation.options.references;
|
|
362
|
+
const foreignKeys = relation.options.columns;
|
|
363
|
+
const { on } = relation.options;
|
|
364
|
+
if (on) {
|
|
365
|
+
_queryWhere(query, [on]);
|
|
366
|
+
_queryDefaults(query, on);
|
|
367
|
+
}
|
|
368
|
+
const len = primaryKeys.length;
|
|
369
|
+
const state = {
|
|
370
|
+
query,
|
|
371
|
+
primaryKeys,
|
|
372
|
+
foreignKeys,
|
|
373
|
+
len,
|
|
374
|
+
on
|
|
375
|
+
};
|
|
376
|
+
addAutoForeignKey(tableConfig, table, query, primaryKeys, foreignKeys, relation.options);
|
|
377
|
+
const join = (baseQuery, joiningQuery, primaryKeys, foreignKeys) => {
|
|
378
|
+
const baseAs = getQueryAs(baseQuery);
|
|
379
|
+
const q = joiningQuery.clone();
|
|
380
|
+
setQueryObjectValueImmutable(q, "joinedShapes", baseAs, baseQuery.q.shape);
|
|
381
|
+
for (let i = 0; i < len; i++) pushQueryOnForOuter(q, baseQuery, joiningQuery, primaryKeys[i], `${baseAs}.${foreignKeys[i]}`);
|
|
382
|
+
return q;
|
|
383
|
+
};
|
|
384
|
+
const reverseJoin = (baseQuery, joiningQuery) => {
|
|
385
|
+
return join(joiningQuery, baseQuery, foreignKeys, primaryKeys);
|
|
386
|
+
};
|
|
387
|
+
return {
|
|
388
|
+
returns: "one",
|
|
389
|
+
queryRelated(params) {
|
|
390
|
+
const obj = {};
|
|
391
|
+
for (let i = 0; i < len; i++) obj[primaryKeys[i]] = params[foreignKeys[i]];
|
|
392
|
+
return query.where(obj);
|
|
393
|
+
},
|
|
394
|
+
virtualColumn: new BelongsToVirtualColumn(defaultSchemaConfig, relationName, state),
|
|
395
|
+
joinQuery: joinQueryChainHOF(getPrimaryKeys(query), reverseJoin, (joiningQuery, baseQuery) => join(baseQuery, joiningQuery, primaryKeys, foreignKeys)),
|
|
396
|
+
reverseJoin
|
|
397
|
+
};
|
|
567
398
|
};
|
|
568
399
|
const nestedUpdate$2 = ({ query, primaryKeys, foreignKeys, len }) => {
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
} else if (params.delete) {
|
|
612
|
-
_hookSelectColumns(self, foreignKeys, noop);
|
|
613
|
-
disconnect(update, foreignKeys);
|
|
614
|
-
const { selectIdsSql, relQuery } = relWithSelectIds(
|
|
615
|
-
self,
|
|
616
|
-
query,
|
|
617
|
-
primaryKeys,
|
|
618
|
-
foreignKeys
|
|
619
|
-
);
|
|
620
|
-
self.q.and = self.q.or = void 0;
|
|
621
|
-
_queryWhereIn(self, true, foreignKeys, selectIdsSql);
|
|
622
|
-
const deleteQuery = _queryDelete(relQuery);
|
|
623
|
-
deleteQuery.q.returnType = "value";
|
|
624
|
-
_appendQuery(self, deleteQuery, noop);
|
|
625
|
-
} else if (params.disconnect) {
|
|
626
|
-
disconnect(update, foreignKeys);
|
|
627
|
-
} else if (params.set) {
|
|
628
|
-
let loadPrimaryKeys;
|
|
629
|
-
let loadForeignKeys;
|
|
630
|
-
for (let i = 0; i < len; i++) {
|
|
631
|
-
const primaryKey = primaryKeys[i];
|
|
632
|
-
if (primaryKey in params.set) {
|
|
633
|
-
update[foreignKeys[i]] = params.set[primaryKey];
|
|
634
|
-
} else {
|
|
635
|
-
(loadPrimaryKeys ?? (loadPrimaryKeys = [])).push(primaryKey);
|
|
636
|
-
(loadForeignKeys ?? (loadForeignKeys = [])).push(foreignKeys[i]);
|
|
637
|
-
}
|
|
638
|
-
}
|
|
639
|
-
if (loadPrimaryKeys) {
|
|
640
|
-
const asFn = setForeignKeysFromCte(
|
|
641
|
-
update,
|
|
642
|
-
loadPrimaryKeys,
|
|
643
|
-
loadForeignKeys,
|
|
644
|
-
true
|
|
645
|
-
);
|
|
646
|
-
_prependWith(
|
|
647
|
-
self,
|
|
648
|
-
asFn,
|
|
649
|
-
_queryFindBy(query.select(...loadPrimaryKeys), params.set)
|
|
650
|
-
);
|
|
651
|
-
}
|
|
652
|
-
}
|
|
653
|
-
};
|
|
400
|
+
return ((self, update, params) => {
|
|
401
|
+
if (params.create) {
|
|
402
|
+
const createQuery = _querySelect(_queryCreate(query.clone(), params.create), primaryKeys);
|
|
403
|
+
_prependWith(self, setForeignKeysFromCte(update, primaryKeys, foreignKeys), createQuery);
|
|
404
|
+
} else if (params.update) {
|
|
405
|
+
let appendedAs;
|
|
406
|
+
_hookSelectColumns(self, foreignKeys, (aliasedForeignKeys) => {
|
|
407
|
+
selectIdsSql._sql = selectCteColumnsSql(appendedAs, aliasedForeignKeys);
|
|
408
|
+
});
|
|
409
|
+
const selectIdsSql = new RawSql("");
|
|
410
|
+
const updateQuery = _queryUpdate(_queryWhereIn(query.clone(), true, primaryKeys, selectIdsSql), params.update);
|
|
411
|
+
updateQuery.q.returnType = "value";
|
|
412
|
+
_appendQuery(self, updateQuery, (as) => appendedAs = as);
|
|
413
|
+
} else if (params.upsert) {
|
|
414
|
+
if (isQueryReturnsAll(self)) throw new Error("`upsert` option is not allowed in a batch update");
|
|
415
|
+
const { relQuery } = relWithSelectIds(self, query, primaryKeys, foreignKeys);
|
|
416
|
+
const upsertQuery = _querySelect(_queryUpsert(relQuery, params.upsert), primaryKeys);
|
|
417
|
+
_prependWith(self, setForeignKeysFromCte(update, primaryKeys, foreignKeys), upsertQuery);
|
|
418
|
+
} else if (params.delete) {
|
|
419
|
+
_hookSelectColumns(self, foreignKeys, noop);
|
|
420
|
+
disconnect(update, foreignKeys);
|
|
421
|
+
const { selectIdsSql, relQuery } = relWithSelectIds(self, query, primaryKeys, foreignKeys);
|
|
422
|
+
self.q.and = self.q.or = void 0;
|
|
423
|
+
_queryWhereIn(self, true, foreignKeys, selectIdsSql);
|
|
424
|
+
const deleteQuery = _queryDelete(relQuery);
|
|
425
|
+
deleteQuery.q.returnType = "value";
|
|
426
|
+
_appendQuery(self, deleteQuery, noop);
|
|
427
|
+
} else if (params.disconnect) disconnect(update, foreignKeys);
|
|
428
|
+
else if (params.set) {
|
|
429
|
+
let loadPrimaryKeys;
|
|
430
|
+
let loadForeignKeys;
|
|
431
|
+
for (let i = 0; i < len; i++) {
|
|
432
|
+
const primaryKey = primaryKeys[i];
|
|
433
|
+
if (primaryKey in params.set) update[foreignKeys[i]] = params.set[primaryKey];
|
|
434
|
+
else {
|
|
435
|
+
(loadPrimaryKeys ??= []).push(primaryKey);
|
|
436
|
+
(loadForeignKeys ??= []).push(foreignKeys[i]);
|
|
437
|
+
}
|
|
438
|
+
}
|
|
439
|
+
if (loadPrimaryKeys) _prependWith(self, setForeignKeysFromCte(update, loadPrimaryKeys, loadForeignKeys, true), _queryFindBy(query.select(...loadPrimaryKeys), params.set));
|
|
440
|
+
}
|
|
441
|
+
});
|
|
654
442
|
};
|
|
655
443
|
const disconnect = (update, foreignKeys) => {
|
|
656
|
-
|
|
657
|
-
update[foreignKey] = null;
|
|
658
|
-
}
|
|
444
|
+
for (const foreignKey of foreignKeys) update[foreignKey] = null;
|
|
659
445
|
};
|
|
660
446
|
const relWithSelectIds = (self, rel, primaryKeys, foreignKeys) => {
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
return {
|
|
671
|
-
selectIdsSql,
|
|
672
|
-
relQuery: _queryWhereIn(rel.clone(), true, primaryKeys, selectIdsSql)
|
|
673
|
-
};
|
|
447
|
+
const selectIdsQuery = makeSelectIdsQuery(self, foreignKeys);
|
|
448
|
+
const selectIdsSql = new RawSql("");
|
|
449
|
+
_prependWith(self, (as) => {
|
|
450
|
+
selectIdsSql._sql = selectCteColumnsSql(as, foreignKeys);
|
|
451
|
+
}, selectIdsQuery);
|
|
452
|
+
return {
|
|
453
|
+
selectIdsSql,
|
|
454
|
+
relQuery: _queryWhereIn(rel.clone(), true, primaryKeys, selectIdsSql)
|
|
455
|
+
};
|
|
674
456
|
};
|
|
675
457
|
const makeSelectIdsQuery = (self, foreignKeys) => {
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
458
|
+
const selectIdsQuery = self.baseQuery.clone();
|
|
459
|
+
selectIdsQuery.q.distinct = emptyArray;
|
|
460
|
+
selectIdsQuery.q.select = foreignKeys;
|
|
461
|
+
selectIdsQuery.q.and = self.q.and;
|
|
462
|
+
selectIdsQuery.q.or = self.q.or;
|
|
463
|
+
return selectIdsQuery;
|
|
682
464
|
};
|
|
683
465
|
const setForeignKeysFromCte = (record, primaryKeys, foreignKeys, mustExist) => {
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
as,
|
|
693
|
-
primaryKeys[i]
|
|
694
|
-
);
|
|
695
|
-
} : (foreignKey, i) => {
|
|
696
|
-
record[foreignKey]._sql = selectCteColumnSql(
|
|
697
|
-
as,
|
|
698
|
-
primaryKeys[i]
|
|
699
|
-
);
|
|
700
|
-
}
|
|
701
|
-
);
|
|
702
|
-
};
|
|
466
|
+
for (const key of foreignKeys) record[key] = new RawSql("");
|
|
467
|
+
return (as) => {
|
|
468
|
+
foreignKeys.forEach(mustExist ? (foreignKey, i) => {
|
|
469
|
+
record[foreignKey]._sql = selectCteColumnMustExistSql(i, as, primaryKeys[i]);
|
|
470
|
+
} : (foreignKey, i) => {
|
|
471
|
+
record[foreignKey]._sql = selectCteColumnSql(as, primaryKeys[i]);
|
|
472
|
+
});
|
|
473
|
+
};
|
|
703
474
|
};
|
|
704
475
|
const selectCteColumnMustExistSql = (i, cteAs, column) => {
|
|
705
|
-
|
|
706
|
-
|
|
476
|
+
const selectColumn = selectCteColumnSql(cteAs, column);
|
|
477
|
+
return i === 0 ? `CASE WHEN (SELECT count(*) FROM "${cteAs}") = 0 AND (SELECT 'not-found')::int = 0 THEN NULL ELSE ${selectColumn} END` : selectColumn;
|
|
478
|
+
};
|
|
479
|
+
var HasOneVirtualColumn = class extends VirtualColumn {
|
|
480
|
+
constructor(schema, key, state) {
|
|
481
|
+
super(schema);
|
|
482
|
+
this.key = key;
|
|
483
|
+
this.state = state;
|
|
484
|
+
this.nestedInsert = nestedInsert$2(state);
|
|
485
|
+
this.setNulls = {};
|
|
486
|
+
for (const foreignKey of state.foreignKeys) this.setNulls[foreignKey] = null;
|
|
487
|
+
}
|
|
488
|
+
create(self, ctx, items, rowIndexes, count) {
|
|
489
|
+
if (count <= self.qb.internal.nestedCreateBatchMax) {
|
|
490
|
+
const { query: rel, primaryKeys, foreignKeys } = this.state;
|
|
491
|
+
let nestedCreateItems;
|
|
492
|
+
items.forEach((item, i) => {
|
|
493
|
+
const value = item[this.key];
|
|
494
|
+
const kind = value.create ? "create" : value.connect ? "connect" : "connectOrCreate";
|
|
495
|
+
if (kind) {
|
|
496
|
+
const nestedCreateItem = (nestedCreateItems ??= {})[kind] ??= {
|
|
497
|
+
indexes: [],
|
|
498
|
+
items: [],
|
|
499
|
+
values: []
|
|
500
|
+
};
|
|
501
|
+
nestedCreateItem.indexes.push(rowIndexes[i]);
|
|
502
|
+
nestedCreateItem.values.push(value[kind]);
|
|
503
|
+
const data = value.create ? { ...value.create } : {};
|
|
504
|
+
for (const key of foreignKeys) data[key] = new RawSql("");
|
|
505
|
+
nestedCreateItem.items.push(data);
|
|
506
|
+
}
|
|
507
|
+
});
|
|
508
|
+
if (!nestedCreateItems) return;
|
|
509
|
+
let createAs;
|
|
510
|
+
let connectAs;
|
|
511
|
+
let connectOrCreateAs;
|
|
512
|
+
_hookSelectColumns(self, primaryKeys, (aliasedPrimaryKeys) => {
|
|
513
|
+
foreignKeys.forEach((key, keyI) => {
|
|
514
|
+
const primaryKey = aliasedPrimaryKeys[keyI];
|
|
515
|
+
if (create && createAs) for (let i = 0; i < create.items.length; i++) create.items[i][key]._sql = selectCteColumnFromManySql(createAs, primaryKey, create.indexes[i], count);
|
|
516
|
+
if (connect && connectAs) for (let i = 0; i < connect.items.length; i++) connect.items[i][key]._sql = selectCteColumnFromManySql(connectAs, primaryKey, connect.indexes[i], count);
|
|
517
|
+
if (connectOrCreate && connectOrCreateAs) for (let i = 0; i < connectOrCreate.items.length; i++) connectOrCreate.items[i][key]._sql = selectCteColumnFromManySql(connectOrCreateAs, primaryKey, connectOrCreate.indexes[i], count);
|
|
518
|
+
});
|
|
519
|
+
});
|
|
520
|
+
const { create, connect, connectOrCreate } = nestedCreateItems;
|
|
521
|
+
if (create) _appendQuery(self, _queryInsertMany(_clone(rel), create.items), (as) => createAs = as);
|
|
522
|
+
if (connect) connect.values.forEach((value, i) => {
|
|
523
|
+
const query = _queryUpdateOrThrow(rel.where(value), connect.items[i]);
|
|
524
|
+
query.q.ensureCount = 1;
|
|
525
|
+
_appendQuery(self, query, (as) => connectAs = as);
|
|
526
|
+
});
|
|
527
|
+
if (connectOrCreate) connectOrCreate.values.forEach((value, i) => {
|
|
528
|
+
_appendQuery(self, _queryUpsert(rel.where(value.where), {
|
|
529
|
+
update: connectOrCreate.items[i],
|
|
530
|
+
create: {
|
|
531
|
+
...value.create,
|
|
532
|
+
...connectOrCreate.items[i]
|
|
533
|
+
}
|
|
534
|
+
}), (as) => connectOrCreateAs = as);
|
|
535
|
+
});
|
|
536
|
+
} else hasRelationHandleCreate(self, ctx, items, rowIndexes, this.key, this.state.primaryKeys, this.nestedInsert);
|
|
537
|
+
}
|
|
538
|
+
update(self, set) {
|
|
539
|
+
const params = set[this.key];
|
|
540
|
+
if ((params.set || params.create || params.upsert) && isQueryReturnsAll(self)) {
|
|
541
|
+
const key = params.set ? "set" : params.create ? "create" : "upsert";
|
|
542
|
+
throw new Error(`\`${key}\` option is not allowed in a batch update`);
|
|
543
|
+
}
|
|
544
|
+
const { primaryKeys, foreignKeys, query: relQuery } = this.state;
|
|
545
|
+
if (params.create || params.update || params.upsert || params.disconnect || params.set || params.delete) {
|
|
546
|
+
let appendedAs;
|
|
547
|
+
_hookSelectColumns(self, primaryKeys, (aliasedPrimaryKeys) => {
|
|
548
|
+
selectIdsSql._sql = selectCteColumnsSql(appendedAs, aliasedPrimaryKeys);
|
|
549
|
+
if (params.create || params.set || params.upsert) foreignKeys.forEach((foreignKey, i) => {
|
|
550
|
+
setIds[foreignKey]._sql = selectCteColumnSql(appendedAs, aliasedPrimaryKeys[i]);
|
|
551
|
+
});
|
|
552
|
+
});
|
|
553
|
+
const selectIdsSql = new RawSql("");
|
|
554
|
+
const existingRelQuery = _queryWhereIn(_clone(relQuery), true, foreignKeys, selectIdsSql);
|
|
555
|
+
let setIds = void 0;
|
|
556
|
+
if (params.create || params.set || params.upsert) {
|
|
557
|
+
setIds = {};
|
|
558
|
+
foreignKeys.forEach((foreignKey) => {
|
|
559
|
+
setIds[foreignKey] = new RawSql("");
|
|
560
|
+
});
|
|
561
|
+
}
|
|
562
|
+
const nullifyOrDeleteQuery = params.update ? _queryUpdate(existingRelQuery, params.update) : params.upsert ? _queryUpsert(existingRelQuery, {
|
|
563
|
+
update: params.upsert.update,
|
|
564
|
+
create: {
|
|
565
|
+
...typeof params.upsert.create === "function" ? params.upsert.create() : params.upsert.create,
|
|
566
|
+
...setIds
|
|
567
|
+
}
|
|
568
|
+
}) : params.delete ? _queryDelete(existingRelQuery) : _queryUpdate(existingRelQuery, this.setNulls);
|
|
569
|
+
nullifyOrDeleteQuery.q.returnType = "void";
|
|
570
|
+
_appendQuery(self, nullifyOrDeleteQuery, (as) => appendedAs = as);
|
|
571
|
+
if (params.create) _appendQuery(self, _queryInsert(_clone(relQuery), {
|
|
572
|
+
...params.create,
|
|
573
|
+
...setIds
|
|
574
|
+
}), noop);
|
|
575
|
+
else if (params.set) {
|
|
576
|
+
const setQuery = _queryUpdate(_queryWhere(_clone(relQuery), [params.set]), setIds);
|
|
577
|
+
setQuery.q.returnType = "void";
|
|
578
|
+
_appendQuery(self, setQuery, noop);
|
|
579
|
+
}
|
|
580
|
+
}
|
|
581
|
+
}
|
|
707
582
|
};
|
|
708
|
-
|
|
709
|
-
class HasOneVirtualColumn extends VirtualColumn {
|
|
710
|
-
constructor(schema, key, state) {
|
|
711
|
-
super(schema);
|
|
712
|
-
this.key = key;
|
|
713
|
-
this.state = state;
|
|
714
|
-
this.nestedInsert = nestedInsert$2(state);
|
|
715
|
-
this.setNulls = {};
|
|
716
|
-
for (const foreignKey of state.foreignKeys) {
|
|
717
|
-
this.setNulls[foreignKey] = null;
|
|
718
|
-
}
|
|
719
|
-
}
|
|
720
|
-
create(self, ctx, items, rowIndexes, count) {
|
|
721
|
-
if (count <= self.qb.internal.nestedCreateBatchMax) {
|
|
722
|
-
const { query: rel, primaryKeys, foreignKeys } = this.state;
|
|
723
|
-
let nestedCreateItems;
|
|
724
|
-
items.forEach((item, i) => {
|
|
725
|
-
var _a;
|
|
726
|
-
const value = item[this.key];
|
|
727
|
-
const kind = value.create ? "create" : value.connect ? "connect" : "connectOrCreate";
|
|
728
|
-
{
|
|
729
|
-
const nestedCreateItem = (_a = nestedCreateItems ?? (nestedCreateItems = {}))[kind] ?? (_a[kind] = {
|
|
730
|
-
indexes: [],
|
|
731
|
-
items: [],
|
|
732
|
-
values: []
|
|
733
|
-
});
|
|
734
|
-
nestedCreateItem.indexes.push(rowIndexes[i]);
|
|
735
|
-
nestedCreateItem.values.push(value[kind]);
|
|
736
|
-
const data = value.create ? { ...value.create } : {};
|
|
737
|
-
for (const key of foreignKeys) {
|
|
738
|
-
data[key] = new RawSql("");
|
|
739
|
-
}
|
|
740
|
-
nestedCreateItem.items.push(data);
|
|
741
|
-
}
|
|
742
|
-
});
|
|
743
|
-
if (!nestedCreateItems) {
|
|
744
|
-
return;
|
|
745
|
-
}
|
|
746
|
-
let createAs;
|
|
747
|
-
let connectAs;
|
|
748
|
-
let connectOrCreateAs;
|
|
749
|
-
_hookSelectColumns(self, primaryKeys, (aliasedPrimaryKeys) => {
|
|
750
|
-
foreignKeys.forEach((key, keyI) => {
|
|
751
|
-
const primaryKey = aliasedPrimaryKeys[keyI];
|
|
752
|
-
if (create && createAs) {
|
|
753
|
-
for (let i = 0; i < create.items.length; i++) {
|
|
754
|
-
create.items[i][key]._sql = selectCteColumnFromManySql(
|
|
755
|
-
createAs,
|
|
756
|
-
primaryKey,
|
|
757
|
-
create.indexes[i],
|
|
758
|
-
count
|
|
759
|
-
);
|
|
760
|
-
}
|
|
761
|
-
}
|
|
762
|
-
if (connect && connectAs) {
|
|
763
|
-
for (let i = 0; i < connect.items.length; i++) {
|
|
764
|
-
connect.items[i][key]._sql = selectCteColumnFromManySql(
|
|
765
|
-
connectAs,
|
|
766
|
-
primaryKey,
|
|
767
|
-
connect.indexes[i],
|
|
768
|
-
count
|
|
769
|
-
);
|
|
770
|
-
}
|
|
771
|
-
}
|
|
772
|
-
if (connectOrCreate && connectOrCreateAs) {
|
|
773
|
-
for (let i = 0; i < connectOrCreate.items.length; i++) {
|
|
774
|
-
connectOrCreate.items[i][key]._sql = selectCteColumnFromManySql(
|
|
775
|
-
connectOrCreateAs,
|
|
776
|
-
primaryKey,
|
|
777
|
-
connectOrCreate.indexes[i],
|
|
778
|
-
count
|
|
779
|
-
);
|
|
780
|
-
}
|
|
781
|
-
}
|
|
782
|
-
});
|
|
783
|
-
});
|
|
784
|
-
const { create, connect, connectOrCreate } = nestedCreateItems;
|
|
785
|
-
if (create) {
|
|
786
|
-
const query = _queryInsertMany(_clone(rel), create.items);
|
|
787
|
-
_appendQuery(self, query, (as) => createAs = as);
|
|
788
|
-
}
|
|
789
|
-
if (connect) {
|
|
790
|
-
connect.values.forEach((value, i) => {
|
|
791
|
-
const query = _queryUpdateOrThrow(
|
|
792
|
-
rel.where(value),
|
|
793
|
-
connect.items[i]
|
|
794
|
-
);
|
|
795
|
-
query.q.ensureCount = 1;
|
|
796
|
-
_appendQuery(self, query, (as) => connectAs = as);
|
|
797
|
-
});
|
|
798
|
-
}
|
|
799
|
-
if (connectOrCreate) {
|
|
800
|
-
connectOrCreate.values.forEach((value, i) => {
|
|
801
|
-
const query = _queryUpsert(rel.where(value.where), {
|
|
802
|
-
update: connectOrCreate.items[i],
|
|
803
|
-
create: {
|
|
804
|
-
...value.create,
|
|
805
|
-
...connectOrCreate.items[i]
|
|
806
|
-
}
|
|
807
|
-
});
|
|
808
|
-
_appendQuery(self, query, (as) => connectOrCreateAs = as);
|
|
809
|
-
});
|
|
810
|
-
}
|
|
811
|
-
} else {
|
|
812
|
-
hasRelationHandleCreate(
|
|
813
|
-
self,
|
|
814
|
-
ctx,
|
|
815
|
-
items,
|
|
816
|
-
rowIndexes,
|
|
817
|
-
this.key,
|
|
818
|
-
this.state.primaryKeys,
|
|
819
|
-
this.nestedInsert
|
|
820
|
-
);
|
|
821
|
-
}
|
|
822
|
-
}
|
|
823
|
-
update(self, set) {
|
|
824
|
-
const params = set[this.key];
|
|
825
|
-
if ((params.set || params.create || params.upsert) && isQueryReturnsAll(self)) {
|
|
826
|
-
const key = params.set ? "set" : params.create ? "create" : "upsert";
|
|
827
|
-
throw new Error(`\`${key}\` option is not allowed in a batch update`);
|
|
828
|
-
}
|
|
829
|
-
const { primaryKeys, foreignKeys, query: relQuery } = this.state;
|
|
830
|
-
if (params.create || params.update || params.upsert || params.disconnect || params.set || params.delete) {
|
|
831
|
-
let appendedAs;
|
|
832
|
-
_hookSelectColumns(self, primaryKeys, (aliasedPrimaryKeys) => {
|
|
833
|
-
selectIdsSql._sql = selectCteColumnsSql(
|
|
834
|
-
appendedAs,
|
|
835
|
-
aliasedPrimaryKeys
|
|
836
|
-
);
|
|
837
|
-
if (params.create || params.set || params.upsert) {
|
|
838
|
-
foreignKeys.forEach((foreignKey, i) => {
|
|
839
|
-
setIds[foreignKey]._sql = selectCteColumnSql(
|
|
840
|
-
appendedAs,
|
|
841
|
-
aliasedPrimaryKeys[i]
|
|
842
|
-
);
|
|
843
|
-
});
|
|
844
|
-
}
|
|
845
|
-
});
|
|
846
|
-
const selectIdsSql = new RawSql("");
|
|
847
|
-
const existingRelQuery = _queryWhereIn(
|
|
848
|
-
_clone(relQuery),
|
|
849
|
-
true,
|
|
850
|
-
foreignKeys,
|
|
851
|
-
selectIdsSql
|
|
852
|
-
);
|
|
853
|
-
let setIds = void 0;
|
|
854
|
-
if (params.create || params.set || params.upsert) {
|
|
855
|
-
setIds = {};
|
|
856
|
-
foreignKeys.forEach((foreignKey) => {
|
|
857
|
-
setIds[foreignKey] = new RawSql("");
|
|
858
|
-
});
|
|
859
|
-
}
|
|
860
|
-
const nullifyOrDeleteQuery = params.update ? _queryUpdate(existingRelQuery, params.update) : params.upsert ? _queryUpsert(existingRelQuery, {
|
|
861
|
-
update: params.upsert.update,
|
|
862
|
-
create: {
|
|
863
|
-
...typeof params.upsert.create === "function" ? params.upsert.create() : params.upsert.create,
|
|
864
|
-
...setIds
|
|
865
|
-
}
|
|
866
|
-
}) : params.delete ? _queryDelete(existingRelQuery) : _queryUpdate(existingRelQuery, this.setNulls);
|
|
867
|
-
nullifyOrDeleteQuery.q.returnType = "void";
|
|
868
|
-
_appendQuery(self, nullifyOrDeleteQuery, (as) => appendedAs = as);
|
|
869
|
-
if (params.create) {
|
|
870
|
-
const createQuery = _queryInsert(_clone(relQuery), {
|
|
871
|
-
...params.create,
|
|
872
|
-
...setIds
|
|
873
|
-
});
|
|
874
|
-
_appendQuery(self, createQuery, noop);
|
|
875
|
-
} else if (params.set) {
|
|
876
|
-
const setQuery = _queryUpdate(
|
|
877
|
-
_queryWhere(_clone(relQuery), [params.set]),
|
|
878
|
-
setIds
|
|
879
|
-
);
|
|
880
|
-
setQuery.q.returnType = "void";
|
|
881
|
-
_appendQuery(self, setQuery, noop);
|
|
882
|
-
}
|
|
883
|
-
}
|
|
884
|
-
}
|
|
885
|
-
}
|
|
886
583
|
const makeHasOneMethod = (tableConfig, table, relation, relationName, query) => {
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
return joinHasRelation(
|
|
953
|
-
joiningQuery,
|
|
954
|
-
baseQuery,
|
|
955
|
-
foreignKeys,
|
|
956
|
-
primaryKeys,
|
|
957
|
-
len
|
|
958
|
-
);
|
|
959
|
-
};
|
|
960
|
-
return {
|
|
961
|
-
returns: "one",
|
|
962
|
-
queryRelated: (params) => {
|
|
963
|
-
const values = {};
|
|
964
|
-
for (let i = 0; i < len; i++) {
|
|
965
|
-
values[foreignKeys[i]] = params[primaryKeys[i]];
|
|
966
|
-
}
|
|
967
|
-
return _queryDefaults(query.where(values), { ...on, ...values });
|
|
968
|
-
},
|
|
969
|
-
virtualColumn: new HasOneVirtualColumn(
|
|
970
|
-
defaultSchemaConfig,
|
|
971
|
-
relationName,
|
|
972
|
-
state
|
|
973
|
-
),
|
|
974
|
-
joinQuery: joinQueryChainHOF(
|
|
975
|
-
relPKeys,
|
|
976
|
-
reverseJoin,
|
|
977
|
-
(joiningQuery, baseQuery) => joinHasRelation(
|
|
978
|
-
baseQuery,
|
|
979
|
-
joiningQuery,
|
|
980
|
-
primaryKeys,
|
|
981
|
-
foreignKeys,
|
|
982
|
-
len
|
|
983
|
-
)
|
|
984
|
-
),
|
|
985
|
-
reverseJoin,
|
|
986
|
-
modifyRelatedQuery(relationQuery) {
|
|
987
|
-
return (query2) => {
|
|
988
|
-
const baseQuery = query2.clone();
|
|
989
|
-
baseQuery.q.select = fromQuerySelect;
|
|
990
|
-
const q = relationQuery.q;
|
|
991
|
-
q.insertFrom = prepareSubQueryForSql(q, baseQuery);
|
|
992
|
-
q.values = [];
|
|
993
|
-
};
|
|
994
|
-
}
|
|
995
|
-
};
|
|
584
|
+
const relPKeys = getPrimaryKeys(query);
|
|
585
|
+
if ("through" in relation.options) {
|
|
586
|
+
const { through, source } = relation.options;
|
|
587
|
+
const throughRelation = getThroughRelation(table, through);
|
|
588
|
+
const sourceRelation = getSourceRelation(throughRelation, source);
|
|
589
|
+
const sourceRelationQuery = sourceRelation.query.as(relationName);
|
|
590
|
+
const sourceQuery = sourceRelation.joinQuery(sourceRelationQuery, throughRelation.query);
|
|
591
|
+
const whereExistsCallback = () => sourceQuery;
|
|
592
|
+
const reverseJoin = (baseQuery, joiningQuery) => {
|
|
593
|
+
return joinHasThrough(baseQuery, baseQuery, joiningQuery, throughRelation, sourceRelation);
|
|
594
|
+
};
|
|
595
|
+
return {
|
|
596
|
+
returns: "one",
|
|
597
|
+
queryRelated: (params) => {
|
|
598
|
+
const throughQuery = table.queryRelated(through, params);
|
|
599
|
+
return query.whereExists(throughQuery, whereExistsCallback);
|
|
600
|
+
},
|
|
601
|
+
joinQuery: joinQueryChainHOF(relPKeys, reverseJoin, (joiningQuery, baseQuery) => joinHasThrough(joiningQuery, baseQuery, joiningQuery, throughRelation, sourceRelation)),
|
|
602
|
+
reverseJoin
|
|
603
|
+
};
|
|
604
|
+
}
|
|
605
|
+
const primaryKeys = relation.options.columns;
|
|
606
|
+
const foreignKeys = relation.options.references;
|
|
607
|
+
const { on } = relation.options;
|
|
608
|
+
if (on) {
|
|
609
|
+
_queryWhere(query, [on]);
|
|
610
|
+
_queryDefaults(query, on);
|
|
611
|
+
}
|
|
612
|
+
addAutoForeignKey(tableConfig, query, table, primaryKeys, foreignKeys, relation.options);
|
|
613
|
+
const state = {
|
|
614
|
+
query,
|
|
615
|
+
primaryKeys,
|
|
616
|
+
foreignKeys,
|
|
617
|
+
on
|
|
618
|
+
};
|
|
619
|
+
const len = primaryKeys.length;
|
|
620
|
+
const reversedOn = {};
|
|
621
|
+
for (let i = 0; i < len; i++) reversedOn[foreignKeys[i]] = primaryKeys[i];
|
|
622
|
+
const fromQuerySelect = [{ selectAs: reversedOn }];
|
|
623
|
+
const reverseJoin = (baseQuery, joiningQuery) => {
|
|
624
|
+
return joinHasRelation(joiningQuery, baseQuery, foreignKeys, primaryKeys, len);
|
|
625
|
+
};
|
|
626
|
+
return {
|
|
627
|
+
returns: "one",
|
|
628
|
+
queryRelated: (params) => {
|
|
629
|
+
const values = {};
|
|
630
|
+
for (let i = 0; i < len; i++) values[foreignKeys[i]] = params[primaryKeys[i]];
|
|
631
|
+
return _queryDefaults(query.where(values), {
|
|
632
|
+
...on,
|
|
633
|
+
...values
|
|
634
|
+
});
|
|
635
|
+
},
|
|
636
|
+
virtualColumn: new HasOneVirtualColumn(defaultSchemaConfig, relationName, state),
|
|
637
|
+
joinQuery: joinQueryChainHOF(relPKeys, reverseJoin, (joiningQuery, baseQuery) => joinHasRelation(baseQuery, joiningQuery, primaryKeys, foreignKeys, len)),
|
|
638
|
+
reverseJoin,
|
|
639
|
+
modifyRelatedQuery(relationQuery) {
|
|
640
|
+
return (query) => {
|
|
641
|
+
const baseQuery = query.clone();
|
|
642
|
+
baseQuery.q.select = fromQuerySelect;
|
|
643
|
+
const q = relationQuery.q;
|
|
644
|
+
q.insertFrom = prepareSubQueryForSql(q, baseQuery);
|
|
645
|
+
q.values = [];
|
|
646
|
+
};
|
|
647
|
+
}
|
|
648
|
+
};
|
|
996
649
|
};
|
|
997
650
|
const nestedInsert$2 = ({ query, primaryKeys, foreignKeys }) => {
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
651
|
+
return (async (_, data) => {
|
|
652
|
+
const t = query.clone();
|
|
653
|
+
const items = [];
|
|
654
|
+
for (const item of data) if (item[1].connect || item[1].connectOrCreate) items.push(item);
|
|
655
|
+
let connected;
|
|
656
|
+
if (items.length) {
|
|
657
|
+
for (let i = 0, len = items.length; i < len; i++) {
|
|
658
|
+
const [selfData, item] = items[i];
|
|
659
|
+
const data = {};
|
|
660
|
+
primaryKeys.forEach((primaryKey, i) => {
|
|
661
|
+
data[foreignKeys[i]] = selfData[primaryKey];
|
|
662
|
+
});
|
|
663
|
+
items[i] = "connect" in item ? _queryUpdateOrThrow(t.where(item.connect), data) : _queryUpdate(t.where(item.connectOrCreate.where), data);
|
|
664
|
+
}
|
|
665
|
+
connected = await Promise.all(items);
|
|
666
|
+
} else connected = [];
|
|
667
|
+
let connectedI = 0;
|
|
668
|
+
items.length = 0;
|
|
669
|
+
for (const item of data) if (item[1].connectOrCreate) {
|
|
670
|
+
if (!connected[connectedI++]) items.push(item);
|
|
671
|
+
} else if (item[1].create) items.push(item);
|
|
672
|
+
if (items.length) {
|
|
673
|
+
for (let i = 0, len = items.length; i < len; i++) {
|
|
674
|
+
const [selfData, item] = items[i];
|
|
675
|
+
const data = { ..."create" in item ? item.create : item.connectOrCreate.create };
|
|
676
|
+
for (let i = 0; i < primaryKeys.length; i++) data[foreignKeys[i]] = selfData[primaryKeys[i]];
|
|
677
|
+
items[i] = data;
|
|
678
|
+
}
|
|
679
|
+
await t.insertMany(items);
|
|
680
|
+
}
|
|
681
|
+
});
|
|
682
|
+
};
|
|
683
|
+
var HasManyVirtualColumn = class extends VirtualColumn {
|
|
684
|
+
constructor(schema, key, state) {
|
|
685
|
+
super(schema);
|
|
686
|
+
this.key = key;
|
|
687
|
+
this.state = state;
|
|
688
|
+
this.nestedInsert = nestedInsert$1(state);
|
|
689
|
+
this.nestedUpdate = nestedUpdate$1(state);
|
|
690
|
+
}
|
|
691
|
+
create(self, ctx, items, rowIndexes, count) {
|
|
692
|
+
if (count <= self.qb.internal.nestedCreateBatchMax) {
|
|
693
|
+
const { query: rel, primaryKeys, foreignKeys } = this.state;
|
|
694
|
+
let nestedCreateItems;
|
|
695
|
+
items.forEach((item, i) => {
|
|
696
|
+
const value = item[this.key];
|
|
697
|
+
if (value.create?.length) {
|
|
698
|
+
const nestedCreateItem = (nestedCreateItems ??= {}).create ??= {
|
|
699
|
+
indexes: [],
|
|
700
|
+
items: []
|
|
701
|
+
};
|
|
702
|
+
nestedCreateItem.indexes.push(rowIndexes[i]);
|
|
703
|
+
const data = value.create.map((obj) => {
|
|
704
|
+
const data = { ...obj };
|
|
705
|
+
for (const key of foreignKeys) data[key] = new RawSql("");
|
|
706
|
+
return data;
|
|
707
|
+
});
|
|
708
|
+
nestedCreateItem.items.push(data);
|
|
709
|
+
} else {
|
|
710
|
+
const kind = value.connect?.length ? "connect" : value.connectOrCreate?.length ? "connectOrCreate" : void 0;
|
|
711
|
+
if (kind) {
|
|
712
|
+
const nestedCreateItem = (nestedCreateItems ??= {})[kind] ??= {
|
|
713
|
+
indexes: [],
|
|
714
|
+
items: [],
|
|
715
|
+
values: []
|
|
716
|
+
};
|
|
717
|
+
nestedCreateItem.indexes.push(rowIndexes[i]);
|
|
718
|
+
nestedCreateItem.values.push(value[kind]);
|
|
719
|
+
const data = {};
|
|
720
|
+
for (const key of foreignKeys) data[key] = new RawSql("");
|
|
721
|
+
nestedCreateItem.items.push(data);
|
|
722
|
+
}
|
|
723
|
+
}
|
|
724
|
+
});
|
|
725
|
+
if (!nestedCreateItems) return;
|
|
726
|
+
let createAs;
|
|
727
|
+
let connectAs;
|
|
728
|
+
let connectOrCreateAs;
|
|
729
|
+
_hookSelectColumns(self, primaryKeys, (aliasedPrimaryKeys) => {
|
|
730
|
+
foreignKeys.forEach((key, keyI) => {
|
|
731
|
+
const primaryKey = aliasedPrimaryKeys[keyI];
|
|
732
|
+
if (create && createAs) for (let i = 0; i < create.items.length; i++) {
|
|
733
|
+
const sql = selectCteColumnFromManySql(createAs, primaryKey, create.indexes[i], count);
|
|
734
|
+
for (const item of create.items[i]) item[key]._sql = sql;
|
|
735
|
+
}
|
|
736
|
+
if (connect && connectAs) for (let i = 0; i < connect.items.length; i++) connect.items[i][key]._sql = selectCteColumnFromManySql(connectAs, primaryKey, connect.indexes[i], count);
|
|
737
|
+
if (connectOrCreate && connectOrCreateAs) for (let i = 0; i < connectOrCreate.items.length; i++) connectOrCreate.items[i][key]._sql = selectCteColumnFromManySql(connectOrCreateAs, primaryKey, connectOrCreate.indexes[i], count);
|
|
738
|
+
});
|
|
739
|
+
});
|
|
740
|
+
const { create, connect, connectOrCreate } = nestedCreateItems;
|
|
741
|
+
if (create) _appendQuery(self, _queryInsertMany(_clone(rel), create.items.flat()), (as) => createAs = as);
|
|
742
|
+
if (connect) connect.values.forEach((value, i) => {
|
|
743
|
+
const query = _queryUpdateOrThrow(rel.whereOneOf(...value), connect.items[i]);
|
|
744
|
+
query.q.ensureCount = value.length;
|
|
745
|
+
_appendQuery(self, query, (as) => connectAs = as);
|
|
746
|
+
});
|
|
747
|
+
if (connectOrCreate) connectOrCreate.values.forEach((array, i) => {
|
|
748
|
+
const foreignKeyValues = connectOrCreate.items[i];
|
|
749
|
+
for (const value of array) _appendQuery(self, _queryUpsert(rel.where(value.where), {
|
|
750
|
+
update: foreignKeyValues,
|
|
751
|
+
create: {
|
|
752
|
+
...value.create,
|
|
753
|
+
...foreignKeyValues
|
|
754
|
+
}
|
|
755
|
+
}), (as) => connectOrCreateAs = as);
|
|
756
|
+
});
|
|
757
|
+
} else hasRelationHandleCreate(self, ctx, items, rowIndexes, this.key, this.state.primaryKeys, this.nestedInsert);
|
|
758
|
+
}
|
|
759
|
+
update(q, set) {
|
|
760
|
+
const params = set[this.key];
|
|
761
|
+
if ((params.set || params.create) && isQueryReturnsAll(q)) {
|
|
762
|
+
const key = params.set ? "set" : "create";
|
|
763
|
+
throw new Error(`\`${key}\` option is not allowed in a batch update`);
|
|
764
|
+
}
|
|
765
|
+
hasRelationHandleUpdate(q, set, this.key, this.state.primaryKeys, this.nestedUpdate);
|
|
766
|
+
}
|
|
1053
767
|
};
|
|
1054
|
-
|
|
1055
|
-
class HasManyVirtualColumn extends VirtualColumn {
|
|
1056
|
-
constructor(schema, key, state) {
|
|
1057
|
-
super(schema);
|
|
1058
|
-
this.key = key;
|
|
1059
|
-
this.state = state;
|
|
1060
|
-
this.nestedInsert = nestedInsert$1(state);
|
|
1061
|
-
this.nestedUpdate = nestedUpdate$1(state);
|
|
1062
|
-
}
|
|
1063
|
-
create(self, ctx, items, rowIndexes, count) {
|
|
1064
|
-
if (count <= self.qb.internal.nestedCreateBatchMax) {
|
|
1065
|
-
const { query: rel, primaryKeys, foreignKeys } = this.state;
|
|
1066
|
-
let nestedCreateItems;
|
|
1067
|
-
items.forEach((item, i) => {
|
|
1068
|
-
var _a, _b;
|
|
1069
|
-
const value = item[this.key];
|
|
1070
|
-
if (value.create?.length) {
|
|
1071
|
-
const nestedCreateItem = (_a = nestedCreateItems ?? (nestedCreateItems = {})).create ?? (_a.create = {
|
|
1072
|
-
indexes: [],
|
|
1073
|
-
items: []
|
|
1074
|
-
});
|
|
1075
|
-
nestedCreateItem.indexes.push(rowIndexes[i]);
|
|
1076
|
-
const data = value.create.map((obj) => {
|
|
1077
|
-
const data2 = { ...obj };
|
|
1078
|
-
for (const key of foreignKeys) {
|
|
1079
|
-
data2[key] = new RawSql("");
|
|
1080
|
-
}
|
|
1081
|
-
return data2;
|
|
1082
|
-
});
|
|
1083
|
-
nestedCreateItem.items.push(data);
|
|
1084
|
-
} else {
|
|
1085
|
-
const kind = value.connect?.length ? "connect" : value.connectOrCreate?.length ? "connectOrCreate" : void 0;
|
|
1086
|
-
if (kind) {
|
|
1087
|
-
const nestedCreateItem = (_b = nestedCreateItems ?? (nestedCreateItems = {}))[kind] ?? (_b[kind] = {
|
|
1088
|
-
indexes: [],
|
|
1089
|
-
items: [],
|
|
1090
|
-
values: []
|
|
1091
|
-
});
|
|
1092
|
-
nestedCreateItem.indexes.push(rowIndexes[i]);
|
|
1093
|
-
nestedCreateItem.values.push(value[kind]);
|
|
1094
|
-
const data = {};
|
|
1095
|
-
for (const key of foreignKeys) {
|
|
1096
|
-
data[key] = new RawSql("");
|
|
1097
|
-
}
|
|
1098
|
-
nestedCreateItem.items.push(data);
|
|
1099
|
-
}
|
|
1100
|
-
}
|
|
1101
|
-
});
|
|
1102
|
-
if (!nestedCreateItems) {
|
|
1103
|
-
return;
|
|
1104
|
-
}
|
|
1105
|
-
let createAs;
|
|
1106
|
-
let connectAs;
|
|
1107
|
-
let connectOrCreateAs;
|
|
1108
|
-
_hookSelectColumns(self, primaryKeys, (aliasedPrimaryKeys) => {
|
|
1109
|
-
foreignKeys.forEach((key, keyI) => {
|
|
1110
|
-
const primaryKey = aliasedPrimaryKeys[keyI];
|
|
1111
|
-
if (create && createAs) {
|
|
1112
|
-
for (let i = 0; i < create.items.length; i++) {
|
|
1113
|
-
const sql = selectCteColumnFromManySql(
|
|
1114
|
-
createAs,
|
|
1115
|
-
primaryKey,
|
|
1116
|
-
create.indexes[i],
|
|
1117
|
-
count
|
|
1118
|
-
);
|
|
1119
|
-
for (const item of create.items[i]) {
|
|
1120
|
-
item[key]._sql = sql;
|
|
1121
|
-
}
|
|
1122
|
-
}
|
|
1123
|
-
}
|
|
1124
|
-
if (connect && connectAs) {
|
|
1125
|
-
for (let i = 0; i < connect.items.length; i++) {
|
|
1126
|
-
connect.items[i][key]._sql = selectCteColumnFromManySql(
|
|
1127
|
-
connectAs,
|
|
1128
|
-
primaryKey,
|
|
1129
|
-
connect.indexes[i],
|
|
1130
|
-
count
|
|
1131
|
-
);
|
|
1132
|
-
}
|
|
1133
|
-
}
|
|
1134
|
-
if (connectOrCreate && connectOrCreateAs) {
|
|
1135
|
-
for (let i = 0; i < connectOrCreate.items.length; i++) {
|
|
1136
|
-
connectOrCreate.items[i][key]._sql = selectCteColumnFromManySql(
|
|
1137
|
-
connectOrCreateAs,
|
|
1138
|
-
primaryKey,
|
|
1139
|
-
connectOrCreate.indexes[i],
|
|
1140
|
-
count
|
|
1141
|
-
);
|
|
1142
|
-
}
|
|
1143
|
-
}
|
|
1144
|
-
});
|
|
1145
|
-
});
|
|
1146
|
-
const { create, connect, connectOrCreate } = nestedCreateItems;
|
|
1147
|
-
if (create) {
|
|
1148
|
-
const query = _queryInsertMany(
|
|
1149
|
-
_clone(rel),
|
|
1150
|
-
create.items.flat()
|
|
1151
|
-
);
|
|
1152
|
-
_appendQuery(self, query, (as) => createAs = as);
|
|
1153
|
-
}
|
|
1154
|
-
if (connect) {
|
|
1155
|
-
connect.values.forEach((value, i) => {
|
|
1156
|
-
const query = _queryUpdateOrThrow(
|
|
1157
|
-
rel.whereOneOf(...value),
|
|
1158
|
-
connect.items[i]
|
|
1159
|
-
);
|
|
1160
|
-
query.q.ensureCount = value.length;
|
|
1161
|
-
_appendQuery(self, query, (as) => connectAs = as);
|
|
1162
|
-
});
|
|
1163
|
-
}
|
|
1164
|
-
if (connectOrCreate) {
|
|
1165
|
-
connectOrCreate.values.forEach((array, i) => {
|
|
1166
|
-
const foreignKeyValues = connectOrCreate.items[i];
|
|
1167
|
-
for (const value of array) {
|
|
1168
|
-
const query = _queryUpsert(rel.where(value.where), {
|
|
1169
|
-
update: foreignKeyValues,
|
|
1170
|
-
create: {
|
|
1171
|
-
...value.create,
|
|
1172
|
-
...foreignKeyValues
|
|
1173
|
-
}
|
|
1174
|
-
});
|
|
1175
|
-
_appendQuery(self, query, (as) => connectOrCreateAs = as);
|
|
1176
|
-
}
|
|
1177
|
-
});
|
|
1178
|
-
}
|
|
1179
|
-
} else {
|
|
1180
|
-
hasRelationHandleCreate(
|
|
1181
|
-
self,
|
|
1182
|
-
ctx,
|
|
1183
|
-
items,
|
|
1184
|
-
rowIndexes,
|
|
1185
|
-
this.key,
|
|
1186
|
-
this.state.primaryKeys,
|
|
1187
|
-
this.nestedInsert
|
|
1188
|
-
);
|
|
1189
|
-
}
|
|
1190
|
-
}
|
|
1191
|
-
update(q, set) {
|
|
1192
|
-
const params = set[this.key];
|
|
1193
|
-
if ((params.set || params.create) && isQueryReturnsAll(q)) {
|
|
1194
|
-
const key = params.set ? "set" : "create";
|
|
1195
|
-
throw new Error(`\`${key}\` option is not allowed in a batch update`);
|
|
1196
|
-
}
|
|
1197
|
-
hasRelationHandleUpdate(
|
|
1198
|
-
q,
|
|
1199
|
-
set,
|
|
1200
|
-
this.key,
|
|
1201
|
-
this.state.primaryKeys,
|
|
1202
|
-
this.nestedUpdate
|
|
1203
|
-
);
|
|
1204
|
-
}
|
|
1205
|
-
}
|
|
1206
768
|
const makeHasManyMethod = (tableConfig, table, relation, relationName, query) => {
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
}
|
|
1273
|
-
const fromQuerySelect = [{ selectAs: reversedOn }];
|
|
1274
|
-
const reverseJoin = (baseQuery, joiningQuery) => {
|
|
1275
|
-
return joinHasRelation(
|
|
1276
|
-
joiningQuery,
|
|
1277
|
-
baseQuery,
|
|
1278
|
-
foreignKeys,
|
|
1279
|
-
primaryKeys,
|
|
1280
|
-
len
|
|
1281
|
-
);
|
|
1282
|
-
};
|
|
1283
|
-
return {
|
|
1284
|
-
returns: "many",
|
|
1285
|
-
queryRelated: (params) => {
|
|
1286
|
-
const values = {};
|
|
1287
|
-
for (let i = 0; i < len; i++) {
|
|
1288
|
-
values[foreignKeys[i]] = params[primaryKeys[i]];
|
|
1289
|
-
}
|
|
1290
|
-
return _queryDefaults(query.where(values), { ...on, ...values });
|
|
1291
|
-
},
|
|
1292
|
-
virtualColumn: new HasManyVirtualColumn(
|
|
1293
|
-
defaultSchemaConfig,
|
|
1294
|
-
relationName,
|
|
1295
|
-
state
|
|
1296
|
-
),
|
|
1297
|
-
joinQuery: joinQueryChainHOF(
|
|
1298
|
-
relPKeys,
|
|
1299
|
-
reverseJoin,
|
|
1300
|
-
(joiningQuery, baseQuery) => joinHasRelation(
|
|
1301
|
-
baseQuery,
|
|
1302
|
-
joiningQuery,
|
|
1303
|
-
primaryKeys,
|
|
1304
|
-
foreignKeys,
|
|
1305
|
-
len
|
|
1306
|
-
)
|
|
1307
|
-
),
|
|
1308
|
-
reverseJoin,
|
|
1309
|
-
modifyRelatedQuery(relationQuery) {
|
|
1310
|
-
return (query2) => {
|
|
1311
|
-
const baseQuery = query2.clone();
|
|
1312
|
-
baseQuery.q.select = fromQuerySelect;
|
|
1313
|
-
const q = relationQuery.q;
|
|
1314
|
-
q.insertFrom = prepareSubQueryForSql(q, baseQuery);
|
|
1315
|
-
q.values = [];
|
|
1316
|
-
};
|
|
1317
|
-
}
|
|
1318
|
-
};
|
|
769
|
+
const relPKeys = getPrimaryKeys(query);
|
|
770
|
+
if ("through" in relation.options) {
|
|
771
|
+
const { through, source } = relation.options;
|
|
772
|
+
const throughRelation = getThroughRelation(table, through);
|
|
773
|
+
const sourceRelation = getSourceRelation(throughRelation, source);
|
|
774
|
+
const sourceRelationQuery = sourceRelation.query.as(relationName);
|
|
775
|
+
const sourceQuery = sourceRelation.joinQuery(sourceRelationQuery, throughRelation.query);
|
|
776
|
+
const whereExistsCallback = () => sourceQuery;
|
|
777
|
+
const reverseJoin = (baseQuery, joiningQuery) => {
|
|
778
|
+
return joinHasThrough(baseQuery, baseQuery, joiningQuery, throughRelation, sourceRelation);
|
|
779
|
+
};
|
|
780
|
+
return {
|
|
781
|
+
returns: "many",
|
|
782
|
+
queryRelated: (params) => {
|
|
783
|
+
const throughQuery = table.queryRelated(through, params);
|
|
784
|
+
return query.whereExists(throughQuery, whereExistsCallback);
|
|
785
|
+
},
|
|
786
|
+
joinQuery: joinQueryChainHOF(relPKeys, reverseJoin, (joiningQuery, baseQuery) => joinHasThrough(joiningQuery, baseQuery, joiningQuery, throughRelation, sourceRelation)),
|
|
787
|
+
reverseJoin
|
|
788
|
+
};
|
|
789
|
+
}
|
|
790
|
+
const primaryKeys = relation.options.columns;
|
|
791
|
+
const foreignKeys = relation.options.references;
|
|
792
|
+
const { on } = relation.options;
|
|
793
|
+
if (on) {
|
|
794
|
+
_queryWhere(query, [on]);
|
|
795
|
+
_queryDefaults(query, on);
|
|
796
|
+
}
|
|
797
|
+
addAutoForeignKey(tableConfig, query, table, primaryKeys, foreignKeys, relation.options);
|
|
798
|
+
const state = {
|
|
799
|
+
query,
|
|
800
|
+
primaryKeys,
|
|
801
|
+
foreignKeys,
|
|
802
|
+
on
|
|
803
|
+
};
|
|
804
|
+
const len = primaryKeys.length;
|
|
805
|
+
const reversedOn = {};
|
|
806
|
+
for (let i = 0; i < len; i++) reversedOn[foreignKeys[i]] = primaryKeys[i];
|
|
807
|
+
const fromQuerySelect = [{ selectAs: reversedOn }];
|
|
808
|
+
const reverseJoin = (baseQuery, joiningQuery) => {
|
|
809
|
+
return joinHasRelation(joiningQuery, baseQuery, foreignKeys, primaryKeys, len);
|
|
810
|
+
};
|
|
811
|
+
return {
|
|
812
|
+
returns: "many",
|
|
813
|
+
queryRelated: (params) => {
|
|
814
|
+
const values = {};
|
|
815
|
+
for (let i = 0; i < len; i++) values[foreignKeys[i]] = params[primaryKeys[i]];
|
|
816
|
+
return _queryDefaults(query.where(values), {
|
|
817
|
+
...on,
|
|
818
|
+
...values
|
|
819
|
+
});
|
|
820
|
+
},
|
|
821
|
+
virtualColumn: new HasManyVirtualColumn(defaultSchemaConfig, relationName, state),
|
|
822
|
+
joinQuery: joinQueryChainHOF(relPKeys, reverseJoin, (joiningQuery, baseQuery) => joinHasRelation(baseQuery, joiningQuery, primaryKeys, foreignKeys, len)),
|
|
823
|
+
reverseJoin,
|
|
824
|
+
modifyRelatedQuery(relationQuery) {
|
|
825
|
+
return (query) => {
|
|
826
|
+
const baseQuery = query.clone();
|
|
827
|
+
baseQuery.q.select = fromQuerySelect;
|
|
828
|
+
const q = relationQuery.q;
|
|
829
|
+
q.insertFrom = prepareSubQueryForSql(q, baseQuery);
|
|
830
|
+
q.values = [];
|
|
831
|
+
};
|
|
832
|
+
}
|
|
833
|
+
};
|
|
1319
834
|
};
|
|
1320
835
|
const getWhereForNestedUpdate = (t, data, params, primaryKeys, foreignKeys) => {
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
|
|
836
|
+
return t.where({
|
|
837
|
+
IN: {
|
|
838
|
+
columns: foreignKeys,
|
|
839
|
+
values: data.map((item) => primaryKeys.map((key) => item[key]))
|
|
840
|
+
},
|
|
841
|
+
OR: params ? toArray(params) : void 0
|
|
842
|
+
});
|
|
1328
843
|
};
|
|
1329
844
|
const nestedInsert$1 = ({ query, primaryKeys, foreignKeys }) => {
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
|
|
1344
|
-
|
|
1345
|
-
|
|
1346
|
-
|
|
1347
|
-
|
|
1348
|
-
|
|
1349
|
-
|
|
1350
|
-
|
|
1351
|
-
|
|
1352
|
-
|
|
1353
|
-
|
|
1354
|
-
|
|
1355
|
-
|
|
1356
|
-
|
|
1357
|
-
|
|
1358
|
-
|
|
1359
|
-
|
|
1360
|
-
|
|
1361
|
-
|
|
1362
|
-
|
|
1363
|
-
|
|
1364
|
-
|
|
1365
|
-
|
|
1366
|
-
|
|
1367
|
-
|
|
1368
|
-
|
|
1369
|
-
|
|
1370
|
-
|
|
1371
|
-
|
|
1372
|
-
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
items.push(item);
|
|
1390
|
-
break;
|
|
1391
|
-
}
|
|
1392
|
-
}
|
|
1393
|
-
} else if (item[1].create) {
|
|
1394
|
-
items.push(item);
|
|
1395
|
-
}
|
|
1396
|
-
}
|
|
1397
|
-
connectedI = 0;
|
|
1398
|
-
if (items.length) {
|
|
1399
|
-
const records = [];
|
|
1400
|
-
for (const [selfData, { create, connectOrCreate }] of items) {
|
|
1401
|
-
const obj = {};
|
|
1402
|
-
for (let i = 0; i < len; i++) {
|
|
1403
|
-
obj[foreignKeys[i]] = selfData[primaryKeys[i]];
|
|
1404
|
-
}
|
|
1405
|
-
if (create) {
|
|
1406
|
-
for (const item of create) {
|
|
1407
|
-
records.push({
|
|
1408
|
-
...item,
|
|
1409
|
-
...obj
|
|
1410
|
-
});
|
|
1411
|
-
}
|
|
1412
|
-
}
|
|
1413
|
-
if (connectOrCreate) {
|
|
1414
|
-
for (const item of connectOrCreate) {
|
|
1415
|
-
if (connected[connectedI++] === 0) {
|
|
1416
|
-
records.push({
|
|
1417
|
-
...item.create,
|
|
1418
|
-
...obj
|
|
1419
|
-
});
|
|
1420
|
-
}
|
|
1421
|
-
}
|
|
1422
|
-
}
|
|
1423
|
-
}
|
|
1424
|
-
await _queryCreateMany(t, records);
|
|
1425
|
-
}
|
|
1426
|
-
};
|
|
845
|
+
const len = primaryKeys.length;
|
|
846
|
+
return (async (_, data) => {
|
|
847
|
+
const t = query.clone();
|
|
848
|
+
const items = [];
|
|
849
|
+
for (const item of data) if (item[1].connect) items.push(item);
|
|
850
|
+
if (items.length) {
|
|
851
|
+
for (let i = 0, len = items.length; i < len; i++) {
|
|
852
|
+
const [selfData, { connect }] = items[i];
|
|
853
|
+
const obj = {};
|
|
854
|
+
for (let i = 0; i < len; i++) obj[foreignKeys[i]] = selfData[primaryKeys[i]];
|
|
855
|
+
items[i] = _queryUpdateOrThrow(t.where({ OR: connect }), obj);
|
|
856
|
+
}
|
|
857
|
+
await Promise.all(items);
|
|
858
|
+
}
|
|
859
|
+
items.length = 0;
|
|
860
|
+
for (const item of data) if (item[1].connectOrCreate) items.push(item);
|
|
861
|
+
let connected;
|
|
862
|
+
if (items.length) {
|
|
863
|
+
const queries = [];
|
|
864
|
+
for (let i = 0, len = items.length; i < len; i++) {
|
|
865
|
+
const [selfData, { connectOrCreate }] = items[i];
|
|
866
|
+
for (const item of connectOrCreate) {
|
|
867
|
+
const obj = {};
|
|
868
|
+
for (let i = 0; i < len; i++) obj[foreignKeys[i]] = selfData[primaryKeys[i]];
|
|
869
|
+
queries.push(_queryUpdate(t.where(item.where), obj));
|
|
870
|
+
}
|
|
871
|
+
}
|
|
872
|
+
connected = await Promise.all(queries);
|
|
873
|
+
} else connected = [];
|
|
874
|
+
let connectedI = 0;
|
|
875
|
+
items.length = 0;
|
|
876
|
+
for (const item of data) if (item[1].connectOrCreate) {
|
|
877
|
+
const length = item[1].connectOrCreate.length;
|
|
878
|
+
connectedI += length;
|
|
879
|
+
for (let i = length; i > 0; i--) if (connected[connectedI - i] === 0) {
|
|
880
|
+
items.push(item);
|
|
881
|
+
break;
|
|
882
|
+
}
|
|
883
|
+
} else if (item[1].create) items.push(item);
|
|
884
|
+
connectedI = 0;
|
|
885
|
+
if (items.length) {
|
|
886
|
+
const records = [];
|
|
887
|
+
for (const [selfData, { create, connectOrCreate }] of items) {
|
|
888
|
+
const obj = {};
|
|
889
|
+
for (let i = 0; i < len; i++) obj[foreignKeys[i]] = selfData[primaryKeys[i]];
|
|
890
|
+
if (create) for (const item of create) records.push({
|
|
891
|
+
...item,
|
|
892
|
+
...obj
|
|
893
|
+
});
|
|
894
|
+
if (connectOrCreate) {
|
|
895
|
+
for (const item of connectOrCreate) if (connected[connectedI++] === 0) records.push({
|
|
896
|
+
...item.create,
|
|
897
|
+
...obj
|
|
898
|
+
});
|
|
899
|
+
}
|
|
900
|
+
}
|
|
901
|
+
await _queryCreateMany(t, records);
|
|
902
|
+
}
|
|
903
|
+
});
|
|
1427
904
|
};
|
|
1428
905
|
const nestedUpdate$1 = ({ query, primaryKeys, foreignKeys }) => {
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
|
|
1439
|
-
|
|
1440
|
-
|
|
1441
|
-
|
|
1442
|
-
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
|
|
1449
|
-
|
|
1450
|
-
|
|
1451
|
-
|
|
1452
|
-
|
|
1453
|
-
|
|
1454
|
-
|
|
1455
|
-
|
|
1456
|
-
|
|
1457
|
-
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
|
|
1472
|
-
|
|
1473
|
-
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
|
|
1481
|
-
|
|
1482
|
-
|
|
1483
|
-
queryToDisconnect = queryToDisconnect.whereNot(setConditions);
|
|
1484
|
-
}
|
|
1485
|
-
await _queryUpdate(queryToDisconnect, obj);
|
|
1486
|
-
if (setConditions) {
|
|
1487
|
-
const obj2 = {};
|
|
1488
|
-
for (let i = 0; i < len; i++) {
|
|
1489
|
-
obj2[foreignKeys[i]] = data[0][primaryKeys[i]];
|
|
1490
|
-
}
|
|
1491
|
-
await _queryUpdate(
|
|
1492
|
-
t.where(setConditions),
|
|
1493
|
-
obj2
|
|
1494
|
-
);
|
|
1495
|
-
}
|
|
1496
|
-
}
|
|
1497
|
-
if (params.delete || params.update) {
|
|
1498
|
-
const q = getWhereForNestedUpdate(
|
|
1499
|
-
t,
|
|
1500
|
-
data,
|
|
1501
|
-
params.delete || params.update?.where,
|
|
1502
|
-
primaryKeys,
|
|
1503
|
-
foreignKeys
|
|
1504
|
-
);
|
|
1505
|
-
if (params.delete) {
|
|
1506
|
-
await _queryDelete(q);
|
|
1507
|
-
} else if (params.update) {
|
|
1508
|
-
await _queryUpdate(q, params.update.data);
|
|
1509
|
-
}
|
|
1510
|
-
}
|
|
1511
|
-
};
|
|
906
|
+
const len = primaryKeys.length;
|
|
907
|
+
return (async (_, data, params) => {
|
|
908
|
+
const t = query.clone();
|
|
909
|
+
if (params.create) {
|
|
910
|
+
const obj = {};
|
|
911
|
+
for (let i = 0; i < len; i++) obj[foreignKeys[i]] = data[0][primaryKeys[i]];
|
|
912
|
+
await t.insertMany(params.create.map((create) => ({
|
|
913
|
+
...create,
|
|
914
|
+
...obj
|
|
915
|
+
})));
|
|
916
|
+
}
|
|
917
|
+
if (params.add) {
|
|
918
|
+
if (data.length > 1) throw new OrchidOrmInternalError(query, "`connect` is not available when updating multiple records, it is only applicable for a single record update");
|
|
919
|
+
const obj = {};
|
|
920
|
+
for (let i = 0; i < len; i++) obj[foreignKeys[i]] = data[0][primaryKeys[i]];
|
|
921
|
+
const relatedWheres = toArray(params.add);
|
|
922
|
+
const count = await _queryUpdate(t.where({ OR: relatedWheres }), obj);
|
|
923
|
+
if (count < relatedWheres.length) throw new OrchidOrmInternalError(query, `Expected to find at least ${relatedWheres.length} record(s) based on \`add\` conditions, but found ${count}`);
|
|
924
|
+
}
|
|
925
|
+
if (params.disconnect || params.set) {
|
|
926
|
+
const obj = {};
|
|
927
|
+
for (const foreignKey of foreignKeys) obj[foreignKey] = null;
|
|
928
|
+
const setConditions = params.set && (Array.isArray(params.set) ? params.set.length : objectHasValues(params.set)) && (Array.isArray(params.set) ? { OR: params.set } : params.set);
|
|
929
|
+
let queryToDisconnect = getWhereForNestedUpdate(t, data, params.disconnect, primaryKeys, foreignKeys);
|
|
930
|
+
if (setConditions) queryToDisconnect = queryToDisconnect.whereNot(setConditions);
|
|
931
|
+
await _queryUpdate(queryToDisconnect, obj);
|
|
932
|
+
if (setConditions) {
|
|
933
|
+
const obj = {};
|
|
934
|
+
for (let i = 0; i < len; i++) obj[foreignKeys[i]] = data[0][primaryKeys[i]];
|
|
935
|
+
await _queryUpdate(t.where(setConditions), obj);
|
|
936
|
+
}
|
|
937
|
+
}
|
|
938
|
+
if (params.delete || params.update) {
|
|
939
|
+
const q = getWhereForNestedUpdate(t, data, params.delete || params.update?.where, primaryKeys, foreignKeys);
|
|
940
|
+
if (params.delete) await _queryDelete(q);
|
|
941
|
+
else if (params.update) await _queryUpdate(q, params.update.data);
|
|
942
|
+
}
|
|
943
|
+
});
|
|
944
|
+
};
|
|
945
|
+
var HasAndBelongsToManyVirtualColumn = class extends VirtualColumn {
|
|
946
|
+
constructor(joinTable, schema, key, state) {
|
|
947
|
+
super(schema);
|
|
948
|
+
this.joinTable = joinTable;
|
|
949
|
+
this.key = key;
|
|
950
|
+
this.state = state;
|
|
951
|
+
this.nestedInsert = nestedInsert(state);
|
|
952
|
+
this.nestedUpdate = nestedUpdate(state);
|
|
953
|
+
}
|
|
954
|
+
create(q, ctx, items, rowIndexes) {
|
|
955
|
+
hasRelationHandleCreate(q, ctx, items, rowIndexes, this.key, this.state.primaryKeys, this.nestedInsert);
|
|
956
|
+
}
|
|
957
|
+
update(q, set) {
|
|
958
|
+
hasRelationHandleUpdate(q, set, this.key, this.state.primaryKeys, this.nestedUpdate);
|
|
959
|
+
}
|
|
1512
960
|
};
|
|
1513
|
-
|
|
1514
|
-
class HasAndBelongsToManyVirtualColumn extends VirtualColumn {
|
|
1515
|
-
constructor(joinTable, schema, key, state) {
|
|
1516
|
-
super(schema);
|
|
1517
|
-
this.joinTable = joinTable;
|
|
1518
|
-
this.key = key;
|
|
1519
|
-
this.state = state;
|
|
1520
|
-
this.nestedInsert = nestedInsert(state);
|
|
1521
|
-
this.nestedUpdate = nestedUpdate(state);
|
|
1522
|
-
}
|
|
1523
|
-
create(q, ctx, items, rowIndexes) {
|
|
1524
|
-
hasRelationHandleCreate(
|
|
1525
|
-
q,
|
|
1526
|
-
ctx,
|
|
1527
|
-
items,
|
|
1528
|
-
rowIndexes,
|
|
1529
|
-
this.key,
|
|
1530
|
-
this.state.primaryKeys,
|
|
1531
|
-
this.nestedInsert
|
|
1532
|
-
);
|
|
1533
|
-
}
|
|
1534
|
-
update(q, set) {
|
|
1535
|
-
hasRelationHandleUpdate(
|
|
1536
|
-
q,
|
|
1537
|
-
set,
|
|
1538
|
-
this.key,
|
|
1539
|
-
this.state.primaryKeys,
|
|
1540
|
-
this.nestedUpdate
|
|
1541
|
-
);
|
|
1542
|
-
}
|
|
1543
|
-
}
|
|
1544
961
|
const removeColumnName = (column) => {
|
|
1545
|
-
|
|
1546
|
-
|
|
1547
|
-
|
|
1548
|
-
|
|
962
|
+
if (!column.data.name) return column;
|
|
963
|
+
const cloned = Object.create(column);
|
|
964
|
+
cloned.data = {
|
|
965
|
+
...column.data,
|
|
966
|
+
name: void 0
|
|
967
|
+
};
|
|
968
|
+
return cloned;
|
|
1549
969
|
};
|
|
1550
970
|
const makeHasAndBelongsToManyMethod = (tableConfig, table, qb, relation, relationName, query, schema) => {
|
|
1551
|
-
|
|
1552
|
-
|
|
1553
|
-
|
|
1554
|
-
|
|
1555
|
-
|
|
1556
|
-
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
|
|
1561
|
-
|
|
1562
|
-
|
|
1563
|
-
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
-
|
|
1568
|
-
|
|
1569
|
-
|
|
1570
|
-
|
|
1571
|
-
|
|
1572
|
-
|
|
1573
|
-
|
|
1574
|
-
|
|
1575
|
-
|
|
1576
|
-
|
|
1577
|
-
|
|
1578
|
-
|
|
1579
|
-
|
|
1580
|
-
|
|
1581
|
-
|
|
1582
|
-
|
|
1583
|
-
|
|
1584
|
-
|
|
1585
|
-
|
|
1586
|
-
|
|
1587
|
-
|
|
1588
|
-
|
|
1589
|
-
|
|
1590
|
-
|
|
1591
|
-
|
|
1592
|
-
|
|
1593
|
-
|
|
1594
|
-
|
|
1595
|
-
|
|
1596
|
-
|
|
1597
|
-
|
|
1598
|
-
|
|
1599
|
-
|
|
1600
|
-
|
|
1601
|
-
|
|
1602
|
-
|
|
1603
|
-
|
|
1604
|
-
|
|
1605
|
-
|
|
1606
|
-
|
|
1607
|
-
|
|
1608
|
-
|
|
1609
|
-
|
|
1610
|
-
|
|
1611
|
-
|
|
1612
|
-
|
|
1613
|
-
|
|
1614
|
-
|
|
1615
|
-
|
|
1616
|
-
|
|
1617
|
-
|
|
1618
|
-
|
|
1619
|
-
|
|
1620
|
-
|
|
1621
|
-
|
|
1622
|
-
|
|
1623
|
-
|
|
1624
|
-
|
|
1625
|
-
|
|
1626
|
-
|
|
1627
|
-
|
|
1628
|
-
|
|
1629
|
-
|
|
1630
|
-
|
|
1631
|
-
|
|
1632
|
-
|
|
1633
|
-
|
|
1634
|
-
|
|
1635
|
-
|
|
1636
|
-
|
|
1637
|
-
|
|
1638
|
-
|
|
1639
|
-
|
|
1640
|
-
|
|
1641
|
-
|
|
1642
|
-
|
|
1643
|
-
|
|
1644
|
-
|
|
1645
|
-
|
|
1646
|
-
|
|
1647
|
-
|
|
1648
|
-
|
|
1649
|
-
|
|
1650
|
-
|
|
1651
|
-
|
|
1652
|
-
|
|
1653
|
-
|
|
1654
|
-
|
|
1655
|
-
|
|
1656
|
-
|
|
1657
|
-
|
|
1658
|
-
|
|
1659
|
-
|
|
1660
|
-
|
|
1661
|
-
|
|
1662
|
-
|
|
1663
|
-
|
|
1664
|
-
...baseQuery2.q.joinedShapes,
|
|
1665
|
-
[foreignAs]: joiningQuery.q.shape
|
|
1666
|
-
}
|
|
1667
|
-
);
|
|
1668
|
-
};
|
|
1669
|
-
return {
|
|
1670
|
-
returns: "many",
|
|
1671
|
-
queryRelated(params) {
|
|
1672
|
-
const q = query.whereExists(subQuery, (q2) => {
|
|
1673
|
-
q2 = q2.clone();
|
|
1674
|
-
const where = {};
|
|
1675
|
-
for (let i = 0; i < len; i++) {
|
|
1676
|
-
where[foreignKeysFull[i]] = params[primaryKeys[i]];
|
|
1677
|
-
}
|
|
1678
|
-
for (let i = 0; i < throughLen; i++) {
|
|
1679
|
-
_queryJoinOn(q2, [
|
|
1680
|
-
throughForeignKeysFull[i],
|
|
1681
|
-
throughPrimaryKeysFull[i]
|
|
1682
|
-
]);
|
|
1683
|
-
}
|
|
1684
|
-
return _queryWhere(q2, [where]);
|
|
1685
|
-
});
|
|
1686
|
-
return on ? _queryDefaults(q, on) : q;
|
|
1687
|
-
},
|
|
1688
|
-
virtualColumn: new HasAndBelongsToManyVirtualColumn(
|
|
1689
|
-
subQuery,
|
|
1690
|
-
defaultSchemaConfig,
|
|
1691
|
-
relationName,
|
|
1692
|
-
state
|
|
1693
|
-
),
|
|
1694
|
-
joinQuery: joinQueryChainHOF(
|
|
1695
|
-
getPrimaryKeys(query),
|
|
1696
|
-
reverseJoin,
|
|
1697
|
-
(joiningQuery, baseQuery2) => joinQuery(
|
|
1698
|
-
joiningQuery,
|
|
1699
|
-
getQueryAs(baseQuery2),
|
|
1700
|
-
getQueryAs(joiningQuery),
|
|
1701
|
-
{
|
|
1702
|
-
...joiningQuery.q.joinedShapes,
|
|
1703
|
-
[baseQuery2.q.as || baseQuery2.table]: baseQuery2.q.shape
|
|
1704
|
-
}
|
|
1705
|
-
)
|
|
1706
|
-
),
|
|
1707
|
-
reverseJoin,
|
|
1708
|
-
modifyRelatedQuery(relationQuery) {
|
|
1709
|
-
const ref = {};
|
|
1710
|
-
_queryHookAfterCreate(
|
|
1711
|
-
relationQuery,
|
|
1712
|
-
[],
|
|
1713
|
-
async (result) => {
|
|
1714
|
-
const baseQuery2 = ref.q.clone();
|
|
1715
|
-
baseQuery2.q.select = selectPrimaryKeysAsForeignKeys;
|
|
1716
|
-
const data = result.map((resultRow) => {
|
|
1717
|
-
const dataRow = {};
|
|
1718
|
-
for (let i = 0; i < throughLen; i++) {
|
|
1719
|
-
dataRow[throughForeignKeys[i]] = resultRow[throughPrimaryKeys[i]];
|
|
1720
|
-
}
|
|
1721
|
-
return dataRow;
|
|
1722
|
-
});
|
|
1723
|
-
const createdCount = await _queryCreateManyFrom(
|
|
1724
|
-
subQuery.count(),
|
|
1725
|
-
baseQuery2,
|
|
1726
|
-
data
|
|
1727
|
-
);
|
|
1728
|
-
if (createdCount === 0) {
|
|
1729
|
-
throw new NotFoundError(baseQuery2);
|
|
1730
|
-
}
|
|
1731
|
-
}
|
|
1732
|
-
);
|
|
1733
|
-
return (q) => {
|
|
1734
|
-
ref.q = q;
|
|
1735
|
-
};
|
|
1736
|
-
}
|
|
1737
|
-
};
|
|
971
|
+
const { options } = relation;
|
|
972
|
+
const { snakeCase } = table.internal;
|
|
973
|
+
const primaryKeys = options.columns;
|
|
974
|
+
const foreignKeys = options.references;
|
|
975
|
+
const originalForeignKeys = snakeCase ? [...foreignKeys] : foreignKeys;
|
|
976
|
+
const joinTable = options.through.table;
|
|
977
|
+
const throughForeignKeys = options.through.columns;
|
|
978
|
+
const originalThroughForeignKeys = snakeCase ? [...throughForeignKeys] : throughForeignKeys;
|
|
979
|
+
const throughPrimaryKeys = options.through.references;
|
|
980
|
+
const { on } = options;
|
|
981
|
+
if (on) {
|
|
982
|
+
_queryWhere(query, [on]);
|
|
983
|
+
_queryDefaults(query, on);
|
|
984
|
+
}
|
|
985
|
+
const foreignKeysFull = foreignKeys.map((key, i) => {
|
|
986
|
+
if (snakeCase) key = foreignKeys[i] = toSnakeCase(key);
|
|
987
|
+
return `${joinTable}.${key}`;
|
|
988
|
+
});
|
|
989
|
+
const throughForeignKeysFull = throughForeignKeys.map((key, i) => {
|
|
990
|
+
if (snakeCase) key = throughForeignKeys[i] = toSnakeCase(key);
|
|
991
|
+
return `${joinTable}.${key}`;
|
|
992
|
+
});
|
|
993
|
+
const foreignTable = getQueryAs(query);
|
|
994
|
+
const throughPrimaryKeysFull = throughPrimaryKeys.map((key) => `${foreignTable}.${key}`);
|
|
995
|
+
const len = primaryKeys.length;
|
|
996
|
+
const throughLen = throughPrimaryKeys.length;
|
|
997
|
+
const baseQuery = Object.create(qb.baseQuery);
|
|
998
|
+
baseQuery.baseQuery = baseQuery;
|
|
999
|
+
baseQuery.table = joinTable;
|
|
1000
|
+
const shape = {};
|
|
1001
|
+
const primaryKeysShape = {};
|
|
1002
|
+
for (let i = 0; i < len; i++) {
|
|
1003
|
+
const pk = primaryKeys[i];
|
|
1004
|
+
shape[foreignKeys[i]] = removeColumnName(table.shape[pk]);
|
|
1005
|
+
primaryKeysShape[pk] = table.shape[pk];
|
|
1006
|
+
}
|
|
1007
|
+
for (let i = 0; i < throughLen; i++) shape[throughForeignKeys[i]] = removeColumnName(query.shape[throughPrimaryKeys[i]]);
|
|
1008
|
+
baseQuery.shape = shape;
|
|
1009
|
+
baseQuery.q = {
|
|
1010
|
+
...baseQuery.q,
|
|
1011
|
+
schema: options.through.schema || schema,
|
|
1012
|
+
shape: baseQuery.shape
|
|
1013
|
+
};
|
|
1014
|
+
const subQuery = Object.create(baseQuery);
|
|
1015
|
+
addAutoForeignKey(tableConfig, subQuery, table, primaryKeys, foreignKeys, relation.options, originalForeignKeys);
|
|
1016
|
+
addAutoForeignKey(tableConfig, subQuery, query, throughPrimaryKeys, throughForeignKeys, relation.options.through, originalThroughForeignKeys);
|
|
1017
|
+
const state = {
|
|
1018
|
+
relatedTableQuery: query,
|
|
1019
|
+
joinTableQuery: subQuery,
|
|
1020
|
+
primaryKeys,
|
|
1021
|
+
foreignKeys,
|
|
1022
|
+
throughForeignKeys,
|
|
1023
|
+
throughPrimaryKeys,
|
|
1024
|
+
foreignKeysFull,
|
|
1025
|
+
throughForeignKeysFull,
|
|
1026
|
+
throughPrimaryKeysFull,
|
|
1027
|
+
primaryKeysShape,
|
|
1028
|
+
on
|
|
1029
|
+
};
|
|
1030
|
+
const joinQuery = (joiningQuery, tableAs, foreignAs, joinedShapes) => {
|
|
1031
|
+
const cloned = joiningQuery.clone();
|
|
1032
|
+
cloned.q.joinedShapes = joinedShapes;
|
|
1033
|
+
return _queryWhereExists(cloned, subQuery, [(q) => {
|
|
1034
|
+
for (let i = 0; i < throughLen; i++) _queryJoinOn(q, [throughForeignKeysFull[i], `${foreignAs}.${throughPrimaryKeys[i]}`]);
|
|
1035
|
+
for (let i = 0; i < len; i++) _queryJoinOn(q, [foreignKeysFull[i], `${tableAs}.${primaryKeys[i]}`]);
|
|
1036
|
+
return q;
|
|
1037
|
+
}]);
|
|
1038
|
+
};
|
|
1039
|
+
const obj = {};
|
|
1040
|
+
for (let i = 0; i < len; i++) obj[foreignKeys[i]] = primaryKeys[i];
|
|
1041
|
+
const selectPrimaryKeysAsForeignKeys = [{ selectAs: obj }];
|
|
1042
|
+
const reverseJoin = (baseQuery, joiningQuery) => {
|
|
1043
|
+
const foreignAs = getQueryAs(joiningQuery);
|
|
1044
|
+
return joinQuery(baseQuery, getQueryAs(baseQuery), foreignAs, {
|
|
1045
|
+
...baseQuery.q.joinedShapes,
|
|
1046
|
+
[foreignAs]: joiningQuery.q.shape
|
|
1047
|
+
});
|
|
1048
|
+
};
|
|
1049
|
+
return {
|
|
1050
|
+
returns: "many",
|
|
1051
|
+
queryRelated(params) {
|
|
1052
|
+
const q = query.whereExists(subQuery, (q) => {
|
|
1053
|
+
q = q.clone();
|
|
1054
|
+
const where = {};
|
|
1055
|
+
for (let i = 0; i < len; i++) where[foreignKeysFull[i]] = params[primaryKeys[i]];
|
|
1056
|
+
for (let i = 0; i < throughLen; i++) _queryJoinOn(q, [throughForeignKeysFull[i], throughPrimaryKeysFull[i]]);
|
|
1057
|
+
return _queryWhere(q, [where]);
|
|
1058
|
+
});
|
|
1059
|
+
return on ? _queryDefaults(q, on) : q;
|
|
1060
|
+
},
|
|
1061
|
+
virtualColumn: new HasAndBelongsToManyVirtualColumn(subQuery, defaultSchemaConfig, relationName, state),
|
|
1062
|
+
joinQuery: joinQueryChainHOF(getPrimaryKeys(query), reverseJoin, (joiningQuery, baseQuery) => joinQuery(joiningQuery, getQueryAs(baseQuery), getQueryAs(joiningQuery), {
|
|
1063
|
+
...joiningQuery.q.joinedShapes,
|
|
1064
|
+
[baseQuery.q.as || baseQuery.table]: baseQuery.q.shape
|
|
1065
|
+
})),
|
|
1066
|
+
reverseJoin,
|
|
1067
|
+
modifyRelatedQuery(relationQuery) {
|
|
1068
|
+
const ref = {};
|
|
1069
|
+
_queryHookAfterCreate(relationQuery, [], async (result) => {
|
|
1070
|
+
const baseQuery = ref.q.clone();
|
|
1071
|
+
baseQuery.q.select = selectPrimaryKeysAsForeignKeys;
|
|
1072
|
+
const data = result.map((resultRow) => {
|
|
1073
|
+
const dataRow = {};
|
|
1074
|
+
for (let i = 0; i < throughLen; i++) dataRow[throughForeignKeys[i]] = resultRow[throughPrimaryKeys[i]];
|
|
1075
|
+
return dataRow;
|
|
1076
|
+
});
|
|
1077
|
+
if (await _queryCreateManyFrom(subQuery.count(), baseQuery, data) === 0) throw new NotFoundError(baseQuery);
|
|
1078
|
+
});
|
|
1079
|
+
return (q) => {
|
|
1080
|
+
ref.q = q;
|
|
1081
|
+
};
|
|
1082
|
+
}
|
|
1083
|
+
};
|
|
1738
1084
|
};
|
|
1739
1085
|
const queryJoinTable = (state, data, conditions) => {
|
|
1740
|
-
|
|
1741
|
-
|
|
1742
|
-
|
|
1743
|
-
|
|
1744
|
-
|
|
1745
|
-
|
|
1746
|
-
|
|
1747
|
-
|
|
1748
|
-
|
|
1749
|
-
|
|
1750
|
-
|
|
1751
|
-
|
|
1752
|
-
|
|
1753
|
-
state.throughPrimaryKeys
|
|
1754
|
-
)
|
|
1755
|
-
}
|
|
1756
|
-
}
|
|
1757
|
-
]);
|
|
1758
|
-
}
|
|
1759
|
-
if (state.on) {
|
|
1760
|
-
_queryWhereExists(t, state.relatedTableQuery, [
|
|
1761
|
-
(q) => {
|
|
1762
|
-
for (let i = 0; i < state.throughPrimaryKeys.length; i++) {
|
|
1763
|
-
_queryJoinOn(q, [
|
|
1764
|
-
state.throughPrimaryKeysFull[i],
|
|
1765
|
-
state.throughForeignKeysFull[i]
|
|
1766
|
-
]);
|
|
1767
|
-
}
|
|
1768
|
-
return q;
|
|
1769
|
-
}
|
|
1770
|
-
]);
|
|
1771
|
-
}
|
|
1772
|
-
return t;
|
|
1086
|
+
const t = state.joinTableQuery.where({ IN: {
|
|
1087
|
+
columns: state.foreignKeys,
|
|
1088
|
+
values: data.map((item) => state.primaryKeys.map((key) => item[key]))
|
|
1089
|
+
} });
|
|
1090
|
+
if (conditions) _queryWhere(t, [{ IN: {
|
|
1091
|
+
columns: state.throughForeignKeys,
|
|
1092
|
+
values: _querySelect(state.relatedTableQuery.where(conditionsToWhereArg(conditions)), state.throughPrimaryKeys)
|
|
1093
|
+
} }]);
|
|
1094
|
+
if (state.on) _queryWhereExists(t, state.relatedTableQuery, [(q) => {
|
|
1095
|
+
for (let i = 0; i < state.throughPrimaryKeys.length; i++) _queryJoinOn(q, [state.throughPrimaryKeysFull[i], state.throughForeignKeysFull[i]]);
|
|
1096
|
+
return q;
|
|
1097
|
+
}]);
|
|
1098
|
+
return t;
|
|
1773
1099
|
};
|
|
1774
1100
|
const conditionsToWhereArg = (conditions) => Array.isArray(conditions) ? { OR: conditions } : conditions;
|
|
1775
1101
|
const insertToJoinTable = (state, joinTableTransaction, data, idsRows) => {
|
|
1776
|
-
|
|
1777
|
-
|
|
1778
|
-
|
|
1779
|
-
|
|
1780
|
-
|
|
1781
|
-
|
|
1782
|
-
|
|
1783
|
-
|
|
1784
|
-
|
|
1785
|
-
|
|
1786
|
-
|
|
1787
|
-
|
|
1788
|
-
|
|
1789
|
-
records.push(record);
|
|
1790
|
-
}
|
|
1791
|
-
}
|
|
1792
|
-
return joinTableTransaction.insertMany(records);
|
|
1102
|
+
const len = state.primaryKeys.length;
|
|
1103
|
+
const throughLen = state.throughPrimaryKeys.length;
|
|
1104
|
+
const records = [];
|
|
1105
|
+
for (const item of data) {
|
|
1106
|
+
const obj = {};
|
|
1107
|
+
for (let i = 0; i < len; i++) obj[state.foreignKeys[i]] = item[state.primaryKeys[i]];
|
|
1108
|
+
for (const ids of idsRows) {
|
|
1109
|
+
const record = { ...obj };
|
|
1110
|
+
for (let i = 0; i < throughLen; i++) record[state.throughForeignKeys[i]] = ids[i];
|
|
1111
|
+
records.push(record);
|
|
1112
|
+
}
|
|
1113
|
+
}
|
|
1114
|
+
return joinTableTransaction.insertMany(records);
|
|
1793
1115
|
};
|
|
1794
|
-
const nestedInsert = ({
|
|
1795
|
-
|
|
1796
|
-
|
|
1797
|
-
|
|
1798
|
-
|
|
1799
|
-
|
|
1800
|
-
|
|
1801
|
-
|
|
1802
|
-
|
|
1803
|
-
|
|
1804
|
-
|
|
1805
|
-
|
|
1806
|
-
|
|
1807
|
-
|
|
1808
|
-
|
|
1809
|
-
|
|
1810
|
-
|
|
1811
|
-
|
|
1812
|
-
|
|
1813
|
-
|
|
1814
|
-
|
|
1815
|
-
|
|
1816
|
-
|
|
1817
|
-
|
|
1818
|
-
|
|
1819
|
-
|
|
1820
|
-
|
|
1821
|
-
|
|
1822
|
-
|
|
1823
|
-
|
|
1824
|
-
|
|
1825
|
-
|
|
1826
|
-
|
|
1827
|
-
|
|
1828
|
-
|
|
1829
|
-
|
|
1830
|
-
|
|
1831
|
-
|
|
1832
|
-
|
|
1833
|
-
|
|
1834
|
-
|
|
1835
|
-
|
|
1836
|
-
|
|
1837
|
-
|
|
1838
|
-
|
|
1839
|
-
|
|
1840
|
-
|
|
1841
|
-
|
|
1842
|
-
|
|
1843
|
-
|
|
1844
|
-
|
|
1845
|
-
|
|
1846
|
-
|
|
1847
|
-
|
|
1848
|
-
|
|
1849
|
-
|
|
1850
|
-
|
|
1851
|
-
|
|
1852
|
-
|
|
1853
|
-
|
|
1854
|
-
|
|
1855
|
-
|
|
1856
|
-
|
|
1857
|
-
|
|
1858
|
-
|
|
1859
|
-
|
|
1860
|
-
|
|
1861
|
-
|
|
1862
|
-
|
|
1863
|
-
|
|
1864
|
-
|
|
1865
|
-
|
|
1866
|
-
|
|
1867
|
-
|
|
1868
|
-
|
|
1869
|
-
|
|
1870
|
-
|
|
1871
|
-
|
|
1872
|
-
|
|
1873
|
-
|
|
1874
|
-
|
|
1875
|
-
|
|
1876
|
-
|
|
1877
|
-
|
|
1878
|
-
if (!connectOrCreated[connectOrCreateI++]) {
|
|
1879
|
-
records2.push(item.create);
|
|
1880
|
-
}
|
|
1881
|
-
}
|
|
1882
|
-
}
|
|
1883
|
-
}
|
|
1884
|
-
created = await _queryCreateMany(
|
|
1885
|
-
t.select(...throughPrimaryKeys),
|
|
1886
|
-
records2
|
|
1887
|
-
);
|
|
1888
|
-
} else {
|
|
1889
|
-
created = [];
|
|
1890
|
-
}
|
|
1891
|
-
const allKeys = data;
|
|
1892
|
-
let createI = 0;
|
|
1893
|
-
let connectI = 0;
|
|
1894
|
-
connectOrCreateI = 0;
|
|
1895
|
-
for (let index = 0, len2 = data.length; index < len2; index++) {
|
|
1896
|
-
const item = data[index][1];
|
|
1897
|
-
if (item.create || item.connectOrCreate) {
|
|
1898
|
-
if (item.create) {
|
|
1899
|
-
const len3 = item.create.length;
|
|
1900
|
-
allKeys[index][1] = created.slice(createI, createI + len3);
|
|
1901
|
-
createI += len3;
|
|
1902
|
-
}
|
|
1903
|
-
if (item.connectOrCreate) {
|
|
1904
|
-
const arr = [];
|
|
1905
|
-
allKeys[index][1] = arr;
|
|
1906
|
-
const len3 = item.connectOrCreate.length;
|
|
1907
|
-
for (let i = 0; i < len3; i++) {
|
|
1908
|
-
const item2 = connectOrCreated[connectOrCreateI++];
|
|
1909
|
-
if (item2) {
|
|
1910
|
-
arr.push(item2);
|
|
1911
|
-
} else {
|
|
1912
|
-
arr.push(created[createI++]);
|
|
1913
|
-
}
|
|
1914
|
-
}
|
|
1915
|
-
}
|
|
1916
|
-
}
|
|
1917
|
-
if (item.connect) {
|
|
1918
|
-
const len3 = item.connect.length;
|
|
1919
|
-
allKeys[index][1] = connected.slice(connectI, connectI + len3);
|
|
1920
|
-
connectI += len3;
|
|
1921
|
-
}
|
|
1922
|
-
}
|
|
1923
|
-
const records = [];
|
|
1924
|
-
for (const [selfData, relationKeys] of allKeys) {
|
|
1925
|
-
const obj = {};
|
|
1926
|
-
for (let i = 0; i < len; i++) {
|
|
1927
|
-
obj[foreignKeys[i]] = selfData[primaryKeys[i]];
|
|
1928
|
-
}
|
|
1929
|
-
for (const relationData of relationKeys) {
|
|
1930
|
-
const record = { ...obj };
|
|
1931
|
-
for (let i = 0; i < throughLen; i++) {
|
|
1932
|
-
record[throughForeignKeys[i]] = relationData[throughPrimaryKeys[i]];
|
|
1933
|
-
}
|
|
1934
|
-
records.push(record);
|
|
1935
|
-
}
|
|
1936
|
-
}
|
|
1937
|
-
await joinTableQuery.insertMany(records);
|
|
1938
|
-
};
|
|
1116
|
+
const nestedInsert = ({ relatedTableQuery, joinTableQuery, primaryKeys, foreignKeys, throughPrimaryKeys, throughForeignKeys }) => {
|
|
1117
|
+
const len = primaryKeys.length;
|
|
1118
|
+
const throughLen = primaryKeys.length;
|
|
1119
|
+
return (async (_, data) => {
|
|
1120
|
+
const t = relatedTableQuery.clone();
|
|
1121
|
+
const items = [];
|
|
1122
|
+
for (const item of data) if (item[1].connect) items.push(item);
|
|
1123
|
+
let connected;
|
|
1124
|
+
if (items.length) {
|
|
1125
|
+
const queries = [];
|
|
1126
|
+
for (const [, { connect }] of items) for (const item of connect) queries.push(_queryFindBy(t.select(...throughPrimaryKeys), item));
|
|
1127
|
+
connected = await Promise.all(queries);
|
|
1128
|
+
} else connected = [];
|
|
1129
|
+
items.length = 0;
|
|
1130
|
+
for (const item of data) if (item[1].connectOrCreate) items.push(item);
|
|
1131
|
+
let connectOrCreated;
|
|
1132
|
+
if (items.length) {
|
|
1133
|
+
const queries = [];
|
|
1134
|
+
for (const [, { connectOrCreate }] of items) for (const item of connectOrCreate) queries.push(_queryFindByOptional(t.select(...throughPrimaryKeys), item.where));
|
|
1135
|
+
connectOrCreated = await Promise.all(queries);
|
|
1136
|
+
} else connectOrCreated = [];
|
|
1137
|
+
let connectOrCreateI = 0;
|
|
1138
|
+
items.length = 0;
|
|
1139
|
+
for (const item of data) if (item[1].connectOrCreate) {
|
|
1140
|
+
const length = item[1].connectOrCreate.length;
|
|
1141
|
+
connectOrCreateI += length;
|
|
1142
|
+
for (let i = length; i > 0; i--) if (!connectOrCreated[connectOrCreateI - i]) {
|
|
1143
|
+
items.push(item);
|
|
1144
|
+
break;
|
|
1145
|
+
}
|
|
1146
|
+
} else if (item[1].create) items.push(item);
|
|
1147
|
+
connectOrCreateI = 0;
|
|
1148
|
+
let created;
|
|
1149
|
+
if (items.length) {
|
|
1150
|
+
const records = [];
|
|
1151
|
+
for (const [, { create, connectOrCreate }] of items) {
|
|
1152
|
+
if (create) records.push(...create);
|
|
1153
|
+
if (connectOrCreate) {
|
|
1154
|
+
for (const item of connectOrCreate) if (!connectOrCreated[connectOrCreateI++]) records.push(item.create);
|
|
1155
|
+
}
|
|
1156
|
+
}
|
|
1157
|
+
created = await _queryCreateMany(t.select(...throughPrimaryKeys), records);
|
|
1158
|
+
} else created = [];
|
|
1159
|
+
const allKeys = data;
|
|
1160
|
+
let createI = 0;
|
|
1161
|
+
let connectI = 0;
|
|
1162
|
+
connectOrCreateI = 0;
|
|
1163
|
+
for (let index = 0, len = data.length; index < len; index++) {
|
|
1164
|
+
const item = data[index][1];
|
|
1165
|
+
if (item.create || item.connectOrCreate) {
|
|
1166
|
+
if (item.create) {
|
|
1167
|
+
const len = item.create.length;
|
|
1168
|
+
allKeys[index][1] = created.slice(createI, createI + len);
|
|
1169
|
+
createI += len;
|
|
1170
|
+
}
|
|
1171
|
+
if (item.connectOrCreate) {
|
|
1172
|
+
const arr = [];
|
|
1173
|
+
allKeys[index][1] = arr;
|
|
1174
|
+
const len = item.connectOrCreate.length;
|
|
1175
|
+
for (let i = 0; i < len; i++) {
|
|
1176
|
+
const item = connectOrCreated[connectOrCreateI++];
|
|
1177
|
+
if (item) arr.push(item);
|
|
1178
|
+
else arr.push(created[createI++]);
|
|
1179
|
+
}
|
|
1180
|
+
}
|
|
1181
|
+
}
|
|
1182
|
+
if (item.connect) {
|
|
1183
|
+
const len = item.connect.length;
|
|
1184
|
+
allKeys[index][1] = connected.slice(connectI, connectI + len);
|
|
1185
|
+
connectI += len;
|
|
1186
|
+
}
|
|
1187
|
+
}
|
|
1188
|
+
const records = [];
|
|
1189
|
+
for (const [selfData, relationKeys] of allKeys) {
|
|
1190
|
+
const obj = {};
|
|
1191
|
+
for (let i = 0; i < len; i++) obj[foreignKeys[i]] = selfData[primaryKeys[i]];
|
|
1192
|
+
for (const relationData of relationKeys) {
|
|
1193
|
+
const record = { ...obj };
|
|
1194
|
+
for (let i = 0; i < throughLen; i++) record[throughForeignKeys[i]] = relationData[throughPrimaryKeys[i]];
|
|
1195
|
+
records.push(record);
|
|
1196
|
+
}
|
|
1197
|
+
}
|
|
1198
|
+
await joinTableQuery.insertMany(records);
|
|
1199
|
+
});
|
|
1939
1200
|
};
|
|
1940
1201
|
const nestedUpdate = (state) => {
|
|
1941
|
-
|
|
1942
|
-
|
|
1943
|
-
|
|
1944
|
-
|
|
1945
|
-
|
|
1946
|
-
|
|
1947
|
-
|
|
1948
|
-
|
|
1949
|
-
|
|
1950
|
-
|
|
1951
|
-
|
|
1952
|
-
|
|
1953
|
-
|
|
1954
|
-
|
|
1955
|
-
|
|
1956
|
-
|
|
1957
|
-
|
|
1958
|
-
|
|
1959
|
-
|
|
1960
|
-
|
|
1961
|
-
|
|
1962
|
-
|
|
1963
|
-
|
|
1964
|
-
|
|
1965
|
-
|
|
1966
|
-
|
|
1967
|
-
|
|
1968
|
-
|
|
1969
|
-
|
|
1970
|
-
|
|
1971
|
-
|
|
1972
|
-
|
|
1973
|
-
|
|
1974
|
-
|
|
1975
|
-
|
|
1976
|
-
|
|
1977
|
-
|
|
1978
|
-
|
|
1979
|
-
|
|
1980
|
-
|
|
1981
|
-
|
|
1982
|
-
|
|
1983
|
-
|
|
1984
|
-
|
|
1985
|
-
|
|
1986
|
-
|
|
1987
|
-
|
|
1988
|
-
|
|
1989
|
-
|
|
1990
|
-
|
|
1991
|
-
|
|
1992
|
-
|
|
1993
|
-
|
|
1994
|
-
|
|
1995
|
-
|
|
1996
|
-
...state.throughForeignKeys
|
|
1997
|
-
];
|
|
1998
|
-
try {
|
|
1999
|
-
const count = await state.joinTableQuery.insertForEachFrom(
|
|
2000
|
-
_querySelect(
|
|
2001
|
-
state.relatedTableQuery.whereOneOf(...relatedWheres),
|
|
2002
|
-
[
|
|
2003
|
-
Object.fromEntries([
|
|
2004
|
-
...state.primaryKeys.map((key, i) => [
|
|
2005
|
-
state.foreignKeys[i],
|
|
2006
|
-
as + "." + (state.primaryKeysShape[key].data.name || key)
|
|
2007
|
-
]),
|
|
2008
|
-
...state.throughForeignKeys.map((key, i) => [
|
|
2009
|
-
key,
|
|
2010
|
-
state.throughPrimaryKeys[i]
|
|
2011
|
-
])
|
|
2012
|
-
])
|
|
2013
|
-
]
|
|
2014
|
-
).joinData(
|
|
2015
|
-
as,
|
|
2016
|
-
() => Object.fromEntries(
|
|
2017
|
-
state.primaryKeys.map((key) => [
|
|
2018
|
-
key,
|
|
2019
|
-
state.primaryKeysShape[key]
|
|
2020
|
-
])
|
|
2021
|
-
),
|
|
2022
|
-
data.map((x) => pick(x, state.primaryKeys))
|
|
2023
|
-
)
|
|
2024
|
-
).onConflict(joinTableColumns).merge([state.foreignKeys[0]]);
|
|
2025
|
-
if (count < data.length * relatedWheres.length) {
|
|
2026
|
-
throw new OrchidOrmInternalError(
|
|
2027
|
-
query,
|
|
2028
|
-
`Expected to find at least ${relatedWheres.length} record(s) based on \`add\` conditions, but found ${count / data.length}`
|
|
2029
|
-
);
|
|
2030
|
-
}
|
|
2031
|
-
} catch (err) {
|
|
2032
|
-
if (err.code === "42P10") {
|
|
2033
|
-
throw new OrchidOrmInternalError(
|
|
2034
|
-
query,
|
|
2035
|
-
`"${state.joinTableQuery.table}" must have a primary key or a unique index on columns (${joinTableColumns.join(
|
|
2036
|
-
", "
|
|
2037
|
-
)}) for this kind of query.`
|
|
2038
|
-
);
|
|
2039
|
-
}
|
|
2040
|
-
throw err;
|
|
2041
|
-
}
|
|
2042
|
-
}
|
|
2043
|
-
if (params.disconnect) {
|
|
2044
|
-
await _queryDelete(
|
|
2045
|
-
queryJoinTable(state, data, params.disconnect)
|
|
2046
|
-
);
|
|
2047
|
-
}
|
|
2048
|
-
if (params.delete) {
|
|
2049
|
-
const j = queryJoinTable(state, data, params.delete);
|
|
2050
|
-
const idsRows = await _queryDelete(
|
|
2051
|
-
_queryRows(_querySelect(j, state.throughForeignKeys))
|
|
2052
|
-
);
|
|
2053
|
-
await _queryDelete(
|
|
2054
|
-
state.relatedTableQuery.where({
|
|
2055
|
-
IN: {
|
|
2056
|
-
columns: state.throughPrimaryKeys,
|
|
2057
|
-
values: idsRows
|
|
2058
|
-
}
|
|
2059
|
-
})
|
|
2060
|
-
);
|
|
2061
|
-
}
|
|
2062
|
-
if (params.set) {
|
|
2063
|
-
const j = queryJoinTable(state, data);
|
|
2064
|
-
await _queryDelete(j);
|
|
2065
|
-
if (Array.isArray(params.set) ? params.set.length : objectHasValues(params.set)) {
|
|
2066
|
-
const idsRows = await _queryRows(
|
|
2067
|
-
_querySelect(
|
|
2068
|
-
state.relatedTableQuery.where(
|
|
2069
|
-
conditionsToWhereArg(params.set)
|
|
2070
|
-
),
|
|
2071
|
-
state.throughPrimaryKeys
|
|
2072
|
-
)
|
|
2073
|
-
);
|
|
2074
|
-
await insertToJoinTable(state, j, data, idsRows);
|
|
2075
|
-
}
|
|
2076
|
-
}
|
|
2077
|
-
};
|
|
1202
|
+
const len = state.primaryKeys.length;
|
|
1203
|
+
const throughLen = state.throughPrimaryKeys.length;
|
|
1204
|
+
return (async (query, data, params) => {
|
|
1205
|
+
if (params.create) {
|
|
1206
|
+
const idsRows = await _queryCreateMany(_queryRows(state.relatedTableQuery.select(...state.throughPrimaryKeys)), params.create);
|
|
1207
|
+
const records = [];
|
|
1208
|
+
for (const item of data) {
|
|
1209
|
+
const obj = {};
|
|
1210
|
+
for (let i = 0; i < len; i++) obj[state.foreignKeys[i]] = item[state.primaryKeys[i]];
|
|
1211
|
+
for (const ids of idsRows) {
|
|
1212
|
+
const record = { ...obj };
|
|
1213
|
+
for (let i = 0; i < throughLen; i++) record[state.throughForeignKeys[i]] = ids[i];
|
|
1214
|
+
records.push(record);
|
|
1215
|
+
}
|
|
1216
|
+
}
|
|
1217
|
+
await state.joinTableQuery.createMany(records);
|
|
1218
|
+
}
|
|
1219
|
+
if (params.update) await _queryUpdate(_queryWhere(state.relatedTableQuery.whereExists(state.joinTableQuery, (q) => {
|
|
1220
|
+
for (let i = 0; i < throughLen; i++) _queryJoinOn(q, [state.throughForeignKeysFull[i], state.throughPrimaryKeysFull[i]]);
|
|
1221
|
+
return _queryWhere(q, [{ IN: {
|
|
1222
|
+
columns: state.foreignKeysFull,
|
|
1223
|
+
values: data.map((item) => state.primaryKeys.map((key) => item[key]))
|
|
1224
|
+
} }]);
|
|
1225
|
+
}), [conditionsToWhereArg(params.update.where)]), params.update.data);
|
|
1226
|
+
/**
|
|
1227
|
+
* Performs `insertForEachFrom` on the joining table,
|
|
1228
|
+
* based on a query to the related table with applied filters of `params.connect`,
|
|
1229
|
+
* joins the main table data using `joinData`.
|
|
1230
|
+
*/
|
|
1231
|
+
if (params.add) {
|
|
1232
|
+
const as = query.table;
|
|
1233
|
+
const relatedWheres = toArray(params.add);
|
|
1234
|
+
const joinTableColumns = [...state.foreignKeys, ...state.throughForeignKeys];
|
|
1235
|
+
try {
|
|
1236
|
+
const count = await state.joinTableQuery.insertForEachFrom(_querySelect(state.relatedTableQuery.whereOneOf(...relatedWheres), [Object.fromEntries([...state.primaryKeys.map((key, i) => [state.foreignKeys[i], as + "." + (state.primaryKeysShape[key].data.name || key)]), ...state.throughForeignKeys.map((key, i) => [key, state.throughPrimaryKeys[i]])])]).joinData(as, () => Object.fromEntries(state.primaryKeys.map((key) => [key, state.primaryKeysShape[key]])), data.map((x) => pick(x, state.primaryKeys)))).onConflict(joinTableColumns).merge([state.foreignKeys[0]]);
|
|
1237
|
+
if (count < data.length * relatedWheres.length) throw new OrchidOrmInternalError(query, `Expected to find at least ${relatedWheres.length} record(s) based on \`add\` conditions, but found ${count / data.length}`);
|
|
1238
|
+
} catch (err) {
|
|
1239
|
+
if (err.code === "42P10") throw new OrchidOrmInternalError(query, `"${state.joinTableQuery.table}" must have a primary key or a unique index on columns (${joinTableColumns.join(", ")}) for this kind of query.`);
|
|
1240
|
+
throw err;
|
|
1241
|
+
}
|
|
1242
|
+
}
|
|
1243
|
+
if (params.disconnect) await _queryDelete(queryJoinTable(state, data, params.disconnect));
|
|
1244
|
+
if (params.delete) {
|
|
1245
|
+
const idsRows = await _queryDelete(_queryRows(_querySelect(queryJoinTable(state, data, params.delete), state.throughForeignKeys)));
|
|
1246
|
+
await _queryDelete(state.relatedTableQuery.where({ IN: {
|
|
1247
|
+
columns: state.throughPrimaryKeys,
|
|
1248
|
+
values: idsRows
|
|
1249
|
+
} }));
|
|
1250
|
+
}
|
|
1251
|
+
if (params.set) {
|
|
1252
|
+
const j = queryJoinTable(state, data);
|
|
1253
|
+
await _queryDelete(j);
|
|
1254
|
+
if (Array.isArray(params.set) ? params.set.length : objectHasValues(params.set)) await insertToJoinTable(state, j, data, await _queryRows(_querySelect(state.relatedTableQuery.where(conditionsToWhereArg(params.set)), state.throughPrimaryKeys)));
|
|
1255
|
+
}
|
|
1256
|
+
});
|
|
2078
1257
|
};
|
|
2079
|
-
|
|
2080
1258
|
const applyRelations = (qb, tables, result, schema) => {
|
|
2081
|
-
|
|
2082
|
-
|
|
2083
|
-
|
|
2084
|
-
|
|
2085
|
-
|
|
2086
|
-
|
|
2087
|
-
|
|
2088
|
-
|
|
2089
|
-
|
|
2090
|
-
|
|
2091
|
-
|
|
2092
|
-
|
|
2093
|
-
|
|
2094
|
-
|
|
2095
|
-
|
|
2096
|
-
|
|
2097
|
-
|
|
2098
|
-
|
|
2099
|
-
|
|
2100
|
-
|
|
2101
|
-
|
|
2102
|
-
|
|
2103
|
-
|
|
2104
|
-
|
|
2105
|
-
|
|
2106
|
-
|
|
2107
|
-
|
|
2108
|
-
|
|
2109
|
-
|
|
2110
|
-
|
|
2111
|
-
|
|
2112
|
-
|
|
2113
|
-
|
|
2114
|
-
|
|
2115
|
-
|
|
2116
|
-
|
|
2117
|
-
|
|
2118
|
-
|
|
2119
|
-
|
|
2120
|
-
|
|
2121
|
-
|
|
2122
|
-
|
|
2123
|
-
|
|
2124
|
-
|
|
2125
|
-
|
|
2126
|
-
|
|
2127
|
-
|
|
2128
|
-
|
|
2129
|
-
|
|
2130
|
-
|
|
2131
|
-
}
|
|
2132
|
-
}
|
|
2133
|
-
if (delayedRelations.size) {
|
|
2134
|
-
const { value } = delayedRelations.values().next();
|
|
2135
|
-
for (const key in value) {
|
|
2136
|
-
for (const item of value[key]) {
|
|
2137
|
-
const { relation } = item;
|
|
2138
|
-
if (item.dbTable.relations[item.relationName]) continue;
|
|
2139
|
-
const as = item.dbTable.definedAs;
|
|
2140
|
-
let message = `Cannot define a \`${item.relationName}\` relation on \`${as}\``;
|
|
2141
|
-
const table = result[as];
|
|
2142
|
-
const { through, source } = relation.options;
|
|
2143
|
-
const throughRel = table.relations[through];
|
|
2144
|
-
if (through && !throughRel) {
|
|
2145
|
-
message += `: cannot find \`${through}\` relation required by the \`through\` option`;
|
|
2146
|
-
} else if (source && throughRel && !throughRel.table.relations[source]) {
|
|
2147
|
-
message += `: cannot find \`${source}\` relation in \`${throughRel.table.definedAs}\` required by the \`source\` option`;
|
|
2148
|
-
}
|
|
2149
|
-
throw new Error(message);
|
|
2150
|
-
}
|
|
2151
|
-
}
|
|
2152
|
-
}
|
|
1259
|
+
const tableEntries = Object.entries(tables);
|
|
1260
|
+
const delayedRelations = /* @__PURE__ */ new Map();
|
|
1261
|
+
for (const name in tables) {
|
|
1262
|
+
const table = tables[name];
|
|
1263
|
+
if (!("relations" in table) || typeof table.relations !== "object") continue;
|
|
1264
|
+
const dbTable = result[name];
|
|
1265
|
+
for (const relationName in table.relations) {
|
|
1266
|
+
const relation = table.relations[relationName];
|
|
1267
|
+
const otherTableClass = relation.fn();
|
|
1268
|
+
const otherTable = tableEntries.find((pair) => pair[1] instanceof otherTableClass);
|
|
1269
|
+
if (!otherTable) throw new Error(`Cannot find table class for class ${otherTableClass.name}`);
|
|
1270
|
+
const otherTableName = otherTable[0];
|
|
1271
|
+
const otherDbTable = result[otherTableName];
|
|
1272
|
+
if (!otherDbTable) throw new Error(`Cannot find table class by name ${otherTableName}`);
|
|
1273
|
+
const data = {
|
|
1274
|
+
relationName,
|
|
1275
|
+
relation,
|
|
1276
|
+
dbTable,
|
|
1277
|
+
otherDbTable
|
|
1278
|
+
};
|
|
1279
|
+
const options = relation.options;
|
|
1280
|
+
if (typeof options.through === "string" && typeof options.source === "string") {
|
|
1281
|
+
const throughRelation = getThroughRelation(dbTable, options.through);
|
|
1282
|
+
if (!throughRelation) {
|
|
1283
|
+
delayRelation(delayedRelations, dbTable, options.through, data);
|
|
1284
|
+
continue;
|
|
1285
|
+
}
|
|
1286
|
+
if (!getSourceRelation(throughRelation, options.source)) {
|
|
1287
|
+
delayRelation(delayedRelations, throughRelation.table, options.source, data);
|
|
1288
|
+
continue;
|
|
1289
|
+
}
|
|
1290
|
+
}
|
|
1291
|
+
applyRelation(table, qb, data, delayedRelations, schema);
|
|
1292
|
+
}
|
|
1293
|
+
}
|
|
1294
|
+
if (delayedRelations.size) {
|
|
1295
|
+
const { value } = delayedRelations.values().next();
|
|
1296
|
+
for (const key in value) for (const item of value[key]) {
|
|
1297
|
+
const { relation } = item;
|
|
1298
|
+
if (item.dbTable.relations[item.relationName]) continue;
|
|
1299
|
+
const as = item.dbTable.definedAs;
|
|
1300
|
+
let message = `Cannot define a \`${item.relationName}\` relation on \`${as}\``;
|
|
1301
|
+
const table = result[as];
|
|
1302
|
+
const { through, source } = relation.options;
|
|
1303
|
+
const throughRel = table.relations[through];
|
|
1304
|
+
if (through && !throughRel) message += `: cannot find \`${through}\` relation required by the \`through\` option`;
|
|
1305
|
+
else if (source && throughRel && !throughRel.table.relations[source]) message += `: cannot find \`${source}\` relation in \`${throughRel.table.definedAs}\` required by the \`source\` option`;
|
|
1306
|
+
throw new Error(message);
|
|
1307
|
+
}
|
|
1308
|
+
}
|
|
2153
1309
|
};
|
|
2154
1310
|
const delayRelation = (delayedRelations, table, relationName, data) => {
|
|
2155
|
-
|
|
2156
|
-
|
|
2157
|
-
|
|
2158
|
-
|
|
2159
|
-
|
|
2160
|
-
|
|
2161
|
-
|
|
2162
|
-
} else {
|
|
2163
|
-
tableRelations[relationName] = [data];
|
|
2164
|
-
}
|
|
1311
|
+
let tableRelations = delayedRelations.get(table);
|
|
1312
|
+
if (!tableRelations) {
|
|
1313
|
+
tableRelations = {};
|
|
1314
|
+
delayedRelations.set(table, tableRelations);
|
|
1315
|
+
}
|
|
1316
|
+
if (tableRelations[relationName]) tableRelations[relationName].push(data);
|
|
1317
|
+
else tableRelations[relationName] = [data];
|
|
2165
1318
|
};
|
|
2166
1319
|
const applyRelation = (table, qb, { relationName, relation, dbTable, otherDbTable }, delayedRelations, schema) => {
|
|
2167
|
-
|
|
2168
|
-
|
|
2169
|
-
|
|
2170
|
-
|
|
2171
|
-
|
|
2172
|
-
|
|
2173
|
-
|
|
2174
|
-
|
|
2175
|
-
|
|
2176
|
-
|
|
2177
|
-
|
|
2178
|
-
|
|
2179
|
-
|
|
2180
|
-
|
|
2181
|
-
|
|
2182
|
-
|
|
2183
|
-
|
|
2184
|
-
|
|
2185
|
-
|
|
2186
|
-
|
|
2187
|
-
|
|
2188
|
-
|
|
2189
|
-
|
|
2190
|
-
|
|
2191
|
-
|
|
2192
|
-
|
|
2193
|
-
|
|
2194
|
-
|
|
2195
|
-
|
|
2196
|
-
|
|
2197
|
-
|
|
2198
|
-
|
|
2199
|
-
|
|
2200
|
-
|
|
2201
|
-
|
|
2202
|
-
|
|
2203
|
-
|
|
2204
|
-
|
|
2205
|
-
|
|
2206
|
-
|
|
2207
|
-
|
|
2208
|
-
baseQuery.joinQuery = data.joinQuery;
|
|
2209
|
-
const { join: originalJoin } = baseQuery;
|
|
2210
|
-
baseQuery.join = function(...args) {
|
|
2211
|
-
if (args.length) {
|
|
2212
|
-
return originalJoin.apply(this, args);
|
|
2213
|
-
} else {
|
|
2214
|
-
const q = this.clone();
|
|
2215
|
-
q.q.innerJoinLateral = true;
|
|
2216
|
-
return q;
|
|
2217
|
-
}
|
|
2218
|
-
};
|
|
2219
|
-
dbTable.relations[relationName] = {
|
|
2220
|
-
table: otherDbTable,
|
|
2221
|
-
query,
|
|
2222
|
-
queryRelated: data.queryRelated,
|
|
2223
|
-
joinQuery: data.joinQuery,
|
|
2224
|
-
reverseJoin: data.reverseJoin,
|
|
2225
|
-
modifyRelatedQuery: data.modifyRelatedQuery
|
|
2226
|
-
};
|
|
2227
|
-
(dbTable.relationQueries ?? (dbTable.relationQueries = {}))[relationName] = query;
|
|
2228
|
-
const tableRelations = delayedRelations.get(dbTable);
|
|
2229
|
-
if (!tableRelations) return;
|
|
2230
|
-
tableRelations[relationName]?.forEach((data2) => {
|
|
2231
|
-
applyRelation(table, qb, data2, delayedRelations, schema);
|
|
2232
|
-
});
|
|
1320
|
+
const baseQuery = Object.create(otherDbTable);
|
|
1321
|
+
baseQuery.baseQuery = baseQuery;
|
|
1322
|
+
const query = baseQuery.as(relationName);
|
|
1323
|
+
if (!query.definedAs) throw new Error(`Table class for table ${query.table} is not attached to db instance`);
|
|
1324
|
+
const { type } = relation;
|
|
1325
|
+
let data;
|
|
1326
|
+
if (type === "belongsTo") data = makeBelongsToMethod(table, dbTable, relation, relationName, query);
|
|
1327
|
+
else if (type === "hasOne") data = makeHasOneMethod(table, dbTable, relation, relationName, query);
|
|
1328
|
+
else if (type === "hasMany") data = makeHasManyMethod(table, dbTable, relation, relationName, query);
|
|
1329
|
+
else if (type === "hasAndBelongsToMany") data = makeHasAndBelongsToManyMethod(table, dbTable, qb, relation, relationName, query, schema);
|
|
1330
|
+
else throw new Error(`Unknown relation type ${type}`);
|
|
1331
|
+
if (data.returns === "one") {
|
|
1332
|
+
if (relation.options.required) _queryTake(query);
|
|
1333
|
+
else _queryTakeOptional(query);
|
|
1334
|
+
query.q.returnsOne = true;
|
|
1335
|
+
}
|
|
1336
|
+
if (data.virtualColumn) dbTable.shape[relationName] = dbTable.q.shape[relationName] = data.virtualColumn;
|
|
1337
|
+
baseQuery.joinQuery = data.joinQuery;
|
|
1338
|
+
const { join: originalJoin } = baseQuery;
|
|
1339
|
+
baseQuery.join = function(...args) {
|
|
1340
|
+
if (args.length) return originalJoin.apply(this, args);
|
|
1341
|
+
else {
|
|
1342
|
+
const q = this.clone();
|
|
1343
|
+
q.q.innerJoinLateral = true;
|
|
1344
|
+
return q;
|
|
1345
|
+
}
|
|
1346
|
+
};
|
|
1347
|
+
dbTable.relations[relationName] = {
|
|
1348
|
+
table: otherDbTable,
|
|
1349
|
+
query,
|
|
1350
|
+
queryRelated: data.queryRelated,
|
|
1351
|
+
joinQuery: data.joinQuery,
|
|
1352
|
+
reverseJoin: data.reverseJoin,
|
|
1353
|
+
modifyRelatedQuery: data.modifyRelatedQuery
|
|
1354
|
+
};
|
|
1355
|
+
(dbTable.relationQueries ??= {})[relationName] = query;
|
|
1356
|
+
const tableRelations = delayedRelations.get(dbTable);
|
|
1357
|
+
if (!tableRelations) return;
|
|
1358
|
+
tableRelations[relationName]?.forEach((data) => {
|
|
1359
|
+
applyRelation(table, qb, data, delayedRelations, schema);
|
|
1360
|
+
});
|
|
2233
1361
|
};
|
|
2234
|
-
|
|
2235
1362
|
function transaction(fnOrOptions, fn) {
|
|
2236
|
-
|
|
2237
|
-
fnOrOptions,
|
|
2238
|
-
fn
|
|
2239
|
-
);
|
|
1363
|
+
return this.$qb.transaction(fnOrOptions, fn);
|
|
2240
1364
|
}
|
|
2241
1365
|
function ensureTransaction(cb) {
|
|
2242
|
-
|
|
1366
|
+
return this.$qb.ensureTransaction(cb);
|
|
2243
1367
|
}
|
|
2244
1368
|
function isInTransaction() {
|
|
2245
|
-
|
|
1369
|
+
return this.$qb.isInTransaction();
|
|
2246
1370
|
}
|
|
2247
1371
|
function afterCommit(hook) {
|
|
2248
|
-
|
|
1372
|
+
this.$qb.afterCommit(hook);
|
|
2249
1373
|
}
|
|
2250
|
-
|
|
2251
|
-
const
|
|
2252
|
-
|
|
2253
|
-
|
|
2254
|
-
|
|
2255
|
-
|
|
2256
|
-
|
|
2257
|
-
|
|
2258
|
-
|
|
2259
|
-
|
|
2260
|
-
|
|
2261
|
-
|
|
2262
|
-
|
|
2263
|
-
|
|
2264
|
-
|
|
2265
|
-
|
|
2266
|
-
|
|
2267
|
-
|
|
2268
|
-
|
|
2269
|
-
|
|
2270
|
-
|
|
2271
|
-
|
|
2272
|
-
|
|
2273
|
-
|
|
2274
|
-
|
|
2275
|
-
|
|
2276
|
-
|
|
2277
|
-
|
|
2278
|
-
|
|
2279
|
-
|
|
2280
|
-
|
|
2281
|
-
|
|
2282
|
-
|
|
2283
|
-
|
|
2284
|
-
|
|
2285
|
-
|
|
2286
|
-
|
|
2287
|
-
|
|
2288
|
-
|
|
2289
|
-
|
|
2290
|
-
|
|
2291
|
-
|
|
2292
|
-
|
|
2293
|
-
|
|
2294
|
-
|
|
2295
|
-
|
|
2296
|
-
|
|
2297
|
-
|
|
2298
|
-
|
|
2299
|
-
|
|
2300
|
-
|
|
2301
|
-
|
|
2302
|
-
|
|
2303
|
-
|
|
2304
|
-
|
|
2305
|
-
|
|
2306
|
-
|
|
2307
|
-
|
|
2308
|
-
|
|
2309
|
-
|
|
2310
|
-
|
|
2311
|
-
|
|
2312
|
-
|
|
2313
|
-
|
|
2314
|
-
|
|
2315
|
-
|
|
2316
|
-
|
|
2317
|
-
|
|
2318
|
-
|
|
2319
|
-
|
|
2320
|
-
|
|
2321
|
-
|
|
2322
|
-
const dbTable = new Db(
|
|
2323
|
-
adapter,
|
|
2324
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
2325
|
-
qb,
|
|
2326
|
-
table.table,
|
|
2327
|
-
table.columns.shape,
|
|
2328
|
-
table.types,
|
|
2329
|
-
asyncStorage,
|
|
2330
|
-
options2,
|
|
2331
|
-
table.constructor.prototype.columns?.data ?? {}
|
|
2332
|
-
);
|
|
2333
|
-
dbTable.definedAs = key;
|
|
2334
|
-
dbTable.db = result;
|
|
2335
|
-
dbTable.filePath = table.filePath;
|
|
2336
|
-
dbTable.name = table.constructor.name;
|
|
2337
|
-
result[key] = dbTable;
|
|
2338
|
-
}
|
|
2339
|
-
applyRelations(qb, tableInstances, result, schema);
|
|
2340
|
-
for (const key in tables) {
|
|
2341
|
-
const table = tableInstances[key];
|
|
2342
|
-
if (table.init) {
|
|
2343
|
-
table.init(result);
|
|
2344
|
-
Object.assign(result[key].baseQuery.q, table.q);
|
|
2345
|
-
}
|
|
2346
|
-
}
|
|
2347
|
-
return result;
|
|
1374
|
+
const orchidORMWithAdapter = ({ log, logger, autoPreparedStatements, noPrimaryKey = "error", schema, ...options }, tables) => {
|
|
1375
|
+
const commonOptions = {
|
|
1376
|
+
log,
|
|
1377
|
+
logger,
|
|
1378
|
+
autoPreparedStatements,
|
|
1379
|
+
noPrimaryKey
|
|
1380
|
+
};
|
|
1381
|
+
let adapter;
|
|
1382
|
+
let asyncStorage;
|
|
1383
|
+
let qb;
|
|
1384
|
+
if ("db" in options) {
|
|
1385
|
+
adapter = options.db.q.adapter;
|
|
1386
|
+
asyncStorage = options.db.internal.asyncStorage;
|
|
1387
|
+
qb = options.db.qb;
|
|
1388
|
+
} else {
|
|
1389
|
+
adapter = options.adapter;
|
|
1390
|
+
asyncStorage = new AsyncLocalStorage();
|
|
1391
|
+
qb = _initQueryBuilder(adapter, makeColumnTypes(defaultSchemaConfig), asyncStorage, commonOptions, options);
|
|
1392
|
+
}
|
|
1393
|
+
const result = {
|
|
1394
|
+
$transaction: transaction,
|
|
1395
|
+
$ensureTransaction: ensureTransaction,
|
|
1396
|
+
$isInTransaction: isInTransaction,
|
|
1397
|
+
$afterCommit: afterCommit,
|
|
1398
|
+
$adapterNotInTransaction: adapter,
|
|
1399
|
+
$getAdapter,
|
|
1400
|
+
$qb: qb,
|
|
1401
|
+
get $query() {
|
|
1402
|
+
return qb.query;
|
|
1403
|
+
},
|
|
1404
|
+
$queryArrays: ((...args) => qb.queryArrays(...args)),
|
|
1405
|
+
$with: qb.with.bind(qb),
|
|
1406
|
+
$withRecursive: qb.withRecursive.bind(qb),
|
|
1407
|
+
$withSql: qb.withSql.bind(qb),
|
|
1408
|
+
$from: qb.from.bind(qb),
|
|
1409
|
+
$close: adapter.close.bind(adapter),
|
|
1410
|
+
$withOptions: qb.withOptions.bind(qb)
|
|
1411
|
+
};
|
|
1412
|
+
const tableInstances = {};
|
|
1413
|
+
for (const key in tables) {
|
|
1414
|
+
if (key[0] === "$") throw new Error(`Table class name must not start with $`);
|
|
1415
|
+
const tableClass = tables[key];
|
|
1416
|
+
const table = tableClass.instance();
|
|
1417
|
+
tableInstances[key] = table;
|
|
1418
|
+
const options = {
|
|
1419
|
+
...commonOptions,
|
|
1420
|
+
schema: table.schema || schema,
|
|
1421
|
+
language: table.language,
|
|
1422
|
+
scopes: table.scopes,
|
|
1423
|
+
softDelete: table.softDelete,
|
|
1424
|
+
snakeCase: table.snakeCase,
|
|
1425
|
+
comment: table.comment,
|
|
1426
|
+
noPrimaryKey: table.noPrimaryKey ? "ignore" : void 0,
|
|
1427
|
+
computed: table.computed,
|
|
1428
|
+
nowSQL: tableClass.nowSQL
|
|
1429
|
+
};
|
|
1430
|
+
const dbTable = new Db(adapter, qb, table.table, table.columns.shape, table.types, asyncStorage, options, table.constructor.prototype.columns?.data ?? {});
|
|
1431
|
+
dbTable.definedAs = key;
|
|
1432
|
+
dbTable.db = result;
|
|
1433
|
+
dbTable.filePath = table.filePath;
|
|
1434
|
+
dbTable.name = table.constructor.name;
|
|
1435
|
+
result[key] = dbTable;
|
|
1436
|
+
}
|
|
1437
|
+
applyRelations(qb, tableInstances, result, schema);
|
|
1438
|
+
for (const key in tables) {
|
|
1439
|
+
const table = tableInstances[key];
|
|
1440
|
+
if (table.init) {
|
|
1441
|
+
table.init(result);
|
|
1442
|
+
Object.assign(result[key].baseQuery.q, table.q);
|
|
1443
|
+
}
|
|
1444
|
+
}
|
|
1445
|
+
return result;
|
|
2348
1446
|
};
|
|
2349
1447
|
function $getAdapter() {
|
|
2350
|
-
|
|
1448
|
+
return this.$qb.$getAdapter();
|
|
2351
1449
|
}
|
|
2352
|
-
|
|
2353
1450
|
const createRepo = (table, methods) => {
|
|
2354
|
-
|
|
2355
|
-
|
|
2356
|
-
|
|
2357
|
-
|
|
2358
|
-
|
|
2359
|
-
|
|
2360
|
-
|
|
2361
|
-
|
|
2362
|
-
|
|
2363
|
-
|
|
2364
|
-
|
|
2365
|
-
|
|
2366
|
-
|
|
2367
|
-
|
|
2368
|
-
|
|
2369
|
-
|
|
2370
|
-
|
|
2371
|
-
|
|
2372
|
-
|
|
2373
|
-
|
|
2374
|
-
|
|
2375
|
-
|
|
2376
|
-
|
|
2377
|
-
|
|
2378
|
-
|
|
2379
|
-
get(_, key) {
|
|
2380
|
-
return q[key];
|
|
2381
|
-
}
|
|
2382
|
-
});
|
|
1451
|
+
const queryMethods = {
|
|
1452
|
+
...methods.queryMethods,
|
|
1453
|
+
...methods.queryOneMethods,
|
|
1454
|
+
...methods.queryWithWhereMethods,
|
|
1455
|
+
...methods.queryOneWithWhereMethods
|
|
1456
|
+
};
|
|
1457
|
+
const plainMethods = methods.methods;
|
|
1458
|
+
const repo = (q) => {
|
|
1459
|
+
const proto = Object.create(q.baseQuery);
|
|
1460
|
+
proto.baseQuery = proto;
|
|
1461
|
+
const result = Object.create(proto);
|
|
1462
|
+
result.q = getClonedQueryData(q.q);
|
|
1463
|
+
if (plainMethods) Object.assign(proto.baseQuery, plainMethods);
|
|
1464
|
+
for (const key in queryMethods) {
|
|
1465
|
+
const method = queryMethods[key];
|
|
1466
|
+
proto.baseQuery[key] = function(...args) {
|
|
1467
|
+
return method(this, ...args);
|
|
1468
|
+
};
|
|
1469
|
+
}
|
|
1470
|
+
return result;
|
|
1471
|
+
};
|
|
1472
|
+
const q = repo(table);
|
|
1473
|
+
return new Proxy(repo, { get(_, key) {
|
|
1474
|
+
return q[key];
|
|
1475
|
+
} });
|
|
2383
1476
|
};
|
|
2384
|
-
|
|
2385
1477
|
export { createBaseTable, createRepo, orchidORMWithAdapter };
|
|
2386
|
-
|
|
1478
|
+
|
|
1479
|
+
//# sourceMappingURL=index.mjs.map
|