pqb 0.28.0 → 0.29.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
@@ -3365,13 +3365,13 @@ const pushInsertSql = (ctx, q, query, quotedAs) => {
3365
3365
  }
3366
3366
  if (query.onConflict) {
3367
3367
  ctx.sql.push("ON CONFLICT");
3368
- const { expr, type } = query.onConflict;
3369
- if (expr) {
3370
- if (typeof expr === "string") {
3371
- ctx.sql.push(`("${((_b = shape[expr]) == null ? void 0 : _b.data.name) || expr}")`);
3372
- } else if (Array.isArray(expr)) {
3368
+ const { target } = query.onConflict;
3369
+ if (target) {
3370
+ if (typeof target === "string") {
3371
+ ctx.sql.push(`("${((_b = shape[target]) == null ? void 0 : _b.data.name) || target}")`);
3372
+ } else if (Array.isArray(target)) {
3373
3373
  ctx.sql.push(
3374
- `(${expr.reduce(
3374
+ `(${target.reduce(
3375
3375
  (sql, item, i) => {
3376
3376
  var _a2;
3377
3377
  return sql + (i ? ", " : "") + `"${((_a2 = shape[item]) == null ? void 0 : _a2.data.name) || item}"`;
@@ -3379,50 +3379,67 @@ const pushInsertSql = (ctx, q, query, quotedAs) => {
3379
3379
  ""
3380
3380
  )})`
3381
3381
  );
3382
- } else if ("toSQL" in expr) {
3383
- ctx.sql.push(expr.toSQL(ctx, quotedAs));
3382
+ } else if ("toSQL" in target) {
3383
+ ctx.sql.push(target.toSQL(ctx, quotedAs));
3384
3384
  } else {
3385
- ctx.sql.push(`ON CONSTRAINT "${expr.constraint}"`);
3385
+ ctx.sql.push(`ON CONSTRAINT "${target.constraint}"`);
3386
3386
  }
3387
3387
  }
3388
- if (type === "ignore") {
3389
- ctx.sql.push("DO NOTHING");
3390
- } else if (type === "merge") {
3391
- let set;
3392
- const { update } = query.onConflict;
3393
- if (update) {
3394
- if (typeof update === "string") {
3395
- const name = ((_c = shape[update]) == null ? void 0 : _c.data.name) || update;
3396
- set = `"${name}" = excluded."${name}"`;
3397
- } else if (Array.isArray(update)) {
3398
- set = update.reduce((sql, item, i) => {
3388
+ if ("merge" in query.onConflict) {
3389
+ let sql;
3390
+ const { merge } = query.onConflict;
3391
+ if (merge) {
3392
+ if (typeof merge === "string") {
3393
+ const name = ((_c = shape[merge]) == null ? void 0 : _c.data.name) || merge;
3394
+ sql = `"${name}" = excluded."${name}"`;
3395
+ } else if ("except" in merge) {
3396
+ const notExcluded = [];
3397
+ const except = orchidCore.toArray(merge.except);
3398
+ for (let i = 0; i < columns.length; i++) {
3399
+ if (!except.includes(columns[i])) {
3400
+ notExcluded.push(quotedColumns[i]);
3401
+ }
3402
+ }
3403
+ sql = mergeColumnsSql(notExcluded);
3404
+ } else {
3405
+ sql = merge.reduce((sql2, item, i) => {
3399
3406
  var _a2;
3400
3407
  const name = ((_a2 = shape[item]) == null ? void 0 : _a2.data.name) || item;
3401
- return sql + (i ? ", " : "") + `"${name}" = excluded."${name}"`;
3408
+ return sql2 + (i ? ", " : "") + `"${name}" = excluded."${name}"`;
3402
3409
  }, "");
3403
- } else if (orchidCore.isExpression(update)) {
3404
- set = update.toSQL(ctx, quotedAs);
3405
- } else {
3406
- const arr = [];
3407
- for (const key in update) {
3408
- arr.push(
3409
- `"${((_d = shape[key]) == null ? void 0 : _d.data.name) || key}" = ${addValue(
3410
- ctx.values,
3411
- update[key]
3412
- )}`
3413
- );
3414
- }
3415
- set = arr.join(", ");
3416
3410
  }
3417
3411
  } else {
3418
- set = quotedColumns.map((column) => `${column} = excluded.${column}`).join(", ");
3412
+ sql = mergeColumnsSql(quotedColumns);
3413
+ }
3414
+ ctx.sql.push("DO UPDATE SET", sql);
3415
+ } else if (query.onConflict.set) {
3416
+ let sql;
3417
+ const { set } = query.onConflict;
3418
+ if (orchidCore.isExpression(set)) {
3419
+ sql = set.toSQL(ctx, quotedAs);
3420
+ } else {
3421
+ const arr = [];
3422
+ for (const key in set) {
3423
+ arr.push(
3424
+ `"${((_d = shape[key]) == null ? void 0 : _d.data.name) || key}" = ${addValue(
3425
+ ctx.values,
3426
+ set[key]
3427
+ )}`
3428
+ );
3429
+ }
3430
+ sql = arr.join(", ");
3419
3431
  }
3420
- ctx.sql.push("DO UPDATE SET", set);
3432
+ ctx.sql.push("DO UPDATE SET", sql);
3433
+ } else {
3434
+ ctx.sql.push("DO NOTHING");
3421
3435
  }
3422
3436
  }
3423
3437
  pushWhereStatementSql(ctx, q, query, quotedAs);
3424
3438
  return pushReturningSql(ctx, q, query, quotedAs, query.afterCreateSelect);
3425
3439
  };
3440
+ const mergeColumnsSql = (quotedColumns2) => {
3441
+ return quotedColumns2.map((column) => `${column} = excluded.${column}`).join(", ");
3442
+ };
3426
3443
  const encodeRow = (ctx, q, QueryClass, row, runtimeDefaults, quotedAs) => {
3427
3444
  const arr = row.map((value) => {
3428
3445
  if (typeof value === "function") {
@@ -6239,9 +6256,9 @@ class Create {
6239
6256
  * password: '1234',
6240
6257
  * });
6241
6258
  *
6242
- * // When using `.onConflictIgnore()`,
6259
+ * // When using `.onConflictDoNothing()`,
6243
6260
  * // the record may be not created and the `createdCount` will be 0.
6244
- * const createdCount = await db.table.insert(data).onConflictIgnore();
6261
+ * const createdCount = await db.table.insert(data).onConflictDoNothing();
6245
6262
  *
6246
6263
  * await db.table.create({
6247
6264
  * // raw SQL
@@ -6434,7 +6451,7 @@ class Create {
6434
6451
  *
6435
6452
  * Columns provided in `defaults` are marked as optional in the following `create`.
6436
6453
  *
6437
- * Default data is the same as in [create](#create) and [createMany](#createMany),
6454
+ * Default data is the same as in {@link create} and {@link createMany},
6438
6455
  * so you can provide a raw SQL, or a query with a query.
6439
6456
  *
6440
6457
  * ```ts
@@ -6462,8 +6479,9 @@ class Create {
6462
6479
  * or a composite primary key unique index on a set of columns,
6463
6480
  * and a row being created has the same value as a row that already exists in the table in this column(s).
6464
6481
  *
6465
- * Use `onConflictIgnore()` to suppress the error and continue without updating the record,
6466
- * or `onConflict(['uniqueColumn']).merge()` to update the record with a new data.
6482
+ * Use {@link onConflictDoNothing} to suppress the error and continue without updating the record,
6483
+ * or the `merge` to update the record with new values automatically,
6484
+ * or the `set` to specify own values for the update.
6467
6485
  *
6468
6486
  * `onConflict` only accepts column names that are defined in `primaryKey` or `unique` in the table definition.
6469
6487
  * To specify a constraint, its name also must be explicitly set in `primaryKey` or `unique` in the table code.
@@ -6472,11 +6490,11 @@ class Create {
6472
6490
  * for updating the record.
6473
6491
  *
6474
6492
  * If your table has multiple potential reasons for unique constraint violation, such as username and email columns in a user table,
6475
- * consider using [upsert](#upsert) instead.
6493
+ * consider using `upsert` instead.
6476
6494
  *
6477
6495
  * ```ts
6478
6496
  * // leave `onConflict` without argument to ignore or merge on any conflict
6479
- * db.table.create(data).onConflictIgnore();
6497
+ * db.table.create(data).onConflictDoNothing();
6480
6498
  *
6481
6499
  * // single column:
6482
6500
  * db.table.create(data).onConfict('email').merge();
@@ -6509,13 +6527,28 @@ class Create {
6509
6527
  * .ignore();
6510
6528
  * ```
6511
6529
  *
6530
+ * For `merge` and `set`, you can append `where` to update data only for the matching rows:
6531
+ *
6532
+ * ```ts
6533
+ * const timestamp = Date.now();
6534
+ *
6535
+ * db.table
6536
+ * .create(data)
6537
+ * .onConflict('email')
6538
+ * .set({
6539
+ * name: 'John Doe',
6540
+ * updatedAt: timestamp,
6541
+ * })
6542
+ * .where({ updatedAt: { lt: timestamp } });
6543
+ * ```
6544
+ *
6512
6545
  * @param arg - optionally provide an array of columns
6513
6546
  */
6514
6547
  onConflict(arg) {
6515
6548
  return new OnConflictQueryBuilder(this, arg);
6516
6549
  }
6517
6550
  /**
6518
- * Use `onConflictIgnore` to suppress unique constraint violation error when creating a record.
6551
+ * Use `onConflictDoNothing` to suppress unique constraint violation error when creating a record.
6519
6552
  *
6520
6553
  * Adds `ON CONFLICT (columns) DO NOTHING` clause to the insert statement, columns are optional.
6521
6554
  *
@@ -6528,38 +6561,37 @@ class Create {
6528
6561
  * name: 'John Doe',
6529
6562
  * })
6530
6563
  * // on any conflict:
6531
- * .onConflictIgnore()
6564
+ * .onConflictDoNothing()
6532
6565
  * // or, for a specific column:
6533
- * .onConflictIgnore('email')
6566
+ * .onConflictDoNothing('email')
6534
6567
  * // or, for a specific constraint:
6535
- * .onConflictIgnore({ constraint: 'unique_index_name' });
6568
+ * .onConflictDoNothing({ constraint: 'unique_index_name' });
6536
6569
  * ```
6537
6570
  *
6538
- * When there is a conflict, nothing can be returned from the database, so `onConflictIgnore` adds `| undefined` part to the response type.
6571
+ * When there is a conflict, nothing can be returned from the database, so `onConflictDoNothing` adds `| undefined` part to the response type.
6539
6572
  *
6540
6573
  * ```ts
6541
6574
  * const maybeRecord: RecordType | undefined = await db.table
6542
6575
  * .create(data)
6543
- * .onConflictIgnore();
6576
+ * .onConflictDoNothing();
6544
6577
  *
6545
6578
  * const maybeId: number | undefined = await db.table
6546
6579
  * .get('id')
6547
6580
  * .create(data)
6548
- * .onConflictIgnore();
6581
+ * .onConflictDoNothing();
6549
6582
  * ```
6550
6583
  *
6551
6584
  * When creating multiple records, only created records will be returned. If no records were created, array will be empty:
6552
6585
  *
6553
6586
  * ```ts
6554
6587
  * // array can be empty
6555
- * const arr = await db.table.createMany([data, data, data]).onConflictIgnore();
6588
+ * const arr = await db.table.createMany([data, data, data]).onConflictDoNothing();
6556
6589
  * ```
6557
6590
  */
6558
- onConflictIgnore(arg) {
6591
+ onConflictDoNothing(arg) {
6559
6592
  const q = this.clone();
6560
6593
  q.q.onConflict = {
6561
- type: "ignore",
6562
- expr: arg
6594
+ target: arg
6563
6595
  };
6564
6596
  if (q.q.returnType === "oneOrThrow") {
6565
6597
  q.q.returnType = "one";
@@ -6575,112 +6607,83 @@ class OnConflictQueryBuilder {
6575
6607
  this.onConflict = onConflict;
6576
6608
  }
6577
6609
  /**
6578
- * Available only after [onConflict](#onconflict).
6610
+ * Available only after `onConflict`.
6579
6611
  *
6580
- * Adds an `ON CONFLICT (columns) DO UPDATE` clause to the insert statement.
6612
+ * Updates the record with a given data when conflict occurs.
6581
6613
  *
6582
6614
  * ```ts
6583
- * db.table
6584
- * .create({
6585
- * email: 'ignore@example.com',
6586
- * name: 'John Doe',
6587
- * })
6588
- * // for a specific column:
6589
- * .onConflict('email')
6590
- * // or, for a specific constraint:
6591
- * .onConflict({ constraint: 'unique_constraint_name' })
6592
- * .merge();
6615
+ * db.table.create(data).onConflict('column').set({
6616
+ * description: 'setting different data on conflict',
6617
+ * });
6593
6618
  * ```
6594
6619
  *
6595
- * This also works with batch creates:
6620
+ * The `set` can take a raw SQL expression:
6596
6621
  *
6597
6622
  * ```ts
6598
6623
  * db.table
6599
- * .createMany([
6600
- * { email: 'john@example.com', name: 'John Doe' },
6601
- * { email: 'jane@example.com', name: 'Jane Doe' },
6602
- * { email: 'alex@example.com', name: 'Alex Doe' },
6603
- * ])
6604
- * .onConflict('email')
6605
- * .merge();
6606
- * ```
6607
- *
6608
- * It is also possible to specify a subset of the columns to merge when a conflict occurs.
6609
- * For example, you may want to set a `createdAt` column when creating but would prefer not to update it if the row already exists:
6610
- *
6611
- * ```ts
6612
- * const timestamp = Date.now();
6624
+ * .create(data)
6625
+ * .onConflict()
6626
+ * .set(db.table.sql`raw SQL expression`);
6613
6627
  *
6628
+ * // update records only on certain conditions
6614
6629
  * db.table
6615
- * .create({
6616
- * email: 'ignore@example.com',
6617
- * name: 'John Doe',
6618
- * createdAt: timestamp,
6619
- * updatedAt: timestamp,
6620
- * })
6630
+ * .create(data)
6621
6631
  * .onConflict('email')
6622
- * // update only a single column
6623
- * .merge('email')
6624
- * // or, update multiple columns
6625
- * .merge(['email', 'name', 'updatedAt']);
6632
+ * .set({ key: 'value' })
6633
+ * .where({ ...certainConditions });
6626
6634
  * ```
6627
6635
  *
6628
- * It's possible to specify data to update separately from the data to create.
6629
- * This is useful if you want to make an update with different data than in creating.
6630
- * For example, changing a value if the row already exists:
6636
+ * @param set - object containing new column values, or raw SQL
6637
+ */
6638
+ set(set) {
6639
+ this.query.q.onConflict = {
6640
+ target: this.onConflict,
6641
+ set
6642
+ };
6643
+ return this.query;
6644
+ }
6645
+ /**
6646
+ * Available only after `onConflict`.
6631
6647
  *
6632
- * ```ts
6633
- * const timestamp = Date.now();
6648
+ * Use this method to merge all the data you have passed into `create` to update the existing record on conflict.
6634
6649
  *
6635
- * db.table
6636
- * .create({
6637
- * email: 'ignore@example.com',
6638
- * name: 'John Doe',
6639
- * createdAt: timestamp,
6640
- * updatedAt: timestamp,
6641
- * })
6642
- * .onConflict('email')
6643
- * .merge({
6644
- * name: 'John Doe The Second',
6645
- * });
6646
- * ```
6650
+ * If the table has columns with **dynamic** default values, such values will be applied as well.
6647
6651
  *
6648
- * You can use `where` to update only the matching rows:
6652
+ * You can exclude certain columns from being merged by passing the `exclude` option.
6649
6653
  *
6650
6654
  * ```ts
6651
- * const timestamp = Date.now();
6655
+ * // merge the full data
6656
+ * db.table.create(data).onConflict('email').merge();
6652
6657
  *
6658
+ * // merge only a single column
6659
+ * db.table.create(data).onConflict('email').merge('name');
6660
+ *
6661
+ * // merge multiple columns
6662
+ * db.table.create(data).onConflict('email').merge(['name', 'quantity']);
6663
+ *
6664
+ * // merge all columns except some
6653
6665
  * db.table
6654
- * .create({
6655
- * email: 'ignore@example.com',
6656
- * name: 'John Doe',
6657
- * createdAt: timestamp,
6658
- * updatedAt: timestamp,
6659
- * })
6666
+ * .create(data)
6660
6667
  * .onConflict('email')
6661
- * .merge({
6662
- * name: 'John Doe',
6663
- * updatedAt: timestamp,
6664
- * })
6665
- * .where({ updatedAt: { lt: timestamp } });
6666
- * ```
6668
+ * .merge({ except: ['name', 'quantity'] });
6667
6669
  *
6668
- * `merge` can take a raw SQL expression:
6670
+ * // merge can be applied also for batch creates
6671
+ * db.table.createMany([data1, data2, data2]).onConflict('email').merge();
6669
6672
  *
6670
- * ```ts
6673
+ * // update records only on certain conditions
6671
6674
  * db.table
6672
6675
  * .create(data)
6673
- * .onConflict()
6674
- * .merge(db.table.sql`raw SQL expression`);
6676
+ * .onConflict('email')
6677
+ * .merge()
6678
+ * .where({ ...certainConditions });
6675
6679
  * ```
6676
6680
  *
6677
- * @param update - column, or array of columns, or object for new column values, or raw SQL
6681
+ * @param merge - no argument will merge all data, or provide a column(s) to merge, or provide `except` to update all except some.
6678
6682
  */
6679
- merge(update) {
6683
+ merge(merge) {
6680
6684
  this.query.q.onConflict = {
6681
- type: "merge",
6682
- expr: this.onConflict,
6683
- update
6685
+ target: this.onConflict,
6686
+ merge
6684
6687
  };
6685
6688
  return this.query;
6686
6689
  }