pqb 0.54.2 → 0.55.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
@@ -2605,7 +2605,7 @@ const columnWithDotToSql = (ctx, data, shape, column, index, quotedAs, select) =
2605
2605
  const shape2 = data.joinedShapes?.[table];
2606
2606
  return shape2 ? select ? makeRowToJson(table, shape2, true) : `"${table}".*` : column;
2607
2607
  }
2608
- const tableName = data.aliases?.[table] || table;
2608
+ const tableName = orchidCore._getQueryAliasOrName(data, table);
2609
2609
  const quoted = `"${table}"`;
2610
2610
  const col = quoted === quotedAs ? shape[key] : data.joinedShapes?.[tableName]?.[key];
2611
2611
  if (col) {
@@ -2644,7 +2644,7 @@ const tableColumnToSqlWithAs = (ctx, data, column, table, key, as, quotedAs, sel
2644
2644
  }
2645
2645
  return column;
2646
2646
  }
2647
- const tableName = data.aliases?.[table] || table;
2647
+ const tableName = orchidCore._getQueryAliasOrName(data, table);
2648
2648
  const quoted = `"${table}"`;
2649
2649
  const col = quoted === quotedAs ? data.shape[key] : data.joinedShapes?.[tableName][key];
2650
2650
  if (jsonList) jsonList[as] = col;
@@ -2705,72 +2705,6 @@ const pushDistinctSql = (ctx, table, distinct, quotedAs) => {
2705
2705
  }
2706
2706
  };
2707
2707
 
