pqb 0.46.1 → 0.46.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
@@ -414,7 +414,7 @@ class ColumnType extends ColumnTypeBase {
414
414
  */
415
415
  generated(...args) {
416
416
  const sql = raw(...args);
417
- return setColumnData(this, "generated", {
417
+ const column = setColumnData(this, "generated", {
418
418
  toSQL(ctx, quoted) {
419
419
  return sql.toSQL(ctx, quoted);
420
420
  },
@@ -429,6 +429,8 @@ class ColumnType extends ColumnTypeBase {
429
429
  return sql2;
430
430
  }
431
431
  });
432
+ column.data.readonly = true;
433
+ return column;
432
434
  }
433
435
  }
434
436
 
@@ -1526,7 +1528,7 @@ class TsVectorColumn extends ColumnType {
1526
1528
  let sql;
1527
1529
  if (Array.isArray(target)) {
1528
1530
  const columns = target.length === 1 ? `"${snakeCase ? toSnakeCase(target[0]) : target[0]}"` : target.map(
1529
- (column) => `coalesce("${snakeCase ? toSnakeCase(column) : column}", '')`
1531
+ (column2) => `coalesce("${snakeCase ? toSnakeCase(column2) : column2}", '')`
1530
1532
  ).join(` || ' ' || `);
1531
1533
  sql = `to_tsvector('${language}', ${columns})`;
1532
1534
  } else {
@@ -1564,10 +1566,12 @@ class TsVectorColumn extends ColumnType {
1564
1566
  }
1565
1567
  return code + ")";
1566
1568
  };
1567
- return setColumnData(this, "generated", {
1569
+ const column = setColumnData(this, "generated", {
1568
1570
  toSQL,
1569
1571
  toCode
1570
1572
  });
1573
+ column.data.readonly = true;
1574
+ return column;
1571
1575
  }
1572
1576
  }
1573
1577
  class TsQueryColumn extends ColumnType {
@@ -2048,7 +2052,8 @@ const columnWithDotToSql = (ctx, data, shape, column, index, quotedAs, select) =
2048
2052
  const table = column.slice(0, index);
2049
2053
  const key = column.slice(index + 1);
2050
2054
  if (key === "*") {
2051
- return data.joinedShapes?.[table] ? select ? `row_to_json("${table}".*)` : `"${table}".*` : column;
2055
+ const shape2 = data.joinedShapes?.[table];
2056
+ return shape2 ? select ? makeRowToJson(table, shape2, true) : `"${table}".*` : column;
2052
2057
  }
2053
2058
  const tableName = data.aliases?.[table] || table;
2054
2059
  const quoted = `"${table}"`;
@@ -2064,7 +2069,7 @@ const columnWithDotToSql = (ctx, data, shape, column, index, quotedAs, select) =
2064
2069
  }
2065
2070
  return `"${tableName}"."${key}"`;
2066
2071
  };
2067
- const columnToSqlWithAs = (ctx, data, column, as, quotedAs, select) => {
2072
+ const columnToSqlWithAs = (ctx, data, column, as, quotedAs, select, jsonList) => {
2068
2073
  const index = column.indexOf(".");
2069
2074
  return index !== -1 ? tableColumnToSqlWithAs(
2070
2075
  ctx,
@@ -2073,26 +2078,18 @@ const columnToSqlWithAs = (ctx, data, column, as, quotedAs, select) => {
2073
2078
  column.slice(0, index),
2074
2079
  column.slice(index + 1),
2075
2080
  as,
2076
- quotedAs) : ownColumnToSqlWithAs(ctx, data, column, as, quotedAs, select);
2081
+ quotedAs,
2082
+ select,
2083
+ jsonList
2084
+ ) : ownColumnToSqlWithAs(ctx, data, column, as, quotedAs, select, jsonList);
2077
2085
  };
2078
- const tableColumnToSqlWithAs = (ctx, data, column, table, key, as, quotedAs, select) => {
2086
+ const tableColumnToSqlWithAs = (ctx, data, column, table, key, as, quotedAs, select, jsonList) => {
2079
2087
  if (key === "*") {
2088
+ if (jsonList) jsonList[as] = void 0;
2080
2089
  const shape = data.joinedShapes?.[table];
2081
2090
  if (shape) {
2082
2091
  {
2083
- let isSimple = true;
2084
- const list = [];
2085
- for (const key2 in shape) {
2086
- const column2 = shape[key2];
2087
- if (column2.data.explicitSelect || column2 instanceof VirtualColumn) {
2088
- continue;
2089
- }
2090
- if (column2.data.name) {
2091
- isSimple = false;
2092
- }
2093
- list.push(`'${key2}'`, `"${table}"."${column2.data.name || key2}"`);
2094
- }
2095
- return (isSimple ? `row_to_json("${table}".*)` : "json_build_object(" + list.join(", ") + ")") + ` "${as}"`;
2092
+ return makeRowToJson(table, shape, true) + ` "${as}"`;
2096
2093
  }
2097
2094
  }
2098
2095
  return column;
@@ -2114,12 +2111,10 @@ const tableColumnToSqlWithAs = (ctx, data, column, table, key, as, quotedAs, sel
2114
2111
  )} "${as}"`;
2115
2112
  }
2116
2113
  }
2114
+ if (jsonList) jsonList[as] = col;
2117
2115
  return `"${tableName}"."${key}"${key === as ? "" : ` "${as}"`}`;
2118
2116
  };
2119
- const ownColumnToSqlWithAs = (ctx, data, column, as, quotedAs, select) => {
2120
- if (!select && data.joinedShapes?.[column]) {
2121
- return select ? `row_to_json("${column}".*) "${as}"` : `"${column}".r "${as}"`;
2122
- }
2117
+ const ownColumnToSqlWithAs = (ctx, data, column, as, quotedAs, select, jsonList) => {
2123
2118
  const col = data.shape[column];
2124
2119
  if (col) {
2125
2120
  if (col.data.name && col.data.name !== column) {
@@ -2135,6 +2130,7 @@ const ownColumnToSqlWithAs = (ctx, data, column, as, quotedAs, select) => {
2135
2130
  )} "${as}"`;
2136
2131
  }
2137
2132
  }
2133
+ if (jsonList) jsonList[as] = col;
2138
2134
  return `${quotedAs ? `${quotedAs}.` : ""}"${column}"${column === as ? "" : ` "${as}"`}`;
2139
2135
  };
2140
2136
  const rawOrColumnToSql = (ctx, data, expr, quotedAs, shape = data.shape, select) => {
@@ -2143,6 +2139,23 @@ const rawOrColumnToSql = (ctx, data, expr, quotedAs, shape = data.shape, select)
2143
2139
  const quoteSchemaAndTable = (schema, table) => {
2144
2140
  return schema ? `"${schema}"."${table}"` : `"${table}"`;
2145
2141
  };
2142
+ const makeRowToJson = (table, shape, aliasName) => {
2143
+ let isSimple = true;
2144
+ const list = [];
2145
+ for (const key in shape) {
2146
+ const column = shape[key];
2147
+ if (column.data.explicitSelect || column instanceof VirtualColumn) {
2148
+ continue;
2149
+ }
2150
+ if (aliasName && column.data.name || column.data.jsonCast) {
2151
+ isSimple = false;
2152
+ }
2153
+ list.push(
2154
+ `'${key}', "${table}"."${aliasName && column.data.name || key}"${column.data.jsonCast ? `::${column.data.jsonCast}` : ""}`
2155
+ );
2156
+ }
2157
+ return isSimple ? `row_to_json("${table}".*)` : "json_build_object(" + list.join(", ") + ")";
2158
+ };
2146
2159
 
2147
2160
  const queryTypeWithLimitOne = {
2148
2161
  one: true,
@@ -2498,6 +2511,7 @@ class NumberAsStringBaseColumn extends ColumnType {
2498
2511
  constructor(schema) {
2499
2512
  super(schema, schema.stringSchema());
2500
2513
  this.operators = Operators.number;
2514
+ this.data.jsonCast = "text";
2501
2515
  }
2502
2516
  }
2503
2517
  class DecimalColumn extends NumberAsStringBaseColumn {
@@ -3057,6 +3071,7 @@ const applyComputedColumns = (q, fn) => {
3057
3071
  const data = (q.shape[key] = item.result.value || UnknownColumn.instance).data;
3058
3072
  data.computed = item;
3059
3073
  data.explicitSelect = true;
3074
+ data.readonly = true;
3060
3075
  }
3061
3076
  }
3062
3077
  q.computeAtRuntime = q.computeBatchAtRuntime = void 0;
@@ -4409,15 +4424,53 @@ function cloneQueryBaseUnscoped(query) {
4409
4424
  return q;
4410
4425
  }
4411
4426
 
4427
+ class RowToJsonExpression extends Expression {
4428
+ constructor(from, one, coalesce) {
4429
+ super();
4430
+ this.from = from;
4431
+ this.one = one;
4432
+ this.coalesce = coalesce;
4433
+ this.result = { value: UnknownColumn.instance };
4434
+ this.q = { expr: this };
4435
+ }
4436
+ makeSQL(ctx) {
4437
+ const q = this.from;
4438
+ const aliases = [];
4439
+ const jsonList = {};
4440
+ const select = selectToSql(
4441
+ ctx,
4442
+ q,
4443
+ q.q,
4444
+ `"${getQueryAs(q)}"`,
4445
+ q.q.hookSelect,
4446
+ aliases,
4447
+ void 0,
4448
+ jsonList
4449
+ );
4450
+ q.q.selectCache = { sql: select, aliases };
4451
+ let rowToJson;
4452
+ if (Object.values(jsonList).some((x) => x?.data.jsonCast)) {
4453
+ rowToJson = `json_build_object(${Object.entries(jsonList).map(
4454
+ ([key, column]) => `'${key}', t.${key}${column?.data.jsonCast ? `::${column.data.jsonCast}` : ""}`
4455
+ ).join(", ")})`;
4456
+ } else {
4457
+ rowToJson = "row_to_json(t.*)";
4458
+ }
4459
+ return this.one ? rowToJson : this.coalesce !== false ? `COALESCE(json_agg(${rowToJson}), '[]')` : `json_agg(${rowToJson})`;
4460
+ }
4461
+ }
4412
4462
  function queryJson(self, coalesce) {
4463
+ const inner = self.clone();
4413
4464
  const q = queryWrap(
4414
- self,
4465
+ inner,
4415
4466
  cloneQueryBaseUnscoped(self)
4416
4467
  );
4417
4468
  _queryGetOptional(
4418
4469
  q,
4419
- new RawSQL(
4420
- queryTypeWithLimitOne[self.q.returnType] ? `row_to_json("t".*)` : coalesce !== false ? `COALESCE(json_agg(row_to_json("t".*)), '[]')` : 'json_agg(row_to_json("t".*))'
4470
+ new RowToJsonExpression(
4471
+ inner,
4472
+ queryTypeWithLimitOne[self.q.returnType],
4473
+ coalesce
4421
4474
  )
4422
4475
  );
4423
4476
  q.q.returnsOne = true;
@@ -4724,17 +4777,22 @@ const makeReturningSql = (ctx, q, data, quotedAs, hookSelectI, addHookSelectI) =
4724
4777
  };
4725
4778
 
4726
4779
  const pushSelectSql = (ctx, table, query, quotedAs, aliases) => {
4727
- const sql = selectToSql(
4728
- ctx,
4729
- table,
4730
- query,
4731
- quotedAs,
4732
- query.hookSelect,
4733
- aliases
4734
- );
4735
- if (sql) ctx.sql.push(sql);
4780
+ if (query.selectCache) {
4781
+ ctx.sql.push(query.selectCache.sql);
4782
+ if (aliases) aliases.push(...query.selectCache.aliases);
4783
+ } else {
4784
+ const sql = selectToSql(
4785
+ ctx,
4786
+ table,
4787
+ query,
4788
+ quotedAs,
4789
+ query.hookSelect,
4790
+ aliases
4791
+ );
4792
+ if (sql) ctx.sql.push(sql);
4793
+ }
4736
4794
  };
4737
- const selectToSql = (ctx, table, query, quotedAs, hookSelect = query.hookSelect, aliases, skipCTE) => {
4795
+ const selectToSql = (ctx, table, query, quotedAs, hookSelect = query.hookSelect, aliases, skipCTE, jsonList) => {
4738
4796
  if (query.inCTE && !skipCTE) {
4739
4797
  const { select } = makeReturningSql(
4740
4798
  ctx,
@@ -4757,13 +4815,15 @@ const selectToSql = (ctx, table, query, quotedAs, hookSelect = query.hookSelect,
4757
4815
  selected[key] = quotedAs;
4758
4816
  }
4759
4817
  }
4760
- sql = selectAllSql(query, quotedAs);
4818
+ sql = selectAllSql(query, quotedAs, jsonList);
4761
4819
  } else {
4762
4820
  const index = item.indexOf(".");
4763
4821
  if (index !== -1) {
4764
4822
  const tableName = item.slice(0, index);
4765
4823
  const key = item.slice(index + 1);
4766
- if (hookSelect?.get(key)) (selected ?? (selected = {}))[key] = `"${tableName}"`;
4824
+ if (hookSelect?.get(key)) {
4825
+ (selected ?? (selected = {}))[key] = `"${tableName}"`;
4826
+ }
4767
4827
  sql = tableColumnToSqlWithAs(
4768
4828
  ctx,
4769
4829
  table.q,
@@ -4771,7 +4831,10 @@ const selectToSql = (ctx, table, query, quotedAs, hookSelect = query.hookSelect,
4771
4831
  tableName,
4772
4832
  key,
4773
4833
  key === "*" ? tableName : key,
4774
- quotedAs);
4834
+ quotedAs,
4835
+ true,
4836
+ jsonList
4837
+ );
4775
4838
  } else {
4776
4839
  if (hookSelect?.get(item)) (selected ?? (selected = {}))[item] = quotedAs;
4777
4840
  sql = ownColumnToSqlWithAs(
@@ -4780,7 +4843,8 @@ const selectToSql = (ctx, table, query, quotedAs, hookSelect = query.hookSelect,
4780
4843
  item,
4781
4844
  item,
4782
4845
  quotedAs,
4783
- true
4846
+ true,
4847
+ jsonList
4784
4848
  );
4785
4849
  }
4786
4850
  }
@@ -4795,9 +4859,15 @@ const selectToSql = (ctx, table, query, quotedAs, hookSelect = query.hookSelect,
4795
4859
  if (typeof value === "object") {
4796
4860
  if (isExpression(value)) {
4797
4861
  list.push(`${value.toSQL(ctx, quotedAs)} "${as}"`);
4862
+ if (jsonList) {
4863
+ jsonList[as] = value.result.value;
4864
+ }
4798
4865
  aliases?.push(as);
4799
4866
  } else {
4800
- pushSubQuerySql(ctx, value, as, list, quotedAs, aliases);
4867
+ pushSubQuerySql(ctx, query, value, as, list, quotedAs, aliases);
4868
+ if (jsonList) {
4869
+ jsonList[as] = value.q.returnType === "value" || value.q.returnType === "valueOrThrow" ? value.q.expr?.result.value || value.result?.value : void 0;
4870
+ }
4801
4871
  }
4802
4872
  } else if (value) {
4803
4873
  list.push(
@@ -4807,7 +4877,8 @@ const selectToSql = (ctx, table, query, quotedAs, hookSelect = query.hookSelect,
4807
4877
  value,
4808
4878
  as,
4809
4879
  quotedAs,
4810
- true
4880
+ true,
4881
+ jsonList
4811
4882
  )
4812
4883
  );
4813
4884
  aliases?.push(as);
@@ -4841,32 +4912,39 @@ const selectToSql = (ctx, table, query, quotedAs, hookSelect = query.hookSelect,
4841
4912
  col = query.shape[select];
4842
4913
  sql = simpleColumnToSQL(ctx, query, select, col, quotedAs);
4843
4914
  }
4915
+ let name = columnName;
4844
4916
  if (selected?.[columnName]) {
4845
4917
  if (selected?.[columnName] === quotedTable) {
4846
4918
  hookSelect.delete(column);
4847
4919
  continue;
4848
4920
  }
4849
4921
  let i = 2;
4850
- let name;
4851
4922
  while (selected[name = `${column}${i}`]) i++;
4852
4923
  item.as = name;
4853
4924
  sql += ` "${name}"`;
4854
4925
  } else if (col?.data.name) {
4855
4926
  sql += ` "${columnName}"`;
4856
4927
  }
4928
+ if (jsonList) jsonList[name] = col;
4857
4929
  list.push(sql);
4858
4930
  }
4859
4931
  }
4860
- return list.length ? list.join(", ") : query.select ? "" : selectAllSql(query, quotedAs);
4932
+ return list.length ? list.join(", ") : query.select ? "" : selectAllSql(query, quotedAs, jsonList);
4861
4933
  };
4862
4934
  function selectedObjectToSQL(ctx, quotedAs, item) {
4863
4935
  const sql = item.toSQL(ctx, quotedAs);
4864
4936
  return ctx.aliasValue ? `${sql} r` : sql;
4865
4937
  }
4866
- const selectAllSql = (query, quotedAs) => {
4938
+ const selectAllSql = (query, quotedAs, jsonList) => {
4939
+ if (jsonList) {
4940
+ Object.assign(
4941
+ jsonList,
4942
+ query.selectAllKeys || query.shape
4943
+ );
4944
+ }
4867
4945
  return query.join?.length ? query.selectAllColumns?.map((item) => `${quotedAs}.${item}`).join(", ") || `${quotedAs}.*` : query.selectAllColumns?.join(", ") || "*";
4868
4946
  };
4869
- const pushSubQuerySql = (ctx, query, as, list, quotedAs, aliases) => {
4947
+ const pushSubQuerySql = (ctx, mainQuery, query, as, list, quotedAs, aliases) => {
4870
4948
  const { returnType = "all" } = query.q;
4871
4949
  if (isQueryNone(query)) {
4872
4950
  let sql;
@@ -4899,9 +4977,12 @@ const pushSubQuerySql = (ctx, query, as, list, quotedAs, aliases) => {
4899
4977
  let sql;
4900
4978
  switch (returnType) {
4901
4979
  case "one":
4902
- case "oneOrThrow":
4903
- sql = `row_to_json("${query.q.joinedForSelect}".*)`;
4980
+ case "oneOrThrow": {
4981
+ const table = query.q.joinedForSelect;
4982
+ const shape = mainQuery.joinedShapes?.[as];
4983
+ sql = makeRowToJson(table, shape, false);
4904
4984
  break;
4985
+ }
4905
4986
  case "all":
4906
4987
  case "pluck":
4907
4988
  case "value":
@@ -5409,6 +5490,7 @@ const makeSQL = (table, options) => {
5409
5490
  const values = options?.values || [];
5410
5491
  const ctx = {
5411
5492
  queryBuilder: table.queryBuilder,
5493
+ q: query,
5412
5494
  sql,
5413
5495
  values,
5414
5496
  aliasValue: options?.aliasValue
@@ -8190,7 +8272,7 @@ const processCreateItem = (q, item, rowIndex, ctx, encoders) => {
8190
8272
  item[key]
8191
8273
  );
8192
8274
  }
8193
- if (!ctx.columns.has(key) && (shape[key] && !shape[key].data.computed || shape === anyShape) && item[key] !== void 0) {
8275
+ if (!ctx.columns.has(key) && (shape[key] && !shape[key].data.readonly || shape === anyShape) && item[key] !== void 0) {
8194
8276
  ctx.columns.set(key, ctx.columns.size);
8195
8277
  encoders[key] = shape[key]?.data.encode;
8196
8278
  }
@@ -10460,7 +10542,7 @@ const _queryUpdate = (query, arg) => {
10460
10542
  if (item instanceof VirtualColumn && item.update) {
10461
10543
  item.update(query, ctx, set);
10462
10544
  delete set[key];
10463
- } else if ((!shape[key] || shape[key].data.computed) && shape !== anyShape) {
10545
+ } else if ((!shape[key] || shape[key].data.readonly) && shape !== anyShape) {
10464
10546
  delete set[key];
10465
10547
  } else {
10466
10548
  let value = set[key];
@@ -12799,6 +12881,7 @@ const performQuery = async (q, args, method) => {
12799
12881
  sql = {
12800
12882
  text: templateLiteralToSQL(args, {
12801
12883
  queryBuilder: q.queryBuilder,
12884
+ q: q.q,
12802
12885
  sql: [],
12803
12886
  values
12804
12887
  }),