pqb 0.30.5 → 0.30.7

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
@@ -1,4 +1,4 @@
1
- import { ExpressionTypeMethod, Expression, RawSQLBase, emptyObject, isTemplateLiteralArgs, ColumnTypeBase, setColumnData, pushColumnData, quoteObjectKey, toArray, singleQuote, addCode, singleQuoteArray, objectHasValues, columnDefaultArgumentToCode, columnErrorMessagesToCode, getValueKey, addValue, isExpression, joinTruthy, numberDataToCode, stringDataToCode, getDefaultLanguage, dateDataToCode, pushOrNewArrayToObject, arrayDataToCode, noop, emptyArray, callWithThis, setParserToQuery, applyTransforms, isRawSQL, pushOrNewArray, setDefaultNowFn, setDefaultLanguage, makeTimestampsHelpers, setCurrentColumnName, setAdapterConnectRetry, isObjectEmpty, ValExpression, applyMixins, toSnakeCase, snakeCaseKey } from 'orchid-core';
1
+ import { ExpressionTypeMethod, Expression, RawSQLBase, emptyObject, isTemplateLiteralArgs, ColumnTypeBase, setColumnData, pushColumnData, quoteObjectKey, toArray, singleQuote, addCode, singleQuoteArray, objectHasValues, columnDefaultArgumentToCode, columnErrorMessagesToCode, getValueKey, addValue, isExpression, joinTruthy, numberDataToCode, stringDataToCode, getDefaultLanguage, dateDataToCode, pushOrNewArrayToObject, returnArg as returnArg$1, noop, arrayDataToCode, emptyArray, callWithThis, setParserToQuery, applyTransforms, isRawSQL, pushOrNewArray, setDefaultNowFn, setDefaultLanguage, makeTimestampsHelpers, setCurrentColumnName, setAdapterConnectRetry, isObjectEmpty, ValExpression, applyMixins, toSnakeCase, snakeCaseKey } from 'orchid-core';
2
2
  import pg from 'pg';
3
3
  import { inspect } from 'node:util';
4
4
  import { AsyncLocalStorage } from 'node:async_hooks';
