pqb 0.54.1 → 0.54.3

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, templateLiteralSQLToCode, quoteObjectKey, toArray, emptyArray, singleQuote, addCode, singleQuoteArray, objectHasValues, toSnakeCase, columnDefaultArgumentToCode, columnErrorMessagesToCode, setObjectValueImmutable, getValueKey, addValue, isExpression, dateDataToCode, joinTruthy, arrayDataToCode, numberDataToCode, noop, stringDataToCode, getDefaultLanguage, setDefaultNowFn, setDefaultLanguage, setCurrentColumnName, timestampHelpers, returnArg as returnArg$1, pushOrNewArrayToObjectImmutable, logColors, applyTransforms, callWithThis, setParserToQuery, pushOrNewArray, isRawSQL, setAdapterConnectRetry, isObjectEmpty, ValExpression, applyMixins, snakeCaseKey } from 'orchid-core';
1
+ import { ExpressionTypeMethod, Expression, RawSQLBase, emptyObject, isTemplateLiteralArgs, ColumnTypeBase, setColumnData, pushColumnData, templateLiteralSQLToCode, quoteObjectKey, toArray, emptyArray, singleQuote, addCode, singleQuoteArray, objectHasValues, toSnakeCase, columnDefaultArgumentToCode, columnErrorMessagesToCode, setObjectValueImmutable, getValueKey, addValue, isExpression, dateDataToCode, joinTruthy, arrayDataToCode, numberDataToCode, noop, stringDataToCode, getDefaultLanguage, setDefaultNowFn, setDefaultLanguage, setCurrentColumnName, timestampHelpers, returnArg as returnArg$1, pushQueryValueImmutable, logColors, applyTransforms, callWithThis, setParserToQuery, pushOrNewArray, isRawSQL, setAdapterConnectRetry, pushOrNewArrayToObjectImmutable, QueryHookUtils, isObjectEmpty, ValExpression, applyMixins, 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';
@@ -430,7 +430,7 @@ class ColumnType extends ColumnTypeBase {
430
430
  return sql2;
431
431
  }
432
432
  });
433
- column.data.readonly = true;
433
+ column.data.readOnly = true;
434
434
  return column;
435
435
  }
436
436
  }
@@ -2156,7 +2156,7 @@ class TsVectorColumn extends ColumnType {
2156
2156
  toSQL,
2157
2157
  toCode
2158
2158
  });
2159
- column.data.readonly = true;
2159
+ column.data.readOnly = true;
2160
2160
  return column;
2161
2161
  }
2162
2162
  }
@@ -2456,8 +2456,7 @@ class VirtualColumn extends ColumnType {
2456
2456
  super(schema, inputSchema);
2457
2457
  this.dataType = "";
2458
2458
  this.operators = Operators.any;
2459
- this.data.explicitSelect = true;
2460
- this.data.insertable = this.data.updatable = false;
2459
+ this.data.explicitSelect = this.data.appReadOnly = this.data.virtual = true;
2461
2460
  }
