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