pqb 0.52.2 → 0.53.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.mjs CHANGED
@@ -2,6 +2,7 @@ import { ExpressionTypeMethod, Expression, RawSQLBase, emptyObject, isTemplateLi
2
2
  import pg from 'pg';
3
3
  import { inspect } from 'node:util';
4
4
  import { AsyncLocalStorage } from 'node:async_hooks';
5
+ import { templateLiteralToSQL as templateLiteralToSQL$1 } from 'pqb';
5
6
 
6
7
  const used = [];
7
8
  const literalValues = [];
@@ -493,7 +494,7 @@ const columnsShapeToCode = (ctx, shape) => {
493
494
  if (name === key) column.data.name = void 0;
494
495
  code.push(
495
496
  ...combineCodeElements([
496
- `${quoteObjectKey(key)}: `,
497
+ `${quoteObjectKey(key, ctx.snakeCase)}: `,
497
498
  ...toArray(shape[key].toCode(ctx, key)),
498
499
  ","
499
500
  ])
@@ -2144,7 +2145,7 @@ class TsVectorColumn extends ColumnType {
2144
2145
  const pairs = [];
2145
2146
  for (const key in target) {
2146
2147
  pairs.push(
2147
- `${quoteObjectKey(key)}: '${target[key]}'`
2148
+ `${quoteObjectKey(key, false)}: '${target[key]}'`
2148
2149
  );
2149
2150
  }
2150
2151
  code += `{ ${pairs.join(", ")} }`;
@@ -2656,8 +2657,8 @@ const _join = (query, require, type, first, args) => {
2656
2657
  joinKey = first;
2657
2658
  const relation = query.relations[joinKey];
2658
2659
  if (relation) {
2659
- shape = getShapeFromSelect(relation.relationConfig.query);
2660
- const r = relation.relationConfig.query;
2660
+ shape = getShapeFromSelect(relation.query);
2661
+ const r = relation.query;
2661
2662
  parsers = r.q.parsers;
2662
2663
  batchParsers = r.q.batchParsers;
2663
2664
  computeds = r.q.computeds;
@@ -2746,11 +2747,11 @@ const _joinLateralProcessArg = (q, arg, cb) => {
2746
2747
  if (typeof arg === "string") {
2747
2748
  relation = q.relations[arg];
2748
2749
  if (relation) {
2749
- arg = _clone(relation.relationConfig.query);
2750
+ arg = _clone(relation.query);
2750
2751
  } else {
2751
2752
  const w = q.q.withShapes?.[arg];
2752
2753
  if (w) {
2753
- const t = Object.create(q.queryBuilder);
2754
+ const t = Object.create(q.qb);
2754
2755
  t.table = arg;
2755
2756
  t.shape = w.shape;
2756
2757
  t.computeds = w.computeds;
@@ -2768,7 +2769,7 @@ const _joinLateralProcessArg = (q, arg, cb) => {
2768
2769
  cb
2769
2770
  );
2770
2771
  if (relation) {
2771
- result = relation.relationConfig.joinQuery(
2772
+ result = relation.joinQuery(
2772
2773
  result,
2773
2774
  q
2774
2775
  );
@@ -3573,7 +3574,7 @@ const then = async (q, adapter, trx, beforeHooks, afterHooks, afterCommitHooks,
3573
3574
  if (query.transform) {
3574
3575
  result = applyTransforms(query, returnType, query.transform, result);
3575
3576
  }
3576
- return resolve?.(result);
3577
+ return resolve ? resolve(result) : result;
3577
3578
  } catch (err) {
3578
3579
  let error;
3579
3580
  if (err instanceof pg.DatabaseError) {
@@ -3879,7 +3880,7 @@ function queryFrom(self, arg) {
3879
3880
  if (typeof arg === "string") {
3880
3881
  data.as || (data.as = arg);
3881
3882
  const w = data.withShapes?.[arg];
3882
- data.shape = w?.shape ?? emptyObject;
3883
+ data.shape = w?.shape ?? anyShape;
3883
3884
  data.computeds = w?.computeds;
3884
3885
  } else if (isExpression(arg)) {
3885
3886
  data.as || (data.as = "t");
@@ -4662,17 +4663,19 @@ const makeInsertSql = (ctx, q, query, quotedAs) => {
4662
4663
  let values = query.values;
4663
4664
  if (quotedColumns.length === 0) {
4664
4665
  const key = Object.keys(q.shape)[0];
4665
- const column = q.shape[key];
4666
- quotedColumns[0] = `"${column?.data.name || key}"`;
4667
- if (Array.isArray(values) && Array.isArray(values[0])) {
4668
- values = values.map(() => [void 0]);
4666
+ if (key) {
4667
+ const column = q.shape[key];
4668
+ quotedColumns[0] = `"${column?.data.name || key}"`;
4669
+ if (Array.isArray(values) && Array.isArray(values[0])) {
4670
+ values = values.map(() => [void 0]);
4671
+ }
4669
4672
  }
4670
4673
  }
4671
4674
  ctx.sql.push(
4672
- `INSERT INTO ${quotedAs}(${quotedColumns.join(", ")})`,
4675
+ `INSERT INTO ${quotedAs}${quotedColumns.length ? "(" + quotedColumns.join(", ") + ")" : ""}`,
4673
4676
  null
4674
4677
  );
4675
- const QueryClass = ctx.queryBuilder.constructor;
4678
+ const QueryClass = ctx.qb.constructor;
4676
4679
  if (query.onConflict) {
4677
4680
  ctx.sql.push("ON CONFLICT");
4678
4681
  const { target } = query.onConflict;
@@ -5478,7 +5481,10 @@ const getTsVector = (ctx, data, lang, source, quotedAs) => {
5478
5481
  };
5479
5482
 
5480
5483
  const pushUpdateSql = (ctx, table, query, quotedAs) => {
5481
- const quotedTable = quoteSchemaAndTable(query.schema, table.table);
5484
+ const quotedTable = quoteSchemaAndTable(
5485
+ query.schema,
5486
+ table.table || query.from
5487
+ );
5482
5488
  const set = [];
5483
5489
  processData(ctx, table, set, query.updateData, quotedAs);
5484
5490
  if (!set.length) {
@@ -5522,7 +5528,7 @@ const pushUpdateReturning = (ctx, table, query, quotedAs, keyword) => {
5522
5528
  };
5523
5529
  const processData = (ctx, table, set, data, quotedAs) => {
5524
5530
  let append;
5525
- const QueryClass = ctx.queryBuilder.constructor;
5531
+ const QueryClass = ctx.qb.constructor;
5526
5532
  for (const item of data) {
5527
5533
  if (typeof item === "function") {
5528
5534
  const result = item(data);
@@ -5568,7 +5574,7 @@ const processValue = (ctx, table, QueryClass, key, value, quotedAs) => {
5568
5574
  };
5569
5575
 
5570
5576
  const pushDeleteSql = (ctx, table, query, quotedAs) => {
5571
- const from = `"${table.table}"`;
5577
+ const from = `"${table.table || query.from}"`;
5572
5578
  ctx.sql.push(`DELETE FROM ${from}`);
5573
5579
  if (from !== quotedAs) {
5574
5580
  ctx.sql.push(quotedAs);
@@ -5676,7 +5682,7 @@ const toSQL = (table, options) => {
5676
5682
  const sql = [];
5677
5683
  const values = options?.values || [];
5678
5684
  const ctx = {
5679
- queryBuilder: table.queryBuilder,
5685
+ qb: table.qb,
5680
5686
  q: query,
5681
5687
  sql,
5682
5688
  values,
@@ -5996,7 +6002,7 @@ const processWhere = (ands, ctx, table, query, data, quotedAs) => {
5996
6002
  throw new Error(`Unknown column ${key} provided to condition`);
5997
6003
  }
5998
6004
  }
5999
- if (value instanceof ctx.queryBuilder.constructor) {
6005
+ if (value instanceof ctx.qb.constructor) {
6000
6006
  ands.push(
6001
6007
  `${quotedColumn} = (${getSqlText(value.toSQL(ctx))})`
6002
6008
  );
@@ -6276,7 +6282,7 @@ const getIsJoinSubQuery = (query) => {
6276
6282
  const processJoinArgs = (joinTo, first, args, joinSubQuery, whereExists) => {
6277
6283
  if (typeof first === "string") {
6278
6284
  if (first in joinTo.relations) {
6279
- const { query: toQuery, joinQuery } = joinTo.relations[first].relationConfig;
6285
+ const { query: toQuery, joinQuery } = joinTo.relations[first];
6280
6286
  const j = joinQuery(toQuery, joinTo);
6281
6287
  if (typeof args[0] === "function") {
6282
6288
  const r = args[0](
@@ -6297,7 +6303,7 @@ const processJoinArgs = (joinTo, first, args, joinSubQuery, whereExists) => {
6297
6303
  if (!w) {
6298
6304
  throw new Error("Cannot find a `with` statement");
6299
6305
  }
6300
- const j = joinTo.queryBuilder.baseQuery.clone();
6306
+ const j = joinTo.qb.baseQuery.clone();
6301
6307
  j.table = first;
6302
6308
  j.q = {
6303
6309
  shape: w.shape,
@@ -6376,7 +6382,9 @@ const processJoinArgs = (joinTo, first, args, joinSubQuery, whereExists) => {
6376
6382
  };
6377
6383
  const preprocessJoinArg = (q, arg) => {
6378
6384
  if (typeof arg !== "function") return arg;
6379
- arg = arg(q.relations);
6385
+ arg = arg(
6386
+ q.relationQueries
6387
+ );
6380
6388
  arg.joinQueryAfterCallback = arg.joinQuery;
6381
6389
  return arg;
6382
6390
  };
@@ -7196,9 +7204,9 @@ const _chain = (fromQuery, toQuery, rel) => {
7196
7204
  q.returnType = q.returnsOne = q.limit = void 0;
7197
7205
  }
7198
7206
  if (self.q.relChain) {
7199
- q.relChain = [...self.q.relChain, self];
7207
+ q.relChain = [...self.q.relChain, { query: self, rel }];
7200
7208
  } else {
7201
- q.relChain = [self];
7209
+ q.relChain = [{ query: self, rel }];
7202
7210
  }
7203
7211
  const aliases = self.q.as ? { ...self.q.aliases } : { ...self.q.aliases, [self.table]: self.table };
7204
7212
  const relAliases = q.aliases;
@@ -7235,7 +7243,7 @@ const resolveSubQueryCallbackV2 = (q, cb) => {
7235
7243
  for (const key in relations) {
7236
7244
  Object.defineProperty(base, key, {
7237
7245
  get() {
7238
- const rel = relations[key].relationConfig;
7246
+ const rel = relations[key];
7239
7247
  const relQuery = _clone(rel.query);
7240
7248
  relQuery.q.withShapes = this.q.withShapes;
7241
7249
  return _chain(this, relQuery, rel);
@@ -7255,11 +7263,8 @@ const resolveSubQueryCallbackV2 = (q, cb) => {
7255
7263
  return cb(arg);
7256
7264
  };
7257
7265
  const joinSubQuery = (q, sub) => {
7258
- if (!("relationConfig" in sub)) return sub;
7259
- return sub.relationConfig.joinQuery(
7260
- sub,
7261
- q
7262
- );
7266
+ if (!("joinQuery" in sub)) return sub;
7267
+ return sub.joinQuery(sub, q);
7263
7268
  };
7264
7269
 
7265
7270
  const defaultSrid = 4326;
@@ -7487,6 +7492,7 @@ class VirtualColumn extends ColumnType {
7487
7492
  this.dataType = "";
7488
7493
  this.operators = Operators.any;
7489
7494
  this.data.explicitSelect = true;
7495
+ this.data.insertable = this.data.updatable = false;
7490
7496
  }
7491
7497
  toCode() {
7492
7498
  throw new Error(`toCode is not implemented for virtual column`);
@@ -7498,6 +7504,7 @@ const _UnknownColumn = class _UnknownColumn extends VirtualColumn {
7498
7504
  super(schema, schema.unknown());
7499
7505
  this.selectable = true;
7500
7506
  this.data.explicitSelect = void 0;
7507
+ this.data.insertable = this.data.updatable = true;
7501
7508
  }
7502
7509
  };
7503
7510
  _UnknownColumn.instance = new _UnknownColumn(defaultSchemaConfig);
@@ -7565,6 +7572,12 @@ const makeColumnsByType = (schema) => {
7565
7572
  };
7566
7573
  };
7567
7574
 
7575
+ const anyShape = new Proxy(emptyObject, {
7576
+ get() {
7577
+ return UnknownColumn.instance;
7578
+ }
7579
+ });
7580
+
7568
7581
  const { types } = pg;
7569
7582
  const defaultTypeParsers = {};
7570
7583
  for (const key in types.builtins) {
@@ -8425,14 +8438,7 @@ const createSelect = (q) => {
8425
8438
  const processCreateItem = (q, item, rowIndex, ctx, encoders) => {
8426
8439
  const { shape } = q.q;
8427
8440
  for (const key in item) {
8428
- if (shape[key] instanceof VirtualColumn) {
8429
- shape[key].create?.(
8430
- q,
8431
- ctx,
8432
- item,
8433
- rowIndex
8434
- );
8435
- } else {
8441
+ if (shape[key]?.data.insertable !== false) {
8436
8442
  if (typeof item[key] === "function") {
8437
8443
  item[key] = resolveSubQueryCallbackV2(
8438
8444
  q,
@@ -8443,6 +8449,13 @@ const processCreateItem = (q, item, rowIndex, ctx, encoders) => {
8443
8449
  ctx.columns.set(key, ctx.columns.size);
8444
8450
  encoders[key] = shape[key]?.data.encode;
8445
8451
  }
8452
+ } else if (shape[key] instanceof VirtualColumn) {
8453
+ shape[key].create?.(
8454
+ q,
8455
+ ctx,
8456
+ item,
8457
+ rowIndex
8458
+ );
8446
8459
  }
8447
8460
  }
8448
8461
  };
@@ -8655,7 +8668,7 @@ class Create {
8655
8668
  * `create` and `insert` can be used in {@link WithMethods.with} expressions:
8656
8669
  *
8657
8670
  * ```ts
8658
- * db.$queryBuilder
8671
+ * db.$qb
8659
8672
  * // create a record in one table
8660
8673
  * .with('a', db.table.select('id').create(data))
8661
8674
  * // create a record in other table using the first table record id
@@ -9194,7 +9207,7 @@ class Delete {
9194
9207
  * `delete` can be used in {@link WithMethods.with} expressions:
9195
9208
  *
9196
9209
  * ```ts
9197
- * db.$queryBuilder
9210
+ * db.$qb
9198
9211
  * // delete a record in one table
9199
9212
  * .with('a', db.table.find(1).select('id').delete())
9200
9213
  * // delete a record in other table using the first table record id
@@ -10602,7 +10615,7 @@ class WithMethods {
10602
10615
  let [options, queryArg] = third ? [second, third] : [void 0, second];
10603
10616
  let query;
10604
10617
  if (typeof queryArg === "function") {
10605
- const arg = q.queryBuilder.clone();
10618
+ const arg = q.qb.clone();
10606
10619
  arg.q.withShapes = q.q.withShapes;
10607
10620
  query = queryArg(arg);
10608
10621
  } else {
@@ -10629,7 +10642,7 @@ class WithMethods {
10629
10642
  var _a;
10630
10643
  const q = _clone(this);
10631
10644
  let [options, baseFn, recursiveFn] = args.length === 2 ? [{}, args[0], args[1]] : args;
10632
- const arg = q.queryBuilder.clone();
10645
+ const arg = q.qb.clone();
10633
10646
  arg.q.withShapes = q.q.withShapes;
10634
10647
  let query = typeof baseFn === "function" ? baseFn(arg) : baseFn;
10635
10648
  const shape = getShapeFromSelect(query, true);
@@ -10910,7 +10923,7 @@ class Update {
10910
10923
  * `update` can be used in {@link WithMethods.with} expressions:
10911
10924
  *
10912
10925
  * ```ts
10913
- * db.$queryBuilder
10926
+ * db.$qb
10914
10927
  * // update record in one table
10915
10928
  * .with('a', db.table.find(1).select('id').update(data))
10916
10929
  * // update record in other table using the first table record id
@@ -11372,12 +11385,12 @@ function orCreate(query, data, updateData, mergeData) {
11372
11385
  q2.q.inCTE = inCTE;
11373
11386
  const c = q2.create(data);
11374
11387
  c.q.select = q2.q.select;
11375
- let q22 = q2.queryBuilder.with("f", q2).with("c", c);
11388
+ let q22 = q2.qb.with("f", q2).with("c", c);
11376
11389
  q22.q.returnsOne = true;
11377
11390
  queryFrom(q22, "f");
11378
11391
  q22 = _queryUnion(
11379
11392
  q22,
11380
- [q2.queryBuilder.from("c")],
11393
+ [q2.qb.from("c")],
11381
11394
  "UNION ALL",
11382
11395
  true,
11383
11396
  true
@@ -12673,12 +12686,10 @@ class QueryMethods {
12673
12686
  return condition ? fn(this) : this;
12674
12687
  }
12675
12688
  queryRelated(relName, params) {
12676
- return this.relations[relName].relationConfig.queryRelated(
12677
- params
12678
- );
12689
+ return this.relations[relName].queryRelated(params);
12679
12690
  }
12680
12691
  chain(relName) {
12681
- const rel = this.relations[relName].relationConfig;
12692
+ const rel = this.relations[relName];
12682
12693
  return _chain(this, _clone(rel.query), rel);
12683
12694
  }
12684
12695
  }
@@ -12814,12 +12825,49 @@ const parseIndexOrExclude = (item) => {
12814
12825
  return item;
12815
12826
  };
12816
12827
 
12817
- const anyShape = {};
12828
+ const performQuery = async (q, args, method) => {
12829
+ const trx = q.internal.transactionStorage.getStore();
12830
+ let sql;
12831
+ if (isRawSQL(args[0])) {
12832
+ const values = [];
12833
+ sql = {
12834
+ text: args[0].toSQL({ values }),
12835
+ values
12836
+ };
12837
+ } else {
12838
+ const values = [];
12839
+ sql = {
12840
+ text: templateLiteralToSQL$1(args, {
12841
+ qb: q.qb,
12842
+ q: q.q,
12843
+ sql: [],
12844
+ values
12845
+ }),
12846
+ values
12847
+ };
12848
+ }
12849
+ const log = trx?.log ?? q.q.log;
12850
+ let logData;
12851
+ if (log) logData = log.beforeQuery(sql);
12852
+ try {
12853
+ const result = await (trx?.adapter || q.adapter)[method](
12854
+ sql
12855
+ );
12856
+ if (log) log.afterQuery(sql, logData);
12857
+ return result;
12858
+ } catch (err) {
12859
+ if (log) {
12860
+ log.onError(err, sql, logData);
12861
+ }
12862
+ throw err;
12863
+ }
12864
+ };
12865
+
12818
12866
  class Db extends QueryMethods {
12819
- constructor(adapter, queryBuilder, table = void 0, shape = anyShape, columnTypes, transactionStorage, options, tableData = {}) {
12867
+ constructor(adapter, qb, table = void 0, shape = anyShape, columnTypes, transactionStorage, options, tableData = {}) {
12820
12868
  super();
12821
12869
  this.adapter = adapter;
12822
- this.queryBuilder = queryBuilder;
12870
+ this.qb = qb;
12823
12871
  this.table = table;
12824
12872
  this.shape = shape;
12825
12873
  this.columnTypes = columnTypes;
@@ -12837,6 +12885,7 @@ class Db extends QueryMethods {
12837
12885
  };
12838
12886
  this.baseQuery = this;
12839
12887
  this.relations = {};
12888
+ this.relationQueries = {};
12840
12889
  const logger = options.logger || console;
12841
12890
  const parsers = {};
12842
12891
  let hasParsers = false;
@@ -12995,11 +13044,54 @@ class Db extends QueryMethods {
12995
13044
  *
12996
13045
  * @param args - SQL template literal, or an object { raw: string, values?: unknown[] }
12997
13046
  */
12998
- query(...args) {
12999
- return performQuery(this, args, "query");
13047
+ get query() {
13048
+ const q = this;
13049
+ let query = q._query;
13050
+ if (!query) {
13051
+ q._query = query = Object.assign(
13052
+ (...args) => performQuery(q, args, "query"),
13053
+ {
13054
+ async records(...args) {
13055
+ const { rows } = await performQuery(q, args, "query");
13056
+ return rows;
13057
+ },
13058
+ async take(...args) {
13059
+ const {
13060
+ rows: [row]
13061
+ } = await performQuery(q, args, "query");
13062
+ if (!row) throw new NotFoundError(q);
13063
+ return row;
13064
+ },
13065
+ async takeOptional(...args) {
13066
+ const { rows } = await performQuery(q, args, "query");
13067
+ return rows[0];
13068
+ },
13069
+ async rows(...args) {
13070
+ const { rows } = await performQuery(q, args, "arrays");
13071
+ return rows;
13072
+ },
13073
+ async pluck(...args) {
13074
+ const { rows } = await performQuery(q, args, "arrays");
13075
+ return rows.map((row) => row[0]);
13076
+ },
13077
+ async get(...args) {
13078
+ const {
13079
+ rows: [row]
13080
+ } = await performQuery(q, args, "arrays");
13081
+ if (!row) throw new NotFoundError(q);
13082
+ return row[0];
13083
+ },
13084
+ async getOptional(...args) {
13085
+ const { rows } = await performQuery(q, args, "arrays");
13086
+ return rows[0]?.[0];
13087
+ }
13088
+ }
13089
+ );
13090
+ }
13091
+ return query;
13000
13092
  }
13001
13093
  /**
13002
- * The same as the {@link query}, but returns an array of arrays instead of objects:
13094
+ * Performs a SQL query, returns a db result with array of arrays instead of objects:
13003
13095
  *
13004
13096
  * ```ts
13005
13097
  * const value = 1;
@@ -13034,43 +13126,6 @@ class Db extends QueryMethods {
13034
13126
  return map.get(name);
13035
13127
  }
13036
13128
  }
13037
- const performQuery = async (q, args, method) => {
13038
- const trx = q.internal.transactionStorage.getStore();
13039
- let sql;
13040
- if (isRawSQL(args[0])) {
13041
- const values = [];
13042
- sql = {
13043
- text: args[0].toSQL({ values }),
13044
- values
13045
- };
13046
- } else {
13047
- const values = [];
13048
- sql = {
13049
- text: templateLiteralToSQL(args, {
13050
- queryBuilder: q.queryBuilder,
13051
- q: q.q,
13052
- sql: [],
13053
- values
13054
- }),
13055
- values
13056
- };
13057
- }
13058
- const log = trx?.log ?? q.q.log;
13059
- let logData;
13060
- if (log) logData = log.beforeQuery(sql);
13061
- try {
13062
- const result = await (trx?.adapter || q.adapter)[method](
13063
- sql
13064
- );
13065
- if (log) log.afterQuery(sql, logData);
13066
- return result;
13067
- } catch (err) {
13068
- if (log) {
13069
- log.onError(err, sql, logData);
13070
- }
13071
- throw err;
13072
- }
13073
- };
13074
13129
  applyMixins(Db, [QueryMethods]);
13075
13130
  Db.prototype.constructor = Db;
13076
13131
  const createDb = ({
@@ -13119,9 +13174,7 @@ const createDb = ({
13119
13174
  adapter,
13120
13175
  close: () => adapter.close()
13121
13176
  });
13122
- for (const name of Object.getOwnPropertyNames(Db.prototype)) {
13123
- db[name] = Db.prototype[name];
13124
- }
13177
+ Object.setPrototypeOf(db, Db.prototype);
13125
13178
  db.sql = (...args) => {
13126
13179
  const sql = raw(...args);
13127
13180
  sql.columnTypes = ct;
@@ -13154,13 +13207,13 @@ const _initQueryBuilder = (adapter, columnTypes, transactionStorage, commonOptio
13154
13207
  }
13155
13208
  qb.internal.domains = options.domains;
13156
13209
  qb.internal.generatorIgnore = options.generatorIgnore;
13157
- return qb.queryBuilder = qb;
13210
+ return qb.qb = qb;
13158
13211
  };
13159
13212
 
13160
13213
  class Rollback extends Error {
13161
13214
  }
13162
13215
  const trxForTest = Symbol("trxForTest");
13163
- const argToDb = (arg) => "$queryBuilder" in arg ? arg.$queryBuilder : arg;
13216
+ const argToDb = (arg) => "$qb" in arg ? arg.$qb : arg;
13164
13217
  const testTransaction = {
13165
13218
  /**
13166
13219
  * Start a test transaction.