@@ -2377,25 +2377,14 @@ const subJoinToSql = (ctx, jq, innerAs, outerAs, cloned) => {
2377
2377
  }).text}) ${outerAs || innerAs}`;
2378
2378
  };
2379
2379
  const processArgs = (args, ctx, query, joinAs, joinShape, quotedAs) => {
2380
- if (args.length === 1) {
2381
- return getObjectOrRawConditions(
2382
- ctx,
2383
- query,
2384
- args[0],
2385
- quotedAs,
2386
- joinAs,
2387
- joinShape
2388
- );
2389
- } else {
2390
- return getConditionsFor3Or4LengthItem(
2391
- ctx,
2392
- query,
2393
- joinAs,
2394
- quotedAs,
2395
- args,
2396
- joinShape
2397
- );
2398
- }
2380
+ return args.length === 1 ? getObjectOrRawConditions(ctx, query, args[0], quotedAs, joinAs, joinShape) : getConditionsFor3Or4LengthItem(
2381
+ ctx,
2382
+ query,
2383
+ joinAs,
2384
+ quotedAs,
2385
+ args,
2386
+ joinShape
2387
+ );
2399
2388
  };
2400
2389
  const getConditionsFor3Or4LengthItem = (ctx, query, target, quotedAs, args, joinShape) => {
2401
2390
  const [leftColumn, opOrRightColumn, maybeRightColumn] = args;
@@ -2548,7 +2537,9 @@ const processJoinArgs = (joinTo, first, args, joinSubQuery) => {
2548
2537
  );
2549
2538
  return { w: first, r, s: joinSubQuery || getIsJoinSubQuery(r) };
2550
2539
  }
2551
- } else if (typeof args[0] === "function") {
2540
+ }
2541
+ const args0 = args.length ? args[0] : returnArg$1;
2542
+ if (typeof args0 === "function") {
2552
2543
  const q = first;
2553
2544
  if (q.joinQueryAfterCallback) {
2554
2545
  let base = q.baseQuery;
@@ -2566,7 +2557,7 @@ const processJoinArgs = (joinTo, first, args, joinSubQuery) => {
2566
2557
  const joinedShapes = __spreadProps$4(__spreadValues$c({}, joinTo.q.joinedShapes), {
2567
2558
  [joinTo.q.as || joinTo.table]: joinTo.shape
2568
2559
  });
2569
- const r = args[0](
2560
+ const r = args0(
2570
2561
  makeJoinQueryBuilder(
2571
2562
  q,
2572
2563
  q.q.joinedShapes ? __spreadValues$c(__spreadValues$c({}, q.q.joinedShapes), joinedShapes) : joinedShapes,
@@ -2591,6 +2582,32 @@ const makeJoinQueryBuilder = (joinedQuery, joinedShapes, joinTo) => {
2591
2582
  return q;
2592
2583
  };
2593
2584
 
2585
+ const noneMethods = {
2586
+ // `then` resolves or rejects based on return type of the query.
2587
+ // It is `async` so it returns a chainable Promise.
2588
+ async then(resolve, reject) {
2589
+ const type = this.q.returnType;
2590
+ if (!type || type === "all" || type === "rows" || type === "pluck")
2591
+ resolve == null ? void 0 : resolve([]);
2592
+ else if (type === "one" || type === "value" || type === "void")
2593
+ resolve == null ? void 0 : resolve();
2594
+ else if (type === "rowCount")
2595
+ resolve == null ? void 0 : resolve(0);
2596
+ else
2597
+ reject == null ? void 0 : reject(new NotFoundError(this));
2598
+ },
2599
+ // `catch` returns a Promise, so it is chainable with then/catch.
2600
+ catch: () => new Promise(noop)
2601
+ };
2602
+ const _queryNone = (q) => {
2603
+ if (isQueryNone(q))
2604
+ return q;
2605
+ q = extendQuery(q, noneMethods);
2606
+ pushQueryValue(q, "and", new RawSQL("false"));
2607
+ return q;
2608
+ };
2609
+ const isQueryNone = (q) => q.then === noneMethods.then;
2610
+
2594
2611
  var __defProp$b = Object.defineProperty;
2595
2612
  var __defProps$3 = Object.defineProperties;
2596
2613
  var __getOwnPropDescs$3 = Object.getOwnPropertyDescriptors;
@@ -2610,36 +2627,39 @@ var __spreadValues$b = (a, b) => {
2610
2627
  return a;
2611
2628
  };
2612
2629
  var __spreadProps$3 = (a, b) => __defProps$3(a, __getOwnPropDescs$3(b));
2613
- const _join = (q, require2, type, first, args) => {
2630
+ const _join = (query, require2, type, first, args) => {
2614
2631
  var _a, _b;
2615
2632
  let joinKey;
2616
2633
  let shape;
2617
2634
  let parsers;
2618
2635
  let joinSubQuery = false;
2619
2636
  if (typeof first === "function") {
2620
- first = first(q.relations);
2637
+ first = first(query.relations);
2621
2638
  first.joinQueryAfterCallback = first.joinQuery;
2622
2639
  }
2623
2640
  if (typeof first === "object") {
2624
- const q2 = first;
2625
- joinSubQuery = getIsJoinSubQuery(q2);
2626
- joinKey = q2.q.as || q2.table;
2641
+ if (require2 && isQueryNone(first)) {
2642
+ return _queryNone(query);
2643
+ }
2644
+ const q = first;
2645
+ joinSubQuery = getIsJoinSubQuery(q);
2646
+ joinKey = q.q.as || q.table;
2627
2647
  if (joinKey) {
2628
- shape = getShapeFromSelect(q2, joinSubQuery);
2629
- parsers = q2.q.parsers;
2648
+ shape = getShapeFromSelect(q, joinSubQuery);
2649
+ parsers = q.q.parsers;
2630
2650
  if (joinSubQuery) {
2631
- first = q2.clone();
2651
+ first = q.clone();
2632
2652
  first.shape = shape;
2633
2653
  }
2634
2654
  }
2635
2655
  } else {
2636
2656
  joinKey = first;
2637
- const relation = q.relations[joinKey];
2657
+ const relation = query.relations[joinKey];
2638
2658
  if (relation) {
2639
2659
  shape = getShapeFromSelect(relation.relationConfig.query);
2640
2660
  parsers = relation.relationConfig.query.q.parsers;
2641
2661
  } else {
2642
- shape = (_a = q.q.withShapes) == null ? void 0 : _a[joinKey];
2662
+ shape = (_a = query.q.withShapes) == null ? void 0 : _a[joinKey];
2643
2663
  if (shape) {
2644
2664
  if (!require2)
2645
2665
  shape = __spreadValues$b({}, shape);
@@ -2655,20 +2675,20 @@ const _join = (q, require2, type, first, args) => {
2655
2675
  }
2656
2676
  if (joinKey) {
2657
2677
  setQueryObjectValue(
2658
- q,
2678
+ query,
2659
2679
  "joinedShapes",
2660
2680
  joinKey,
2661
2681
  shape
2662
2682
  );
2663
2683
  setQueryObjectValue(
2664
- q,
2684
+ query,
2665
2685
  "joinedParsers",
2666
2686
  joinKey,
2667
2687
  parsers
2668
2688
  );
2669
2689
  }
2670
2690
  const joinArgs = processJoinArgs(
2671
- q,
2691
+ query,
2672
2692
  first,
2673
2693
  args,
2674
2694
  joinSubQuery
@@ -2678,20 +2698,22 @@ const _join = (q, require2, type, first, args) => {
2678
2698
  if (j.q.select || !j.internal.columnsForSelectAll) {
2679
2699
  const shape2 = getShapeFromSelect(j, true);
2680
2700
  setQueryObjectValue(
2681
- q,
2701
+ query,
2682
2702
  "joinedShapes",
2683
2703
  joinKey,
2684
2704
  shape2
2685
2705
  );
2686
2706
  setQueryObjectValue(
2687
- q,
2707
+ query,
2688
2708
  "joinedParsers",
2689
2709
  joinKey,
2690
2710
  j.q.parsers
2691
2711
  );
2692
2712
  }
2713
+ } else if (require2 && "r" in joinArgs && isQueryNone(joinArgs.r)) {
2714
+ return _queryNone(query);
2693
2715
  }
2694
- return pushQueryValue(q, "join", {
2716
+ return pushQueryValue(query, "join", {
2695
2717
  type,
2696
2718
  args: joinArgs
2697
2719
  });
@@ -3326,6 +3348,26 @@ const addParserForSelectItem = (q, as, key, arg) => {
3326
3348
  );
3327
3349
  });
3328
3350
  }
3351
+ if (query.returnType === "valueOrThrow" || query.returnType === "oneOrThrow") {
3352
+ pushQueryValue(
3353
+ q,
3354
+ "transform",
3355
+ (data) => {
3356
+ if (Array.isArray(data)) {
3357
+ for (const item of data) {
3358
+ if (item[key] === void 0) {
3359
+ throw new NotFoundError(q);
3360
+ }
3361
+ }
3362
+ } else {
3363
+ if (data[key] === void 0) {
3364
+ throw new NotFoundError(q);
3365
+ }
3366
+ }
3367
+ return data;
3368
+ }
3369
+ );
3370
+ }
3329
3371
  }
3330
3372
  return arg;
3331
3373
  }
@@ -3342,7 +3384,11 @@ const processSelectArg = (q, as, arg, columnAs) => {
3342
3384
  let value = arg[key];
3343
3385
  if (typeof value === "function") {
3344
3386
  value = resolveSubQueryCallback(q, value);
3345
- if (!isExpression(value) && value.joinQuery) {
3387
+ if (isQueryNone(value)) {
3388
+ if (value.q.innerJoinLateral) {
3389
+ return;
3390
+ }
3391
+ } else if (!isExpression(value) && value.joinQuery) {
3346
3392
  value = value.joinQuery(value, q);
3347
3393
  let query;
3348
3394
  const returnType = value.q.returnType;
@@ -3499,11 +3545,18 @@ const maybeUnNameColumn = (column, isSubQuery) => {
3499
3545
  return isSubQuery && (column == null ? void 0 : column.data.name) ? setColumnData(column, "name", void 0) : column;
3500
3546
  };
3501
3547
  function _querySelect(q, args) {
3502
- if (!args.length) {
3548
+ const len = args.length;
3549
+ if (!len) {
3503
3550
  return q;
3504
3551
  }
3505
3552
  const as = q.q.as || q.table;
3506
- const selectArgs = args.map((item) => processSelectArg(q, as, item));
3553
+ const selectArgs = new Array(len);
3554
+ for (let i = 0; i < len; i++) {
3555
+ selectArgs[i] = processSelectArg(q, as, args[i]);
3556
+ if (!selectArgs[i]) {
3557
+ return _queryNone(q);
3558
+ }
3559
+ }
3507
3560
  return pushQueryArray(q, "select", selectArgs);
3508
3561
  }
3509
3562
  class Select {
@@ -3853,7 +3906,37 @@ const selectAllSql = (table, query, quotedAs) => {
3853
3906
  return ((_a = query.join) == null ? void 0 : _a.length) ? ((_b = table.internal.columnsForSelectAll) == null ? void 0 : _b.map((item) => `${quotedAs}.${item}`).join(", ")) || `${quotedAs}.*` : ((_c = table.internal.columnsForSelectAll) == null ? void 0 : _c.join(", ")) || "*";
3854
3907
  };
3855
3908
  const pushSubQuerySql = (ctx, query, as, list, quotedAs) => {
3909
+ var _a;
3856
3910
  const { returnType = "all" } = query.q;
3911
+ if (isQueryNone(query)) {
3912
+ let sql;
3913
+ switch (returnType) {
3914
+ case "one":
3915
+ case "oneOrThrow":
3916
+ case "void":
3917
+ return;
3918
+ case "value":
3919
+ case "valueOrThrow":
3920
+ if (((_a = query.q.expr) == null ? void 0 : _a.result.value) instanceof IntegerBaseColumn) {
3921
+ sql = "0";
3922
+ } else {
3923
+ return;
3924
+ }
3925
+ break;
3926
+ case "all":
3927
+ case "pluck":
3928
+ case "rows":
3929
+ sql = `'[]'::json`;
3930
+ break;
3931
+ case "rowCount":
3932
+ sql = "0";
3933
+ break;
3934
+ default:
3935
+ throw new UnhandledTypeError(query, returnType);
3936
+ }
3937
+ list.push(`${sql} "${as}"`);
3938
+ return;
3939
+ }
3857
3940
  if (query.q.joinedForSelect) {
3858
3941
  let sql;
3859
3942
  switch (returnType) {
@@ -6272,7 +6355,7 @@ class Create {
6272
6355
  *
6273
6356
  * await db.table.create({
6274
6357
  * // raw SQL
6275
- * column1: sql`'John' || ' ' || 'Doe'`,
6358
+ * column1: (q) => q.sql`'John' || ' ' || 'Doe'`,
6276
6359
  *
6277
6360
  * // query that returns a single value
6278
6361
  * // returning multiple values will result in Postgres error
@@ -6507,6 +6590,7 @@ class Create {
6507
6590
  * db.table.create(data).onConflictDoNothing();
6508
6591
  *
6509
6592
  * // single column:
6593
+ * // (this requires a composite primary key or unique index, see below)
6510
6594
  * db.table.create(data).onConfict('email').merge();
6511
6595
  *
6512
6596
  * // array of columns:
@@ -6522,6 +6606,34 @@ class Create {
6522
6606
  * .merge();
6523
6607
  * ```
