bun-query-builder 0.1.35 → 0.1.37
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/bin/cli.js +299 -246
- package/dist/orm.d.ts +5 -1
- package/dist/src/index.js +298 -245
- package/package.json +1 -1
package/dist/bin/cli.js
CHANGED
|
@@ -15036,7 +15036,7 @@ function createQueryBuilder(state) {
|
|
|
15036
15036
|
return ensureBuilt().values();
|
|
15037
15037
|
},
|
|
15038
15038
|
toParams() {
|
|
15039
|
-
return
|
|
15039
|
+
return [...whereParams];
|
|
15040
15040
|
},
|
|
15041
15041
|
__rawState() {
|
|
15042
15042
|
return { sql: reorderSelectClauses(text), params: [...whereParams] };
|
|
@@ -15133,265 +15133,247 @@ function createQueryBuilder(state) {
|
|
|
15133
15133
|
throw new Error(`[query-builder] selectFromSub(...).${methodName}() is not supported. ` + `Apply ${methodName}() to the underlying subquery BEFORE passing it to selectFromSub, ` + `or use the regular selectFrom(...) builder. This previously silently returned without ` + `affecting the SQL, producing wrong results \u2014 see stacksjs/stacks#1862 #11.`);
|
|
15134
15134
|
};
|
|
15135
15135
|
}
|
|
15136
|
-
|
|
15137
|
-
const
|
|
15138
|
-
const
|
|
15139
|
-
|
|
15140
|
-
|
|
15141
|
-
|
|
15142
|
-
|
|
15143
|
-
|
|
15144
|
-
|
|
15145
|
-
|
|
15146
|
-
|
|
15147
|
-
const
|
|
15148
|
-
|
|
15149
|
-
|
|
15150
|
-
|
|
15151
|
-
|
|
15152
|
-
|
|
15153
|
-
|
|
15154
|
-
|
|
15155
|
-
|
|
15156
|
-
return
|
|
15157
|
-
}
|
|
15158
|
-
|
|
15159
|
-
|
|
15160
|
-
|
|
15161
|
-
|
|
15162
|
-
|
|
15163
|
-
|
|
15164
|
-
|
|
15165
|
-
|
|
15166
|
-
|
|
15167
|
-
|
|
15168
|
-
const current = String(q);
|
|
15169
|
-
const newQ = SQL_PATTERNS.ORDER_BY.test(current) ? sql.unsafe(`${current}, ${column} ${dir}`) : sql`${q} ORDER BY ${sql(column)} ${direction === "asc" ? sql`ASC` : sql`DESC`}`;
|
|
15170
|
-
return createSubQueryBuilder(newQ);
|
|
15171
|
-
},
|
|
15172
|
-
limit(n) {
|
|
15173
|
-
const current = String(q);
|
|
15174
|
-
const newQ = SQL_PATTERNS.LIMIT.test(current) ? sql.unsafe(current.replace(SQL_PATTERNS.LIMIT, ` LIMIT ${n}`)) : sql`${q} LIMIT ${n}`;
|
|
15175
|
-
return createSubQueryBuilder(newQ);
|
|
15176
|
-
},
|
|
15177
|
-
offset(n) {
|
|
15178
|
-
const current = String(q);
|
|
15179
|
-
const newQ = SQL_PATTERNS.OFFSET.test(current) ? sql.unsafe(current.replace(SQL_PATTERNS.OFFSET, ` OFFSET ${n}`)) : sql`${q} OFFSET ${n}`;
|
|
15180
|
-
return createSubQueryBuilder(newQ);
|
|
15181
|
-
},
|
|
15182
|
-
toSQL() {
|
|
15183
|
-
return makeExecutableQuery(q);
|
|
15184
|
-
},
|
|
15185
|
-
async execute() {
|
|
15186
|
-
return runWithHooks(q, "select");
|
|
15187
|
-
},
|
|
15188
|
-
async executeTakeFirst() {
|
|
15189
|
-
const rows = await runWithHooks(q, "select");
|
|
15190
|
-
return Array.isArray(rows) ? rows[0] : rows;
|
|
15191
|
-
},
|
|
15192
|
-
async executeTakeFirstOrThrow() {
|
|
15193
|
-
const rows = await runWithHooks(q, "select");
|
|
15194
|
-
const first = Array.isArray(rows) ? rows[0] : rows;
|
|
15195
|
-
if (!first)
|
|
15196
|
-
throw new Error("Record not found");
|
|
15197
|
-
return first;
|
|
15198
|
-
},
|
|
15199
|
-
async get() {
|
|
15200
|
-
return runWithHooks(q, "select");
|
|
15201
|
-
},
|
|
15202
|
-
async first() {
|
|
15203
|
-
const rows = await runWithHooks(q, "select");
|
|
15204
|
-
return Array.isArray(rows) ? rows[0] : rows;
|
|
15205
|
-
},
|
|
15206
|
-
async firstOrFail() {
|
|
15207
|
-
const rows = await runWithHooks(q, "select");
|
|
15208
|
-
const first = Array.isArray(rows) ? rows[0] : rows;
|
|
15209
|
-
if (!first)
|
|
15210
|
-
throw new Error("No rows found");
|
|
15211
|
-
return first;
|
|
15212
|
-
},
|
|
15213
|
-
async exists() {
|
|
15214
|
-
const countQ = sql`SELECT EXISTS(${q}) as exists`;
|
|
15215
|
-
const result = await runWithHooks(countQ, "select");
|
|
15216
|
-
return result?.[0]?.exists === true;
|
|
15217
|
-
},
|
|
15218
|
-
async doesntExist() {
|
|
15219
|
-
const exists = await this.exists();
|
|
15220
|
-
return !exists;
|
|
15221
|
-
},
|
|
15222
|
-
values() {
|
|
15223
|
-
return q.values();
|
|
15224
|
-
},
|
|
15225
|
-
raw() {
|
|
15226
|
-
return q.raw();
|
|
15227
|
-
},
|
|
15228
|
-
cancel() {
|
|
15229
|
-
try {
|
|
15230
|
-
q.cancel();
|
|
15231
|
-
} catch {}
|
|
15232
|
-
},
|
|
15233
|
-
whereRaw: subqueryNotSupported("whereRaw"),
|
|
15234
|
-
whereColumn: subqueryNotSupported("whereColumn"),
|
|
15235
|
-
orWhereColumn: subqueryNotSupported("orWhereColumn"),
|
|
15236
|
-
whereIn: subqueryNotSupported("whereIn"),
|
|
15237
|
-
orWhereIn: subqueryNotSupported("orWhereIn"),
|
|
15238
|
-
whereNotIn: subqueryNotSupported("whereNotIn"),
|
|
15239
|
-
orWhereNotIn: subqueryNotSupported("orWhereNotIn"),
|
|
15240
|
-
whereLike: subqueryNotSupported("whereLike"),
|
|
15241
|
-
whereILike: subqueryNotSupported("whereILike"),
|
|
15242
|
-
orWhereLike: subqueryNotSupported("orWhereLike"),
|
|
15243
|
-
orWhereILike: subqueryNotSupported("orWhereILike"),
|
|
15244
|
-
whereNotLike: subqueryNotSupported("whereNotLike"),
|
|
15245
|
-
whereNotILike: subqueryNotSupported("whereNotILike"),
|
|
15246
|
-
orWhereNotLike: subqueryNotSupported("orWhereNotLike"),
|
|
15247
|
-
orWhereNotILike: subqueryNotSupported("orWhereNotILike"),
|
|
15248
|
-
whereAny: subqueryNotSupported("whereAny"),
|
|
15249
|
-
whereAll: subqueryNotSupported("whereAll"),
|
|
15250
|
-
whereNone: subqueryNotSupported("whereNone"),
|
|
15251
|
-
whereNested: subqueryNotSupported("whereNested"),
|
|
15252
|
-
orWhereNested: subqueryNotSupported("orWhereNested"),
|
|
15253
|
-
whereDate: subqueryNotSupported("whereDate"),
|
|
15254
|
-
whereBetween: subqueryNotSupported("whereBetween"),
|
|
15255
|
-
whereNotBetween: subqueryNotSupported("whereNotBetween"),
|
|
15256
|
-
whereJsonContains: subqueryNotSupported("whereJsonContains"),
|
|
15257
|
-
whereJsonPath: subqueryNotSupported("whereJsonPath"),
|
|
15258
|
-
whereNull: subqueryNotSupported("whereNull"),
|
|
15259
|
-
whereNotNull: subqueryNotSupported("whereNotNull"),
|
|
15260
|
-
whereExists: subqueryNotSupported("whereExists"),
|
|
15261
|
-
whereJsonDoesntContain: subqueryNotSupported("whereJsonDoesntContain"),
|
|
15262
|
-
whereJsonContainsKey: subqueryNotSupported("whereJsonContainsKey"),
|
|
15263
|
-
whereJsonDoesntContainKey: subqueryNotSupported("whereJsonDoesntContainKey"),
|
|
15264
|
-
whereJsonLength: subqueryNotSupported("whereJsonLength"),
|
|
15265
|
-
join: subqueryNotSupported("join"),
|
|
15266
|
-
joinSub: subqueryNotSupported("joinSub"),
|
|
15267
|
-
innerJoin: subqueryNotSupported("innerJoin"),
|
|
15268
|
-
leftJoin: subqueryNotSupported("leftJoin"),
|
|
15269
|
-
leftJoinSub: subqueryNotSupported("leftJoinSub"),
|
|
15270
|
-
rightJoin: subqueryNotSupported("rightJoin"),
|
|
15271
|
-
crossJoin: subqueryNotSupported("crossJoin"),
|
|
15272
|
-
crossJoinSub: subqueryNotSupported("crossJoinSub"),
|
|
15273
|
-
groupBy: subqueryNotSupported("groupBy"),
|
|
15274
|
-
groupByRaw: subqueryNotSupported("groupByRaw"),
|
|
15275
|
-
having: subqueryNotSupported("having"),
|
|
15276
|
-
havingRaw: subqueryNotSupported("havingRaw"),
|
|
15277
|
-
addSelect: subqueryNotSupported("addSelect"),
|
|
15278
|
-
select: subqueryNotSupported("select"),
|
|
15279
|
-
selectAll: subqueryNotSupported("selectAll"),
|
|
15280
|
-
orderByDesc: subqueryNotSupported("orderByDesc"),
|
|
15281
|
-
inRandomOrder: subqueryNotSupported("inRandomOrder"),
|
|
15282
|
-
reorder: subqueryNotSupported("reorder"),
|
|
15283
|
-
orderByRaw: subqueryNotSupported("orderByRaw"),
|
|
15284
|
-
union: subqueryNotSupported("union"),
|
|
15285
|
-
unionAll: subqueryNotSupported("unionAll"),
|
|
15286
|
-
forPage: subqueryNotSupported("forPage"),
|
|
15287
|
-
selectAllRelations: subqueryNotSupported("selectAllRelations"),
|
|
15288
|
-
with: subqueryNotSupported("with"),
|
|
15289
|
-
value: subqueryNotSupported("value"),
|
|
15290
|
-
pluck: subqueryNotSupported("pluck"),
|
|
15291
|
-
cursorPaginate: subqueryNotSupported("cursorPaginate"),
|
|
15292
|
-
paginate: subqueryNotSupported("paginate"),
|
|
15293
|
-
simplePaginate: subqueryNotSupported("simplePaginate"),
|
|
15294
|
-
chunk: subqueryNotSupported("chunk"),
|
|
15295
|
-
chunkById: subqueryNotSupported("chunkById"),
|
|
15296
|
-
eachById: subqueryNotSupported("eachById"),
|
|
15297
|
-
count: subqueryNotSupported("count"),
|
|
15298
|
-
avg: subqueryNotSupported("avg"),
|
|
15299
|
-
sum: subqueryNotSupported("sum"),
|
|
15300
|
-
max: subqueryNotSupported("max"),
|
|
15301
|
-
min: subqueryNotSupported("min"),
|
|
15302
|
-
find: subqueryNotSupported("find"),
|
|
15303
|
-
findOrFail: subqueryNotSupported("findOrFail"),
|
|
15304
|
-
findMany: subqueryNotSupported("findMany"),
|
|
15305
|
-
latest: subqueryNotSupported("latest"),
|
|
15306
|
-
oldest: subqueryNotSupported("oldest"),
|
|
15307
|
-
lazy: subqueryNotSupported("lazy"),
|
|
15308
|
-
lazyById: subqueryNotSupported("lazyById"),
|
|
15309
|
-
pipe: (fn) => fn(this),
|
|
15310
|
-
when: subqueryNotSupported("when"),
|
|
15311
|
-
tap: () => this,
|
|
15312
|
-
dump: () => this,
|
|
15313
|
-
dd: () => {
|
|
15314
|
-
throw new Error("Dump and Die");
|
|
15315
|
-
},
|
|
15316
|
-
explain: () => Promise.resolve([]),
|
|
15317
|
-
simple: () => q.simple(),
|
|
15318
|
-
toText: () => String(q),
|
|
15319
|
-
toParams: () => q.values?.() ?? [],
|
|
15320
|
-
withTimeout: () => this,
|
|
15321
|
-
abort: () => this,
|
|
15322
|
-
lockForUpdate: () => this,
|
|
15323
|
-
sharedLock: () => this,
|
|
15324
|
-
withCTE: () => this,
|
|
15325
|
-
withRecursive: () => this,
|
|
15326
|
-
cache: () => this,
|
|
15327
|
-
clone: () => this,
|
|
15328
|
-
withTrashed: () => this,
|
|
15329
|
-
onlyTrashed: () => this,
|
|
15330
|
-
scope: () => this,
|
|
15331
|
-
get rows() {
|
|
15332
|
-
return [];
|
|
15333
|
-
},
|
|
15334
|
-
get row() {
|
|
15335
|
-
return;
|
|
15336
|
-
}
|
|
15136
|
+
validateIdentifier(String(alias), "selectFromSub(alias)");
|
|
15137
|
+
const rawState = typeof sub.__rawState === "function" ? sub.__rawState() : null;
|
|
15138
|
+
const subExec = sub.toSQL();
|
|
15139
|
+
const subText = rawState?.sql ?? (typeof subExec === "string" ? subExec : subExec?.sql ?? String(subExec));
|
|
15140
|
+
const subParams = rawState?.params ?? (Array.isArray(subExec?.values) ? subExec.values : []);
|
|
15141
|
+
const baseText = `SELECT * FROM (${subText}) AS ${String(alias)}`;
|
|
15142
|
+
const appendWhere = (text, params, hasWhere, expr, op, value, connector) => {
|
|
15143
|
+
const kw = !hasWhere ? "WHERE" : connector === "WHERE" ? "AND" : connector;
|
|
15144
|
+
const out = [...params];
|
|
15145
|
+
const cmp = (col, operator, val) => {
|
|
15146
|
+
validateIdentifier(col, "selectFromSub where(column)");
|
|
15147
|
+
const o = assertSafeWhereOperator(operator, "selectFromSub where(operator)");
|
|
15148
|
+
if (o === "in" || o === "not in") {
|
|
15149
|
+
const vals = Array.isArray(val) ? val : [val];
|
|
15150
|
+
const phs = getPlaceholders(vals.length, out.length + 1);
|
|
15151
|
+
out.push(...vals);
|
|
15152
|
+
return `${col} ${o.toUpperCase()} (${phs})`;
|
|
15153
|
+
}
|
|
15154
|
+
const ph = getPlaceholder(out.length + 1);
|
|
15155
|
+
out.push(val);
|
|
15156
|
+
return `${col} ${o} ${ph}`;
|
|
15157
|
+
};
|
|
15158
|
+
let clause;
|
|
15159
|
+
if (typeof expr === "string" && op !== undefined)
|
|
15160
|
+
clause = cmp(expr, op, value);
|
|
15161
|
+
else if (Array.isArray(expr) && expr.length === 3)
|
|
15162
|
+
clause = cmp(expr[0], expr[1], expr[2]);
|
|
15163
|
+
else if (expr && typeof expr === "object")
|
|
15164
|
+
clause = Object.entries(expr).map(([k, v]) => cmp(k, "=", v)).join(" AND ");
|
|
15165
|
+
else
|
|
15166
|
+
return { text, params };
|
|
15167
|
+
return { text: `${text} ${kw} ${clause}`, params: out };
|
|
15337
15168
|
};
|
|
15338
|
-
function
|
|
15339
|
-
|
|
15340
|
-
|
|
15341
|
-
|
|
15342
|
-
|
|
15343
|
-
|
|
15344
|
-
|
|
15345
|
-
const
|
|
15169
|
+
function makeSub(text, params, hasWhere = false) {
|
|
15170
|
+
const build = () => params.length > 0 ? _sql.unsafe(text, params) : _sql.unsafe(text);
|
|
15171
|
+
const base = {
|
|
15172
|
+
distinct() {
|
|
15173
|
+
return makeSub(text.replace(/^SELECT\s+/i, "SELECT DISTINCT "), params, hasWhere);
|
|
15174
|
+
},
|
|
15175
|
+
distinctOn(...columns) {
|
|
15176
|
+
const cols = columns.map(String).join(", ");
|
|
15177
|
+
return makeSub(text.replace(/^SELECT\s+/i, `SELECT DISTINCT ON (${cols}) `), params, hasWhere);
|
|
15178
|
+
},
|
|
15179
|
+
selectRaw(fragment) {
|
|
15180
|
+
const frag = renderRawFragment(fragment, "selectFromSub.selectRaw(fragment)");
|
|
15181
|
+
const fromIdx = text.indexOf(" FROM ");
|
|
15182
|
+
const newText = fromIdx !== -1 ? `${text.slice(0, fromIdx)}, ${frag}${text.slice(fromIdx)}` : `${text}, ${frag}`;
|
|
15183
|
+
return makeSub(newText, params, hasWhere);
|
|
15184
|
+
},
|
|
15185
|
+
where(expr, op, value) {
|
|
15186
|
+
const r = appendWhere(text, params, hasWhere, expr, op, value, "WHERE");
|
|
15187
|
+
return makeSub(r.text, r.params, true);
|
|
15188
|
+
},
|
|
15189
|
+
andWhere(expr, op, value) {
|
|
15190
|
+
const r = appendWhere(text, params, hasWhere, expr, op, value, "AND");
|
|
15191
|
+
return makeSub(r.text, r.params, true);
|
|
15192
|
+
},
|
|
15193
|
+
orWhere(expr, op, value) {
|
|
15194
|
+
const r = appendWhere(text, params, hasWhere, expr, op, value, "OR");
|
|
15195
|
+
return makeSub(r.text, r.params, true);
|
|
15196
|
+
},
|
|
15197
|
+
orderBy(column, direction = "asc") {
|
|
15198
|
+
validateIdentifier(String(column), "selectFromSub.orderBy(column)");
|
|
15199
|
+
const dir = direction === "asc" ? "ASC" : "DESC";
|
|
15200
|
+
const newText = SQL_PATTERNS.ORDER_BY.test(text) ? `${text}, ${column} ${dir}` : `${text} ORDER BY ${column} ${dir}`;
|
|
15201
|
+
return makeSub(newText, params, hasWhere);
|
|
15202
|
+
},
|
|
15203
|
+
limit(n) {
|
|
15204
|
+
if (!Number.isInteger(n) || n < 0)
|
|
15205
|
+
throw new TypeError(`[query-builder] selectFromSub.limit(n): expected non-negative integer, got ${n}`);
|
|
15206
|
+
const newText = SQL_PATTERNS.LIMIT.test(text) ? text.replace(SQL_PATTERNS.LIMIT, ` LIMIT ${n}`) : `${text} LIMIT ${n}`;
|
|
15207
|
+
return makeSub(newText, params, hasWhere);
|
|
15208
|
+
},
|
|
15209
|
+
offset(n) {
|
|
15210
|
+
if (!Number.isInteger(n) || n < 0)
|
|
15211
|
+
throw new TypeError(`[query-builder] selectFromSub.offset(n): expected non-negative integer, got ${n}`);
|
|
15212
|
+
const newText = SQL_PATTERNS.OFFSET.test(text) ? text.replace(SQL_PATTERNS.OFFSET, ` OFFSET ${n}`) : `${text} OFFSET ${n}`;
|
|
15213
|
+
return makeSub(newText, params, hasWhere);
|
|
15214
|
+
},
|
|
15215
|
+
toSQL() {
|
|
15216
|
+
return makeExecutableQuery(build(), text);
|
|
15217
|
+
},
|
|
15218
|
+
async execute() {
|
|
15219
|
+
return runWithHooks(build(), "select");
|
|
15220
|
+
},
|
|
15221
|
+
async executeTakeFirst() {
|
|
15222
|
+
const rows = await runWithHooks(build(), "select");
|
|
15346
15223
|
return Array.isArray(rows) ? rows[0] : rows;
|
|
15347
15224
|
},
|
|
15348
|
-
|
|
15349
|
-
const rows = await runWithHooks(
|
|
15225
|
+
async executeTakeFirstOrThrow() {
|
|
15226
|
+
const rows = await runWithHooks(build(), "select");
|
|
15227
|
+
const first = Array.isArray(rows) ? rows[0] : rows;
|
|
15228
|
+
if (!first)
|
|
15229
|
+
throw new Error("Record not found");
|
|
15230
|
+
return first;
|
|
15231
|
+
},
|
|
15232
|
+
async get() {
|
|
15233
|
+
return runWithHooks(build(), "select");
|
|
15234
|
+
},
|
|
15235
|
+
async first() {
|
|
15236
|
+
const rows = await runWithHooks(build(), "select");
|
|
15237
|
+
return Array.isArray(rows) ? rows[0] : rows;
|
|
15238
|
+
},
|
|
15239
|
+
async firstOrFail() {
|
|
15240
|
+
const rows = await runWithHooks(build(), "select");
|
|
15350
15241
|
const first = Array.isArray(rows) ? rows[0] : rows;
|
|
15351
15242
|
if (!first)
|
|
15352
15243
|
throw new Error("No rows found");
|
|
15353
15244
|
return first;
|
|
15354
15245
|
},
|
|
15355
|
-
|
|
15356
|
-
const
|
|
15357
|
-
const
|
|
15358
|
-
return
|
|
15246
|
+
async count() {
|
|
15247
|
+
const q = params.length > 0 ? _sql.unsafe(`SELECT COUNT(*) as c FROM (${text}) as sub`, params) : _sql.unsafe(`SELECT COUNT(*) as c FROM (${text}) as sub`);
|
|
15248
|
+
const rows = await runWithHooks(q, "select");
|
|
15249
|
+
return Number(rows?.[0]?.c ?? 0);
|
|
15250
|
+
},
|
|
15251
|
+
async exists() {
|
|
15252
|
+
const q = params.length > 0 ? _sql.unsafe(`SELECT EXISTS(${text}) as e`, params) : _sql.unsafe(`SELECT EXISTS(${text}) as e`);
|
|
15253
|
+
const result = await runWithHooks(q, "select");
|
|
15254
|
+
return Boolean(result?.[0]?.e);
|
|
15359
15255
|
},
|
|
15360
|
-
|
|
15361
|
-
|
|
15362
|
-
return !exists;
|
|
15256
|
+
async doesntExist() {
|
|
15257
|
+
return !await base.exists();
|
|
15363
15258
|
},
|
|
15364
|
-
values
|
|
15365
|
-
|
|
15366
|
-
|
|
15259
|
+
values() {
|
|
15260
|
+
return build().values();
|
|
15261
|
+
},
|
|
15262
|
+
raw() {
|
|
15263
|
+
return build().raw();
|
|
15264
|
+
},
|
|
15265
|
+
cancel() {
|
|
15367
15266
|
try {
|
|
15368
|
-
|
|
15267
|
+
build().cancel();
|
|
15369
15268
|
} catch {}
|
|
15370
15269
|
},
|
|
15371
|
-
|
|
15372
|
-
|
|
15373
|
-
|
|
15270
|
+
whereRaw: subqueryNotSupported("whereRaw"),
|
|
15271
|
+
whereColumn: subqueryNotSupported("whereColumn"),
|
|
15272
|
+
orWhereColumn: subqueryNotSupported("orWhereColumn"),
|
|
15273
|
+
whereIn: subqueryNotSupported("whereIn"),
|
|
15274
|
+
orWhereIn: subqueryNotSupported("orWhereIn"),
|
|
15275
|
+
whereNotIn: subqueryNotSupported("whereNotIn"),
|
|
15276
|
+
orWhereNotIn: subqueryNotSupported("orWhereNotIn"),
|
|
15277
|
+
whereLike: subqueryNotSupported("whereLike"),
|
|
15278
|
+
whereILike: subqueryNotSupported("whereILike"),
|
|
15279
|
+
orWhereLike: subqueryNotSupported("orWhereLike"),
|
|
15280
|
+
orWhereILike: subqueryNotSupported("orWhereILike"),
|
|
15281
|
+
whereNotLike: subqueryNotSupported("whereNotLike"),
|
|
15282
|
+
whereNotILike: subqueryNotSupported("whereNotILike"),
|
|
15283
|
+
orWhereNotLike: subqueryNotSupported("orWhereNotLike"),
|
|
15284
|
+
orWhereNotILike: subqueryNotSupported("orWhereNotILike"),
|
|
15285
|
+
whereAny: subqueryNotSupported("whereAny"),
|
|
15286
|
+
whereAll: subqueryNotSupported("whereAll"),
|
|
15287
|
+
whereNone: subqueryNotSupported("whereNone"),
|
|
15288
|
+
whereNested: subqueryNotSupported("whereNested"),
|
|
15289
|
+
orWhereNested: subqueryNotSupported("orWhereNested"),
|
|
15290
|
+
whereDate: subqueryNotSupported("whereDate"),
|
|
15291
|
+
whereBetween: subqueryNotSupported("whereBetween"),
|
|
15292
|
+
whereNotBetween: subqueryNotSupported("whereNotBetween"),
|
|
15293
|
+
whereJsonContains: subqueryNotSupported("whereJsonContains"),
|
|
15294
|
+
whereJsonPath: subqueryNotSupported("whereJsonPath"),
|
|
15295
|
+
whereNull: subqueryNotSupported("whereNull"),
|
|
15296
|
+
whereNotNull: subqueryNotSupported("whereNotNull"),
|
|
15297
|
+
whereExists: subqueryNotSupported("whereExists"),
|
|
15298
|
+
whereJsonDoesntContain: subqueryNotSupported("whereJsonDoesntContain"),
|
|
15299
|
+
whereJsonContainsKey: subqueryNotSupported("whereJsonContainsKey"),
|
|
15300
|
+
whereJsonDoesntContainKey: subqueryNotSupported("whereJsonDoesntContainKey"),
|
|
15301
|
+
whereJsonLength: subqueryNotSupported("whereJsonLength"),
|
|
15302
|
+
join: subqueryNotSupported("join"),
|
|
15303
|
+
joinSub: subqueryNotSupported("joinSub"),
|
|
15304
|
+
innerJoin: subqueryNotSupported("innerJoin"),
|
|
15305
|
+
leftJoin: subqueryNotSupported("leftJoin"),
|
|
15306
|
+
leftJoinSub: subqueryNotSupported("leftJoinSub"),
|
|
15307
|
+
rightJoin: subqueryNotSupported("rightJoin"),
|
|
15308
|
+
crossJoin: subqueryNotSupported("crossJoin"),
|
|
15309
|
+
crossJoinSub: subqueryNotSupported("crossJoinSub"),
|
|
15310
|
+
groupBy: subqueryNotSupported("groupBy"),
|
|
15311
|
+
groupByRaw: subqueryNotSupported("groupByRaw"),
|
|
15312
|
+
having: subqueryNotSupported("having"),
|
|
15313
|
+
havingRaw: subqueryNotSupported("havingRaw"),
|
|
15314
|
+
addSelect: subqueryNotSupported("addSelect"),
|
|
15315
|
+
select: subqueryNotSupported("select"),
|
|
15316
|
+
selectAll: subqueryNotSupported("selectAll"),
|
|
15317
|
+
orderByDesc: subqueryNotSupported("orderByDesc"),
|
|
15318
|
+
inRandomOrder: subqueryNotSupported("inRandomOrder"),
|
|
15319
|
+
reorder: subqueryNotSupported("reorder"),
|
|
15320
|
+
orderByRaw: subqueryNotSupported("orderByRaw"),
|
|
15321
|
+
union: subqueryNotSupported("union"),
|
|
15322
|
+
unionAll: subqueryNotSupported("unionAll"),
|
|
15323
|
+
forPage: subqueryNotSupported("forPage"),
|
|
15324
|
+
selectAllRelations: subqueryNotSupported("selectAllRelations"),
|
|
15325
|
+
with: subqueryNotSupported("with"),
|
|
15326
|
+
value: subqueryNotSupported("value"),
|
|
15327
|
+
pluck: subqueryNotSupported("pluck"),
|
|
15328
|
+
cursorPaginate: subqueryNotSupported("cursorPaginate"),
|
|
15329
|
+
paginate: subqueryNotSupported("paginate"),
|
|
15330
|
+
simplePaginate: subqueryNotSupported("simplePaginate"),
|
|
15331
|
+
chunk: subqueryNotSupported("chunk"),
|
|
15332
|
+
chunkById: subqueryNotSupported("chunkById"),
|
|
15333
|
+
eachById: subqueryNotSupported("eachById"),
|
|
15334
|
+
avg: subqueryNotSupported("avg"),
|
|
15335
|
+
sum: subqueryNotSupported("sum"),
|
|
15336
|
+
max: subqueryNotSupported("max"),
|
|
15337
|
+
min: subqueryNotSupported("min"),
|
|
15338
|
+
find: subqueryNotSupported("find"),
|
|
15339
|
+
findOrFail: subqueryNotSupported("findOrFail"),
|
|
15340
|
+
findMany: subqueryNotSupported("findMany"),
|
|
15341
|
+
latest: subqueryNotSupported("latest"),
|
|
15342
|
+
oldest: subqueryNotSupported("oldest"),
|
|
15343
|
+
lazy: subqueryNotSupported("lazy"),
|
|
15344
|
+
lazyById: subqueryNotSupported("lazyById"),
|
|
15345
|
+
pipe: (fn) => fn(base),
|
|
15346
|
+
when: subqueryNotSupported("when"),
|
|
15347
|
+
tap: () => base,
|
|
15348
|
+
dump: () => base,
|
|
15349
|
+
dd: () => {
|
|
15350
|
+
throw new Error("Dump and Die");
|
|
15351
|
+
},
|
|
15352
|
+
explain: () => Promise.resolve([]),
|
|
15353
|
+
simple: () => build().simple(),
|
|
15354
|
+
toText: () => text,
|
|
15355
|
+
toParams: () => [...params],
|
|
15356
|
+
withTimeout: () => base,
|
|
15357
|
+
abort: () => base,
|
|
15358
|
+
lockForUpdate: () => base,
|
|
15359
|
+
sharedLock: () => base,
|
|
15360
|
+
withCTE: () => base,
|
|
15361
|
+
withRecursive: () => base,
|
|
15362
|
+
cache: () => base,
|
|
15363
|
+
clone: () => base,
|
|
15364
|
+
withTrashed: () => base,
|
|
15365
|
+
onlyTrashed: () => base,
|
|
15366
|
+
scope: () => base,
|
|
15367
|
+
get rows() {
|
|
15368
|
+
return [];
|
|
15369
|
+
},
|
|
15370
|
+
get row() {
|
|
15371
|
+
return;
|
|
15372
|
+
}
|
|
15374
15373
|
};
|
|
15374
|
+
return base;
|
|
15375
15375
|
}
|
|
15376
|
-
|
|
15377
|
-
if (typeof expr === "string" && op !== undefined) {
|
|
15378
|
-
const clause = Array.isArray(value) ? `${expr} IN (?)` : `${expr} ${op} ?`;
|
|
15379
|
-
return sql`${query} ${sql(prefix)} ${sql(clause)}`;
|
|
15380
|
-
} else if (Array.isArray(expr) && expr.length === 3) {
|
|
15381
|
-
const [column, operator, val] = expr;
|
|
15382
|
-
const clause = Array.isArray(val) ? `${column} IN (?)` : `${column} ${operator} ?`;
|
|
15383
|
-
return sql`${query} ${sql(prefix)} ${sql(clause)}`;
|
|
15384
|
-
} else if (typeof expr === "object" && expr !== null) {
|
|
15385
|
-
const conditions = Object.entries(expr).map(([key, val]) => {
|
|
15386
|
-
const clause = Array.isArray(val) ? `${key} IN (?)` : `${key} = ?`;
|
|
15387
|
-
return sql`${sql(clause)}`;
|
|
15388
|
-
});
|
|
15389
|
-
const combined = conditions.reduce((acc, cond, i) => i === 0 ? cond : sql`${acc} AND ${cond}`);
|
|
15390
|
-
return sql`${query} ${sql(prefix)} ${combined}`;
|
|
15391
|
-
}
|
|
15392
|
-
return query;
|
|
15393
|
-
}
|
|
15394
|
-
return base;
|
|
15376
|
+
return makeSub(baseText, subParams);
|
|
15395
15377
|
},
|
|
15396
15378
|
insertInto(table) {
|
|
15397
15379
|
let built;
|
|
@@ -24639,8 +24621,45 @@ function resolveRelation(definition, relationName) {
|
|
|
24639
24621
|
pivotTimestamps: Boolean(config6?.pivot?.timestamps)
|
|
24640
24622
|
};
|
|
24641
24623
|
}
|
|
24624
|
+
const resolveThrough = (field, type) => {
|
|
24625
|
+
if (!field || typeof field !== "object" || Array.isArray(field))
|
|
24626
|
+
return null;
|
|
24627
|
+
const entry = field[relationName] ?? field[Object.keys(field).find((k2) => k2.toLowerCase() === relationName.toLowerCase()) ?? ""];
|
|
24628
|
+
if (!entry || typeof entry !== "object")
|
|
24629
|
+
return null;
|
|
24630
|
+
const throughModelName = entry.through;
|
|
24631
|
+
const targetModelName = entry.target;
|
|
24632
|
+
if (!throughModelName || !targetModelName)
|
|
24633
|
+
return null;
|
|
24634
|
+
const throughModel = getModelFromRegistry(throughModelName);
|
|
24635
|
+
const throughDef = throughModel?.getDefinition?.() || throughModel?.definition;
|
|
24636
|
+
const throughTable = throughModel?.getTable?.() || throughDef?.table || toTableName(throughModelName);
|
|
24637
|
+
const throughPk = throughDef?.primaryKey || "id";
|
|
24638
|
+
const targetModel = getModelFromRegistry(targetModelName);
|
|
24639
|
+
const targetTable = targetModel?.getTable?.() || toTableName(targetModelName);
|
|
24640
|
+
return {
|
|
24641
|
+
type,
|
|
24642
|
+
relatedModelName: targetModelName,
|
|
24643
|
+
relatedTable: targetTable,
|
|
24644
|
+
foreignKey: `${toSnakeCase(parentName)}_id`,
|
|
24645
|
+
localKey: parentPk,
|
|
24646
|
+
throughTable,
|
|
24647
|
+
throughForeignKey: `${toSnakeCase(parentName)}_id`,
|
|
24648
|
+
throughLocalKey: throughPk,
|
|
24649
|
+
targetForeignKey: `${singularizeWord(throughTable)}_id`
|
|
24650
|
+
};
|
|
24651
|
+
};
|
|
24652
|
+
const hmt = resolveThrough(definition.hasManyThrough, "hasManyThrough");
|
|
24653
|
+
if (hmt)
|
|
24654
|
+
return hmt;
|
|
24655
|
+
const hot = resolveThrough(definition.hasOneThrough, "hasOneThrough");
|
|
24656
|
+
if (hot)
|
|
24657
|
+
return hot;
|
|
24642
24658
|
return null;
|
|
24643
24659
|
}
|
|
24660
|
+
function singularizeWord(table) {
|
|
24661
|
+
return table.endsWith("s") ? table.slice(0, -1) : table;
|
|
24662
|
+
}
|
|
24644
24663
|
|
|
24645
24664
|
class BelongsToManyRelationBuilder {
|
|
24646
24665
|
_parent;
|
|
@@ -25277,6 +25296,40 @@ class ModelQueryBuilder {
|
|
|
25277
25296
|
instance.setRelation(relationName, relatedInstances);
|
|
25278
25297
|
}
|
|
25279
25298
|
}
|
|
25299
|
+
if (rel.type === "hasManyThrough" || rel.type === "hasOneThrough") {
|
|
25300
|
+
const parentIds = instances.map((i2) => i2.get(pk)).filter((id) => id != null);
|
|
25301
|
+
if (parentIds.length === 0)
|
|
25302
|
+
continue;
|
|
25303
|
+
const throughPk = rel.throughLocalKey || "id";
|
|
25304
|
+
const throughPh = parentIds.map(() => "?").join(", ");
|
|
25305
|
+
const throughRows = await exec.all(`SELECT ${throughPk}, ${rel.throughForeignKey} FROM ${rel.throughTable} WHERE ${rel.throughForeignKey} IN (${throughPh})`, parentIds);
|
|
25306
|
+
if (throughRows.length === 0) {
|
|
25307
|
+
for (const instance of instances)
|
|
25308
|
+
instance.setRelation(relationName, rel.type === "hasManyThrough" ? [] : null);
|
|
25309
|
+
continue;
|
|
25310
|
+
}
|
|
25311
|
+
const throughToParent = new Map;
|
|
25312
|
+
for (const t2 of throughRows)
|
|
25313
|
+
throughToParent.set(t2[throughPk], t2[rel.throughForeignKey]);
|
|
25314
|
+
const throughIds = [...new Set(throughRows.map((t2) => t2[throughPk]))];
|
|
25315
|
+
const targetPh = throughIds.map(() => "?").join(", ");
|
|
25316
|
+
const targetRows = await exec.all(`SELECT * FROM ${rel.relatedTable} WHERE ${rel.targetForeignKey} IN (${targetPh})`, throughIds);
|
|
25317
|
+
const relatedModelDef = getModelFromRegistry(rel.relatedModelName);
|
|
25318
|
+
const relDef = relatedModelDef?.getDefinition?.() || relatedModelDef?.definition || this._definition;
|
|
25319
|
+
const byParent = new Map;
|
|
25320
|
+
for (const row of targetRows) {
|
|
25321
|
+
const parentVal = throughToParent.get(row[rel.targetForeignKey]);
|
|
25322
|
+
if (parentVal == null)
|
|
25323
|
+
continue;
|
|
25324
|
+
if (!byParent.has(parentVal))
|
|
25325
|
+
byParent.set(parentVal, []);
|
|
25326
|
+
byParent.get(parentVal).push(new ModelInstance(relDef, row));
|
|
25327
|
+
}
|
|
25328
|
+
for (const instance of instances) {
|
|
25329
|
+
const group = byParent.get(instance.get(pk)) || [];
|
|
25330
|
+
instance.setRelation(relationName, rel.type === "hasManyThrough" ? group : group[0] ?? null);
|
|
25331
|
+
}
|
|
25332
|
+
}
|
|
25280
25333
|
}
|
|
25281
25334
|
}
|
|
25282
25335
|
async get() {
|
|
@@ -30153,7 +30206,7 @@ function getPrefix() {
|
|
|
30153
30206
|
}
|
|
30154
30207
|
var prefix = getPrefix();
|
|
30155
30208
|
// package.json
|
|
30156
|
-
var version2 = "0.1.
|
|
30209
|
+
var version2 = "0.1.37";
|
|
30157
30210
|
|
|
30158
30211
|
// bin/cli.ts
|
|
30159
30212
|
init_actions();
|
package/dist/orm.d.ts
CHANGED
|
@@ -163,11 +163,15 @@ declare interface OrmExecutor {
|
|
|
163
163
|
* populated only for `belongsToMany` relations.
|
|
164
164
|
*/
|
|
165
165
|
declare interface ResolvedRelation {
|
|
166
|
-
type: 'hasMany' | 'hasOne' | 'belongsTo' | 'belongsToMany'
|
|
166
|
+
type: 'hasMany' | 'hasOne' | 'belongsTo' | 'belongsToMany' | 'hasManyThrough' | 'hasOneThrough'
|
|
167
167
|
relatedModelName: string
|
|
168
168
|
relatedTable: string
|
|
169
169
|
foreignKey: string
|
|
170
170
|
localKey: string
|
|
171
|
+
throughTable?: string
|
|
172
|
+
throughForeignKey?: string
|
|
173
|
+
throughLocalKey?: string
|
|
174
|
+
targetForeignKey?: string
|
|
171
175
|
pivotTable?: string
|
|
172
176
|
pivotFkParent?: string
|
|
173
177
|
pivotFkRelated?: string
|
package/dist/src/index.js
CHANGED
|
@@ -15036,7 +15036,7 @@ function createQueryBuilder(state) {
|
|
|
15036
15036
|
return ensureBuilt().values();
|
|
15037
15037
|
},
|
|
15038
15038
|
toParams() {
|
|
15039
|
-
return
|
|
15039
|
+
return [...whereParams];
|
|
15040
15040
|
},
|
|
15041
15041
|
__rawState() {
|
|
15042
15042
|
return { sql: reorderSelectClauses(text), params: [...whereParams] };
|
|
@@ -15133,265 +15133,247 @@ function createQueryBuilder(state) {
|
|
|
15133
15133
|
throw new Error(`[query-builder] selectFromSub(...).${methodName}() is not supported. ` + `Apply ${methodName}() to the underlying subquery BEFORE passing it to selectFromSub, ` + `or use the regular selectFrom(...) builder. This previously silently returned without ` + `affecting the SQL, producing wrong results \u2014 see stacksjs/stacks#1862 #11.`);
|
|
15134
15134
|
};
|
|
15135
15135
|
}
|
|
15136
|
-
|
|
15137
|
-
const
|
|
15138
|
-
const
|
|
15139
|
-
|
|
15140
|
-
|
|
15141
|
-
|
|
15142
|
-
|
|
15143
|
-
|
|
15144
|
-
|
|
15145
|
-
|
|
15146
|
-
|
|
15147
|
-
const
|
|
15148
|
-
|
|
15149
|
-
|
|
15150
|
-
|
|
15151
|
-
|
|
15152
|
-
|
|
15153
|
-
|
|
15154
|
-
|
|
15155
|
-
|
|
15156
|
-
return
|
|
15157
|
-
}
|
|
15158
|
-
|
|
15159
|
-
|
|
15160
|
-
|
|
15161
|
-
|
|
15162
|
-
|
|
15163
|
-
|
|
15164
|
-
|
|
15165
|
-
|
|
15166
|
-
|
|
15167
|
-
|
|
15168
|
-
const current = String(q);
|
|
15169
|
-
const newQ = SQL_PATTERNS.ORDER_BY.test(current) ? sql.unsafe(`${current}, ${column} ${dir}`) : sql`${q} ORDER BY ${sql(column)} ${direction === "asc" ? sql`ASC` : sql`DESC`}`;
|
|
15170
|
-
return createSubQueryBuilder(newQ);
|
|
15171
|
-
},
|
|
15172
|
-
limit(n) {
|
|
15173
|
-
const current = String(q);
|
|
15174
|
-
const newQ = SQL_PATTERNS.LIMIT.test(current) ? sql.unsafe(current.replace(SQL_PATTERNS.LIMIT, ` LIMIT ${n}`)) : sql`${q} LIMIT ${n}`;
|
|
15175
|
-
return createSubQueryBuilder(newQ);
|
|
15176
|
-
},
|
|
15177
|
-
offset(n) {
|
|
15178
|
-
const current = String(q);
|
|
15179
|
-
const newQ = SQL_PATTERNS.OFFSET.test(current) ? sql.unsafe(current.replace(SQL_PATTERNS.OFFSET, ` OFFSET ${n}`)) : sql`${q} OFFSET ${n}`;
|
|
15180
|
-
return createSubQueryBuilder(newQ);
|
|
15181
|
-
},
|
|
15182
|
-
toSQL() {
|
|
15183
|
-
return makeExecutableQuery(q);
|
|
15184
|
-
},
|
|
15185
|
-
async execute() {
|
|
15186
|
-
return runWithHooks(q, "select");
|
|
15187
|
-
},
|
|
15188
|
-
async executeTakeFirst() {
|
|
15189
|
-
const rows = await runWithHooks(q, "select");
|
|
15190
|
-
return Array.isArray(rows) ? rows[0] : rows;
|
|
15191
|
-
},
|
|
15192
|
-
async executeTakeFirstOrThrow() {
|
|
15193
|
-
const rows = await runWithHooks(q, "select");
|
|
15194
|
-
const first = Array.isArray(rows) ? rows[0] : rows;
|
|
15195
|
-
if (!first)
|
|
15196
|
-
throw new Error("Record not found");
|
|
15197
|
-
return first;
|
|
15198
|
-
},
|
|
15199
|
-
async get() {
|
|
15200
|
-
return runWithHooks(q, "select");
|
|
15201
|
-
},
|
|
15202
|
-
async first() {
|
|
15203
|
-
const rows = await runWithHooks(q, "select");
|
|
15204
|
-
return Array.isArray(rows) ? rows[0] : rows;
|
|
15205
|
-
},
|
|
15206
|
-
async firstOrFail() {
|
|
15207
|
-
const rows = await runWithHooks(q, "select");
|
|
15208
|
-
const first = Array.isArray(rows) ? rows[0] : rows;
|
|
15209
|
-
if (!first)
|
|
15210
|
-
throw new Error("No rows found");
|
|
15211
|
-
return first;
|
|
15212
|
-
},
|
|
15213
|
-
async exists() {
|
|
15214
|
-
const countQ = sql`SELECT EXISTS(${q}) as exists`;
|
|
15215
|
-
const result = await runWithHooks(countQ, "select");
|
|
15216
|
-
return result?.[0]?.exists === true;
|
|
15217
|
-
},
|
|
15218
|
-
async doesntExist() {
|
|
15219
|
-
const exists = await this.exists();
|
|
15220
|
-
return !exists;
|
|
15221
|
-
},
|
|
15222
|
-
values() {
|
|
15223
|
-
return q.values();
|
|
15224
|
-
},
|
|
15225
|
-
raw() {
|
|
15226
|
-
return q.raw();
|
|
15227
|
-
},
|
|
15228
|
-
cancel() {
|
|
15229
|
-
try {
|
|
15230
|
-
q.cancel();
|
|
15231
|
-
} catch {}
|
|
15232
|
-
},
|
|
15233
|
-
whereRaw: subqueryNotSupported("whereRaw"),
|
|
15234
|
-
whereColumn: subqueryNotSupported("whereColumn"),
|
|
15235
|
-
orWhereColumn: subqueryNotSupported("orWhereColumn"),
|
|
15236
|
-
whereIn: subqueryNotSupported("whereIn"),
|
|
15237
|
-
orWhereIn: subqueryNotSupported("orWhereIn"),
|
|
15238
|
-
whereNotIn: subqueryNotSupported("whereNotIn"),
|
|
15239
|
-
orWhereNotIn: subqueryNotSupported("orWhereNotIn"),
|
|
15240
|
-
whereLike: subqueryNotSupported("whereLike"),
|
|
15241
|
-
whereILike: subqueryNotSupported("whereILike"),
|
|
15242
|
-
orWhereLike: subqueryNotSupported("orWhereLike"),
|
|
15243
|
-
orWhereILike: subqueryNotSupported("orWhereILike"),
|
|
15244
|
-
whereNotLike: subqueryNotSupported("whereNotLike"),
|
|
15245
|
-
whereNotILike: subqueryNotSupported("whereNotILike"),
|
|
15246
|
-
orWhereNotLike: subqueryNotSupported("orWhereNotLike"),
|
|
15247
|
-
orWhereNotILike: subqueryNotSupported("orWhereNotILike"),
|
|
15248
|
-
whereAny: subqueryNotSupported("whereAny"),
|
|
15249
|
-
whereAll: subqueryNotSupported("whereAll"),
|
|
15250
|
-
whereNone: subqueryNotSupported("whereNone"),
|
|
15251
|
-
whereNested: subqueryNotSupported("whereNested"),
|
|
15252
|
-
orWhereNested: subqueryNotSupported("orWhereNested"),
|
|
15253
|
-
whereDate: subqueryNotSupported("whereDate"),
|
|
15254
|
-
whereBetween: subqueryNotSupported("whereBetween"),
|
|
15255
|
-
whereNotBetween: subqueryNotSupported("whereNotBetween"),
|
|
15256
|
-
whereJsonContains: subqueryNotSupported("whereJsonContains"),
|
|
15257
|
-
whereJsonPath: subqueryNotSupported("whereJsonPath"),
|
|
15258
|
-
whereNull: subqueryNotSupported("whereNull"),
|
|
15259
|
-
whereNotNull: subqueryNotSupported("whereNotNull"),
|
|
15260
|
-
whereExists: subqueryNotSupported("whereExists"),
|
|
15261
|
-
whereJsonDoesntContain: subqueryNotSupported("whereJsonDoesntContain"),
|
|
15262
|
-
whereJsonContainsKey: subqueryNotSupported("whereJsonContainsKey"),
|
|
15263
|
-
whereJsonDoesntContainKey: subqueryNotSupported("whereJsonDoesntContainKey"),
|
|
15264
|
-
whereJsonLength: subqueryNotSupported("whereJsonLength"),
|
|
15265
|
-
join: subqueryNotSupported("join"),
|
|
15266
|
-
joinSub: subqueryNotSupported("joinSub"),
|
|
15267
|
-
innerJoin: subqueryNotSupported("innerJoin"),
|
|
15268
|
-
leftJoin: subqueryNotSupported("leftJoin"),
|
|
15269
|
-
leftJoinSub: subqueryNotSupported("leftJoinSub"),
|
|
15270
|
-
rightJoin: subqueryNotSupported("rightJoin"),
|
|
15271
|
-
crossJoin: subqueryNotSupported("crossJoin"),
|
|
15272
|
-
crossJoinSub: subqueryNotSupported("crossJoinSub"),
|
|
15273
|
-
groupBy: subqueryNotSupported("groupBy"),
|
|
15274
|
-
groupByRaw: subqueryNotSupported("groupByRaw"),
|
|
15275
|
-
having: subqueryNotSupported("having"),
|
|
15276
|
-
havingRaw: subqueryNotSupported("havingRaw"),
|
|
15277
|
-
addSelect: subqueryNotSupported("addSelect"),
|
|
15278
|
-
select: subqueryNotSupported("select"),
|
|
15279
|
-
selectAll: subqueryNotSupported("selectAll"),
|
|
15280
|
-
orderByDesc: subqueryNotSupported("orderByDesc"),
|
|
15281
|
-
inRandomOrder: subqueryNotSupported("inRandomOrder"),
|
|
15282
|
-
reorder: subqueryNotSupported("reorder"),
|
|
15283
|
-
orderByRaw: subqueryNotSupported("orderByRaw"),
|
|
15284
|
-
union: subqueryNotSupported("union"),
|
|
15285
|
-
unionAll: subqueryNotSupported("unionAll"),
|
|
15286
|
-
forPage: subqueryNotSupported("forPage"),
|
|
15287
|
-
selectAllRelations: subqueryNotSupported("selectAllRelations"),
|
|
15288
|
-
with: subqueryNotSupported("with"),
|
|
15289
|
-
value: subqueryNotSupported("value"),
|
|
15290
|
-
pluck: subqueryNotSupported("pluck"),
|
|
15291
|
-
cursorPaginate: subqueryNotSupported("cursorPaginate"),
|
|
15292
|
-
paginate: subqueryNotSupported("paginate"),
|
|
15293
|
-
simplePaginate: subqueryNotSupported("simplePaginate"),
|
|
15294
|
-
chunk: subqueryNotSupported("chunk"),
|
|
15295
|
-
chunkById: subqueryNotSupported("chunkById"),
|
|
15296
|
-
eachById: subqueryNotSupported("eachById"),
|
|
15297
|
-
count: subqueryNotSupported("count"),
|
|
15298
|
-
avg: subqueryNotSupported("avg"),
|
|
15299
|
-
sum: subqueryNotSupported("sum"),
|
|
15300
|
-
max: subqueryNotSupported("max"),
|
|
15301
|
-
min: subqueryNotSupported("min"),
|
|
15302
|
-
find: subqueryNotSupported("find"),
|
|
15303
|
-
findOrFail: subqueryNotSupported("findOrFail"),
|
|
15304
|
-
findMany: subqueryNotSupported("findMany"),
|
|
15305
|
-
latest: subqueryNotSupported("latest"),
|
|
15306
|
-
oldest: subqueryNotSupported("oldest"),
|
|
15307
|
-
lazy: subqueryNotSupported("lazy"),
|
|
15308
|
-
lazyById: subqueryNotSupported("lazyById"),
|
|
15309
|
-
pipe: (fn) => fn(this),
|
|
15310
|
-
when: subqueryNotSupported("when"),
|
|
15311
|
-
tap: () => this,
|
|
15312
|
-
dump: () => this,
|
|
15313
|
-
dd: () => {
|
|
15314
|
-
throw new Error("Dump and Die");
|
|
15315
|
-
},
|
|
15316
|
-
explain: () => Promise.resolve([]),
|
|
15317
|
-
simple: () => q.simple(),
|
|
15318
|
-
toText: () => String(q),
|
|
15319
|
-
toParams: () => q.values?.() ?? [],
|
|
15320
|
-
withTimeout: () => this,
|
|
15321
|
-
abort: () => this,
|
|
15322
|
-
lockForUpdate: () => this,
|
|
15323
|
-
sharedLock: () => this,
|
|
15324
|
-
withCTE: () => this,
|
|
15325
|
-
withRecursive: () => this,
|
|
15326
|
-
cache: () => this,
|
|
15327
|
-
clone: () => this,
|
|
15328
|
-
withTrashed: () => this,
|
|
15329
|
-
onlyTrashed: () => this,
|
|
15330
|
-
scope: () => this,
|
|
15331
|
-
get rows() {
|
|
15332
|
-
return [];
|
|
15333
|
-
},
|
|
15334
|
-
get row() {
|
|
15335
|
-
return;
|
|
15336
|
-
}
|
|
15136
|
+
validateIdentifier(String(alias), "selectFromSub(alias)");
|
|
15137
|
+
const rawState = typeof sub.__rawState === "function" ? sub.__rawState() : null;
|
|
15138
|
+
const subExec = sub.toSQL();
|
|
15139
|
+
const subText = rawState?.sql ?? (typeof subExec === "string" ? subExec : subExec?.sql ?? String(subExec));
|
|
15140
|
+
const subParams = rawState?.params ?? (Array.isArray(subExec?.values) ? subExec.values : []);
|
|
15141
|
+
const baseText = `SELECT * FROM (${subText}) AS ${String(alias)}`;
|
|
15142
|
+
const appendWhere = (text, params, hasWhere, expr, op, value, connector) => {
|
|
15143
|
+
const kw = !hasWhere ? "WHERE" : connector === "WHERE" ? "AND" : connector;
|
|
15144
|
+
const out = [...params];
|
|
15145
|
+
const cmp = (col, operator, val) => {
|
|
15146
|
+
validateIdentifier(col, "selectFromSub where(column)");
|
|
15147
|
+
const o = assertSafeWhereOperator(operator, "selectFromSub where(operator)");
|
|
15148
|
+
if (o === "in" || o === "not in") {
|
|
15149
|
+
const vals = Array.isArray(val) ? val : [val];
|
|
15150
|
+
const phs = getPlaceholders(vals.length, out.length + 1);
|
|
15151
|
+
out.push(...vals);
|
|
15152
|
+
return `${col} ${o.toUpperCase()} (${phs})`;
|
|
15153
|
+
}
|
|
15154
|
+
const ph = getPlaceholder(out.length + 1);
|
|
15155
|
+
out.push(val);
|
|
15156
|
+
return `${col} ${o} ${ph}`;
|
|
15157
|
+
};
|
|
15158
|
+
let clause;
|
|
15159
|
+
if (typeof expr === "string" && op !== undefined)
|
|
15160
|
+
clause = cmp(expr, op, value);
|
|
15161
|
+
else if (Array.isArray(expr) && expr.length === 3)
|
|
15162
|
+
clause = cmp(expr[0], expr[1], expr[2]);
|
|
15163
|
+
else if (expr && typeof expr === "object")
|
|
15164
|
+
clause = Object.entries(expr).map(([k, v]) => cmp(k, "=", v)).join(" AND ");
|
|
15165
|
+
else
|
|
15166
|
+
return { text, params };
|
|
15167
|
+
return { text: `${text} ${kw} ${clause}`, params: out };
|
|
15337
15168
|
};
|
|
15338
|
-
function
|
|
15339
|
-
|
|
15340
|
-
|
|
15341
|
-
|
|
15342
|
-
|
|
15343
|
-
|
|
15344
|
-
|
|
15345
|
-
const
|
|
15169
|
+
function makeSub(text, params, hasWhere = false) {
|
|
15170
|
+
const build = () => params.length > 0 ? _sql.unsafe(text, params) : _sql.unsafe(text);
|
|
15171
|
+
const base = {
|
|
15172
|
+
distinct() {
|
|
15173
|
+
return makeSub(text.replace(/^SELECT\s+/i, "SELECT DISTINCT "), params, hasWhere);
|
|
15174
|
+
},
|
|
15175
|
+
distinctOn(...columns) {
|
|
15176
|
+
const cols = columns.map(String).join(", ");
|
|
15177
|
+
return makeSub(text.replace(/^SELECT\s+/i, `SELECT DISTINCT ON (${cols}) `), params, hasWhere);
|
|
15178
|
+
},
|
|
15179
|
+
selectRaw(fragment) {
|
|
15180
|
+
const frag = renderRawFragment(fragment, "selectFromSub.selectRaw(fragment)");
|
|
15181
|
+
const fromIdx = text.indexOf(" FROM ");
|
|
15182
|
+
const newText = fromIdx !== -1 ? `${text.slice(0, fromIdx)}, ${frag}${text.slice(fromIdx)}` : `${text}, ${frag}`;
|
|
15183
|
+
return makeSub(newText, params, hasWhere);
|
|
15184
|
+
},
|
|
15185
|
+
where(expr, op, value) {
|
|
15186
|
+
const r = appendWhere(text, params, hasWhere, expr, op, value, "WHERE");
|
|
15187
|
+
return makeSub(r.text, r.params, true);
|
|
15188
|
+
},
|
|
15189
|
+
andWhere(expr, op, value) {
|
|
15190
|
+
const r = appendWhere(text, params, hasWhere, expr, op, value, "AND");
|
|
15191
|
+
return makeSub(r.text, r.params, true);
|
|
15192
|
+
},
|
|
15193
|
+
orWhere(expr, op, value) {
|
|
15194
|
+
const r = appendWhere(text, params, hasWhere, expr, op, value, "OR");
|
|
15195
|
+
return makeSub(r.text, r.params, true);
|
|
15196
|
+
},
|
|
15197
|
+
orderBy(column, direction = "asc") {
|
|
15198
|
+
validateIdentifier(String(column), "selectFromSub.orderBy(column)");
|
|
15199
|
+
const dir = direction === "asc" ? "ASC" : "DESC";
|
|
15200
|
+
const newText = SQL_PATTERNS.ORDER_BY.test(text) ? `${text}, ${column} ${dir}` : `${text} ORDER BY ${column} ${dir}`;
|
|
15201
|
+
return makeSub(newText, params, hasWhere);
|
|
15202
|
+
},
|
|
15203
|
+
limit(n) {
|
|
15204
|
+
if (!Number.isInteger(n) || n < 0)
|
|
15205
|
+
throw new TypeError(`[query-builder] selectFromSub.limit(n): expected non-negative integer, got ${n}`);
|
|
15206
|
+
const newText = SQL_PATTERNS.LIMIT.test(text) ? text.replace(SQL_PATTERNS.LIMIT, ` LIMIT ${n}`) : `${text} LIMIT ${n}`;
|
|
15207
|
+
return makeSub(newText, params, hasWhere);
|
|
15208
|
+
},
|
|
15209
|
+
offset(n) {
|
|
15210
|
+
if (!Number.isInteger(n) || n < 0)
|
|
15211
|
+
throw new TypeError(`[query-builder] selectFromSub.offset(n): expected non-negative integer, got ${n}`);
|
|
15212
|
+
const newText = SQL_PATTERNS.OFFSET.test(text) ? text.replace(SQL_PATTERNS.OFFSET, ` OFFSET ${n}`) : `${text} OFFSET ${n}`;
|
|
15213
|
+
return makeSub(newText, params, hasWhere);
|
|
15214
|
+
},
|
|
15215
|
+
toSQL() {
|
|
15216
|
+
return makeExecutableQuery(build(), text);
|
|
15217
|
+
},
|
|
15218
|
+
async execute() {
|
|
15219
|
+
return runWithHooks(build(), "select");
|
|
15220
|
+
},
|
|
15221
|
+
async executeTakeFirst() {
|
|
15222
|
+
const rows = await runWithHooks(build(), "select");
|
|
15346
15223
|
return Array.isArray(rows) ? rows[0] : rows;
|
|
15347
15224
|
},
|
|
15348
|
-
|
|
15349
|
-
const rows = await runWithHooks(
|
|
15225
|
+
async executeTakeFirstOrThrow() {
|
|
15226
|
+
const rows = await runWithHooks(build(), "select");
|
|
15227
|
+
const first = Array.isArray(rows) ? rows[0] : rows;
|
|
15228
|
+
if (!first)
|
|
15229
|
+
throw new Error("Record not found");
|
|
15230
|
+
return first;
|
|
15231
|
+
},
|
|
15232
|
+
async get() {
|
|
15233
|
+
return runWithHooks(build(), "select");
|
|
15234
|
+
},
|
|
15235
|
+
async first() {
|
|
15236
|
+
const rows = await runWithHooks(build(), "select");
|
|
15237
|
+
return Array.isArray(rows) ? rows[0] : rows;
|
|
15238
|
+
},
|
|
15239
|
+
async firstOrFail() {
|
|
15240
|
+
const rows = await runWithHooks(build(), "select");
|
|
15350
15241
|
const first = Array.isArray(rows) ? rows[0] : rows;
|
|
15351
15242
|
if (!first)
|
|
15352
15243
|
throw new Error("No rows found");
|
|
15353
15244
|
return first;
|
|
15354
15245
|
},
|
|
15355
|
-
|
|
15356
|
-
const
|
|
15357
|
-
const
|
|
15358
|
-
return
|
|
15246
|
+
async count() {
|
|
15247
|
+
const q = params.length > 0 ? _sql.unsafe(`SELECT COUNT(*) as c FROM (${text}) as sub`, params) : _sql.unsafe(`SELECT COUNT(*) as c FROM (${text}) as sub`);
|
|
15248
|
+
const rows = await runWithHooks(q, "select");
|
|
15249
|
+
return Number(rows?.[0]?.c ?? 0);
|
|
15250
|
+
},
|
|
15251
|
+
async exists() {
|
|
15252
|
+
const q = params.length > 0 ? _sql.unsafe(`SELECT EXISTS(${text}) as e`, params) : _sql.unsafe(`SELECT EXISTS(${text}) as e`);
|
|
15253
|
+
const result = await runWithHooks(q, "select");
|
|
15254
|
+
return Boolean(result?.[0]?.e);
|
|
15359
15255
|
},
|
|
15360
|
-
|
|
15361
|
-
|
|
15362
|
-
return !exists;
|
|
15256
|
+
async doesntExist() {
|
|
15257
|
+
return !await base.exists();
|
|
15363
15258
|
},
|
|
15364
|
-
values
|
|
15365
|
-
|
|
15366
|
-
|
|
15259
|
+
values() {
|
|
15260
|
+
return build().values();
|
|
15261
|
+
},
|
|
15262
|
+
raw() {
|
|
15263
|
+
return build().raw();
|
|
15264
|
+
},
|
|
15265
|
+
cancel() {
|
|
15367
15266
|
try {
|
|
15368
|
-
|
|
15267
|
+
build().cancel();
|
|
15369
15268
|
} catch {}
|
|
15370
15269
|
},
|
|
15371
|
-
|
|
15372
|
-
|
|
15373
|
-
|
|
15270
|
+
whereRaw: subqueryNotSupported("whereRaw"),
|
|
15271
|
+
whereColumn: subqueryNotSupported("whereColumn"),
|
|
15272
|
+
orWhereColumn: subqueryNotSupported("orWhereColumn"),
|
|
15273
|
+
whereIn: subqueryNotSupported("whereIn"),
|
|
15274
|
+
orWhereIn: subqueryNotSupported("orWhereIn"),
|
|
15275
|
+
whereNotIn: subqueryNotSupported("whereNotIn"),
|
|
15276
|
+
orWhereNotIn: subqueryNotSupported("orWhereNotIn"),
|
|
15277
|
+
whereLike: subqueryNotSupported("whereLike"),
|
|
15278
|
+
whereILike: subqueryNotSupported("whereILike"),
|
|
15279
|
+
orWhereLike: subqueryNotSupported("orWhereLike"),
|
|
15280
|
+
orWhereILike: subqueryNotSupported("orWhereILike"),
|
|
15281
|
+
whereNotLike: subqueryNotSupported("whereNotLike"),
|
|
15282
|
+
whereNotILike: subqueryNotSupported("whereNotILike"),
|
|
15283
|
+
orWhereNotLike: subqueryNotSupported("orWhereNotLike"),
|
|
15284
|
+
orWhereNotILike: subqueryNotSupported("orWhereNotILike"),
|
|
15285
|
+
whereAny: subqueryNotSupported("whereAny"),
|
|
15286
|
+
whereAll: subqueryNotSupported("whereAll"),
|
|
15287
|
+
whereNone: subqueryNotSupported("whereNone"),
|
|
15288
|
+
whereNested: subqueryNotSupported("whereNested"),
|
|
15289
|
+
orWhereNested: subqueryNotSupported("orWhereNested"),
|
|
15290
|
+
whereDate: subqueryNotSupported("whereDate"),
|
|
15291
|
+
whereBetween: subqueryNotSupported("whereBetween"),
|
|
15292
|
+
whereNotBetween: subqueryNotSupported("whereNotBetween"),
|
|
15293
|
+
whereJsonContains: subqueryNotSupported("whereJsonContains"),
|
|
15294
|
+
whereJsonPath: subqueryNotSupported("whereJsonPath"),
|
|
15295
|
+
whereNull: subqueryNotSupported("whereNull"),
|
|
15296
|
+
whereNotNull: subqueryNotSupported("whereNotNull"),
|
|
15297
|
+
whereExists: subqueryNotSupported("whereExists"),
|
|
15298
|
+
whereJsonDoesntContain: subqueryNotSupported("whereJsonDoesntContain"),
|
|
15299
|
+
whereJsonContainsKey: subqueryNotSupported("whereJsonContainsKey"),
|
|
15300
|
+
whereJsonDoesntContainKey: subqueryNotSupported("whereJsonDoesntContainKey"),
|
|
15301
|
+
whereJsonLength: subqueryNotSupported("whereJsonLength"),
|
|
15302
|
+
join: subqueryNotSupported("join"),
|
|
15303
|
+
joinSub: subqueryNotSupported("joinSub"),
|
|
15304
|
+
innerJoin: subqueryNotSupported("innerJoin"),
|
|
15305
|
+
leftJoin: subqueryNotSupported("leftJoin"),
|
|
15306
|
+
leftJoinSub: subqueryNotSupported("leftJoinSub"),
|
|
15307
|
+
rightJoin: subqueryNotSupported("rightJoin"),
|
|
15308
|
+
crossJoin: subqueryNotSupported("crossJoin"),
|
|
15309
|
+
crossJoinSub: subqueryNotSupported("crossJoinSub"),
|
|
15310
|
+
groupBy: subqueryNotSupported("groupBy"),
|
|
15311
|
+
groupByRaw: subqueryNotSupported("groupByRaw"),
|
|
15312
|
+
having: subqueryNotSupported("having"),
|
|
15313
|
+
havingRaw: subqueryNotSupported("havingRaw"),
|
|
15314
|
+
addSelect: subqueryNotSupported("addSelect"),
|
|
15315
|
+
select: subqueryNotSupported("select"),
|
|
15316
|
+
selectAll: subqueryNotSupported("selectAll"),
|
|
15317
|
+
orderByDesc: subqueryNotSupported("orderByDesc"),
|
|
15318
|
+
inRandomOrder: subqueryNotSupported("inRandomOrder"),
|
|
15319
|
+
reorder: subqueryNotSupported("reorder"),
|
|
15320
|
+
orderByRaw: subqueryNotSupported("orderByRaw"),
|
|
15321
|
+
union: subqueryNotSupported("union"),
|
|
15322
|
+
unionAll: subqueryNotSupported("unionAll"),
|
|
15323
|
+
forPage: subqueryNotSupported("forPage"),
|
|
15324
|
+
selectAllRelations: subqueryNotSupported("selectAllRelations"),
|
|
15325
|
+
with: subqueryNotSupported("with"),
|
|
15326
|
+
value: subqueryNotSupported("value"),
|
|
15327
|
+
pluck: subqueryNotSupported("pluck"),
|
|
15328
|
+
cursorPaginate: subqueryNotSupported("cursorPaginate"),
|
|
15329
|
+
paginate: subqueryNotSupported("paginate"),
|
|
15330
|
+
simplePaginate: subqueryNotSupported("simplePaginate"),
|
|
15331
|
+
chunk: subqueryNotSupported("chunk"),
|
|
15332
|
+
chunkById: subqueryNotSupported("chunkById"),
|
|
15333
|
+
eachById: subqueryNotSupported("eachById"),
|
|
15334
|
+
avg: subqueryNotSupported("avg"),
|
|
15335
|
+
sum: subqueryNotSupported("sum"),
|
|
15336
|
+
max: subqueryNotSupported("max"),
|
|
15337
|
+
min: subqueryNotSupported("min"),
|
|
15338
|
+
find: subqueryNotSupported("find"),
|
|
15339
|
+
findOrFail: subqueryNotSupported("findOrFail"),
|
|
15340
|
+
findMany: subqueryNotSupported("findMany"),
|
|
15341
|
+
latest: subqueryNotSupported("latest"),
|
|
15342
|
+
oldest: subqueryNotSupported("oldest"),
|
|
15343
|
+
lazy: subqueryNotSupported("lazy"),
|
|
15344
|
+
lazyById: subqueryNotSupported("lazyById"),
|
|
15345
|
+
pipe: (fn) => fn(base),
|
|
15346
|
+
when: subqueryNotSupported("when"),
|
|
15347
|
+
tap: () => base,
|
|
15348
|
+
dump: () => base,
|
|
15349
|
+
dd: () => {
|
|
15350
|
+
throw new Error("Dump and Die");
|
|
15351
|
+
},
|
|
15352
|
+
explain: () => Promise.resolve([]),
|
|
15353
|
+
simple: () => build().simple(),
|
|
15354
|
+
toText: () => text,
|
|
15355
|
+
toParams: () => [...params],
|
|
15356
|
+
withTimeout: () => base,
|
|
15357
|
+
abort: () => base,
|
|
15358
|
+
lockForUpdate: () => base,
|
|
15359
|
+
sharedLock: () => base,
|
|
15360
|
+
withCTE: () => base,
|
|
15361
|
+
withRecursive: () => base,
|
|
15362
|
+
cache: () => base,
|
|
15363
|
+
clone: () => base,
|
|
15364
|
+
withTrashed: () => base,
|
|
15365
|
+
onlyTrashed: () => base,
|
|
15366
|
+
scope: () => base,
|
|
15367
|
+
get rows() {
|
|
15368
|
+
return [];
|
|
15369
|
+
},
|
|
15370
|
+
get row() {
|
|
15371
|
+
return;
|
|
15372
|
+
}
|
|
15374
15373
|
};
|
|
15374
|
+
return base;
|
|
15375
15375
|
}
|
|
15376
|
-
|
|
15377
|
-
if (typeof expr === "string" && op !== undefined) {
|
|
15378
|
-
const clause = Array.isArray(value) ? `${expr} IN (?)` : `${expr} ${op} ?`;
|
|
15379
|
-
return sql`${query} ${sql(prefix)} ${sql(clause)}`;
|
|
15380
|
-
} else if (Array.isArray(expr) && expr.length === 3) {
|
|
15381
|
-
const [column, operator, val] = expr;
|
|
15382
|
-
const clause = Array.isArray(val) ? `${column} IN (?)` : `${column} ${operator} ?`;
|
|
15383
|
-
return sql`${query} ${sql(prefix)} ${sql(clause)}`;
|
|
15384
|
-
} else if (typeof expr === "object" && expr !== null) {
|
|
15385
|
-
const conditions = Object.entries(expr).map(([key, val]) => {
|
|
15386
|
-
const clause = Array.isArray(val) ? `${key} IN (?)` : `${key} = ?`;
|
|
15387
|
-
return sql`${sql(clause)}`;
|
|
15388
|
-
});
|
|
15389
|
-
const combined = conditions.reduce((acc, cond, i) => i === 0 ? cond : sql`${acc} AND ${cond}`);
|
|
15390
|
-
return sql`${query} ${sql(prefix)} ${combined}`;
|
|
15391
|
-
}
|
|
15392
|
-
return query;
|
|
15393
|
-
}
|
|
15394
|
-
return base;
|
|
15376
|
+
return makeSub(baseText, subParams);
|
|
15395
15377
|
},
|
|
15396
15378
|
insertInto(table) {
|
|
15397
15379
|
let built;
|
|
@@ -24639,8 +24621,45 @@ function resolveRelation(definition, relationName) {
|
|
|
24639
24621
|
pivotTimestamps: Boolean(config6?.pivot?.timestamps)
|
|
24640
24622
|
};
|
|
24641
24623
|
}
|
|
24624
|
+
const resolveThrough = (field, type) => {
|
|
24625
|
+
if (!field || typeof field !== "object" || Array.isArray(field))
|
|
24626
|
+
return null;
|
|
24627
|
+
const entry = field[relationName] ?? field[Object.keys(field).find((k2) => k2.toLowerCase() === relationName.toLowerCase()) ?? ""];
|
|
24628
|
+
if (!entry || typeof entry !== "object")
|
|
24629
|
+
return null;
|
|
24630
|
+
const throughModelName = entry.through;
|
|
24631
|
+
const targetModelName = entry.target;
|
|
24632
|
+
if (!throughModelName || !targetModelName)
|
|
24633
|
+
return null;
|
|
24634
|
+
const throughModel = getModelFromRegistry(throughModelName);
|
|
24635
|
+
const throughDef = throughModel?.getDefinition?.() || throughModel?.definition;
|
|
24636
|
+
const throughTable = throughModel?.getTable?.() || throughDef?.table || toTableName(throughModelName);
|
|
24637
|
+
const throughPk = throughDef?.primaryKey || "id";
|
|
24638
|
+
const targetModel = getModelFromRegistry(targetModelName);
|
|
24639
|
+
const targetTable = targetModel?.getTable?.() || toTableName(targetModelName);
|
|
24640
|
+
return {
|
|
24641
|
+
type,
|
|
24642
|
+
relatedModelName: targetModelName,
|
|
24643
|
+
relatedTable: targetTable,
|
|
24644
|
+
foreignKey: `${toSnakeCase(parentName)}_id`,
|
|
24645
|
+
localKey: parentPk,
|
|
24646
|
+
throughTable,
|
|
24647
|
+
throughForeignKey: `${toSnakeCase(parentName)}_id`,
|
|
24648
|
+
throughLocalKey: throughPk,
|
|
24649
|
+
targetForeignKey: `${singularizeWord(throughTable)}_id`
|
|
24650
|
+
};
|
|
24651
|
+
};
|
|
24652
|
+
const hmt = resolveThrough(definition.hasManyThrough, "hasManyThrough");
|
|
24653
|
+
if (hmt)
|
|
24654
|
+
return hmt;
|
|
24655
|
+
const hot = resolveThrough(definition.hasOneThrough, "hasOneThrough");
|
|
24656
|
+
if (hot)
|
|
24657
|
+
return hot;
|
|
24642
24658
|
return null;
|
|
24643
24659
|
}
|
|
24660
|
+
function singularizeWord(table) {
|
|
24661
|
+
return table.endsWith("s") ? table.slice(0, -1) : table;
|
|
24662
|
+
}
|
|
24644
24663
|
|
|
24645
24664
|
class BelongsToManyRelationBuilder {
|
|
24646
24665
|
_parent;
|
|
@@ -25277,6 +25296,40 @@ class ModelQueryBuilder {
|
|
|
25277
25296
|
instance.setRelation(relationName, relatedInstances);
|
|
25278
25297
|
}
|
|
25279
25298
|
}
|
|
25299
|
+
if (rel.type === "hasManyThrough" || rel.type === "hasOneThrough") {
|
|
25300
|
+
const parentIds = instances.map((i2) => i2.get(pk)).filter((id) => id != null);
|
|
25301
|
+
if (parentIds.length === 0)
|
|
25302
|
+
continue;
|
|
25303
|
+
const throughPk = rel.throughLocalKey || "id";
|
|
25304
|
+
const throughPh = parentIds.map(() => "?").join(", ");
|
|
25305
|
+
const throughRows = await exec.all(`SELECT ${throughPk}, ${rel.throughForeignKey} FROM ${rel.throughTable} WHERE ${rel.throughForeignKey} IN (${throughPh})`, parentIds);
|
|
25306
|
+
if (throughRows.length === 0) {
|
|
25307
|
+
for (const instance of instances)
|
|
25308
|
+
instance.setRelation(relationName, rel.type === "hasManyThrough" ? [] : null);
|
|
25309
|
+
continue;
|
|
25310
|
+
}
|
|
25311
|
+
const throughToParent = new Map;
|
|
25312
|
+
for (const t2 of throughRows)
|
|
25313
|
+
throughToParent.set(t2[throughPk], t2[rel.throughForeignKey]);
|
|
25314
|
+
const throughIds = [...new Set(throughRows.map((t2) => t2[throughPk]))];
|
|
25315
|
+
const targetPh = throughIds.map(() => "?").join(", ");
|
|
25316
|
+
const targetRows = await exec.all(`SELECT * FROM ${rel.relatedTable} WHERE ${rel.targetForeignKey} IN (${targetPh})`, throughIds);
|
|
25317
|
+
const relatedModelDef = getModelFromRegistry(rel.relatedModelName);
|
|
25318
|
+
const relDef = relatedModelDef?.getDefinition?.() || relatedModelDef?.definition || this._definition;
|
|
25319
|
+
const byParent = new Map;
|
|
25320
|
+
for (const row of targetRows) {
|
|
25321
|
+
const parentVal = throughToParent.get(row[rel.targetForeignKey]);
|
|
25322
|
+
if (parentVal == null)
|
|
25323
|
+
continue;
|
|
25324
|
+
if (!byParent.has(parentVal))
|
|
25325
|
+
byParent.set(parentVal, []);
|
|
25326
|
+
byParent.get(parentVal).push(new ModelInstance(relDef, row));
|
|
25327
|
+
}
|
|
25328
|
+
for (const instance of instances) {
|
|
25329
|
+
const group = byParent.get(instance.get(pk)) || [];
|
|
25330
|
+
instance.setRelation(relationName, rel.type === "hasManyThrough" ? group : group[0] ?? null);
|
|
25331
|
+
}
|
|
25332
|
+
}
|
|
25280
25333
|
}
|
|
25281
25334
|
}
|
|
25282
25335
|
async get() {
|
package/package.json
CHANGED