pqb 0.72.0 → 0.72.1

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.mjs CHANGED
@@ -2291,6 +2291,17 @@ const make = (_op) => {
2291
2291
  (q.chain ??= []).push(_op, val || value);
2292
2292
  if (getValueParser(q.parsers)) setValueParser(q, void 0);
2293
2293
  q.getColumn = BooleanColumn.instance;
2294
+ if (this instanceof Expression && this.result) {
2295
+ let column;
2296
+ if (this.result.value?.data.name) {
2297
+ column = Object.create(BooleanColumn.instance);
2298
+ column.data = {
2299
+ ...column.data,
2300
+ name: this.result.value.data.name
2301
+ };
2302
+ } else column = BooleanColumn.instance;
2303
+ this.result.value = column;
2304
+ }
2294
2305
  return setQueryOperators(this, boolean);
2295
2306
  }, { _op });
2296
2307
  };
@@ -2797,7 +2808,8 @@ var SimpleRawSQL = class extends RawSql {
2797
2808
  };
2798
2809
  const raw$1 = (sql) => new SimpleRawSQL(sql);
2799
2810
  const makeTimestamps = (timestamp) => {
2800
- const nowRaw = raw$1(getDefaultNowFn());
2811
+ const now = getDefaultNowFn();
2812
+ const nowRaw = raw$1(now);
2801
2813
  const updatedAt = timestamp().default(nowRaw);
2802
2814
  let updater;
2803
2815
  updatedAt.data.modifyQuery = (q, column) => {
@@ -2830,7 +2842,7 @@ const timestampHelpers = {
2830
2842
  };
2831
2843
  const defaultSrid = 4326;
2832
2844
  const encode = ({ srid = defaultSrid, lon, lat }) => {
2833
- const arr = new Uint8Array(25);
2845
+ const arr = /* @__PURE__ */ new Uint8Array(25);
2834
2846
  const view = new DataView(arr.buffer);
2835
2847
  view.setInt8(0, 1);
2836
2848
  view.setInt8(1, 1);
@@ -2859,7 +2871,7 @@ var PostgisGeographyPointColumn = class extends Column {
2859
2871
  }
2860
2872
  };
2861
2873
  const parse = (input) => {
2862
- const bytes = new Uint8Array(20);
2874
+ const bytes = /* @__PURE__ */ new Uint8Array(20);
2863
2875
  for (let i = 0; i < 40; i += 2) bytes[i / 2] = parseInt(input.slice(10 + i, 12 + i), 16);
2864
2876
  const view = new DataView(bytes.buffer);
2865
2877
  const srid = view.getUint32(0, true);
@@ -3804,7 +3816,8 @@ var QueryTransaction = class QueryTransaction {
3804
3816
  return QueryTransaction.prototype.transaction.call(this, cb);
3805
3817
  }
3806
3818
  isInTransaction() {
3807
- return isInUserTransaction(this.internal.asyncStorage.getStore());
3819
+ const trx = this.internal.asyncStorage.getStore();
3820
+ return isInUserTransaction(trx);
3808
3821
  }
3809
3822
  /**
3810
3823
  * Schedules a hook to run after the outermost transaction commits:
@@ -5664,7 +5677,8 @@ const resolveCallbacksInArgs = (q, args) => {
5664
5677
  qb.q.and = qb.q.or = qb.q.scopes = void 0;
5665
5678
  qb.q.subQuery = 1;
5666
5679
  _setSubQueryAliases(qb);
5667
- args[i] = prepareSubQueryForSql(q, resolveSubQueryCallback(qb, arg));
5680
+ const resolved = resolveSubQueryCallback(qb, arg);
5681
+ args[i] = prepareSubQueryForSql(q, resolved);
5668
5682
  } else if (arg.constructor === Object) {
5669
5683
  const copy = args[i] = { ...arg };
5670
5684
  for (const key in arg) {
@@ -6436,7 +6450,8 @@ var Where = class {
6436
6450
  * @param args - no arguments needed when the first argument is a relation name, or conditions to join the table with.
6437
6451
  */
6438
6452
  whereNotExists(arg, ...args) {
6439
- return _queryWhereNotExists(_clone(this), arg, args);
6453
+ const q = _clone(this);
6454
+ return _queryWhereNotExists(q, arg, args);
6440
6455
  }
6441
6456
  /**
6442
6457
  * Acts as `whereExists`, but prepends the condition with `OR` and negates it with `NOT`:
@@ -6583,7 +6598,11 @@ const tableColumnToSql = (ctx, queryData, shape, table, key, quotedAs, select, a
6583
6598
  const columnToSqlNotSelect = (ctx, data, shape, column, quotedAs, useSelectList) => columnToSql(ctx, data, shape, column, quotedAs, void 0, void 0, void 0, useSelectList, true);
6584
6599
  const columnToSql = (ctx, data, shape, column, quotedAs, select, as, jsonList, useSelectList, skipValueToArray) => {
6585
6600
  let index = column.indexOf(".");
6586
- if (index !== -1) return tableColumnToSql(ctx, data, shape, column.slice(0, index), column.slice(index + 1), quotedAs, select, as, jsonList, skipValueToArray);
6601
+ if (index !== -1) {
6602
+ const table = column.slice(0, index);
6603
+ const key = column.slice(index + 1);
6604
+ return tableColumnToSql(ctx, data, shape, table, key, quotedAs, select, as, jsonList, skipValueToArray);
6605
+ }
6587
6606
  return simpleColumnToSQL(ctx, data, shape, column, shape[column], quotedAs, select, as, jsonList, useSelectList, void 0, skipValueToArray);
6588
6607
  };
6589
6608
  const rawOrColumnToSql = (ctx, data, shape, expr, quotedAs, select, skipValueToArray) => {
@@ -6826,11 +6845,20 @@ const _addToHookSelectWithTable = (query, selects, table) => {
6826
6845
  };
6827
6846
  const moveQueryToCte = (ctx, query, type, dontAddTableHook) => {
6828
6847
  const { returnType } = query.q;
6848
+ const throwOnNotFound = returnType === "valueOrThrow";
6829
6849
  let valueAs;
6830
6850
  if (returnType === "value" || returnType === "valueOrThrow" || returnType === "pluck") {
6831
6851
  const first = query.q.select[0];
6832
- if (first instanceof SelectItemExpression && typeof first.item === "string") valueAs = first.item;
6833
- else {
6852
+ if (first instanceof SelectItemExpression && typeof first.item === "string") {
6853
+ const columnName = first.result.value?.data.name;
6854
+ if (columnName && columnName !== first.item) {
6855
+ query = _clone(query);
6856
+ query.q.returnType = "one";
6857
+ query.q.select = [{ selectAs: { [first.item]: first } }];
6858
+ if (throwOnNotFound && query.q.type !== "upsert") query.q.cteThrowOnNotFound = true;
6859
+ }
6860
+ valueAs = first.item;
6861
+ } else {
6834
6862
  query = _clone(query);
6835
6863
  query.q.returnType = "one";
6836
6864
  query.q.select = [{ selectAs: { value: query.q.select[0] } }];
@@ -6887,7 +6915,7 @@ const addTableHook = (ctx, q, data, select, hookPurpose, dontAddTableHook) => {
6887
6915
  const afterUpdateCommit = data.afterUpdateCommit;
6888
6916
  const afterSaveCommit = data.afterSaveCommit;
6889
6917
  const afterDeleteCommit = data.afterDeleteCommit;
6890
- const throwOnNotFound = hookPurpose !== "Create" && (data.returnType === "oneOrThrow" || data.returnType === "valueOrThrow");
6918
+ const throwOnNotFound = hookPurpose !== "Create" && (data.cteThrowOnNotFound || data.returnType === "oneOrThrow" || data.returnType === "valueOrThrow");
6891
6919
  const hasAfterHook = afterCreate || afterUpdate || afterSave || afterDelete || afterCreateCommit || afterUpdateCommit || afterSaveCommit || afterDeleteCommit;
6892
6920
  if (!select && !hasAfterHook && !throwOnNotFound) return;
6893
6921
  const tableHook = {
@@ -6912,7 +6940,8 @@ const addTableHook = (ctx, q, data, select, hookPurpose, dontAddTableHook) => {
6912
6940
  tableHook,
6913
6941
  throwOnNotFound
6914
6942
  };
6915
- const cteHooks = setCteHooks(ctx, throwOnNotFound || !!tableHook.select);
6943
+ const hasSelect = throwOnNotFound || !!tableHook.select;
6944
+ const cteHooks = setCteHooks(ctx, hasSelect);
6916
6945
  (cteHooks.tableHooks ??= {})[ctx.cteName] ??= item;
6917
6946
  }
6918
6947
  } else ctx.topCtx.tableHook = tableHook;
@@ -7305,7 +7334,8 @@ const processWhere = (ands, ctx, table, query, data, quotedAs) => {
7305
7334
  const value = data[key];
7306
7335
  if (value === void 0) continue;
7307
7336
  if (key === "AND") {
7308
- const sql = processAnds(toArray(value), ctx, table, query, quotedAs);
7337
+ const arr = toArray(value);
7338
+ const sql = processAnds(arr, ctx, table, query, quotedAs);
7309
7339
  if (sql) ands.push(sql);
7310
7340
  } else if (key === "OR") {
7311
7341
  const sqls = value.map(toArray).reduce((acc, and) => {
@@ -8948,7 +8978,9 @@ const _queryCreate = (q, data) => {
8948
8978
  };
8949
8979
  const _queryInsert = (query, data) => {
8950
8980
  throwIfReadOnly(query);
8951
- return insert(query, handleOneData(query, data, createCtx()));
8981
+ const ctx = createCtx();
8982
+ const obj = handleOneData(query, data, ctx);
8983
+ return insert(query, obj);
8952
8984
  };
8953
8985
  const _queryCreateMany = (q, data) => {
8954
8986
  throwIfReadOnly(q);
@@ -8957,7 +8989,8 @@ const _queryCreateMany = (q, data) => {
8957
8989
  };
8958
8990
  const _queryInsertMany = (q, data) => {
8959
8991
  throwIfReadOnly(q);
8960
- let result = insert(q, handleManyData(q, data, createCtx()), true);
8992
+ const ctx = createCtx();
8993
+ let result = insert(q, handleManyData(q, data, ctx), true);
8961
8994
  if (!data.length) result = result.none();
8962
8995
  return result;
8963
8996
  };
@@ -9561,7 +9594,8 @@ const toSql = (table, type, topCtx, isSubSql, cteName, calledByThen, dontAddTabl
9561
9594
  upsertOrCreate.q.or = upsertOrCreate.q.scopes = void 0;
9562
9595
  upsertOrCreate.q.and = [new RawSql(`NOT EXISTS (SELECT 1 FROM "${as}")`)];
9563
9596
  if (query.upsertInsert) {
9564
- _queryInsert(upsertOrCreate, query.upsertInsert());
9597
+ const insertData = query.upsertInsert();
9598
+ _queryInsert(upsertOrCreate, insertData);
9565
9599
  upsertOrCreate.q.type = "upsert";
9566
9600
  }
9567
9601
  upsertOrCreate.q.with = query.upsertCreateWith;
@@ -9674,7 +9708,8 @@ const cteToSqlGiveAs = (ctx, item, type, dontAddTableHook) => {
9674
9708
  let as;
9675
9709
  if (typeof item.n === "string") as = item.n;
9676
9710
  else if (ctx === ctx.topCtx) {
9677
- as = setFreeAlias((ctx.topCtx.topCTE ??= newTopCte(ctx)).names, "q", true);
9711
+ const topCTE = ctx.topCtx.topCTE ??= newTopCte(ctx);
9712
+ as = setFreeAlias(topCTE.names, "q", true);
9678
9713
  item.n(as);
9679
9714
  } else throw new Error("not implemented yet");
9680
9715
  if (item.q) inner = getSqlText(toSql(item.q, type, ctx.topCtx, true, as, void 0, dontAddTableHook));
@@ -10798,12 +10833,15 @@ var OnMethods = class {
10798
10833
  const setSelectRelation = (q) => {
10799
10834
  q.selectRelation = true;
10800
10835
  };
10801
- const addParsersForSelectJoined = (q, arg, as = arg) => {
10836
+ const addParsersForSelectJoinedWildcard = (q, arg, as = arg) => {
10802
10837
  const parsers = q.q.joinedParsers?.[arg];
10803
10838
  if (parsers) setParserToQuery(q.q, as, (row) => parseRecord(parsers, row));
10804
10839
  const batchParsers = q.q.joinedBatchParsers?.[arg];
10805
10840
  if (batchParsers) pushQueryArrayImmutable(q, "batchParsers", batchParsers.map((x) => ({
10806
- path: [{ key: as }, ...x.path],
10841
+ path: [{
10842
+ key: as,
10843
+ returnType: "one"
10844
+ }, ...x.path],
10807
10845
  fn: x.fn
10808
10846
  })));
10809
10847
  };
@@ -10985,7 +11023,8 @@ const processSelectAsArg = (q, selectAs, as, key, arg, columnAlias, outerReturnT
10985
11023
  subQuery = value;
10986
11024
  } else subQuery = value.json(false);
10987
11025
  else subQuery = value;
10988
- const as = _joinLateral(q, innerJoinLateral || query.q.returnType === "valueOrThrow" ? "JOIN" : "LEFT JOIN", subQuery, key, innerJoinLateral && returnType !== "one" && returnType !== "oneOrThrow");
11026
+ const joinLateral = innerJoinLateral || query.q.returnType === "valueOrThrow";
11027
+ const as = _joinLateral(q, joinLateral ? "JOIN" : "LEFT JOIN", subQuery, key, innerJoinLateral && returnType !== "one" && returnType !== "oneOrThrow");
10989
11028
  if (as) value.q.joinedForSelect = _copyQueryAliasToQuery(value, q, as);
10990
11029
  }
10991
11030
  if (value.q.getColumn?.data.skipValueToArray) value.q.notFoundDefault ??= null;
@@ -11017,7 +11056,7 @@ const setParserForSelectedString = (query, arg, as, columnAs, columnAlias) => {
11017
11056
  const table = getFullColumnTable(query, arg, index, as);
11018
11057
  const column = arg.slice(index + 1);
11019
11058
  if (column === "*") {
11020
- addParsersForSelectJoined(query, table, columnAs);
11059
+ addParsersForSelectJoinedWildcard(query, table, columnAs);
11021
11060
  return table === as ? column : arg;
11022
11061
  }
11023
11062
  if (table === as) return selectColumn(query, q, column, columnAs, columnAlias);
@@ -12443,7 +12482,7 @@ const _prependWithOnUpsertCreate = (q, name, query) => {
12443
12482
  q.q.upsertCreateWith = q.q.with;
12444
12483
  q.q.with = prev;
12445
12484
  };
12446
- const mergableObjects = new Set([
12485
+ const mergableObjects = /* @__PURE__ */ new Set([
12447
12486
  "selectShape",
12448
12487
  "withShapes",
12449
12488
  "defaultParsers",
@@ -12455,7 +12494,7 @@ const mergableObjects = new Set([
12455
12494
  "joinedBatchParsers",
12456
12495
  "selectedComputeds"
12457
12496
  ]);
12458
- const dontMergeArrays = new Set(["selectAllColumns"]);
12497
+ const dontMergeArrays = /* @__PURE__ */ new Set(["selectAllColumns"]);
12459
12498
  var MergeQueryMethods = class {
12460
12499
  merge(q) {
12461
12500
  const query = _clone(this);
@@ -12469,20 +12508,18 @@ var MergeQueryMethods = class {
12469
12508
  case "number":
12470
12509
  a[key] = value;
12471
12510
  break;
12472
- case "object":
12473
- if (Array.isArray(value)) {
12474
- if (!dontMergeArrays.has(key)) a[key] = a[key] ? [...a[key], ...value] : value;
12475
- } else if (mergableObjects.has(key)) a[key] = a[key] ? {
12476
- ...a[key],
12477
- ...value
12478
- } : value;
12479
- else if (key === "union") a[key] = a[key] ? {
12480
- b: a[key].b,
12481
- u: [...a[key].u, ...value.u]
12482
- } : value;
12483
- else if (value instanceof Set) a[key] = a[key] ? new Set([...a[key], ...value]) : value;
12484
- else a[key] = value;
12485
- break;
12511
+ case "object": if (Array.isArray(value)) {
12512
+ if (!dontMergeArrays.has(key)) a[key] = a[key] ? [...a[key], ...value] : value;
12513
+ } else if (mergableObjects.has(key)) a[key] = a[key] ? {
12514
+ ...a[key],
12515
+ ...value
12516
+ } : value;
12517
+ else if (key === "union") a[key] = a[key] ? {
12518
+ b: a[key].b,
12519
+ u: [...a[key].u, ...value.u]
12520
+ } : value;
12521
+ else if (value instanceof Set) a[key] = a[key] ? /* @__PURE__ */ new Set([...a[key], ...value]) : value;
12522
+ else a[key] = value;
12486
12523
  }
12487
12524
  }
12488
12525
  if (b.returnType) a.returnType = b.returnType;
@@ -13460,7 +13497,8 @@ var QueryMethods = class {
13460
13497
  * @param args - SQL expression
13461
13498
  */
13462
13499
  findBySql(...args) {
13463
- return _queryTake(_queryWhereSql(_clone(this), args));
13500
+ const q = _clone(this);
13501
+ return _queryTake(_queryWhereSql(q, args));
13464
13502
  }
13465
13503
  /**
13466
13504
  * Finds a single record by the primary key (id), returns `undefined` when not found.
@@ -14000,7 +14038,8 @@ var Db = class extends QueryMethods {
14000
14038
  if (options.noPrimaryKey === "error") throw new Error(message);
14001
14039
  else logger.warn(message);
14002
14040
  }
14003
- this.columns = Object.keys(shape);
14041
+ const columns = Object.keys(shape);
14042
+ this.columns = columns;
14004
14043
  if (options.computed) applyComputedColumns(this, options.computed);
14005
14044
  if (prepareSelectAll) {
14006
14045
  const selectAllShape = this.q.selectAllShape = {};
@@ -14456,6 +14495,12 @@ var Rollback = class extends Error {};
14456
14495
  const trxForTest = Symbol("trxForTest");
14457
14496
  const argToDb = (arg) => "$qb" in arg ? arg.$qb : arg;
14458
14497
  const testTransaction = {
14498
+ /**
14499
+ * Start a test transaction.
14500
+ * The returned promise is resolved immediately when transaction starts, not waiting for it to end.
14501
+ *
14502
+ * @param arg - ORM instance or a queryable instance (such as db.someTable).
14503
+ */
14459
14504
  start(arg) {
14460
14505
  const db = argToDb(arg);
14461
14506
  const { asyncStorage } = db.internal;
@@ -14491,6 +14536,11 @@ const testTransaction = {
14491
14536
  });
14492
14537
  });
14493
14538
  },
14539
+ /**
14540
+ * Rollback a test transaction.
14541
+ *
14542
+ * @param arg - the same ORM or query argument passed into the `testTransaction.start`.
14543
+ */
14494
14544
  rollback(arg) {
14495
14545
  const db = argToDb(arg);
14496
14546
  const data = db.internal[trxForTest];
@@ -14500,6 +14550,12 @@ const testTransaction = {
14500
14550
  last.reject?.(new Rollback());
14501
14551
  return last.promise;
14502
14552
  },
14553
+ /**
14554
+ * Will roll back the current `testTransaction` (won't have any effect if it was rolled back already),
14555
+ * and if there's no nested test transactions left, it will close the db connection.
14556
+ *
14557
+ * @param arg - the same ORM or query argument passed into the `testTransaction.start`.
14558
+ */
14503
14559
  async close(arg) {
14504
14560
  const db = argToDb(arg);
14505
14561
  await this.rollback(db);