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