2708
- var __typeError = (msg) => {
2709
- throw TypeError(msg);
2710
- };
2711
- var __accessCheck = (obj, member, msg) => member.has(obj) || __typeError("Cannot " + msg);
2712
- var __privateGet = (obj, member, getter) => (__accessCheck(obj, member, "read from private field"), getter ? getter.call(obj) : member.get(obj));
2713
- var __privateAdd = (obj, member, value) => member.has(obj) ? __typeError("Cannot add the same private member more than once") : member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
2714
- var __privateSet = (obj, member, value, setter) => (__accessCheck(obj, member, "write to private field"), member.set(obj, value), value);
2715
- var _query, _query2;
2716
- class OrchidOrmError extends Error {
2717
- }
2718
- class NotFoundError extends OrchidOrmError {
2719
- constructor(query, message = "Record is not found") {
2720
- super(message);
2721
- // `#query` is private to prevent it from serializing to not cause problems to test runner reports
2722
- __privateAdd(this, _query);
2723
- __privateSet(this, _query, query);
2724
- }
2725
- get query() {
2726
- return __privateGet(this, _query);
2727
- }
2728
- }
2729
- _query = new WeakMap();
2730
- class OrchidOrmInternalError extends Error {
2731
- constructor(query, message, data) {
2732
- super(message);
2733
- this.data = data;
2734
- // `#query` is private to prevent it from serializing to not cause problems to test runner reports
2735
- __privateAdd(this, _query2);
2736
- __privateSet(this, _query2, query);
2737
- }
2738
- get query() {
2739
- return __privateGet(this, _query2);
2740
- }
2741
- }
2742
- _query2 = new WeakMap();
2743
- class QueryError extends OrchidOrmInternalError {
2744
- get isUnique() {
2745
- return this.code === "23505";
2746
- }
2747
- get columns() {
2748
- if (this.columnsCache) return this.columnsCache;
2749
- const columns = {};
2750
- if (this.detail) {
2751
- const list = this.detail.match(/\((.*)\)=/)?.[1];
2752
- if (list) {
2753
- list.split(", ").forEach((item) => {
2754
- const column = item.startsWith('"') ? item.slice(1, -1) : item;
2755
- const key = this.query.columnNameToKey(column) ?? column;
2756
- columns[key] = true;
2757
- });
2758
- }
2759
- }
2760
- return this.columnsCache = columns;
2761
- }
2762
- }
2763
- class MoreThanOneRowError extends OrchidOrmInternalError {
2764
- constructor(query, message) {
2765
- super(query, message);
2766
- }
2767
- }
2768
- class UnhandledTypeError extends OrchidOrmInternalError {
2769
- constructor(query, value) {
2770
- super(query, `Unhandled type: ${JSON.stringify(value)} received`);
2771
- }
2772
- }
2773
-
2774
2708
  const pushWhereStatementSql = (ctx, table, query, quotedAs) => {
2775
2709
  const res = whereToSql(ctx, table, query, quotedAs);
2776
2710
  if (res) {
@@ -2892,7 +2826,7 @@ const processWhere = (ands, ctx, table, query, data, quotedAs) => {
2892
2826
  const joinAs = `"${getJoinItemSource(item.joinFrom)}"`;
2893
2827
  const q = item.useOuterAliases ? {
2894
2828
  joinedShapes: query.joinedShapes,
2895
- aliases: query.outerAliases,
2829
+ aliases: orchidCore._getQueryOuterAliases(query),
2896
2830
  shape: query.shape
2897
2831
  } : query;
2898
2832
  ands.push(
@@ -3018,7 +2952,10 @@ const processJoinItem = (ctx, table, query, args, quotedAs) => {
3018
2952
  if ("l" in args) {
3019
2953
  const { aliasValue } = ctx;
3020
2954
  ctx.aliasValue = true;
3021
- target = `(${getSqlText(args.l.toSQL(ctx))}) "${query.aliases?.[args.a] || args.a}"`;
2955
+ target = `(${getSqlText(args.l.toSQL(ctx))}) "${orchidCore._getQueryAliasOrName(
2956
+ query,
2957
+ args.a
2958
+ )}"`;
3022
2959
  on = `${args.i ? `"${args.a}".r IS NOT NULL` : "true"}`;
3023
2960
  ctx.aliasValue = aliasValue;
3024
2961
  } else if ("j" in args) {
@@ -3359,7 +3296,7 @@ const noneResult = (q, queryData, type) => {
3359
3296
  } else if (type === "valueOrThrow" && queryData.returning) {
3360
3297
  return 0;
3361
3298
  } else {
3362
- throw new NotFoundError(q);
3299
+ throw new orchidCore.NotFoundError(q);
3363
3300
  }
3364
3301
  };
3365
3302
  const noneMethods = {
@@ -3397,7 +3334,7 @@ const resolveCallbacksInArgs = (q, args) => {
3397
3334
  qb.q = getClonedQueryData(q.q);
3398
3335
  qb.q.and = qb.q.or = qb.q.scopes = void 0;
3399
3336
  qb.q.subQuery = 1;
3400
- qb.q.outerAliases = qb.q.aliases;
3337
+ orchidCore._setSubQueryAliases(qb);
3401
3338
  args[i] = resolveSubQueryCallbackV2(qb, arg);
3402
3339
  }
3403
3340
  }
@@ -4165,42 +4102,6 @@ class Where {
4165
4102
  }
4166
4103
  }
4167
4104
 
4168
- const _queryAs = (self, as) => {
4169
- const { q } = self;
4170
- q.as = as;
4171
- q.aliases = {
4172
- ...q.aliases,
4173
- [as]: q.aliases ? _queryResolveAlias(q.aliases, as) : as
4174
- };
4175
- return self;
4176
- };
4177
- const _queryResolveAlias = (aliases, as) => {
4178
- if (!aliases[as]) return as;
4179
- let suffix = 2;
4180
- let privateAs;
4181
- while (aliases[privateAs = as + suffix]) {
4182
- suffix++;
4183
- }
4184
- return privateAs;
4185
- };
4186
- class AsMethods {
4187
- /**
4188
- * Sets table alias:
4189
- *
4190
- * ```ts
4191
- * db.table.as('u').select('u.name');
4192
- *
4193
- * // Can be used in the join:
4194
- * db.table.join(Profile.as('p'), 'p.userId', 'user.id');
4195
- * ```
4196
- *
4197
- * @param as - alias for the table of this query
4198
- */
4199
- as(as) {
4200
- return _queryAs(_clone(this), as);
4201
- }
4202
- }
4203
-
4204
4105
  const _chain = (fromQuery, toQuery, rel) => {
4205
4106
  const self = fromQuery;
4206
4107
  const toTable = toQuery;
@@ -4232,13 +4133,7 @@ const _chain = (fromQuery, toQuery, rel) => {
4232
4133
  } else {
4233
4134
  q.relChain = [{ query: self, rel }];
4234
4135
  }
4235
- const aliases = self.q.as ? { ...self.q.aliases } : { ...self.q.aliases, [self.table]: self.table };
4236
- const relAliases = q.aliases;
4237
- for (const as in relAliases) {
4238
- aliases[as] = _queryResolveAlias(aliases, as);
4239
- }
4240
- q.as = aliases[q.as];
4241
- q.aliases = aliases;
4136
+ orchidCore._applyRelationAliases(self, q);
4242
4137
  q.joinedShapes = {
4243
4138
  [getQueryAs(self)]: self.q.shape,
4244
4139
  ...self.q.joinedShapes
@@ -4279,14 +4174,11 @@ const resolveSubQueryCallbackV2 = (q, cb) => {
4279
4174
  const arg = Object.create(base);
4280
4175
  arg.q = getClonedQueryData(q.q);
4281
4176
  arg.q.subQuery = 1;
4282
- arg.q.relChain = void 0;
4283
- arg.q.outerAliases = q.q.aliases;
4177
+ arg.q.with = arg.q.relChain = void 0;
4178
+ orchidCore._setSubQueryAliases(arg);
4284
4179
  return cb(arg);
4285
4180
  };
4286
- const joinSubQuery = (q, sub) => {
4287
- if (!("joinQuery" in sub)) return sub;
4288
- return sub.joinQuery(sub, q);
4289
- };
4181
+ const joinSubQuery = (q, sub) => orchidCore.isRelationQuery(sub) ? sub.joinQuery(sub, q) : sub;
4290
4182
 
4291
4183
  const _clone = (q) => q.clone();
4292
4184
  const pushQueryArrayImmutable = (q, key, value) => {
@@ -4303,17 +4195,15 @@ const setQueryObjectValueImmutable = (q, object, key, value) => {
4303
4195
  };
4304
4196
  const throwIfNoWhere = (q, method) => {
4305
4197
  if (!q.q.or && !q.q.and && !q.q.scopes && !q.q.all) {
4306
- throw new OrchidOrmInternalError(
4198
+ throw new orchidCore.OrchidOrmInternalError(
4307
4199
  q,
4308
4200
  `Dangerous ${method} without conditions`
4309
4201
  );
4310
4202
  }
4311
4203
  };
4312
4204
  const throwIfJoinLateral = (q, method) => {
4313
- if (q.q.join?.some(
4314
- (x) => Array.isArray(x) || "s" in x.args && x.args.s
4315
- )) {
4316
- throw new OrchidOrmInternalError(
4205
+ if (q.q.join?.some((x) => Array.isArray(x) || "s" in x.args && x.args.s)) {
4206
+ throw new orchidCore.OrchidOrmInternalError(
4317
4207
  q,
4318
4208
  `Cannot join a complex query in ${method}`
4319
4209
  );
@@ -4340,24 +4230,6 @@ const extendQuery = (q, methods) => {
4340
4230
  cloned.q = getClonedQueryData(q.q);
4341
4231
  return cloned;
4342
4232
  };
4343
- const getPrimaryKeys = (q) => {
4344
- var _a;
4345
- return (_a = q.internal).primaryKeys ?? (_a.primaryKeys = collectPrimaryKeys(q));
4346
- };
4347
- const collectPrimaryKeys = (q) => {
4348
- const primaryKeys = [];
4349
- const { shape } = q.q;
4350
- for (const key in shape) {
4351
- if (shape[key].data.primaryKey) {
4352
- primaryKeys.push(key);
4353
- }
4354
- }
4355
- const pkey = q.internal.tableData.primaryKey;
4356
- if (pkey) {
4357
- primaryKeys.push(...pkey.columns);
4358
- }
4359
- return primaryKeys;
4360
- };
4361
4233
  const _queryAll = (q) => {
4362
4234
  q.q.returnType = "all";
4363
4235
  q.q.all = true;
@@ -4407,7 +4279,7 @@ const _queryRows = (q) => {
4407
4279
  };
4408
4280
  const getFullColumnTable = (q, column, index, as) => {
4409
4281
  const table = column.slice(0, index);
4410
- return as && table !== as && q.q.aliases?.[table] === as ? as : table;
4282
+ return as && table !== as && orchidCore._checkIfAliased(q, table, as) ? as : table;
4411
4283
  };
4412
4284
 
4413
4285
  const _join = (query, require, type, first, args) => {
@@ -4673,7 +4545,7 @@ const commitSql$1 = {
4673
4545
  const rollbackSql$1 = {
4674
4546
  text: "ROLLBACK"
4675
4547
  };
4676
- class AfterCommitError extends OrchidOrmError {
4548
+ class AfterCommitError extends orchidCore.OrchidOrmError {
4677
4549
  constructor(result, hookResults) {
4678
4550
  super("After commit hooks have failed");
4679
4551
  this.result = result;
@@ -5155,7 +5027,7 @@ function maybeWrappedThen(resolve, reject) {
5155
5027
  }
5156
5028
  }
5157
5029
  const trx = this.internal.transactionStorage.getStore();
5158
- if ((q.wrapInTransaction || afterHooks) && !trx) {
5030
+ if ((q.wrapInTransaction || q.selectRelation && q.type || afterHooks) && !trx) {
5159
5031
  return this.transaction(
5160
5032
  () => new Promise((resolve2, reject2) => {
5161
5033
  const trx2 = this.internal.transactionStorage.getStore();
@@ -5191,6 +5063,7 @@ const callAfterHook = function(cb) {
5191
5063
  };
5192
5064
  const beginSql = { text: "BEGIN" };
5193
5065
  const then = async (q, adapter, trx, beforeHooks, afterHooks, afterCommitHooks, resolve, reject) => {
5066
+ var _a;
5194
5067
  const { q: query } = q;
5195
5068
  let sql;
5196
5069
  let logData;
@@ -5206,9 +5079,9 @@ const then = async (q, adapter, trx, beforeHooks, afterHooks, afterCommitHooks,
5206
5079
  );
5207
5080
  }
5208
5081
  sql = q.toSQL();
5209
- const { hookSelect } = sql;
5082
+ const { hookSelect, delayedRelationSelect } = sql;
5210
5083
  const { returnType = "all" } = query;
5211
- const tempReturnType = hookSelect || returnType === "rows" && q.q.batchParsers ? "all" : returnType;
5084
+ const tempReturnType = hookSelect || returnType === "rows" && q.q.batchParsers || delayedRelationSelect?.value ? "all" : returnType;
5212
5085
  let result;
5213
5086
  let queryResult;
5214
5087
  if ("text" in sql) {
@@ -5340,6 +5213,51 @@ const then = async (q, adapter, trx, beforeHooks, afterHooks, afterCommitHooks,
5340
5213
  await Promise.all(query.after.map(callAfterHook, args));
5341
5214
  }
5342
5215
  }
5216
+ if (delayedRelationSelect?.value) {
5217
+ const q2 = delayedRelationSelect.query;
5218
+ const primaryKeys = orchidCore.requirePrimaryKeys(
5219
+ q2,
5220
+ "Cannot select a relation of a table that has no primary keys"
5221
+ );
5222
+ const selectQuery = q2.clone();
5223
+ selectQuery.q.type = selectQuery.q.returnType = void 0;
5224
+ ((_a = selectQuery.q).and ?? (_a.and = [])).push(orchidCore.pick(result, primaryKeys));
5225
+ const relationsSelect = delayedRelationSelect.value;
5226
+ let selectAs;
5227
+ if (renames) {
5228
+ selectAs = {};
5229
+ for (const key in renames) {
5230
+ if (key in relationsSelect) {
5231
+ selectAs[renames[key]] = relationsSelect[key];
5232
+ }
5233
+ }
5234
+ } else {
5235
+ selectAs = { ...relationsSelect };
5236
+ }
5237
+ const select = [{ selectAs }];
5238
+ const relationKeyAliases = primaryKeys.map((key) => {
5239
+ if (key in selectAs) {
5240
+ const as = orchidCore.getFreeAlias(selectAs, key);
5241
+ selectAs[as] = key;
5242
+ return as;
5243
+ } else {
5244
+ select.push(key);
5245
+ return key;
5246
+ }
5247
+ });
5248
+ selectQuery.q.select = select;
5249
+ const relationsResult = await selectQuery;
5250
+ for (const row of result) {
5251
+ const relationRow = relationsResult.find((relationRow2) => {
5252
+ return !primaryKeys.some(
5253
+ (key, i) => relationRow2[relationKeyAliases[i]] !== row[key]
5254
+ );
5255
+ });
5256
+ if (relationRow) {
5257
+ Object.assign(row, relationRow);
5258
+ }
5259
+ }
5260
+ }
5343
5261
  if (hookSelect || tempReturnType !== returnType) {
5344
5262
  if (renames) {
5345
5263
  for (const a in renames) {
@@ -5431,7 +5349,7 @@ const handleResult = (q, returnType, result, isSubQuery) => {
5431
5349
  switch (returnType) {
5432
5350
  case "all": {
5433
5351
  if (q.q.throwOnNotFound && result.rows.length === 0)
5434
- throw new NotFoundError(q);
5352
+ throw new orchidCore.NotFoundError(q);
5435
5353
  const promise = parseBatch(q, result);
5436
5354
  const { rows } = result;
5437
5355
  if (parsers) {
@@ -5450,7 +5368,7 @@ const handleResult = (q, returnType, result, isSubQuery) => {
5450
5368
  }
5451
5369
  case "oneOrThrow": {
5452
5370
  const { rows } = result;
5453
- if (!rows.length) throw new NotFoundError(q);
5371
+ if (!rows.length) throw new orchidCore.NotFoundError(q);
5454
5372
  const promise = parseBatch(q, result);
5455
5373
  if (parsers) parseRecord(parsers, rows[0]);
5456
5374
  return promise ? promise.then(() => rows[0]) : rows[0];
@@ -5493,7 +5411,7 @@ const handleResult = (q, returnType, result, isSubQuery) => {
5493
5411
  case "valueOrThrow": {
5494
5412
  if (q.q.returning) {
5495
5413
  if (q.q.throwOnNotFound && result.rowCount === 0) {
5496
- throw new NotFoundError(q);
5414
+ throw new orchidCore.NotFoundError(q);
5497
5415
  }
5498
5416
  return result.rowCount;
5499
5417
  }
@@ -5501,11 +5419,11 @@ const handleResult = (q, returnType, result, isSubQuery) => {
5501
5419
  const promise = parseBatch(q, result);
5502
5420
  if (promise) {
5503
5421
  return promise.then(() => {
5504
- if (rows[0]?.[0] === void 0) throw new NotFoundError(q);
5422
+ if (rows[0]?.[0] === void 0) throw new orchidCore.NotFoundError(q);
5505
5423
  return parseValue(rows[0][0], parsers);
5506
5424
  });
5507
5425
  }
5508
- if (rows[0]?.[0] === void 0) throw new NotFoundError(q);
5426
+ if (rows[0]?.[0] === void 0) throw new orchidCore.NotFoundError(q);
5509
5427
  return parseValue(rows[0][0], parsers);
5510
5428
  }
5511
5429
  case "void": {
@@ -5564,7 +5482,7 @@ const filterResult = (q, returnType, queryResult, result, tempColumns, hasAfterH
5564
5482
  if (returnType === "oneOrThrow" || returnType === "one") {
5565
5483
  let row = result[0];
5566
5484
  if (!row) {
5567
- if (returnType === "oneOrThrow") throw new NotFoundError(q);
5485
+ if (returnType === "oneOrThrow") throw new orchidCore.NotFoundError(q);
5568
5486
  return void 0;
5569
5487
  } else if (!tempColumns?.size) {
5570
5488
  return row;
@@ -5584,7 +5502,7 @@ const filterResult = (q, returnType, queryResult, result, tempColumns, hasAfterH
5584
5502
  return queryResult.rowCount;
5585
5503
  }
5586
5504
  const row = result[0];
5587
- if (!row) throw new NotFoundError(q);
5505
+ if (!row) throw new orchidCore.NotFoundError(q);
5588
5506
  return row[getFirstResultKey(q, queryResult)];
5589
5507
  }
5590
5508
  if (returnType === "pluck") {
@@ -5749,7 +5667,7 @@ class FromMethods {
5749
5667
  }
5750
5668
 
5751
5669
  function queryWrap(self, query, as = "t") {
5752
- return _queryAs(queryFrom(query, self), as);
5670
+ return orchidCore._setQueryAs(queryFrom(query, self), as);
5753
5671
  }
5754
5672
  function cloneQueryBaseUnscoped(query) {
5755
5673
  const q = query.baseQuery.clone();
@@ -5835,7 +5753,7 @@ const addParserForSelectItem = (q, as, key, arg, columnAlias, joinQuery) => {
5835
5753
  }
5836
5754
  } else {
5837
5755
  for (const { data } of batches) {
5838
- if (!data) throw new NotFoundError(arg);
5756
+ if (!data) throw new orchidCore.NotFoundError(arg);
5839
5757
  parseRecord(parsers, data);
5840
5758
  }
5841
5759
  }
@@ -5845,7 +5763,7 @@ const addParserForSelectItem = (q, as, key, arg, columnAlias, joinQuery) => {
5845
5763
  }
5846
5764
  } else {
5847
5765
  for (const { data } of batches) {
5848
- if (!data) throw new NotFoundError(arg);
5766
+ if (!data) throw new orchidCore.NotFoundError(arg);
5849
5767
  }
5850
5768
  }
5851
5769
  if (hookSelect) {
@@ -5877,13 +5795,13 @@ const addParserForSelectItem = (q, as, key, arg, columnAlias, joinQuery) => {
5877
5795
  } else {
5878
5796
  for (const item of batches) {
5879
5797
  if (item.data === void 0)
5880
- throw new NotFoundError(arg);
5798
+ throw new orchidCore.NotFoundError(arg);
5881
5799
  item.parent[item.key] = item.data = parse(item.data);
5882
5800
  }
5883
5801
  }
5884
5802
  } else if (returnType !== "value") {
5885
5803
  for (const { data } of batches) {
5886
- if (data === void 0) throw new NotFoundError(arg);
5804
+ if (data === void 0) throw new orchidCore.NotFoundError(arg);
5887
5805
  }
5888
5806
  }
5889
5807
  if (hookSelect) {
@@ -5986,11 +5904,11 @@ const collectNestedSelectBatches = (batches, rows, path, last) => {
5986
5904
  };
5987
5905
  const emptyArrSQL = new RawSQL("'[]'");
5988
5906
  const processSelectArg = (q, as, arg, columnAs) => {
5907
+ const query = q;
5989
5908
  if (typeof arg === "string") {
5990
5909
  return setParserForSelectedString(q, arg, as, columnAs);
5991
5910
  }
5992
5911
  const selectAs = {};
5993
- let aliases;
5994
5912
  for (const key in arg) {
5995
5913
  let value = arg[key];
5996
5914
  let joinQuery;
@@ -6001,18 +5919,18 @@ const processSelectArg = (q, as, arg, columnAs) => {
6001
5919
  return false;
6002
5920
  }
6003
5921
  }
6004
- if (!orchidCore.isExpression(value) && value.joinQuery) {
6005
- joinQuery = true;
5922
+ if (!orchidCore.isExpression(value) && orchidCore.isRelationQuery(value)) {
5923
+ query.q.selectRelation = joinQuery = true;
6006
5924
  value = value.joinQuery(value, q);
6007
- let query;
5925
+ let subQuery;
6008
5926
  const { returnType, innerJoinLateral } = value.q;
6009
5927
  if (!returnType || returnType === "all") {
6010
- query = value.json(false);
5928
+ subQuery = value.json(false);
6011
5929
  if (!innerJoinLateral) {
6012
5930
  value.q.coalesceValue = emptyArrSQL;
6013
5931
  }
6014
5932
  } else if (returnType === "pluck") {
6015
- query = value.q.select ? value.wrap(cloneQueryBaseUnscoped(value)).jsonAgg(value.q.select[0]) : value.json(false);
5933
+ subQuery = value.q.select ? value.wrap(cloneQueryBaseUnscoped(value)).jsonAgg(value.q.select[0]) : value.json(false);
6016
5934
  value.q.coalesceValue = emptyArrSQL;
6017
5935
  } else {
6018
5936
  if (returnType === "value" || returnType === "valueOrThrow") {
@@ -6022,23 +5940,23 @@ const processSelectArg = (q, as, arg, columnAs) => {
6022
5940
  selectAs: { r: value.q.select[0] }
6023
5941
  };
6024
5942
  }
6025
- query = value;
5943
+ subQuery = value;
6026
5944
  } else {
6027
- query = value.json(false);
5945
+ subQuery = value.json(false);
6028
5946
  }
6029
5947
  } else {
6030
- query = value;
5948
+ subQuery = value;
6031
5949
  }
6032
5950
  }
6033
- const asOverride = value.q.aliases[key] ?? key;
6034
- value.q.joinedForSelect = asOverride;
6035
- if (asOverride !== key) {
6036
- aliases = { ...q.q.aliases, [key]: asOverride };
6037
- }
5951
+ value.q.joinedForSelect = orchidCore._copyQueryAliasToQuery(
5952
+ value,
5953
+ q,
5954
+ key
5955
+ );
6038
5956
  _joinLateral(
6039
5957
  q,
6040
5958
  innerJoinLateral ? "JOIN" : "LEFT JOIN",
6041
- query,
5959
+ subQuery,
6042
5960
  key,
6043
5961
  // no need for `ON p.r IS NOT NULL` check when joining a single record,
6044
5962
  // `JOIN` will handle it on itself.
@@ -6046,7 +5964,6 @@ const processSelectArg = (q, as, arg, columnAs) => {
6046
5964
  );
6047
5965
  }
6048
5966
  }
6049
- if (aliases) q.q.aliases = aliases;
6050
5967
  selectAs[key] = addParserForSelectItem(
6051
5968
  q,
6052
5969
  as,
@@ -6463,6 +6380,7 @@ const makeInsertSql = (ctx, q, query, quotedAs) => {
6463
6380
  }
6464
6381
  }
6465
6382
  const insertSql = `INSERT INTO ${quotedAs}${quotedColumns.length ? "(" + quotedColumns.join(", ") + ")" : ""}`;
6383
+ const hasNonSelect = ctx.hasNonSelect;
6466
6384
  if ("from" in values && query.insertWith) {
6467
6385
  pushWithSql(ctx, Object.values(query.insertWith).flat());
6468
6386
  }
@@ -6521,6 +6439,7 @@ const makeInsertSql = (ctx, q, query, quotedAs) => {
6521
6439
  }
6522
6440
  pushWhereStatementSql(ctx, q, query, quotedAs);
6523
6441
  let returning;
6442
+ let delayedRelationSelect;
6524
6443
  if (inCTE) {
6525
6444
  const select = inCTE.returning?.select;
6526
6445
  returning = {
@@ -6528,7 +6447,15 @@ const makeInsertSql = (ctx, q, query, quotedAs) => {
6528
6447
  hookSelect: inCTE.returning?.hookSelect
6529
6448
  };
6530
6449
  } else {
6531
- returning = makeReturningSql(ctx, q, query, quotedAs, 2);
6450
+ delayedRelationSelect = q.q.selectRelation ? orchidCore.newDelayedRelationSelect(q) : void 0;
6451
+ returning = makeReturningSql(
6452
+ ctx,
6453
+ q,
6454
+ query,
6455
+ quotedAs,
6456
+ delayedRelationSelect,
6457
+ 2
6458
+ );
6532
6459
  }
6533
6460
  if (returning.select) ctx.sql.push("RETURNING", returning.select);
6534
6461
  if ("from" in values) {
@@ -6551,7 +6478,7 @@ const makeInsertSql = (ctx, q, query, quotedAs) => {
6551
6478
  )
6552
6479
  );
6553
6480
  }
6554
- ctx.sql[valuesPos] = getSqlText(toSQL(q2, { values: ctx.values }));
6481
+ ctx.sql[valuesPos] = getSqlText(toSQL(q2, ctx));
6555
6482
  } else {
6556
6483
  const valuesSql = [];
6557
6484
  let ctxValues = ctx.values;
@@ -6608,6 +6535,12 @@ const makeInsertSql = (ctx, q, query, quotedAs) => {
6608
6535
  ctx.sql[valuesPos - 1] = "WITH " + withSqls.join(", ") + " " + insertSql;
6609
6536
  }
6610
6537
  if (batch) {
6538
+ if (hasNonSelect) {
6539
+ throw new orchidCore.OrchidOrmInternalError(
6540
+ q,
6541
+ `Cannot insert many records when having a non-select sub-query`
6542
+ );
6543
+ }
6611
6544
  ctx.sql[valuesPos] = (inCTE ? "SELECT " : "VALUES ") + valuesSql.join(", ");
6612
6545
  batch.push({
6613
6546
  text: ctx.sql.join(" "),
@@ -6615,6 +6548,7 @@ const makeInsertSql = (ctx, q, query, quotedAs) => {
6615
6548
  });
6616
6549
  return {
6617
6550
  hookSelect: returning.hookSelect,
6551
+ delayedRelationSelect,
6618
6552
  batch
6619
6553
  };
6620
6554
  } else {
@@ -6626,6 +6560,7 @@ const makeInsertSql = (ctx, q, query, quotedAs) => {
6626
6560
  }
6627
6561
  return {
6628
6562
  hookSelect: returning.hookSelect,
6563
+ delayedRelationSelect,
6629
6564
  text: ctx.sql.join(" "),
6630
6565
  values: ctx.values
6631
6566
  };
@@ -6797,7 +6732,7 @@ const hookSelectKeys = [
6797
6732
  "afterCreateSelect",
6798
6733
  "afterDeleteSelect"
6799
6734
  ];
6800
- const makeReturningSql = (ctx, q, data, quotedAs, hookSelectI, addHookSelectI) => {
6735
+ const makeReturningSql = (ctx, q, data, quotedAs, delayedRelationSelect, hookSelectI, addHookSelectI) => {
6801
6736
  if (data.inCTE) {
6802
6737
  if (hookSelectI !== 2) {
6803
6738
  const returning = makeReturningSql(
@@ -6805,6 +6740,7 @@ const makeReturningSql = (ctx, q, data, quotedAs, hookSelectI, addHookSelectI) =
6805
6740
  q,
6806
6741
  data,
6807
6742
  quotedAs,
6743
+ delayedRelationSelect,
6808
6744
  2,
6809
6745
  hookSelectI
6810
6746
  );
@@ -6826,7 +6762,7 @@ const makeReturningSql = (ctx, q, data, quotedAs, hookSelectI, addHookSelectI) =
6826
6762
  }
6827
6763
  const otherCTEHookSelect = addHookSelectI && data[hookSelectKeys[addHookSelectI]];
6828
6764
  let tempSelect;
6829
- if (q.q.hookSelect || hookSelect || otherCTEHookSelect) {
6765
+ if (q.q.hookSelect || hookSelect || otherCTEHookSelect || q.q.selectRelation) {
6830
6766
  tempSelect = new Map(q.q.hookSelect);
6831
6767
  if (hookSelect) {
6832
6768
  for (const column of hookSelect) {
@@ -6838,12 +6774,30 @@ const makeReturningSql = (ctx, q, data, quotedAs, hookSelectI, addHookSelectI) =
6838
6774
  tempSelect.set(column, { select: column });
6839
6775
  }
6840
6776
  }
6777
+ if (q.q.selectRelation) {
6778
+ for (const column of orchidCore.getPrimaryKeys(q)) {
6779
+ tempSelect.set(column, { select: column });
6780
+ }
6781
+ }
6841
6782
  }
6842
6783
  let sql;
6843
6784
  if (tempSelect?.size || select?.length) {
6844
- sql = selectToSql(ctx, q, data, quotedAs, tempSelect, void 0, true);
6785
+ sql = selectToSql(
6786
+ ctx,
6787
+ q,
6788
+ data,
6789
+ quotedAs,
6790
+ tempSelect,
6791
+ void 0,
6792
+ true,
6793
+ void 0,
6794
+ delayedRelationSelect
6795
+ );
6845
6796
  }
6846
- return { select: sql, hookSelect: tempSelect };
6797
+ return {
6798
+ select: sql,
6799
+ hookSelect: tempSelect
6800
+ };
6847
6801
  };
6848
6802
 
6849
6803
  const pushSelectSql = (ctx, table, query, quotedAs, aliases) => {
@@ -6862,13 +6816,14 @@ const pushSelectSql = (ctx, table, query, quotedAs, aliases) => {
6862
6816
  if (sql) ctx.sql.push(sql);
6863
6817
  }
6864
6818
  };
6865
- const selectToSql = (ctx, table, query, quotedAs, hookSelect = query.hookSelect, aliases, skipCTE, jsonList) => {
6819
+ const selectToSql = (ctx, table, query, quotedAs, hookSelect = query.hookSelect, aliases, skipCTE, jsonList, delayedRelationSelect) => {
6866
6820
  if (query.inCTE && !skipCTE) {
6867
6821
  const { select } = makeReturningSql(
6868
6822
  ctx,
6869
6823
  table,
6870
6824
  query,
6871
- quotedAs
6825
+ quotedAs,
6826
+ query.inCTE.delayedRelationSelect
6872
6827
  );
6873
6828
  return query.inCTE.selectNum || !select ? select ? "0, " + select : "0" : select;
6874
6829
  }
@@ -6942,6 +6897,8 @@ const selectToSql = (ctx, table, query, quotedAs, hookSelect = query.hookSelect,
6942
6897
  jsonList[as] = value.result.value;
6943
6898
  }
6944
6899
  aliases?.push(as);
6900
+ } else if (delayedRelationSelect && orchidCore.isRelationQuery(value)) {
6901
+ orchidCore.setDelayedRelation(delayedRelationSelect, as, value);
6945
6902
  } else {
6946
6903
  pushSubQuerySql(ctx, query, value, as, list, quotedAs, aliases);
6947
6904
  if (jsonList) {
@@ -7059,7 +7016,7 @@ const pushSubQuerySql = (ctx, mainQuery, query, as, list, quotedAs, aliases) =>
7059
7016
  sql = `'[]'::json`;
7060
7017
  break;
7061
7018
  default:
7062
- throw new UnhandledTypeError(query, returnType);
7019
+ throw new orchidCore.UnhandledTypeError(query, returnType);
7063
7020
  }
7064
7021
  list.push(`${sql} "${as}"`);
7065
7022
  aliases?.push(as);
@@ -7088,7 +7045,7 @@ const pushSubQuerySql = (ctx, mainQuery, query, as, list, quotedAs, aliases) =>
7088
7045
  case "void":
7089
7046
  return;
7090
7047
  default:
7091
- throw new UnhandledTypeError(query, returnType);
7048
+ throw new orchidCore.UnhandledTypeError(query, returnType);
7092
7049
  }
7093
7050
  if (sql) {
7094
7051
  list.push(`${coalesce(ctx, query, sql, quotedAs)} "${as}"`);
@@ -7108,7 +7065,7 @@ const pushSubQuerySql = (ctx, mainQuery, query, as, list, quotedAs, aliases) =>
7108
7065
  if (!first && query.q.computeds?.[as]) {
7109
7066
  query = queryJson(query);
7110
7067
  } else if (!first) {
7111
- throw new OrchidOrmInternalError(
7068
+ throw new orchidCore.OrchidOrmInternalError(
7112
7069
  query,
7113
7070
  `Nothing was selected for pluck`
7114
7071
  );
@@ -7130,7 +7087,7 @@ const pushSubQuerySql = (ctx, mainQuery, query, as, list, quotedAs, aliases) =>
7130
7087
  case "void":
7131
7088
  break;
7132
7089
  default:
7133
- throw new UnhandledTypeError(query, returnType);
7090
+ throw new orchidCore.UnhandledTypeError(query, returnType);
7134
7091
  }
7135
7092
  list.push(
7136
7093
  `${coalesce(
@@ -7304,6 +7261,14 @@ const fromToSql = (ctx, data, from, quotedAs) => {
7304
7261
  fromQuery = from;
7305
7262
  }
7306
7263
  } else {
7264
+ if (data.with) {
7265
+ for (const w of data.with) {
7266
+ if (w?.n === from && w.q?.q.inCTE) {
7267
+ ctx.delayedRelationSelect = w.q.q.inCTE.delayedRelationSelect;
7268
+ break;
7269
+ }
7270
+ }
7271
+ }
7307
7272
  sql = quoteSchemaAndTable(data.schema, from);
7308
7273
  }
7309
7274
  return (only === void 0 ? data.only : only) ? `ONLY ${sql}` : sql;
@@ -7383,38 +7348,55 @@ const pushUpdateSql = (ctx, table, query, quotedAs) => {
7383
7348
  if (query.hookUpdateSet) {
7384
7349
  applySet(ctx, table, set, hookSet, orchidCore.emptyObject, quotedAs);
7385
7350
  }
7351
+ let hookSelect;
7352
+ const delayedRelationSelect = query.selectRelation ? orchidCore.newDelayedRelationSelect(table) : void 0;
7386
7353
  if (!set.length) {
7387
7354
  if (!query.select) {
7388
7355
  query.select = countSelect;
7389
7356
  }
7390
- const hookSelect = pushUpdateReturning(
7357
+ hookSelect = pushUpdateReturning(
7391
7358
  ctx,
7392
7359
  table,
7393
7360
  query,
7394
7361
  quotedAs,
7395
- "SELECT"
7362
+ "SELECT",
7363
+ delayedRelationSelect
7396
7364
  );
7397
7365
  ctx.sql.push(`FROM ${quotedTable}`);
7398
7366
  pushWhereStatementSql(ctx, table, query, quotedAs);
7399
7367
  pushLimitSQL(ctx.sql, ctx.values, query);
7400
- return hookSelect;
7401
- }
7402
- ctx.sql.push(`UPDATE ${quotedTable}`);
7403
- if (quotedTable !== quotedAs) {
7404
- ctx.sql.push(quotedAs);
7368
+ } else {
7369
+ ctx.sql.push(`UPDATE ${quotedTable}`);
7370
+ if (quotedTable !== quotedAs) {
7371
+ ctx.sql.push(quotedAs);
7372
+ }
7373
+ ctx.sql.push("SET");
7374
+ ctx.sql.push(set.join(", "));
7375
+ pushWhereStatementSql(ctx, table, query, quotedAs);
7376
+ hookSelect = pushUpdateReturning(
7377
+ ctx,
7378
+ table,
7379
+ query,
7380
+ quotedAs,
7381
+ "RETURNING",
7382
+ delayedRelationSelect
7383
+ );
7405
7384
  }
7406
- ctx.sql.push("SET");
7407
- ctx.sql.push(set.join(", "));
7408
- pushWhereStatementSql(ctx, table, query, quotedAs);
7409
- return pushUpdateReturning(ctx, table, query, quotedAs, "RETURNING");
7385
+ return {
7386
+ hookSelect,
7387
+ delayedRelationSelect,
7388
+ text: ctx.sql.join(" "),
7389
+ values: ctx.values
7390
+ };
7410
7391
  };
7411
- const pushUpdateReturning = (ctx, table, query, quotedAs, keyword) => {
7392
+ const pushUpdateReturning = (ctx, table, query, quotedAs, keyword, delayedRelationSelect) => {
7412
7393
  const { inCTE } = query;
7413
7394
  const { select, hookSelect } = makeReturningSql(
7414
7395
  ctx,
7415
7396
  table,
7416
7397
  query,
7417
7398
  quotedAs,
7399
+ delayedRelationSelect,
7418
7400
  1,
7419
7401
  inCTE && 2
7420
7402
  );
@@ -7482,8 +7464,12 @@ const pushDeleteSql = (ctx, table, query, quotedAs) => {
7482
7464
  const ons = [];
7483
7465
  const joinSet = query.join.length > 1 ? /* @__PURE__ */ new Set() : null;
7484
7466
  for (const item of query.join) {
7485
- if (Array.isArray(item)) {
7486
- throw new OrchidOrmInternalError(
7467
+ const lateral = "l" in item.args && item.args.l;
7468
+ if (lateral) {
7469
+ if (orchidCore.isRelationQuery(lateral)) {
7470
+ continue;
7471
+ }
7472
+ throw new orchidCore.OrchidOrmInternalError(
7487
7473
  table,
7488
7474
  "Join lateral is not supported in delete"
7489
7475
  );
@@ -7510,9 +7496,22 @@ const pushDeleteSql = (ctx, table, query, quotedAs) => {
7510
7496
  ctx.sql.push("WHERE", conditions);
7511
7497
  }
7512
7498
  }
7513
- const returning = makeReturningSql(ctx, table, query, quotedAs, 3);
7499
+ const delayedRelationSelect = query.selectRelation ? orchidCore.newDelayedRelationSelect(table) : void 0;
7500
+ const returning = makeReturningSql(
7501
+ ctx,
7502
+ table,
7503
+ query,
7504
+ quotedAs,
7505
+ delayedRelationSelect,
7506
+ 3
7507
+ );
7514
7508
  if (returning.select) ctx.sql.push("RETURNING", returning.select);
7515
- return returning.hookSelect;
7509
+ return {
7510
+ hookSelect: returning.hookSelect,
7511
+ delayedRelationSelect,
7512
+ text: ctx.sql.join(" "),
7513
+ values: ctx.values
7514
+ };
7516
7515
  };
7517
7516
 
7518
7517
  const pushTruncateSql = (ctx, table, query) => {
@@ -7584,126 +7583,137 @@ const toSQL = (table, options) => {
7584
7583
  sql,
7585
7584
  values,
7586
7585
  aliasValue: options?.aliasValue,
7587
- skipBatchCheck: options?.skipBatchCheck
7586
+ skipBatchCheck: options?.skipBatchCheck,
7587
+ hasNonSelect: options?.hasNonSelect
7588
7588
  };
7589
7589
  if (query.with) {
7590
7590
  pushWithSql(ctx, query.with);
7591
7591
  }
7592
+ let result;
7592
7593
  let fromQuery;
7593
7594
  if (query.type && query.type !== "upsert") {
7594
7595
  const tableName = table.table ?? query.as;
7595
7596
  if (!tableName) throw new Error(`Table is missing for ${query.type}`);
7596
7597
  if (query.type === "truncate") {
7597
7598
  pushTruncateSql(ctx, tableName, query);
7598
- return { text: sql.join(" "), values };
7599
- }
7600
- if (query.type === "columnInfo") {
7599
+ result = { text: sql.join(" "), values };
7600
+ } else if (query.type === "columnInfo") {
7601
7601
  pushColumnInfoSql(ctx, table, query);
7602
- return { text: sql.join(" "), values };
7603
- }
7604
- const quotedAs2 = `"${query.as || tableName}"`;
7605
- if (query.type === "insert") {
7606
- return makeInsertSql(ctx, table, query, `"${tableName}"`);
7607
- }
7608
- if (query.type === "update") {
7609
- return {
7610
- hookSelect: pushUpdateSql(ctx, table, query, quotedAs2),
7611
- text: sql.join(" "),
7612
- values
7613
- };
7614
- }
7615
- if (query.type === "delete") {
7616
- return {
7617
- hookSelect: pushDeleteSql(ctx, table, query, quotedAs2),
7618
- text: sql.join(" "),
7619
- values
7620
- };
7621
- }
7622
- if (query.type === "copy") {
7623
- pushCopySql(ctx, table, query, quotedAs2);
7624
- return { text: sql.join(" "), values };
7625
- }
7626
- }
7627
- const quotedAs = (query.as || table.table) && `"${query.as || table.table}"`;
7628
- if (query.union) {
7629
- const s = getSqlText(toSQL(query.union.b, { values }));
7630
- sql.push(query.union.p ? s : `(${s})`);
7631
- for (const u of query.union.u) {
7632
- const s2 = orchidCore.isExpression(u.a) ? u.a.toSQL(ctx, quotedAs) : getSqlText(toSQL(u.a, { values }));
7633
- sql.push(`${u.k} ${u.p ? s2 : "(" + s2 + ")"}`);
7602
+ result = { text: sql.join(" "), values };
7603
+ } else {
7604
+ const quotedAs = `"${query.as || tableName}"`;
7605
+ if (query.type === "insert") {
7606
+ result = makeInsertSql(ctx, table, query, `"${tableName}"`);
7607
+ } else if (query.type === "update") {
7608
+ result = pushUpdateSql(ctx, table, query, quotedAs);
7609
+ } else if (query.type === "delete") {
7610
+ result = pushDeleteSql(ctx, table, query, quotedAs);
7611
+ } else if (query.type === "copy") {
7612
+ pushCopySql(ctx, table, query, quotedAs);
7613
+ result = { text: sql.join(" "), values };
7614
+ } else {
7615
+ throw new Error(`Unsupported query type ${query.type}`);
7616
+ }
7634
7617
  }
7635
7618
  } else {
7636
- sql.push("SELECT");
7637
- if (query.distinct) {
7638
- pushDistinctSql(ctx, table, query.distinct, quotedAs);
7639
- }
7640
- const aliases = query.group ? [] : void 0;
7641
- pushSelectSql(ctx, table, query, quotedAs, aliases);
7642
- fromQuery = (table.table || query.from) && pushFromAndAs(ctx, table, query, quotedAs) || void 0;
7643
- if (query.join) {
7644
- pushJoinSql(
7645
- ctx,
7646
- table,
7647
- query,
7648
- quotedAs
7649
- );
7650
- }
7651
- if (query.and || query.or || query.scopes) {
7652
- pushWhereStatementSql(ctx, table, query, quotedAs);
7653
- }
7654
- if (query.group) {
7655
- const group = query.group.map((item) => {
7656
- if (orchidCore.isExpression(item)) {
7657
- return item.toSQL(ctx, quotedAs);
7658
- } else {
7659
- const i = aliases.indexOf(item);
7660
- return i !== -1 ? i + 1 : columnToSql(ctx, table.q, table.shape, item, quotedAs);
7661
- }
7662
- });
7663
- sql.push(`GROUP BY ${group.join(", ")}`);
7664
- }
7665
- if (query.having) pushHavingSql(ctx, query, quotedAs);
7666
- if (query.window) {
7667
- const window = [];
7668
- for (const item of query.window) {
7669
- for (const key in item) {
7670
- window.push(
7671
- `"${key}" AS ${windowToSql(ctx, query, item[key], quotedAs)}`
7672
- );
7619
+ const quotedAs = (query.as || table.table) && `"${query.as || table.table}"`;
7620
+ if (query.union) {
7621
+ const firstSql = toSQL(query.union.b, ctx);
7622
+ ctx.delayedRelationSelect = firstSql.delayedRelationSelect;
7623
+ const s = getSqlText(firstSql);
7624
+ sql.push(query.union.p ? s : `(${s})`);
7625
+ for (const u of query.union.u) {
7626
+ const s2 = orchidCore.isExpression(u.a) ? u.a.toSQL(ctx, quotedAs) : getSqlText(toSQL(u.a, ctx));
7627
+ sql.push(`${u.k} ${u.p ? s2 : "(" + s2 + ")"}`);
7628
+ }
7629
+ } else {
7630
+ sql.push("SELECT");
7631
+ if (query.distinct) {
7632
+ pushDistinctSql(ctx, table, query.distinct, quotedAs);
7633
+ }
7634
+ const aliases = query.group ? [] : void 0;
7635
+ pushSelectSql(ctx, table, query, quotedAs, aliases);
7636
+ fromQuery = (table.table || query.from) && pushFromAndAs(ctx, table, query, quotedAs) || void 0;
7637
+ if (query.join) {
7638
+ pushJoinSql(
7639
+ ctx,
7640
+ table,
7641
+ query,
7642
+ quotedAs
7643
+ );
7644
+ }
7645
+ if (query.and || query.or || query.scopes) {
7646
+ pushWhereStatementSql(ctx, table, query, quotedAs);
7647
+ }
7648
+ if (query.group) {
7649
+ const group = query.group.map((item) => {
7650
+ if (orchidCore.isExpression(item)) {
7651
+ return item.toSQL(ctx, quotedAs);
7652
+ } else {
7653
+ const i = aliases.indexOf(item);
7654
+ return i !== -1 ? i + 1 : columnToSql(
7655
+ ctx,
7656
+ table.q,
7657
+ table.shape,
7658
+ item,
7659
+ quotedAs
7660
+ );
7661
+ }
7662
+ });
7663
+ sql.push(`GROUP BY ${group.join(", ")}`);
7664
+ }
7665
+ if (query.having) pushHavingSql(ctx, query, quotedAs);
7666
+ if (query.window) {
7667
+ const window = [];
7668
+ for (const item of query.window) {
7669
+ for (const key in item) {
7670
+ window.push(
7671
+ `"${key}" AS ${windowToSql(ctx, query, item[key], quotedAs)}`
7672
+ );
7673
+ }
7673
7674
  }
7675
+ sql.push(`WINDOW ${window.join(", ")}`);
7674
7676
  }
7675
- sql.push(`WINDOW ${window.join(", ")}`);
7676
7677
  }
7677
- }
7678
- if (query.order) {
7679
- pushOrderBySql(ctx, query, quotedAs, query.order);
7680
- }
7681
- if (query.useFromLimitOffset) {
7682
- const q = fromQuery?.q;
7683
- if (q.limit) {
7684
- sql.push(`LIMIT ${orchidCore.addValue(values, q.limit)}`);
7678
+ if (query.order) {
7679
+ pushOrderBySql(ctx, query, quotedAs, query.order);
7685
7680
  }
7686
- if (q.offset) {
7687
- sql.push(`OFFSET ${orchidCore.addValue(values, q.offset)}`);
7688
- }
7689
- } else {
7690
- pushLimitSQL(sql, values, query);
7691
- if (query.offset && !query.returnsOne) {
7692
- sql.push(`OFFSET ${orchidCore.addValue(values, query.offset)}`);
7681
+ if (query.useFromLimitOffset) {
7682
+ const q = fromQuery?.q;
7683
+ if (q.limit) {
7684
+ sql.push(`LIMIT ${orchidCore.addValue(values, q.limit)}`);
7685
+ }
7686
+ if (q.offset) {
7687
+ sql.push(`OFFSET ${orchidCore.addValue(values, q.offset)}`);
7688
+ }
7689
+ } else {
7690
+ pushLimitSQL(sql, values, query);
7691
+ if (query.offset && !query.returnsOne) {
7692
+ sql.push(`OFFSET ${orchidCore.addValue(values, query.offset)}`);
7693
+ }
7694
+ }
7695
+ if (query.for) {
7696
+ sql.push("FOR", query.for.type);
7697
+ const { tableNames } = query.for;
7698
+ if (tableNames) {
7699
+ sql.push(
7700
+ "OF",
7701
+ orchidCore.isExpression(tableNames) ? tableNames.toSQL(ctx, quotedAs) : tableNames.map((x) => `"${x}"`).join(", ")
7702
+ );
7703
+ }
7704
+ if (query.for.mode) sql.push(query.for.mode);
7693
7705
  }
7706
+ result = {
7707
+ text: sql.join(" "),
7708
+ values,
7709
+ hookSelect: query.hookSelect,
7710
+ delayedRelationSelect: ctx.delayedRelationSelect
7711
+ };
7694
7712
  }
7695
- if (query.for) {
7696
- sql.push("FOR", query.for.type);
7697
- const { tableNames } = query.for;
7698
- if (tableNames) {
7699
- sql.push(
7700
- "OF",
7701
- orchidCore.isExpression(tableNames) ? tableNames.toSQL(ctx, quotedAs) : tableNames.map((x) => `"${x}"`).join(", ")
7702
- );
7703
- }
7704
- if (query.for.mode) sql.push(query.for.mode);
7713
+ if (options && (query.type || ctx.hasNonSelect)) {
7714
+ options.hasNonSelect = true;
7705
7715
  }
7706
- return { text: sql.join(" "), values, hookSelect: query.hookSelect };
7716
+ return result;
7707
7717
  };
7708
7718
  function pushLimitSQL(sql, values, q) {
7709
7719
  if (!q.returnsOne) {
@@ -8530,6 +8540,24 @@ class AggregateMethods {
8530
8540
  }
8531
8541
  }
8532
8542
 
8543
+ class QueryAsMethods {
8544
+ /**
8545
+ * Sets table alias:
8546
+ *
8547
+ * ```ts
8548
+ * db.table.as('u').select('u.name');
8549
+ *
8550
+ * // Can be used in the join:
8551
+ * db.table.join(Profile.as('p'), 'p.userId', 'user.id');
8552
+ * ```
8553
+ *
8554
+ * @param as - alias for the table of this query
8555
+ */
8556
+ as(as) {
8557
+ return orchidCore._setQueryAs(_clone(this), as);
8558
+ }
8559
+ }
8560
+
8533
8561
  class Clear {
8534
8562
  clear(...clears) {
8535
8563
  const q = _clone(this);
@@ -8573,7 +8601,7 @@ const _queryUnion = (base, args, k, p, m) => {
8573
8601
  m
8574
8602
  })
8575
8603
  );
8576
- const q = query.q;
8604
+ const { q } = query;
8577
8605
  const baseQ = base.q;
8578
8606
  q.union = baseQ.union ? {
8579
8607
  ...baseQ.union,
@@ -8727,7 +8755,7 @@ const addWith = (q, withStore, item, key = "with") => {
8727
8755
  }
8728
8756
  orchidCore.pushOrNewArrayToObjectImmutable(withStore, key, item);
8729
8757
  };
8730
- const moveQueryValueToWith = (q, withStore, value, set, key, withKey) => {
8758
+ const moveQueryValueToWith = (q, withStore, value, withKey, set, key) => {
8731
8759
  if (value.q.type) {
8732
8760
  const as = saveAliasedShape(q, "q", "withShapes");
8733
8761
  addWith(
@@ -8739,8 +8767,12 @@ const moveQueryValueToWith = (q, withStore, value, set, key, withKey) => {
8739
8767
  },
8740
8768
  withKey
8741
8769
  );
8742
- set[key] = new RawSQL(`(SELECT * FROM "${as}")`);
8770
+ if (set) {
8771
+ set[key] = new RawSQL(`(SELECT * FROM "${as}")`);
8772
+ }
8773
+ return as;
8743
8774
  }
8775
+ return;
8744
8776
  };
8745
8777
  class WithMethods {
8746
8778
  with(name, second, third) {
@@ -8839,9 +8871,9 @@ const processCreateItem = (q, item, rowIndex, ctx, encoders) => {
8839
8871
  q,
8840
8872
  (_a = q.q).insertWith ?? (_a.insertWith = {}),
8841
8873
  value,
8874
+ rowIndex,
8842
8875
  item,
8843
- key,
8844
- rowIndex
8876
+ key
8845
8877
  );
8846
8878
  }
8847
8879
  }
@@ -8853,7 +8885,7 @@ const processCreateItem = (q, item, rowIndex, ctx, encoders) => {
8853
8885
  };
8854
8886
  const throwOnReadOnly$1 = (q, column, key) => {
8855
8887
  if (column.data.appReadOnly || column.data.readOnly) {
8856
- throw new OrchidOrmInternalError(
8888
+ throw new orchidCore.OrchidOrmInternalError(
8857
8889
  q,
8858
8890
  "Trying to insert a readonly column",
8859
8891
  { column: key }
@@ -9733,9 +9765,7 @@ const _queryHookBeforeCreate = (q, cb) => {
9733
9765
  return before(
9734
9766
  q,
9735
9767
  "Create",
9736
- (q2) => cb(
9737
- new orchidCore.QueryHookUtils(q2, q2.q.columns, "hookCreateSet")
9738
- )
9768
+ (q2) => cb(new orchidCore.QueryHookUtils(q2, q2.q.columns, "hookCreateSet"))
9739
9769
  );
9740
9770
  };
9741
9771
  const _queryHookAfterCreate = (q, select, cb) => {
@@ -10817,7 +10847,7 @@ class MergeQueryMethods {
10817
10847
 
10818
10848
  const throwOnReadOnly = (q, column, key) => {
10819
10849
  if (column.data.appReadOnly || column.data.readOnly) {
10820
- throw new OrchidOrmInternalError(
10850
+ throw new orchidCore.OrchidOrmInternalError(
10821
10851
  q,
10822
10852
  "Trying to update a readonly column",
10823
10853
  { column: key }
@@ -10855,19 +10885,10 @@ const _queryChangeCounter = (self, op, data) => {
10855
10885
  orchidCore.pushQueryValueImmutable(self, "updateData", map);
10856
10886
  return self;
10857
10887
  };
10858
- const update = (self) => {
10859
- const q = self.q;
10860
- q.type = "update";
10861
- if (!q.select) {
10862
- q.returningMany = !q.returnType || q.returnType === "all";
10863
- q.returnType = "valueOrThrow";
10864
- q.returning = true;
10865
- }
10866
- throwIfNoWhere(self, "update");
10867
- return self;
10868
- };
10869
10888
  const _queryUpdate = (query, arg) => {
10870
10889
  const { q } = query;
10890
+ q.type = "update";
10891
+ const returnCount = !q.select;
10871
10892
  const set = { ...arg };
10872
10893
  orchidCore.pushQueryValueImmutable(query, "updateData", set);
10873
10894
  const { shape } = q;
@@ -10888,7 +10909,7 @@ const _queryUpdate = (query, arg) => {
10888
10909
  value
10889
10910
  );
10890
10911
  if (value instanceof Db && value.q.type && value.q.subQuery) {
10891
- throw new OrchidOrmInternalError(
10912
+ throw new orchidCore.OrchidOrmInternalError(
10892
10913
  value,
10893
10914
  `Only selecting queries are allowed inside a callback of update, ${value.q.type} is given instead.`
10894
10915
  );
@@ -10901,9 +10922,9 @@ const _queryUpdate = (query, arg) => {
10901
10922
  query,
10902
10923
  q,
10903
10924
  value,
10925
+ "with",
10904
10926
  set,
10905
- key,
10906
- "with"
10927
+ key
10907
10928
  );
10908
10929
  } else {
10909
10930
  const encode = item?.data.encode;
@@ -10914,17 +10935,25 @@ const _queryUpdate = (query, arg) => {
10914
10935
  }
10915
10936
  const { queries } = ctx;
10916
10937
  if (queries) {
10938
+ const primaryKeys = orchidCore.requirePrimaryKeys(
10939
+ query,
10940
+ "Cannot perform complex update on a table without primary keys"
10941
+ );
10942
+ const hookSelect = q.hookSelect = new Map(q.hookSelect);
10943
+ for (const column of primaryKeys) {
10944
+ hookSelect.set(column, { select: column });
10945
+ }
10917
10946
  q.patchResult = async (_, _h, queryResult) => {
10918
10947
  await Promise.all(queries.map(orchidCore.callWithThis, queryResult));
10919
10948
  if (ctx.collect) {
10920
10949
  const t = query.baseQuery.clone();
10921
- const { keys } = ctx.collect;
10922
10950
  _queryWhereIn(
10923
10951
  t,
10924
- keys,
10925
- queryResult.rows.map((item) => keys.map((key) => item[key]))
10952
+ true,
10953
+ primaryKeys,
10954
+ queryResult.rows.map((item) => primaryKeys.map((key) => item[key]))
10926
10955
  );
10927
- _queryUpdate(
10956
+ await _queryUpdate(
10928
10957
  t,
10929
10958
  ctx.collect.data
10930
10959
  );
@@ -10934,7 +10963,13 @@ const _queryUpdate = (query, arg) => {
10934
10963
  }
10935
10964
  };
10936
10965
  }
10937
- return update(query);
10966
+ if (returnCount) {
10967
+ q.returningMany = !q.returnType || q.returnType === "all";
10968
+ q.returnType = "valueOrThrow";
10969
+ q.returning = true;
10970
+ }
10971
+ throwIfNoWhere(query, "update");
10972
+ return query;
10938
10973
  };
10939
10974
  const _queryUpdateOrThrow = (q, arg) => {
10940
10975
  q.q.throwOnNotFound = true;
@@ -11277,7 +11312,7 @@ AggregateMethods.prototype.headline = function(search, params) {
11277
11312
  const q = this;
11278
11313
  const source = q.q.sources?.[search];
11279
11314
  if (!source)
11280
- throw new OrchidOrmInternalError(q, `Search \`${search}\` is not defined`);
11315
+ throw new orchidCore.OrchidOrmInternalError(q, `Search \`${search}\` is not defined`);
11281
11316
  return new Headline(
11282
11317
  q.q,
11283
11318
  source,
@@ -11518,7 +11553,10 @@ function orCreate(query, data, updateData, mergeData) {
11518
11553
  }
11519
11554
  const inCTE = {
11520
11555
  selectNum: !!(hasAfterCallback || hasAfterCommitCallback),
11521
- targetHookSelect: hookSelect
11556
+ targetHookSelect: hookSelect,
11557
+ delayedRelationSelect: orchidCore.newDelayedRelationSelect(
11558
+ query
11559
+ )
11522
11560
  };
11523
11561
  q2 = q2.clone();
11524
11562
  q2.q.inCTE = inCTE;
@@ -11568,7 +11606,7 @@ function orCreate(query, data, updateData, mergeData) {
11568
11606
  await q22;
11569
11607
  created = true;
11570
11608
  } else if (queryResult.rowCount > 1) {
11571
- throw new MoreThanOneRowError(
11609
+ throw new orchidCore.MoreThanOneRowError(
11572
11610
  q2,
11573
11611
  `Only one row was expected to find, found ${queryResult.rowCount} rows.`
11574
11612
  );
@@ -12154,7 +12192,7 @@ class QueryMethods {
12154
12192
  find(value) {
12155
12193
  const q = _clone(this);
12156
12194
  if (value === null || value === void 0) {
12157
- throw new OrchidOrmInternalError(
12195
+ throw new orchidCore.OrchidOrmInternalError(
12158
12196
  q,
12159
12197
  `${value} is not allowed in the find method`
12160
12198
  );
@@ -12444,7 +12482,7 @@ class QueryMethods {
12444
12482
  */
12445
12483
  truncate(options) {
12446
12484
  const query = _clone(this);
12447
- const q = query.q;
12485
+ const { q } = query;
12448
12486
  q.type = "truncate";
12449
12487
  if (options?.restartIdentity) {
12450
12488
  q.restartIdentity = true;
@@ -12574,11 +12612,12 @@ class QueryMethods {
12574
12612
  * @param fn - helper function
12575
12613
  */
12576
12614
  makeHelper(fn) {
12577
- const as = this.q.as || this.table;
12615
+ const helperAs = this.q.as || this.table;
12578
12616
  return (query, ...args) => {
12579
12617
  const q = _clone(query);
12580
- if (q.q.as) {
12581
- setQueryObjectValueImmutable(q, "aliases", as, q.q.as);
12618
+ const as = orchidCore._getQueryAs(q);
12619
+ if (as) {
12620
+ orchidCore._setQueryAlias(q, as, helperAs);
12582
12621
  }
12583
12622
  return fn(q, ...args);
12584
12623
  };
@@ -12684,7 +12723,7 @@ class QueryMethods {
12684
12723
  Object.assign(QueryMethods.prototype, QueryUpsert);
12685
12724
  Object.assign(QueryMethods.prototype, QueryOrCreate);
12686
12725
  orchidCore.applyMixins(QueryMethods, [
12687
- AsMethods,
12726
+ QueryAsMethods,
12688
12727
  AggregateMethods,
12689
12728
  Select,
12690
12729
  FromMethods,
@@ -12973,7 +13012,7 @@ class Db extends QueryMethods {
12973
13012
  cb(this);
12974
13013
  }
12975
13014
  }
12976
- this.error = class extends QueryError {
13015
+ this.error = class extends orchidCore.QueryError {
12977
13016
  constructor(message) {
12978
13017
  super(self, message);
12979
13018
  }
@@ -13073,7 +13112,7 @@ class Db extends QueryMethods {
13073
13112
  const {
13074
13113
  rows: [row]
13075
13114
  } = await performQuery(q, args, "query");
13076
- if (!row) throw new NotFoundError(q);
13115
+ if (!row) throw new orchidCore.NotFoundError(q);
13077
13116
  return row;
13078
13117
  },
13079
13118
  async takeOptional(...args) {
@@ -13092,7 +13131,7 @@ class Db extends QueryMethods {
13092
13131
  const {
13093
13132
  rows: [row]
13094
13133
  } = await performQuery(q, args, "arrays");
13095
- if (!row) throw new NotFoundError(q);
13134
+ if (!row) throw new orchidCore.NotFoundError(q);
13096
13135
  return row[0];
13097
13136
  },
13098
13137
  async getOptional(...args) {
@@ -13123,22 +13162,6 @@ class Db extends QueryMethods {
13123
13162
  queryArrays(...args) {
13124
13163
  return performQuery(this, args, "arrays");
13125
13164
  }
13126
- /**
13127
- * In snake case mode, or when columns have custom names,
13128
- * use this method to exchange a db column name to its runtime key.
13129
- */
13130
- columnNameToKey(name) {
13131
- let map = this.internal.columnNameToKeyMap;
13132
- if (!map) {
13133
- this.internal.columnNameToKeyMap = map = /* @__PURE__ */ new Map();
13134
- const { shape } = this;
13135
- for (const key in this.shape) {
13136
- const column = shape[key];
13137
- map.set(column.data.name ?? key, key);
13138
- }
13139
- }
13140
- return map.get(name);
13141
- }
13142
13165
  }
13143
13166
  orchidCore.applyMixins(Db, [QueryMethods]);
13144
13167
  Db.prototype.constructor = Db;
@@ -13351,7 +13374,6 @@ exports.Adapter = Adapter;
13351
13374
  exports.AfterCommitError = AfterCommitError;
13352
13375
  exports.AggregateMethods = AggregateMethods;
13353
13376
  exports.ArrayColumn = ArrayColumn;
13354
- exports.AsMethods = AsMethods;
13355
13377
  exports.BigIntColumn = BigIntColumn;
13356
13378
  exports.BigSerialColumn = BigSerialColumn;
13357
13379
  exports.BitColumn = BitColumn;
@@ -13398,22 +13420,18 @@ exports.MacAddr8Column = MacAddr8Column;
13398
13420
  exports.MacAddrColumn = MacAddrColumn;
13399
13421
  exports.MergeQueryMethods = MergeQueryMethods;
13400
13422
  exports.MoneyColumn = MoneyColumn;
13401
- exports.MoreThanOneRowError = MoreThanOneRowError;
13402
- exports.NotFoundError = NotFoundError;
13403
13423
  exports.NumberAsStringBaseColumn = NumberAsStringBaseColumn;
13404
13424
  exports.NumberBaseColumn = NumberBaseColumn;
13405
13425
  exports.OnConflictQueryBuilder = OnConflictQueryBuilder;
13406
13426
  exports.OnMethods = OnMethods;
13407
13427
  exports.Operators = Operators;
13408
13428
  exports.OrExpression = OrExpression;
13409
- exports.OrchidOrmError = OrchidOrmError;
13410
- exports.OrchidOrmInternalError = OrchidOrmInternalError;
13411
13429
  exports.PathColumn = PathColumn;
13412
13430
  exports.PointColumn = PointColumn;
13413
13431
  exports.PolygonColumn = PolygonColumn;
13414
13432
  exports.PostgisGeographyPointColumn = PostgisGeographyPointColumn;
13433
+ exports.QueryAsMethods = QueryAsMethods;
13415
13434
  exports.QueryCreate = QueryCreate;
13416
- exports.QueryError = QueryError;
13417
13435
  exports.QueryGet = QueryGet;
13418
13436
  exports.QueryHooks = QueryHooks;
13419
13437
  exports.QueryLog = QueryLog;
@@ -13441,7 +13459,6 @@ exports.TransformMethods = TransformMethods;
13441
13459
  exports.TsQueryColumn = TsQueryColumn;
13442
13460
  exports.TsVectorColumn = TsVectorColumn;
13443
13461
  exports.UUIDColumn = UUIDColumn;
13444
- exports.UnhandledTypeError = UnhandledTypeError;
13445
13462
  exports.Union = Union;
13446
13463
  exports.UnknownColumn = UnknownColumn;
13447
13464
  exports.Update = Update;
@@ -13455,7 +13472,6 @@ exports._getSelectableColumn = _getSelectableColumn;
13455
13472
  exports._initQueryBuilder = _initQueryBuilder;
13456
13473
  exports._queryAfterSaveCommit = _queryAfterSaveCommit;
13457
13474
  exports._queryAll = _queryAll;
13458
- exports._queryAs = _queryAs;
13459
13475
  exports._queryChangeCounter = _queryChangeCounter;
13460
13476
  exports._queryCreate = _queryCreate;
13461
13477
  exports._queryCreateFrom = _queryCreateFrom;
@@ -13490,7 +13506,6 @@ exports._queryJoinOnJsonPathEquals = _queryJoinOnJsonPathEquals;
13490
13506
  exports._queryJoinOrOn = _queryJoinOrOn;
13491
13507
  exports._queryOr = _queryOr;
13492
13508
  exports._queryOrNot = _queryOrNot;
13493
- exports._queryResolveAlias = _queryResolveAlias;
13494
13509
  exports._queryRows = _queryRows;
13495
13510
  exports._querySelect = _querySelect;
13496
13511
  exports._queryTake = _queryTake;
@@ -13542,7 +13557,6 @@ exports.getColumnBaseType = getColumnBaseType;
13542
13557
  exports.getColumnInfo = getColumnInfo;
13543
13558
  exports.getColumnTypes = getColumnTypes;
13544
13559
  exports.getFullColumnTable = getFullColumnTable;
13545
- exports.getPrimaryKeys = getPrimaryKeys;
13546
13560
  exports.getQueryAs = getQueryAs;
13547
13561
  exports.getShapeFromSelect = getShapeFromSelect;
13548
13562
  exports.getSqlText = getSqlText;