2462
2461
  toCode() {
2463
2462
  throw new Error(`toCode is not implemented for virtual column`);
@@ -2468,8 +2467,7 @@ const _UnknownColumn = class _UnknownColumn extends VirtualColumn {
2468
2467
  constructor(schema) {
2469
2468
  super(schema, schema.unknown());
2470
2469
  this.selectable = true;
2471
- this.data.explicitSelect = void 0;
2472
- this.data.insertable = this.data.updatable = true;
2470
+ this.data.explicitSelect = this.data.appReadOnly = this.data.virtual = void 0;
2473
2471
  }
2474
2472
  };
2475
2473
  _UnknownColumn.instance = new _UnknownColumn(defaultSchemaConfig);
@@ -2728,8 +2726,9 @@ class NotFoundError extends OrchidOrmError {
2728
2726
  }
2729
2727
  _query = new WeakMap();
2730
2728
  class OrchidOrmInternalError extends Error {
2731
- constructor(query, message) {
2729
+ constructor(query, message, data) {
2732
2730
  super(message);
2731
+ this.data = data;
2733
2732
  // `#query` is private to prevent it from serializing to not cause problems to test runner reports
2734
2733
  __privateAdd(this, _query2);
2735
2734
  __privateSet(this, _query2, query);
@@ -3403,11 +3402,7 @@ const resolveCallbacksInArgs = (q, args) => {
3403
3402
  };
3404
3403
  const _queryWhere = (q, args) => {
3405
3404
  resolveCallbacksInArgs(q, args);
3406
- return pushQueryArrayImmutable(
3407
- q,
3408
- "and",
3409
- args
3410
- );
3405
+ return pushQueryArrayImmutable(q, "and", args);
3411
3406
  };
3412
3407
  const _queryFindBy = (q, args) => {
3413
3408
  return _queryTake(_queryWhere(q, args));
@@ -4297,10 +4292,6 @@ const pushQueryArrayImmutable = (q, key, value) => {
4297
4292
  q.q[key] = arr ? [...arr, ...value] : value;
4298
4293
  return q;
4299
4294
  };
4300
- const pushQueryValueImmutable = (q, key, value) => {
4301
- pushOrNewArrayToObjectImmutable(q.q, key, value);
4302
- return q;
4303
- };
4304
4295
  const setQueryObjectValueImmutable = (q, object, key, value) => {
4305
4296
  q.q[object] = {
4306
4297
  ...q.q[object],
@@ -4984,7 +4975,7 @@ const applyComputedColumns = (q, fn) => {
4984
4975
  const { data } = col;
4985
4976
  data.computed = item;
4986
4977
  data.explicitSelect = true;
4987
- data.readonly = true;
4978
+ data.readOnly = true;
4988
4979
  addColumnParserToQuery(
4989
4980
  q.q,
4990
4981
  key,
@@ -8823,36 +8814,48 @@ const processCreateItem = (q, item, rowIndex, ctx, encoders) => {
8823
8814
  var _a;
8824
8815
  const { shape } = q.q;
8825
8816
  for (const key in item) {
8826
- if (shape[key]?.data.insertable !== false) {
8827
- let value = item[key];
8828
- if (typeof value === "function") {
8829
- value = item[key] = resolveSubQueryCallbackV2(
8830
- q,
8831
- value
8832
- );
8833
- if (value && typeof value === "object" && value instanceof Db) {
8834
- moveQueryValueToWith(
8835
- q,
8836
- (_a = q.q).insertWith ?? (_a.insertWith = {}),
8837
- value,
8838
- item,
8839
- key,
8840
- rowIndex
8841
- );
8842
- }
8843
- }
8844
- if (!ctx.columns.has(key) && (shape[key] && !shape[key].data.readonly || shape === anyShape) && value !== void 0) {
8845
- ctx.columns.set(key, ctx.columns.size);
8846
- encoders[key] = shape[key]?.data.encode;
8847
- }
8848
- } else if (shape[key] instanceof VirtualColumn) {
8849
- shape[key].create?.(
8817
+ const column = shape[key];
8818
+ if (!column) continue;
8819
+ if (column.data.virtual) {
8820
+ column.create?.(
8850
8821
  q,
8851
8822
  ctx,
8852
8823
  item,
8853
8824
  rowIndex
8854
8825
  );
8826
+ continue;
8855
8827
  }
8828
+ throwOnReadOnly$1(q, column, key);
8829
+ let value = item[key];
8830
+ if (typeof value === "function") {
8831
+ value = item[key] = resolveSubQueryCallbackV2(
8832
+ q,
8833
+ value
8834
+ );
8835
+ if (value && typeof value === "object" && value instanceof Db) {
8836
+ moveQueryValueToWith(
8837
+ q,
8838
+ (_a = q.q).insertWith ?? (_a.insertWith = {}),
8839
+ value,
8840
+ item,
8841
+ key,
8842
+ rowIndex
8843
+ );
8844
+ }
8845
+ }
8846
+ if (!ctx.columns.has(key) && (column && !column.data.readOnly || shape === anyShape) && value !== void 0) {
8847
+ ctx.columns.set(key, ctx.columns.size);
8848
+ encoders[key] = column?.data.encode;
8849
+ }
8850
+ }
8851
+ };
8852
+ const throwOnReadOnly$1 = (q, column, key) => {
8853
+ if (column.data.appReadOnly || column.data.readOnly) {
8854
+ throw new OrchidOrmInternalError(
8855
+ q,
8856
+ "Trying to insert a readonly column",
8857
+ { column: key }
8858
+ );
8856
8859
  }
8857
8860
  };
8858
8861
  const createCtx = () => ({
@@ -8928,7 +8931,7 @@ const insert = (self, {
8928
8931
  }
8929
8932
  return self;
8930
8933
  };
8931
- const getFromSelectColumns = (from, obj, many) => {
8934
+ const getFromSelectColumns = (q, from, obj, many) => {
8932
8935
  if (!many && !queryTypeWithLimitOne[from.q.returnType]) {
8933
8936
  throw new Error(
8934
8937
  "Cannot create based on a query which returns multiple records"
@@ -8946,12 +8949,16 @@ const getFromSelectColumns = (from, obj, many) => {
8946
8949
  if (obj?.columns) {
8947
8950
  queryColumns.push(...obj.columns);
8948
8951
  }
8952
+ for (const key of queryColumns) {
8953
+ const column = q.shape[key];
8954
+ if (column) throwOnReadOnly$1(from, column, key);
8955
+ }
8949
8956
  return queryColumns;
8950
8957
  };
8951
8958
  const insertFromQuery = (q, from, many, data) => {
8952
8959
  const ctx = createCtx();
8953
8960
  const obj = data && handleOneData(q, data, ctx);
8954
- const columns = getFromSelectColumns(from, obj, many);
8961
+ const columns = getFromSelectColumns(q, from, obj, many);
8955
8962
  return insert(
8956
8963
  q,
8957
8964
  {
@@ -8970,7 +8977,7 @@ const _queryInsert = (q, data) => {
8970
8977
  const obj = handleOneData(q, data, ctx);
8971
8978
  const values = q.q.values;
8972
8979
  if (values && "from" in values) {
8973
- obj.columns = getFromSelectColumns(values.from, obj);
8980
+ obj.columns = getFromSelectColumns(q, values.from, obj);
8974
8981
  values.values = obj.values[0];
8975
8982
  obj.values = values;
8976
8983
  }
@@ -9004,7 +9011,7 @@ const _queryDefaults = (q, data) => {
9004
9011
  q.q.defaults = data;
9005
9012
  return q;
9006
9013
  };
9007
- class Create {
9014
+ class QueryCreate {
9008
9015
  /**
9009
9016
  * `create` and `insert` create a single record.
9010
9017
  *
@@ -9408,6 +9415,8 @@ class OnConflictQueryBuilder {
9408
9415
  set(set) {
9409
9416
  let resolved;
9410
9417
  for (const key in set) {
9418
+ const column = this.query.shape[key];
9419
+ if (column) throwOnReadOnly$1(this.query, column, key);
9411
9420
  if (typeof set[key] === "function") {
9412
9421
  if (!resolved) resolved = { ...set };
9413
9422
  resolved[key] = set[key]();
@@ -9700,7 +9709,11 @@ class Having {
9700
9709
  const before = (q, key, cb) => pushQueryValueImmutable(q, `before${key}`, cb);
9701
9710
  const after = (query, key, select, cb, commit) => {
9702
9711
  const q = query;
9703
- pushQueryValueImmutable(q, `after${key}${commit ? "Commit" : ""}`, cb);
9712
+ pushQueryValueImmutable(
9713
+ q,
9714
+ `after${key}${commit ? "Commit" : ""}`,
9715
+ cb
9716
+ );
9704
9717
  const prop = `after${key}Select`;
9705
9718
  const set = q.q[prop] = new Set(q.q[prop]);
9706
9719
  for (const column of select) {
@@ -9715,7 +9728,13 @@ const _queryHookAfterQuery = (q, cb) => {
9715
9728
  return pushQueryValueImmutable(q, "after", cb);
9716
9729
  };
9717
9730
  const _queryHookBeforeCreate = (q, cb) => {
9718
- return before(q, "Create", (q2) => cb(new QueryHookUtils(q2, "hookCreateSet")));
9731
+ return before(
9732
+ q,
9733
+ "Create",
9734
+ (q2) => cb(
9735
+ new QueryHookUtils(q2, q2.q.columns, "hookCreateSet")
9736
+ )
9737
+ );
9719
9738
  };
9720
9739
  const _queryHookAfterCreate = (q, select, cb) => {
9721
9740
  return after(q, "Create", select, cb);
@@ -9724,7 +9743,15 @@ const _queryHookAfterCreateCommit = (q, select, cb) => {
9724
9743
  return after(q, "Create", select, cb, true);
9725
9744
  };
9726
9745
  const _queryHookBeforeUpdate = (q, cb) => {
9727
- return before(q, "Update", (q2) => cb(new QueryHookUtils(q2, "hookUpdateSet")));
9746
+ return before(q, "Update", (q2) => {
9747
+ const columns = [];
9748
+ for (const item of q2.q.updateData) {
9749
+ if (typeof item === "object") {
9750
+ columns.push(...Object.keys(item));
9751
+ }
9752
+ }
9753
+ return cb(new QueryHookUtils(q2, columns, "hookUpdateSet"));
9754
+ });
9728
9755
  };
9729
9756
  const _queryHookAfterUpdate = (q, select, cb) => {
9730
9757
  return after(q, "Update", select, cb);
@@ -9733,11 +9760,7 @@ const _queryHookAfterUpdateCommit = (q, select, cb) => {
9733
9760
  return after(q, "Update", select, cb, true);
9734
9761
  };
9735
9762
  const _queryHookBeforeSave = (q, cb) => {
9736
- return before(
9737
- before(q, "Create", (q2) => cb(new QueryHookUtils(q2, "hookCreateSet"))),
9738
- "Update",
9739
- (q2) => cb(new QueryHookUtils(q2, "hookUpdateSet"))
9740
- );
9763
+ return _queryHookBeforeUpdate(_queryHookBeforeCreate(q, cb), cb);
9741
9764
  };
9742
9765
  const _queryHookAfterSave = (q, select, cb) => {
9743
9766
  return after(after(q, "Create", select, cb), "Update", select, cb);
@@ -9760,21 +9783,6 @@ const _queryHookAfterDelete = (q, select, cb) => {
9760
9783
  const _queryHookAfterDeleteCommit = (q, select, cb) => {
9761
9784
  return after(q, "Delete", select, cb, true);
9762
9785
  };
9763
- class QueryHookUtils {
9764
- constructor(query, key) {
9765
- this.query = query;
9766
- this.key = key;
9767
- this.set = (data) => {
9768
- const set = {};
9769
- for (const key in data) {
9770
- if (data[key] !== void 0) {
9771
- set[key] = data[key];
9772
- }
9773
- }
9774
- pushQueryValueImmutable(this.query, this.key, set);
9775
- };
9776
- }
9777
- }
9778
9786
  class QueryHooks {
9779
9787
  /**
9780
9788
  * Run the function before any kind of query.
@@ -10805,6 +10813,15 @@ class MergeQueryMethods {
10805
10813
  }
10806
10814
  }
10807
10815
 
10816
+ const throwOnReadOnly = (q, column, key) => {
10817
+ if (column.data.appReadOnly || column.data.readOnly) {
10818
+ throw new OrchidOrmInternalError(
10819
+ q,
10820
+ "Trying to update a readonly column",
10821
+ { column: key }
10822
+ );
10823
+ }
10824
+ };
10808
10825
  const _queryChangeCounter = (self, op, data) => {
10809
10826
  const q = self.q;
10810
10827
  q.type = "update";
@@ -10821,38 +10838,38 @@ const _queryChangeCounter = (self, op, data) => {
10821
10838
  map = {};
10822
10839
  for (const key in data) {
10823
10840
  map[key] = { op, arg: data[key] };
10841
+ const column = self.shape[key];
10842
+ if (column) {
10843
+ throwOnReadOnly(self, column, key);
10844
+ }
10824
10845
  }
10825
10846
  } else {
10826
10847
  map = { [data]: { op, arg: 1 } };
10848
+ const column = self.shape[data];
10849
+ if (column) {
10850
+ throwOnReadOnly(self, column, data);
10851
+ }
10827
10852
  }
10828
10853
  pushQueryValueImmutable(self, "updateData", map);
10829
10854
  return self;
10830
10855
  };
10831
- const update = (self) => {
10832
- const q = self.q;
10833
- q.type = "update";
10834
- if (!q.select) {
10835
- q.returningMany = !q.returnType || q.returnType === "all";
10836
- q.returnType = "valueOrThrow";
10837
- q.returning = true;
10838
- }
10839
- throwIfNoWhere(self, "update");
10840
- return self;
10841
- };
10842
10856
  const _queryUpdate = (query, arg) => {
10843
10857
  const { q } = query;
10858
+ q.type = "update";
10859
+ const returnCount = !q.select;
10844
10860
  const set = { ...arg };
10845
10861
  pushQueryValueImmutable(query, "updateData", set);
10846
10862
  const { shape } = q;
10847
10863
  const ctx = {};
10848
10864
  for (const key in arg) {
10849
10865
  const item = shape[key];
10850
- if (item instanceof VirtualColumn && item.update) {
10851
- item.update(query, ctx, set);
10866
+ if (!item && shape !== anyShape) {
10852
10867
  delete set[key];
10853
- } else if ((!shape[key] || shape[key].data.readonly) && shape !== anyShape) {
10868
+ } else if (item.data.virtual) {
10869
+ item.update?.(query, ctx, set);
10854
10870
  delete set[key];
10855
10871
  } else {
10872
+ if (item) throwOnReadOnly(query, item, key);
10856
10873
  let value = set[key];
10857
10874
  if (typeof value === "function") {
10858
10875
  value = resolveSubQueryCallbackV2(
@@ -10878,7 +10895,7 @@ const _queryUpdate = (query, arg) => {
10878
10895
  "with"
10879
10896
  );
10880
10897
  } else {
10881
- const encode = shape[key].data.encode;
10898
+ const encode = item?.data.encode;
10882
10899
  if (encode) set[key] = encode(value);
10883
10900
  }
10884
10901
  }
@@ -10906,7 +10923,13 @@ const _queryUpdate = (query, arg) => {
10906
10923
  }
10907
10924
  };
10908
10925
  }
10909
- return update(query);
10926
+ if (returnCount) {
10927
+ q.returningMany = !q.returnType || q.returnType === "all";
10928
+ q.returnType = "valueOrThrow";
10929
+ q.returning = true;
10930
+ }
10931
+ throwIfNoWhere(query, "update");
10932
+ return query;
10910
10933
  };
10911
10934
  const _queryUpdateOrThrow = (q, arg) => {
10912
10935
  q.q.throwOnNotFound = true;
@@ -11548,109 +11571,13 @@ function orCreate(query, data, updateData, mergeData) {
11548
11571
  };
11549
11572
  return query;
11550
11573
  }
11551
- class QueryUpsertOrCreate {
11552
- /**
11553
- * `upsert` tries to update a single record, and then it creates the record if it doesn't yet exist.
11554
- *
11555
- * `find` or `findBy` must precede `upsert` because it does not work with multiple updates.
11556
- *
11557
- * In case more than one row was updated, it will throw `MoreThanOneRowError` and the transaction will be rolled back.
11558
- *
11559
- * It can take `update` and `create` objects, then they are used separately for update and create queries.
11560
- * Or, it can take `data` and `create` objects, `data` will be used for update and be mixed to `create` object.
11561
- *
11562
- * `data` and `update` objects are of the same type that's expected by `update` method, `create` object is of type of `create` method argument.
11563
- *
11564
- * No values are returned by default, place `select` or `selectAll` before `upsert` to specify returning columns.
11565
- *
11566
- * ```ts
11567
- * await User.selectAll()
11568
- * .findBy({ email: 'some@email.com' })
11569
- * .upsert({
11570
- * data: {
11571
- * // update record's name
11572
- * name: 'new name',
11573
- * // supports sql and nested queries
11574
- * fromSQL: () => sql`*SQL expression*`,
11575
- * fromQuery: () => db.someTable.create(data).get('column'),
11576
- * },
11577
- * create: {
11578
- * // create a new record with this email and a name 'new name'
11579
- * email: 'some@email.com',
11580
- * // supports sql and nested queries as well
11581
- * },
11582
- * create: {
11583
- * // create a new record with this email and a name 'new name'
11584
- * email: 'some@email.com',
11585
- * },
11586
- * });
11587
- *
11588
- * // the same as above but using `update` and `create`
11589
- * await User.selectAll()
11590
- * .findBy({ email: 'some@email.com' })
11591
- * .upsert({
11592
- * update: {
11593
- * name: 'updated user',
11594
- * },
11595
- * create: {
11596
- * email: 'some@email.com',
11597
- * // here we use a different name when creating a record
11598
- * name: 'created user',
11599
- * },
11600
- * });
11601
- * ```
11602
- *
11603
- * The data for `create` may be returned from a function, it won't be called if a record was updated:
11604
- *
11605
- * ```ts
11606
- * await User.selectAll()
11607
- * .findBy({ email: 'some@email.com' })
11608
- * .upsert({
11609
- * update: {
11610
- * name: 'updated user',
11611
- * },
11612
- * create: () => ({
11613
- * email: 'some@email.com',
11614
- * name: 'created user',
11615
- * }),
11616
- * });
11617
- *
11618
- * // the same as above using `data`
11619
- * await User.selectAll()
11620
- * .findBy({ email: 'some@email.com' })
11621
- * .upsert({
11622
- * data: {
11623
- * name: 'updated user',
11624
- * },
11625
- * create: () => ({
11626
- * email: 'some@email.com',
11627
- * // name in `create` is overriding the name from `data`
11628
- * name: 'created user',
11629
- * }),
11630
- * });
11631
- * ```
11632
- *
11633
- * Data from `data` or `update` is passed to the `create` function and can be used:
11634
- *
11635
- * ```ts
11636
- * const user = await User.selectAll()
11637
- * .findBy({ email: 'some@email.com' })
11638
- * .upsert({
11639
- * data: {
11640
- * name: 'updated user',
11641
- * },
11642
- * // `updateData` has the exact type of what is passed to `data`
11643
- * create: (updateData) => ({
11644
- * email: `${updateData.name}@email.com`,
11645
- * }),
11646
- * });
11647
- * ```
11648
- *
11649
- * `upsert` works in the exact same way as [orCreate](#orCreate), but with `UPDATE` statement instead of `SELECT`.
11650
- * it also performs a single query if the record exists, and two queries if there is no record yet.
11651
- *
11652
- * @param data - `update` property for the data to update, `create` property for the data to create
11653
- */
11574
+ const QueryOrCreate = {
11575
+ orCreate(data) {
11576
+ return orCreate(_clone(this), data);
11577
+ }
11578
+ };
11579
+
11580
+ const QueryUpsert = {
11654
11581
  upsert(data) {
11655
11582
  const q = _clone(this);
11656
11583
  let updateData;
@@ -11665,75 +11592,7 @@ class QueryUpsertOrCreate {
11665
11592
  }
11666
11593
  return orCreate(q, data.create, updateData, mergeData);
11667
11594
  }
11668
- /**
11669
- * `orCreate` creates a record only if it was not found by conditions.
11670
- *
11671
- * `find` or `findBy` must precede `orCreate`.
11672
- *
11673
- * It is accepting the same argument as `create` commands.
11674
- *
11675
- * No result is returned by default, place `get`, `select`, or `selectAll` before `orCreate` to specify returning columns.
11676
- *
11677
- * ```ts
11678
- * const user = await db.user
11679
- * .selectAll()
11680
- * .findBy({ email: 'some@email.com' })
11681
- * .orCreate({
11682
- * email: 'some@email.com',
11683
- * name: 'created user',
11684
- * // supports sql and nested queries
11685
- * fromSQL: () => sql`*SQL expression*`,
11686
- * fromQuery: () => db.someTable.create(data).get('column'),
11687
- * fromRelated: (q) => q.relatedTable.update(data).get('column'),
11688
- * });
11689
- * ```
11690
- *
11691
- * The data can be returned from a function, it won't be called if the record was found:
11692
- *
11693
- * ```ts
11694
- * const user = await User.selectAll()
11695
- * .findBy({ email: 'some@email.com' })
11696
- * .orCreate(() => ({
11697
- * email: 'some@email.com',
11698
- * name: 'created user',
11699
- * }));
11700
- * ```
11701
- *
11702
- * `orCreate` works by performing just a single query in the case if the record exists, and one additional query when the record does not exist.
11703
- *
11704
- * At first, it performs a "find" query, the query cost is exact same as if you didn't use `orCreate`.
11705
- *
11706
- * Then, if the record wasn't found, it performs a single query with CTE expressions to try finding it again, for the case it was already created just a moment before,
11707
- * and then it creates the record if it's still not found. Using such CTE allows to skip using transactions, while still conforming to atomicity.
11708
- *
11709
- * ```sql
11710
- * -- first query
11711
- * SELECT * FROM "table" WHERE "key" = 'value'
11712
- *
11713
- * -- the record could have been created in between these two queries
11714
- *
11715
- * -- second query
11716
- * WITH find_row AS (
11717
- * SELECT * FROM "table" WHERE "key" = 'value'
11718
- * )
11719
- * WITH insert_row AS (
11720
- * INSERT INTO "table" ("key")
11721
- * SELECT 'value'
11722
- * -- skip the insert if the row already exists
11723
- * WHERE NOT EXISTS (SELECT 1 FROM find_row)
11724
- * RETURNING *
11725
- * )
11726
- * SELECT * FROM find_row
11727
- * UNION ALL
11728
- * SELECT * FROM insert_row
11729
- * ```
11730
- *
11731
- * @param data - the same data as for `create`, it may be returned from a callback
11732
- */
11733
- orCreate(data) {
11734
- return orCreate(_clone(this), data);
11735
- }
11736
- }
11595
+ };
11737
11596
 
11738
11597
  class SqlMethod {
11739
11598
  sql(...args) {
@@ -12817,6 +12676,8 @@ class QueryMethods {
12817
12676
  return _chain(this, _clone(rel.query), rel);
12818
12677
  }
12819
12678
  }
12679
+ Object.assign(QueryMethods.prototype, QueryUpsert);
12680
+ Object.assign(QueryMethods.prototype, QueryOrCreate);
12820
12681
  applyMixins(QueryMethods, [
12821
12682
  AsMethods,
12822
12683
  AggregateMethods,
@@ -12827,7 +12688,7 @@ applyMixins(QueryMethods, [
12827
12688
  WithMethods,
12828
12689
  Union,
12829
12690
  JsonMethods,
12830
- Create,
12691
+ QueryCreate,
12831
12692
  Update,
12832
12693
  Delete,
12833
12694
  Transaction,
@@ -12839,7 +12700,6 @@ applyMixins(QueryMethods, [
12839
12700
  Then,
12840
12701
  QueryLog,
12841
12702
  QueryHooks,
12842
- QueryUpsertOrCreate,
12843
12703
  QueryGet,
12844
12704
  MergeQueryMethods,
12845
12705
  SqlMethod,
@@ -13015,6 +12875,7 @@ class Db extends QueryMethods {
13015
12875
  let hasParsers = false;
13016
12876
  let modifyQuery = void 0;
13017
12877
  let prepareSelectAll = false;
12878
+ let hasHookSetters;
13018
12879
  const { snakeCase } = options;
13019
12880
  for (const key in shape) {
13020
12881
  const column = shape[key];
@@ -13050,6 +12911,9 @@ class Db extends QueryMethods {
13050
12911
  column.data.runtimeDefault = encode ? () => encode(def()) : def;
13051
12912
  }
13052
12913
  }
12914
+ if (column.data.setOnCreate || column.data.setOnUpdate || column.data.setOnSave) {
12915
+ hasHookSetters = true;
12916
+ }
13053
12917
  }
13054
12918
  this.q = {
13055
12919
  adapter,
@@ -13124,6 +12988,27 @@ class Db extends QueryMethods {
13124
12988
  if (softDelete) {
13125
12989
  enableSoftDelete(this, table, shape, softDelete, scopes);
13126
12990
  }
12991
+ if (hasHookSetters) {
12992
+ const hooks = {
12993
+ setOnCreate: _queryHookBeforeCreate,
12994
+ setOnUpdate: _queryHookBeforeUpdate,
12995
+ setOnSave: _queryHookBeforeSave
12996
+ };
12997
+ for (const key in shape) {
12998
+ const { data } = shape[key];
12999
+ for (const hookKey in hooks) {
13000
+ const fn = data[hookKey];
13001
+ if (fn) {
13002
+ hooks[hookKey](this, (arg) => {
13003
+ const value = fn(arg);
13004
+ if (value !== void 0) {
13005
+ arg.set({ [key]: value });
13006
+ }
13007
+ });
13008
+ }
13009
+ }
13010
+ }
13011
+ }
13127
13012
  }
13128
13013
  [inspect.custom]() {
13129
13014
  return `Query<${this.table}>`;
@@ -13457,5 +13342,5 @@ function copyTableData(query, arg) {
13457
13342
  return q;
13458
13343
  }
13459
13344
 
13460
- export { Adapter, AfterCommitError, AggregateMethods, ArrayColumn, AsMethods, BigIntColumn, BigSerialColumn, BitColumn, BitVaryingColumn, BooleanColumn, BoxColumn, ByteaColumn, CidrColumn, CircleColumn, CitextColumn, Clear, ColumnRefExpression, ColumnType, ComputedColumn, Create, CustomTypeColumn, DateBaseColumn, DateColumn, DateTimeBaseClass, DateTimeTzBaseClass, Db, DecimalColumn, Delete, DomainColumn, DoublePrecisionColumn, DynamicRawSQL, EnumColumn, ExpressionMethods, FnExpression, For, FromMethods, Having, InetColumn, IntegerBaseColumn, IntegerColumn, IntervalColumn, JSONColumn, JSONTextColumn, Join, JsonMethods, LimitedTextBaseColumn, LineColumn, LsegColumn, MacAddr8Column, MacAddrColumn, MergeQueryMethods, MoneyColumn, MoreThanOneRowError, NotFoundError, NumberAsStringBaseColumn, NumberBaseColumn, OnConflictQueryBuilder, OnMethods, Operators, OrExpression, OrchidOrmError, OrchidOrmInternalError, PathColumn, PointColumn, PolygonColumn, PostgisGeographyPointColumn, QueryError, QueryGet, QueryHookUtils, QueryHooks, QueryLog, QueryMethods, QueryUpsertOrCreate, RawSQL, RealColumn, RefExpression, SearchMethods, Select, SerialColumn, SmallIntColumn, SmallSerialColumn, SqlMethod, StringColumn, TextBaseColumn, TextColumn, Then, TimeColumn, TimestampColumn, TimestampTZColumn, Transaction, TransactionAdapter, TransformMethods, TsQueryColumn, TsVectorColumn, UUIDColumn, UnhandledTypeError, Union, UnknownColumn, Update, VarCharColumn, VirtualColumn, Where, WithMethods, XMLColumn, _clone, _getSelectableColumn, _initQueryBuilder, _queryAfterSaveCommit, _queryAll, _queryAs, _queryChangeCounter, _queryCreate, _queryCreateFrom, _queryCreateMany, _queryCreateManyFrom, _queryDefaults, _queryDelete, _queryExec, _queryFindBy, _queryFindByOptional, _queryGet, _queryGetOptional, _queryHookAfterCreate, _queryHookAfterCreateCommit, _queryHookAfterDelete, _queryHookAfterDeleteCommit, _queryHookAfterQuery, _queryHookAfterSave, _queryHookAfterUpdate, _queryHookAfterUpdateCommit, _queryHookBeforeCreate, _queryHookBeforeDelete, _queryHookBeforeQuery, _queryHookBeforeSave, _queryHookBeforeUpdate, _queryInsert, _queryInsertFrom, _queryInsertMany, _queryInsertManyFrom, _queryJoinOn, _queryJoinOnJsonPathEquals, _queryJoinOrOn, _queryOr, _queryOrNot, _queryResolveAlias, _queryRows, _querySelect, _queryTake, _queryTakeOptional, _queryUnion, _queryUpdate, _queryUpdateOrThrow, _queryWhere, _queryWhereExists, _queryWhereIn, _queryWhereNot, _queryWhereNotOneOf, _queryWhereNotSql, _queryWhereOneOf, _queryWhereSql, _runAfterCommitHooks, addColumnParserToQuery, addParserForRawExpression, addParserForSelectItem, addQueryOn, anyShape, applyComputedColumns, assignDbDataToColumn, checkIfASimpleQuery, cloneQueryBaseUnscoped, columnCheckToCode, columnCode, columnExcludesToCode, columnForeignKeysToCode, columnIndexesToCode, columnsShapeToCode, commitSql$1 as commitSql, constraintInnerToCode, constraintToCode, copyTableData, countSelect, createDb, defaultSchemaConfig, escapeForLog, escapeForMigration, escapeString, excludeInnerToCode, excludeToCode, extendQuery, filterResult, foreignKeyArgumentToCode, getClonedQueryData, getColumnBaseType, getColumnInfo, getColumnTypes, getFullColumnTable, getPrimaryKeys, getQueryAs, getShapeFromSelect, getSqlText, handleResult, identityToCode, indexInnerToCode, indexToCode, isDefaultTimeStamp, isInUserTransaction, isQueryReturnsAll, isSelectingCount, joinSubQuery, logParamToLogObject, makeColumnTypes, makeColumnsByType, makeFnExpression, moveQueryValueToWith, parseRecord, parseTableData, parseTableDataInput, postgisTypmodToSql, primaryKeyInnerToCode, processComputedBatches, processComputedResult, processSelectArg, pushLimitSQL, pushQueryArrayImmutable, pushQueryOn, pushQueryOnForOuter, pushQueryOrOn, pushQueryValueImmutable, pushTableDataCode, queryFrom, queryFromSql, queryJson, queryMethodByReturnType, queryTypeWithLimitOne, queryWrap, raw, referencesArgsToCode, resolveSubQueryCallbackV2, rollbackSql$1 as rollbackSql, saveAliasedShape, setColumnDefaultParse, setColumnEncode, setColumnParse, setColumnParseNull, setParserForSelectedString, setQueryObjectValueImmutable, setQueryOperators, simplifyColumnDefault, sqlFn, sqlQueryArgsToExpression, tableDataMethods, templateLiteralToSQL, testTransaction, throwIfJoinLateral, throwIfNoWhere, toSQL };
13345
+ export { Adapter, AfterCommitError, AggregateMethods, ArrayColumn, AsMethods, BigIntColumn, BigSerialColumn, BitColumn, BitVaryingColumn, BooleanColumn, BoxColumn, ByteaColumn, CidrColumn, CircleColumn, CitextColumn, Clear, ColumnRefExpression, ColumnType, ComputedColumn, CustomTypeColumn, DateBaseColumn, DateColumn, DateTimeBaseClass, DateTimeTzBaseClass, Db, DecimalColumn, Delete, DomainColumn, DoublePrecisionColumn, DynamicRawSQL, EnumColumn, ExpressionMethods, FnExpression, For, FromMethods, Having, InetColumn, IntegerBaseColumn, IntegerColumn, IntervalColumn, JSONColumn, JSONTextColumn, Join, JsonMethods, LimitedTextBaseColumn, LineColumn, LsegColumn, MacAddr8Column, MacAddrColumn, MergeQueryMethods, MoneyColumn, MoreThanOneRowError, NotFoundError, NumberAsStringBaseColumn, NumberBaseColumn, OnConflictQueryBuilder, OnMethods, Operators, OrExpression, OrchidOrmError, OrchidOrmInternalError, PathColumn, PointColumn, PolygonColumn, PostgisGeographyPointColumn, QueryCreate, QueryError, QueryGet, QueryHooks, QueryLog, QueryMethods, QueryUpsert, RawSQL, RealColumn, RefExpression, SearchMethods, Select, SerialColumn, SmallIntColumn, SmallSerialColumn, SqlMethod, StringColumn, TextBaseColumn, TextColumn, Then, TimeColumn, TimestampColumn, TimestampTZColumn, Transaction, TransactionAdapter, TransformMethods, TsQueryColumn, TsVectorColumn, UUIDColumn, UnhandledTypeError, Union, UnknownColumn, Update, VarCharColumn, VirtualColumn, Where, WithMethods, XMLColumn, _clone, _getSelectableColumn, _initQueryBuilder, _queryAfterSaveCommit, _queryAll, _queryAs, _queryChangeCounter, _queryCreate, _queryCreateFrom, _queryCreateMany, _queryCreateManyFrom, _queryDefaults, _queryDelete, _queryExec, _queryFindBy, _queryFindByOptional, _queryGet, _queryGetOptional, _queryHookAfterCreate, _queryHookAfterCreateCommit, _queryHookAfterDelete, _queryHookAfterDeleteCommit, _queryHookAfterQuery, _queryHookAfterSave, _queryHookAfterUpdate, _queryHookAfterUpdateCommit, _queryHookBeforeCreate, _queryHookBeforeDelete, _queryHookBeforeQuery, _queryHookBeforeSave, _queryHookBeforeUpdate, _queryInsert, _queryInsertFrom, _queryInsertMany, _queryInsertManyFrom, _queryJoinOn, _queryJoinOnJsonPathEquals, _queryJoinOrOn, _queryOr, _queryOrNot, _queryResolveAlias, _queryRows, _querySelect, _queryTake, _queryTakeOptional, _queryUnion, _queryUpdate, _queryUpdateOrThrow, _queryWhere, _queryWhereExists, _queryWhereIn, _queryWhereNot, _queryWhereNotOneOf, _queryWhereNotSql, _queryWhereOneOf, _queryWhereSql, _runAfterCommitHooks, addColumnParserToQuery, addParserForRawExpression, addParserForSelectItem, addQueryOn, anyShape, applyComputedColumns, assignDbDataToColumn, checkIfASimpleQuery, cloneQueryBaseUnscoped, columnCheckToCode, columnCode, columnExcludesToCode, columnForeignKeysToCode, columnIndexesToCode, columnsShapeToCode, commitSql$1 as commitSql, constraintInnerToCode, constraintToCode, copyTableData, countSelect, createDb, defaultSchemaConfig, escapeForLog, escapeForMigration, escapeString, excludeInnerToCode, excludeToCode, extendQuery, filterResult, foreignKeyArgumentToCode, getClonedQueryData, getColumnBaseType, getColumnInfo, getColumnTypes, getFullColumnTable, getPrimaryKeys, getQueryAs, getShapeFromSelect, getSqlText, handleResult, identityToCode, indexInnerToCode, indexToCode, isDefaultTimeStamp, isInUserTransaction, isQueryReturnsAll, isSelectingCount, joinSubQuery, logParamToLogObject, makeColumnTypes, makeColumnsByType, makeFnExpression, moveQueryValueToWith, parseRecord, parseTableData, parseTableDataInput, postgisTypmodToSql, primaryKeyInnerToCode, processComputedBatches, processComputedResult, processSelectArg, pushLimitSQL, pushQueryArrayImmutable, pushQueryOn, pushQueryOnForOuter, pushQueryOrOn, pushTableDataCode, queryFrom, queryFromSql, queryJson, queryMethodByReturnType, queryTypeWithLimitOne, queryWrap, raw, referencesArgsToCode, resolveSubQueryCallbackV2, rollbackSql$1 as rollbackSql, saveAliasedShape, setColumnDefaultParse, setColumnEncode, setColumnParse, setColumnParseNull, setParserForSelectedString, setQueryObjectValueImmutable, setQueryOperators, simplifyColumnDefault, sqlFn, sqlQueryArgsToExpression, tableDataMethods, templateLiteralToSQL, testTransaction, throwIfJoinLateral, throwIfNoWhere, toSQL };
13461
13346
  //# sourceMappingURL=index.mjs.map