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