6524
6608
  *
6609
+ * :::info
6610
+ * A primary key or a unique index for a **single** column can be fined on a column:
6611
+ *
6612
+ * ```ts
6613
+ * export class MyTable extends BaseTable {
6614
+ * columns = this.setColumns((t) => ({
6615
+ * pkey: t.uuid().primaryKey(),
6616
+ * unique: t.string().unique(),
6617
+ * }));
6618
+ * }
6619
+ * ```
6620
+ *
6621
+ * But for composite primary keys or indexes (having multiple columns), define it in a separate function:
6622
+ *
6623
+ * ```ts
6624
+ * export class MyTable extends BaseTable {
6625
+ * columns = this.setColumns(
6626
+ * (t) => ({
6627
+ * one: t.integer(),
6628
+ * two: t.string(),
6629
+ * three: t.boolean(),
6630
+ * }),
6631
+ * (t) => [t.primaryKey(['one', 'two']), t.unique(['two', 'three'])],
6632
+ * );
6633
+ * }
6634
+ * ```
6635
+ * :::
6636
+ *
6525
6637
  * You can use the `sql` function exported from your `BaseTable` file in onConflict.
6526
6638
  * It can be useful to specify a condition when you have a partial index:
6527
6639
  *
@@ -8429,6 +8541,9 @@ const _queryOrNot = (q, args) => {
8429
8541
  const _queryWhereIn = (q, and, arg, values, not) => {
8430
8542
  let item;
8431
8543
  if (values) {
8544
+ if ("length" in values && !values.length) {
8545
+ return _queryNone(q);
8546
+ }
8432
8547
  if (Array.isArray(arg)) {
8433
8548
  item = {
8434
8549
  IN: {
@@ -8442,7 +8557,11 @@ const _queryWhereIn = (q, and, arg, values, not) => {
8442
8557
  } else {
8443
8558
  item = {};
8444
8559
  for (const key in arg) {
8445
- item[key] = { in: arg[key] };
8560
+ const values2 = arg[key];
8561
+ if ("length" in values2 && !values2.length) {
8562
+ return _queryNone(q);
8563
+ }
8564
+ item[key] = { in: values2 };
8446
8565
  }
8447
8566
  }
8448
8567
  if (not)
@@ -8991,6 +9110,15 @@ class Where {
8991
9110
  * ```ts
8992
9111
  * db.table.whereIn(['id', 'name'], sql`((1, 'one'), (2, 'two'))`);
8993
9112
  * ```
9113
+ *
9114
+ * When empty set of values is given, `whereIn` will resolve into a {@link QueryMethods.none} query that has a special behavior.
9115
+ *
9116
+ * ```ts
9117
+ * // following queries resolves into `none`:
9118
+ * db.table.where('id', [])
9119
+ * db.table.where(['id', 'name'], [])
9120
+ * db.table.where({ id: [] })
9121
+ * ```
8994
9122
  */
8995
9123
  whereIn(...args) {
8996
9124
  return _queryWhereIn(
@@ -9303,7 +9431,7 @@ class Update {
9303
9431
  * column1: 123,
9304
9432
  *
9305
9433
  * // use raw SQL to update the column
9306
- * column2: sql`2 + 2`,
9434
+ * column2: (q) => q.sql`2 + 2`,
9307
9435
  *
9308
9436
  * // use query that returns a single value
9309
9437
  * // returning multiple values will result in Postgres error
@@ -9417,7 +9545,7 @@ class Update {
9417
9545
  );
9418
9546
  }
9419
9547
  /**
9420
- * `updateRaw` is for updating records with raw expression.
9548
+ * `updateSql` is for updating records with raw expression.
9421
9549
  *
9422
9550
  * The behavior is the same as a regular `update` method has:
9423
9551
  * `find` or `where` must precede calling this method,
@@ -9428,14 +9556,14 @@ class Update {
9428
9556
  * const value = 'new name';
9429
9557
  *
9430
9558
  * // update with SQL template string
9431
- * const updatedCount = await db.table.find(1).updateRaw`name = ${value}`;
9559
+ * const updatedCount = await db.table.find(1).updateSql`name = ${value}`;
9432
9560
  *
9433
9561
  * // or update with `sql` function:
9434
- * await db.table.find(1).updateRaw(sql`name = ${value}`);
9562
+ * await db.table.find(1).updateSql(sql`name = ${value}`);
9435
9563
  * ```
9436
9564
  * @param args - raw SQL via a template string or by using a `sql` method
9437
9565
  */
9438
- updateRaw(...args) {
9566
+ updateSql(...args) {
9439
9567
  return _queryUpdateRaw(
9440
9568
  this.clone(),
9441
9569
  sqlQueryArgsToExpression(args)
@@ -10195,24 +10323,6 @@ class TransformMethods {
10195
10323
  }
10196
10324
  }
10197
10325
 
10198
- const noneMethods = {
10199
- // `then` resolves or rejects based on return type of the query.
10200
- // It is `async` so it returns a chainable Promise.
10201
- async then(resolve, reject) {
10202
- const type = this.q.returnType;
10203
- if (!type || type === "all" || type === "rows" || type === "pluck")
10204
- resolve == null ? void 0 : resolve([]);
10205
- else if (type === "one" || type === "value" || type === "void")
10206
- resolve == null ? void 0 : resolve();
10207
- else if (type === "rowCount")
10208
- resolve == null ? void 0 : resolve(0);
10209
- else
10210
- reject == null ? void 0 : reject(new NotFoundError(this));
10211
- },
10212
- // `catch` returns a Promise, so it is chainable with then/catch.
10213
- catch: () => new Promise(noop)
10214
- };
10215
-
10216
10326
  class ScopeMethods {
10217
10327
  /**
10218
10328
  * See {@link ScopeMethods}
@@ -10996,9 +11106,55 @@ class QueryMethods {
10996
11106
  * await db.table.all().update(data); // -> 0
10997
11107
  * await db.table.all().delete(); // -> 0
10998
11108
  * ```
11109
+ *
11110
+ * When it's being used in sub-selects, it will return empty arrays, `undefined`'s, or `0` for count,
11111
+ * or it will throw if the sub-query require a result:
11112
+ *
11113
+ * ```ts
11114
+ * await db.user.select({
11115
+ * // returns empty array
11116
+ * pets: (q) => q.pets.none(),
11117
+ * // returns `undefined`
11118
+ * firstPet: (q) => q.pets.none().takeOptional(),
11119
+ * // throws NotFound error
11120
+ * requriedFirstPet: (q) => q.pets.none().take(),
11121
+ * // returns `undefined`
11122
+ * firstPetName: (q) => q.pets.none().getOptional('name'),
11123
+ * // throws NotFound error
11124
+ * requiredFirstPetName: (q) => q.pets.none().get('name'),
11125
+ * // returns empty array
11126
+ * petsNames: (q) => q.pets.none().pluck('name'),
11127
+ * // returns 0
11128
+ * petsCount: (q) => q.pets.none().count(),
11129
+ * });
11130
+ * ```
11131
+ *
11132
+ * When the `none` query is being used for joins that require match, the host query will return an empty result:
11133
+ *
11134
+ * ```ts
11135
+ * // all the following queries will resolve into empty arrays
11136
+ *
11137
+ * await db.user.select({
11138
+ * pets: (q) => q.pets.join().none(),
11139
+ * });
11140
+ *
11141
+ * await db.user.join((q) => q.pets.none());
11142
+ *
11143
+ * await db.user.join('pets', (q) => q.none());
11144
+ * ```
11145
+ *
11146
+ * When it's being used in `leftJoin` or `fullJoin`, it implicitly adds `ON false` into the join's SQL.
11147
+ *
11148
+ * ```ts
11149
+ * // this query can return user records
11150
+ * await db.user.leftJoin('pets', (q) => q.none());
11151
+ *
11152
+ * // this query won't return user records, because of the added where condition
11153
+ * await db.user.leftJoin('pets', (q) => q.none()).where({ 'pets.name': 'Kitty' });
11154
+ * ```
10999
11155
  */
11000
11156
  none() {
11001
- return this.then === noneMethods.then ? this : extendQuery(this, noneMethods);
11157
+ return _queryNone(this);
11002
11158
  }
11003
11159
  /**
11004
11160
  * `modify` allows modifying the query with your function: