pqb 0.23.4 → 0.24.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
@@ -1,4 +1,4 @@
1
- import { ExpressionTypeMethod, Expression, RawSQLBase, isTemplateLiteralArgs, ColumnTypeBase, setColumnData, pushColumnData, quoteObjectKey, toArray, singleQuote, addCode, objectHasValues, singleQuoteArray, columnDefaultArgumentToCode, columnErrorMessagesToCode, isExpression, arrayDataToCode, noop, setParserToQuery, applyTransforms, getValueKey, emptyObject, emptyArray, isRawSQL, pushOrNewArray, pushOrNewArrayToObject, joinTruthy, numberDataToCode, stringDataToCode, getDefaultLanguage, dateDataToCode, setDefaultNowFn, setDefaultLanguage, makeTimestampsHelpers, setCurrentColumnName, setAdapterConnectRetry, applyMixins, callWithThis, isObjectEmpty, toSnakeCase, snakeCaseKey } from 'orchid-core';
1
+ import { ExpressionTypeMethod, Expression, RawSQLBase, isTemplateLiteralArgs, ColumnTypeBase, setColumnData, pushColumnData, emptyObject, quoteObjectKey, toArray, singleQuote, addCode, objectHasValues, singleQuoteArray, columnDefaultArgumentToCode, columnErrorMessagesToCode, isExpression, dateDataToCode, joinTruthy, arrayDataToCode, noop, setParserToQuery, applyTransforms, getValueKey, emptyArray, isRawSQL, pushOrNewArray, pushOrNewArrayToObject, numberDataToCode, stringDataToCode, getDefaultLanguage, setDefaultNowFn, setDefaultLanguage, makeTimestampsHelpers, setCurrentColumnName, setAdapterConnectRetry, applyMixins, callWithThis, isObjectEmpty, toSnakeCase, 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';
@@ -138,13 +138,9 @@ class ColumnType extends ColumnTypeBase {
138
138
  * ```
139
139
  */
140
140
  primaryKey() {
141
- return setColumnData(
142
- this,
143
- "isPrimaryKey",
144
- true
145
- );
141
+ return setColumnData(this, "isPrimaryKey", true);
146
142
  }
147
- foreignKey(fnOrTable, column, options = {}) {
143
+ foreignKey(fnOrTable, column, options = emptyObject) {
148
144
  const item = typeof fnOrTable === "string" ? __spreadValues$g({ table: fnOrTable, columns: [column] }, options) : __spreadValues$g({ fn: fnOrTable, columns: [column] }, options);
149
145
  return pushColumnData(this, "foreignKeys", item);
150
146
  }
@@ -727,7 +723,7 @@ const columnToSqlWithAs = (ctx, data, column, quotedAs, select) => {
727
723
  const col = data.shape[column];
728
724
  if (col) {
729
725
  if (col.data.name && col.data.name !== column) {
730
- return `${quotedAs ? `${quotedAs}.` : ""}"${col.data.name}" AS "${column}"`;
726
+ return `${quotedAs ? `${quotedAs}.` : ""}"${col.data.name}" "${column}"`;
731
727
  }
732
728
  if (col.data.computed) {
733
729
  return `${col.data.computed.toSQL(ctx, quotedAs)} "${column}"`;
@@ -738,7 +734,7 @@ const columnToSqlWithAs = (ctx, data, column, quotedAs, select) => {
738
734
  const ownColumnToSql = (data, column, quotedAs) => {
739
735
  var _a;
740
736
  const name = (_a = data.shape[column]) == null ? void 0 : _a.data.name;
741
- return `${quotedAs ? `${quotedAs}.` : ""}"${name || column}"${name && name !== column ? ` AS "${column}"` : ""}`;
737
+ return `${quotedAs ? `${quotedAs}.` : ""}"${name || column}"${name && name !== column ? ` "${column}"` : ""}`;
742
738
  };
743
739
  const rawOrColumnToSql = (ctx, data, expr, quotedAs, shape = data.shape, select) => {
744
740
  return typeof expr === "string" ? columnToSql(ctx, data, shape, expr, quotedAs, select) : expr.toSQL(ctx, quotedAs);
@@ -830,7 +826,7 @@ class JSONColumn extends ColumnType {
830
826
  JSONColumn.prototype.encodeFn = JSON.stringify;
831
827
  class JSONTextColumn extends ColumnType {
832
828
  constructor(schema) {
833
- super(schema, schema.string);
829
+ super(schema, schema.stringSchema);
834
830
  this.dataType = "json";
835
831
  this.operators = Operators.text;
836
832
  }
@@ -1105,8 +1101,7 @@ var __spreadProps$8 = (a, b) => __defProps$8(a, __getOwnPropDescs$8(b));
1105
1101
  const processJoinItem = (ctx, table, query, item, quotedAs) => {
1106
1102
  let target;
1107
1103
  let conditions;
1108
- const { args } = item;
1109
- const [first] = args;
1104
+ const { first, args } = item;
1110
1105
  if (typeof first === "string") {
1111
1106
  if (first in table.relations) {
1112
1107
  const { query: toQuery, joinQuery } = table.relations[first].relationConfig;
@@ -1127,8 +1122,8 @@ const processJoinItem = (ctx, table, query, item, quotedAs) => {
1127
1122
  and: j.and ? [...j.and] : [],
1128
1123
  or: j.or ? [...j.or] : []
1129
1124
  };
1130
- if (args[1]) {
1131
- const arg = args[1](
1125
+ if (args[0]) {
1126
+ const arg = args[0](
1132
1127
  new ctx.queryBuilder.onQueryBuilder(jq, j, table)
1133
1128
  ).q;
1134
1129
  if (arg.and)
@@ -1205,8 +1200,8 @@ const processJoinItem = (ctx, table, query, item, quotedAs) => {
1205
1200
  };
1206
1201
  const processArgs = (args, ctx, table, query, first, joinAs, joinShape, quotedAs) => {
1207
1202
  var _a;
1208
- if (args.length === 2) {
1209
- const arg = args[1];
1203
+ if (args.length === 1) {
1204
+ const arg = args[0];
1210
1205
  if (typeof arg === "function") {
1211
1206
  const joinedShapes = __spreadProps$8(__spreadValues$e({}, query.joinedShapes), {
1212
1207
  [table.q.as || table.table]: table.shape
@@ -1267,7 +1262,7 @@ const processArgs = (args, ctx, table, query, first, joinAs, joinShape, quotedAs
1267
1262
  joinShape
1268
1263
  );
1269
1264
  }
1270
- } else if (args.length >= 3) {
1265
+ } else if (args.length >= 2) {
1271
1266
  return getConditionsFor3Or4LengthItem(
1272
1267
  ctx,
1273
1268
  query,
@@ -1280,7 +1275,7 @@ const processArgs = (args, ctx, table, query, first, joinAs, joinShape, quotedAs
1280
1275
  return void 0;
1281
1276
  };
1282
1277
  const getConditionsFor3Or4LengthItem = (ctx, query, target, quotedAs, args, joinShape) => {
1283
- const [, leftColumn, opOrRightColumn, maybeRightColumn] = args;
1278
+ const [leftColumn, opOrRightColumn, maybeRightColumn] = args;
1284
1279
  const op = maybeRightColumn ? opOrRightColumn : "=";
1285
1280
  const rightColumn = maybeRightColumn ? maybeRightColumn : opOrRightColumn;
1286
1281
  return `${rawOrColumnToSql(
@@ -1379,17 +1374,16 @@ var __spreadValues$d = (a, b) => {
1379
1374
  return a;
1380
1375
  };
1381
1376
  var __spreadProps$7 = (a, b) => __defProps$7(a, __getOwnPropDescs$7(b));
1382
- const _join = (q, require2, type, args) => {
1377
+ const _join = (q, require2, type, first, args) => {
1383
1378
  var _a;
1384
1379
  let joinKey;
1385
1380
  let shape;
1386
1381
  let parsers;
1387
1382
  let isSubQuery = false;
1388
- if (typeof args[0] === "function") {
1389
- args[0] = args[0](q.relations);
1390
- args[0].joinQueryAfterCallback = args[0].joinQuery;
1383
+ if (typeof first === "function") {
1384
+ first = first(q.relations);
1385
+ first.joinQueryAfterCallback = first.joinQuery;
1391
1386
  }
1392
- const first = args[0];
1393
1387
  if (typeof first === "object") {
1394
1388
  isSubQuery = getIsJoinSubQuery(first.q, first.baseQuery.q);
1395
1389
  joinKey = first.q.as || first.table;
@@ -1397,8 +1391,8 @@ const _join = (q, require2, type, args) => {
1397
1391
  shape = getShapeFromSelect(first, isSubQuery);
1398
1392
  parsers = first.q.parsers;
1399
1393
  if (isSubQuery) {
1400
- args[0] = first.clone();
1401
- args[0].shape = shape;
1394
+ first = first.clone();
1395
+ first.shape = shape;
1402
1396
  }
1403
1397
  }
1404
1398
  } else {
@@ -1428,12 +1422,14 @@ const _join = (q, require2, type, args) => {
1428
1422
  }
1429
1423
  return pushQueryValue(q, "join", {
1430
1424
  type,
1425
+ first,
1431
1426
  args,
1432
1427
  isSubQuery
1433
1428
  });
1434
1429
  };
1435
- const _joinLateral = (q, type, arg, cb, as) => {
1430
+ const _joinLateral = (self, type, arg, cb, as) => {
1436
1431
  var _a, _b, _c;
1432
+ const q = self;
1437
1433
  let relation;
1438
1434
  if (typeof arg === "string") {
1439
1435
  relation = q.relations[arg];
@@ -1476,6 +1472,129 @@ const _joinLateral = (q, type, arg, cb, as) => {
1476
1472
  ]);
1477
1473
  };
1478
1474
 
1475
+ const dateTimeEncode = (input) => {
1476
+ return typeof input === "number" ? new Date(input) : input;
1477
+ };
1478
+ const skipDateMethodsFromToCode = { encodeFn: dateTimeEncode };
1479
+ class DateBaseColumn extends ColumnType {
1480
+ constructor(schema) {
1481
+ super(schema, schema.stringNumberDate);
1482
+ this.operators = Operators.date;
1483
+ this.encodeFn = dateTimeEncode;
1484
+ this.asNumber = schema.dateAsNumber;
1485
+ this.asDate = schema.dateAsDate;
1486
+ }
1487
+ }
1488
+ class DateColumn extends DateBaseColumn {
1489
+ constructor() {
1490
+ super(...arguments);
1491
+ this.dataType = "date";
1492
+ }
1493
+ toCode(t) {
1494
+ return columnCode(
1495
+ this,
1496
+ t,
1497
+ `date()${dateDataToCode(this.data)}`,
1498
+ this.data,
1499
+ skipDateMethodsFromToCode
1500
+ );
1501
+ }
1502
+ }
1503
+ class DateTimeBaseClass extends DateBaseColumn {
1504
+ constructor(schema, dateTimePrecision) {
1505
+ super(schema);
1506
+ this.data.dateTimePrecision = dateTimePrecision;
1507
+ }
1508
+ toSQL() {
1509
+ return joinTruthy(
1510
+ this.dataType,
1511
+ this.data.dateTimePrecision !== void 0 && `(${this.data.dateTimePrecision})`
1512
+ );
1513
+ }
1514
+ }
1515
+ class DateTimeTzBaseClass extends DateTimeBaseClass {
1516
+ toSQL() {
1517
+ return joinTruthy(
1518
+ this.baseDataType,
1519
+ this.data.dateTimePrecision !== void 0 && `(${this.data.dateTimePrecision})`,
1520
+ " with time zone"
1521
+ );
1522
+ }
1523
+ }
1524
+ const timestampToCode = (self, t) => {
1525
+ const { dateTimePrecision: p } = self.data;
1526
+ return columnCode(
1527
+ self,
1528
+ t,
1529
+ `${self instanceof TimestampColumn ? "timestampNoTZ" : "timestamp"}(${p && p !== 6 ? p : ""})${dateDataToCode(self.data)}`,
1530
+ self.data,
1531
+ skipDateMethodsFromToCode
1532
+ );
1533
+ };
1534
+ class TimestampColumn extends DateTimeBaseClass {
1535
+ constructor() {
1536
+ super(...arguments);
1537
+ this.dataType = "timestamp";
1538
+ }
1539
+ toCode(t) {
1540
+ return timestampToCode(this, t);
1541
+ }
1542
+ }
1543
+ class TimestampTZColumn extends DateTimeTzBaseClass {
1544
+ constructor() {
1545
+ super(...arguments);
1546
+ this.dataType = "timestamptz";
1547
+ this.baseDataType = "timestamp";
1548
+ }
1549
+ toCode(t) {
1550
+ return timestampToCode(this, t);
1551
+ }
1552
+ }
1553
+ class TimeColumn extends ColumnType {
1554
+ constructor(schema, dateTimePrecision) {
1555
+ super(schema, schema.stringSchema);
1556
+ this.dataType = "time";
1557
+ this.operators = Operators.time;
1558
+ this.data.dateTimePrecision = dateTimePrecision;
1559
+ }
1560
+ toCode(t) {
1561
+ const { dateTimePrecision } = this.data;
1562
+ return columnCode(
1563
+ this,
1564
+ t,
1565
+ `time(${dateTimePrecision || ""})${dateDataToCode(this.data)}`,
1566
+ this.data,
1567
+ skipDateMethodsFromToCode
1568
+ );
1569
+ }
1570
+ }
1571
+ class IntervalColumn extends ColumnType {
1572
+ constructor(schema, fields, precision) {
1573
+ super(schema, schema.timeInterval);
1574
+ this.dataType = "interval";
1575
+ this.operators = Operators.date;
1576
+ this.data.fields = fields;
1577
+ this.data.precision = precision;
1578
+ }
1579
+ toCode(t) {
1580
+ const { fields, precision } = this.data;
1581
+ return columnCode(
1582
+ this,
1583
+ t,
1584
+ `interval(${[fields && `'${fields}'`, precision && String(precision)].filter((part) => part).join(", ")})`,
1585
+ this.data,
1586
+ skipDateMethodsFromToCode
1587
+ );
1588
+ }
1589
+ toSQL() {
1590
+ return joinTruthy(
1591
+ this.dataType,
1592
+ this.data.fields && ` ${this.data.fields}`,
1593
+ this.data.precision !== void 0 && ` (${this.data.precision})`
1594
+ );
1595
+ }
1596
+ }
1597
+
1479
1598
  class EnumColumn extends ColumnType {
1480
1599
  constructor(schema, enumName, options, schemaType) {
1481
1600
  super(schema, schemaType);
@@ -1634,7 +1753,25 @@ const defaultSchemaConfig = {
1634
1753
  json() {
1635
1754
  return new JSONColumn(defaultSchemaConfig, void 0);
1636
1755
  },
1637
- setErrors: noop
1756
+ setErrors: noop,
1757
+ smallint: () => new SmallIntColumn(defaultSchemaConfig),
1758
+ integer: () => new IntegerColumn(defaultSchemaConfig),
1759
+ real: () => new RealColumn(defaultSchemaConfig),
1760
+ smallSerial: () => new SmallSerialColumn(defaultSchemaConfig),
1761
+ serial: () => new SerialColumn(defaultSchemaConfig),
1762
+ bigint: () => new BigIntColumn(defaultSchemaConfig),
1763
+ decimal: (precision, scale) => new DecimalColumn(defaultSchemaConfig, precision, scale),
1764
+ doublePrecision: () => new DoublePrecisionColumn(defaultSchemaConfig),
1765
+ bigSerial: () => new BigSerialColumn(defaultSchemaConfig),
1766
+ money: () => new MoneyColumn(defaultSchemaConfig),
1767
+ varchar: (limit) => new VarCharColumn(defaultSchemaConfig, limit),
1768
+ char: (limit) => new CharColumn(defaultSchemaConfig, limit),
1769
+ text: (min, max) => new TextColumn(defaultSchemaConfig, min, max),
1770
+ string: (limit) => new StringColumn(defaultSchemaConfig, limit),
1771
+ citext: (min, max) => new CitextColumn(defaultSchemaConfig, min, max),
1772
+ date: () => new DateColumn(defaultSchemaConfig),
1773
+ timestampNoTZ: (precision) => new TimestampColumn(defaultSchemaConfig, precision),
1774
+ timestamp: (precision) => new TimestampTZColumn(defaultSchemaConfig, precision)
1638
1775
  };
1639
1776
 
1640
1777
  const addParserForRawExpression = (q, key, raw) => {
@@ -1675,17 +1812,15 @@ const addParserForSelectItem = (q, as, key, arg) => {
1675
1812
  });
1676
1813
  }
1677
1814
  }
1678
- } else {
1679
- setParserForSelectedString(q, arg, as, key);
1815
+ return arg;
1680
1816
  }
1681
- return arg;
1817
+ return setParserForSelectedString(q, arg, as, key);
1682
1818
  };
1683
1819
  const emptyArrSQL = new RawSQL("'[]'");
1684
1820
  const processSelectArg = (q, as, arg, columnAs) => {
1685
1821
  var _a, _b, _c, _d;
1686
1822
  if (typeof arg === "string") {
1687
- setParserForSelectedString(q, arg, as, columnAs);
1688
- return arg;
1823
+ return setParserForSelectedString(q, arg, as, columnAs);
1689
1824
  }
1690
1825
  const selectAs = {};
1691
1826
  for (const key in arg) {
@@ -1734,7 +1869,12 @@ const processSelectArg = (q, as, arg, columnAs) => {
1734
1869
  value = value.q.expr;
1735
1870
  }
1736
1871
  }
1737
- selectAs[key] = addParserForSelectItem(q, as, key, value);
1872
+ selectAs[key] = addParserForSelectItem(
1873
+ q,
1874
+ as,
1875
+ key,
1876
+ value
1877
+ );
1738
1878
  }
1739
1879
  return { selectAs };
1740
1880
  };
@@ -1746,21 +1886,25 @@ const setParserForSelectedString = (q, arg, as, columnAs) => {
1746
1886
  const column = arg.slice(index + 1);
1747
1887
  if (column === "*") {
1748
1888
  addParsersForSelectJoined(q, table, columnAs);
1889
+ return table === as ? column : arg;
1749
1890
  } else {
1750
1891
  if (table === as) {
1751
1892
  const parser = (_a = q.q.parsers) == null ? void 0 : _a[column];
1752
1893
  if (parser)
1753
1894
  setParserToQuery(q.q, columnAs || column, parser);
1895
+ return column;
1754
1896
  } else {
1755
1897
  const parser = (_c = (_b = q.q.joinedParsers) == null ? void 0 : _b[table]) == null ? void 0 : _c[column];
1756
1898
  if (parser)
1757
1899
  setParserToQuery(q.q, columnAs || column, parser);
1900
+ return arg;
1758
1901
  }
1759
1902
  }
1760
1903
  } else {
1761
1904
  const parser = (_d = q.q.parsers) == null ? void 0 : _d[arg];
1762
1905
  if (parser)
1763
1906
  setParserToQuery(q.q, columnAs || arg, parser);
1907
+ return arg;
1764
1908
  }
1765
1909
  };
1766
1910
  const getShapeFromSelect = (q, isSubQuery) => {
@@ -1892,40 +2036,46 @@ class SelectItemExpression extends Expression {
1892
2036
  }
1893
2037
  }
1894
2038
 
1895
- const _get = (q, returnType, arg) => {
2039
+ const _get = (query, returnType, arg) => {
1896
2040
  var _a, _b;
1897
- q.q.returnType = returnType;
2041
+ const q = query.q;
2042
+ q.returnType = returnType;
1898
2043
  let type;
1899
2044
  if (typeof arg === "string") {
1900
- type = q.q.shape[arg];
2045
+ type = q.shape[arg];
1901
2046
  if (!type) {
1902
2047
  const index = arg.indexOf(".");
1903
2048
  if (index !== -1) {
1904
2049
  const table = arg.slice(0, index);
1905
2050
  const column = arg.slice(index + 1);
1906
- if (table === (q.q.as || q.table)) {
1907
- type = q.q.shape[column];
2051
+ if (table === (q.as || query.table)) {
2052
+ type = q.shape[column];
1908
2053
  } else {
1909
- type = (_b = (_a = q.q.joinedShapes) == null ? void 0 : _a[table]) == null ? void 0 : _b[column];
2054
+ type = (_b = (_a = q.joinedShapes) == null ? void 0 : _a[table]) == null ? void 0 : _b[column];
1910
2055
  }
1911
2056
  }
1912
2057
  }
1913
- q.q[getValueKey] = type;
1914
- setParserForSelectedString(q, arg, getQueryAs(q), getValueKey);
1915
- q.q.expr = new SelectItemExpression(
1916
- q,
2058
+ q[getValueKey] = type;
2059
+ setParserForSelectedString(
2060
+ query,
2061
+ arg,
2062
+ getQueryAs(query),
2063
+ getValueKey
2064
+ );
2065
+ q.expr = new SelectItemExpression(
2066
+ query,
1917
2067
  arg,
1918
2068
  type || emptyObject
1919
2069
  );
1920
2070
  } else {
1921
2071
  type = arg._type;
1922
- q.q[getValueKey] = type;
1923
- addParserForRawExpression(q, getValueKey, arg);
1924
- q.q.expr = arg;
2072
+ q[getValueKey] = type;
2073
+ addParserForRawExpression(query, getValueKey, arg);
2074
+ q.expr = arg;
1925
2075
  }
1926
- q.q.select = [q.q.expr];
2076
+ q.select = [q.expr];
1927
2077
  return setQueryOperators(
1928
- q,
2078
+ query,
1929
2079
  (type == null ? void 0 : type.operators) || Operators.any
1930
2080
  );
1931
2081
  };
@@ -1936,27 +2086,11 @@ function _queryGetOptional(self, arg) {
1936
2086
  return _get(self, "value", arg);
1937
2087
  }
1938
2088
 
1939
- class QueryBase {
1940
- constructor() {
1941
- this.q = {};
1942
- }
1943
- /**
1944
- * Clones the current query chain, useful for re-using partial query snippets in other queries without mutating the original.
1945
- *
1946
- * Used under the hood, and not really needed on the app side.
1947
- */
1948
- clone() {
1949
- const cloned = Object.create(this.baseQuery);
1950
- cloned.q = getClonedQueryData(this.q);
1951
- return cloned;
1952
- }
1953
- }
1954
-
1955
2089
  const _queryAs = (self, as) => {
1956
2090
  self.q.as = as;
1957
2091
  return self;
1958
2092
  };
1959
- class AsMethods extends QueryBase {
2093
+ class AsMethods {
1960
2094
  /**
1961
2095
  * Sets table alias:
1962
2096
  *
@@ -1975,30 +2109,30 @@ class AsMethods extends QueryBase {
1975
2109
  }
1976
2110
 
1977
2111
  function queryFrom(self, args) {
1978
- var _a, _b, _c;
1979
2112
  if (Array.isArray(args[0])) {
1980
2113
  return queryFrom(self, [
1981
2114
  new RawSQL(args)
1982
2115
  ]);
1983
2116
  }
2117
+ const data = self.q;
1984
2118
  if (typeof args[0] === "string") {
1985
- (_a = self.q).as || (_a.as = args[0]);
2119
+ data.as || (data.as = args[0]);
1986
2120
  } else if (!isExpression(args[0])) {
1987
2121
  const q = args[0];
1988
- (_b = self.q).as || (_b.as = q.q.as || q.table || "t");
1989
- self.q.shape = getShapeFromSelect(
2122
+ data.as || (data.as = q.q.as || q.table || "t");
2123
+ data.shape = getShapeFromSelect(
1990
2124
  args[0],
1991
2125
  true
1992
2126
  );
1993
- self.q.parsers = q.q.parsers;
2127
+ data.parsers = q.q.parsers;
1994
2128
  } else {
1995
- (_c = self.q).as || (_c.as = "t");
2129
+ data.as || (data.as = "t");
1996
2130
  }
1997
2131
  const options = args[1];
1998
2132
  if (options == null ? void 0 : options.only) {
1999
- self.q.fromOnly = options.only;
2133
+ data.fromOnly = options.only;
2000
2134
  }
2001
- self.q.from = args[0];
2135
+ data.from = args[0];
2002
2136
  return self;
2003
2137
  }
2004
2138
  class From {
@@ -2031,19 +2165,22 @@ class From {
2031
2165
  * @param args - query, raw SQL, name of CTE table, or a template string
2032
2166
  */
2033
2167
  from(...args) {
2034
- return queryFrom(this.clone(), args);
2168
+ return queryFrom(
2169
+ this.clone(),
2170
+ args
2171
+ );
2035
2172
  }
2036
2173
  }
2037
2174
 
2038
2175
  function queryWrap(self, query, as = "t") {
2039
- return _queryAs(
2040
- queryFrom(query, [self]),
2041
- as
2042
- );
2176
+ return _queryAs(queryFrom(query, [self]), as);
2043
2177
  }
2044
2178
 
2045
2179
  function queryJson(self, coalesce) {
2046
- const q = queryWrap(self, self.baseQuery.clone());
2180
+ const q = queryWrap(
2181
+ self,
2182
+ self.baseQuery.clone()
2183
+ );
2047
2184
  _queryGetOptional(
2048
2185
  q,
2049
2186
  new RawSQL(
@@ -2113,7 +2250,7 @@ const selectToSql = (ctx, table, query, quotedAs) => {
2113
2250
  const value = obj[as];
2114
2251
  if (typeof value === "object" || typeof value === "function") {
2115
2252
  if (isExpression(value)) {
2116
- list.push(`${value.toSQL(ctx, quotedAs)} AS "${as}"`);
2253
+ list.push(`${value.toSQL(ctx, quotedAs)} "${as}"`);
2117
2254
  } else {
2118
2255
  pushSubQuerySql(ctx, value, as, list, quotedAs);
2119
2256
  }
@@ -2126,7 +2263,7 @@ const selectToSql = (ctx, table, query, quotedAs) => {
2126
2263
  value,
2127
2264
  quotedAs,
2128
2265
  true
2129
- )} AS "${as}"`
2266
+ )} "${as}"`
2130
2267
  );
2131
2268
  }
2132
2269
  }
@@ -2212,7 +2349,7 @@ const pushSubQuerySql = (ctx, query, as, list, quotedAs) => {
2212
2349
  query,
2213
2350
  `(${makeSQL(query, ctx).text})`,
2214
2351
  quotedAs
2215
- )} AS "${as}"`
2352
+ )} "${as}"`
2216
2353
  );
2217
2354
  };
2218
2355
  const coalesce = (ctx, query, sql, quotedAs) => {
@@ -3238,16 +3375,17 @@ var __spreadValues$a = (a, b) => {
3238
3375
  return a;
3239
3376
  };
3240
3377
  var __spreadProps$6 = (a, b) => __defProps$6(a, __getOwnPropDescs$6(b));
3241
- function setQueryOperators(q, operators) {
3242
- if (q.q.operators) {
3243
- if (q.q.operators === operators)
3244
- return q;
3245
- q.baseQuery = q.q.originalQuery;
3378
+ function setQueryOperators(query, operators) {
3379
+ const q = query.q;
3380
+ if (q.operators) {
3381
+ if (q.operators === operators)
3382
+ return query;
3383
+ query.baseQuery = q.originalQuery;
3246
3384
  } else {
3247
- q.q.originalQuery = q.baseQuery;
3385
+ q.originalQuery = query.baseQuery;
3248
3386
  }
3249
- q.q.operators = operators;
3250
- return extendQuery(q, operators);
3387
+ q.operators = operators;
3388
+ return extendQuery(query, operators);
3251
3389
  }
3252
3390
  const make = (_op) => {
3253
3391
  return Object.assign(
@@ -3380,13 +3518,13 @@ class IntegerBaseColumn extends NumberBaseColumn {
3380
3518
  }
3381
3519
  class NumberAsStringBaseColumn extends ColumnType {
3382
3520
  constructor(schema) {
3383
- super(schema, schema.string);
3521
+ super(schema, schema.stringSchema);
3384
3522
  this.operators = Operators.number;
3385
3523
  }
3386
3524
  }
3387
3525
  class DecimalColumn extends ColumnType {
3388
3526
  constructor(schema, numericPrecision, numericScale) {
3389
- super(schema, schema.string);
3527
+ super(schema, schema.stringSchema);
3390
3528
  this.operators = Operators.number;
3391
3529
  this.dataType = "decimal";
3392
3530
  this.data.numericPrecision = numericPrecision;
@@ -3545,14 +3683,14 @@ var __spreadValues$9 = (a, b) => {
3545
3683
  };
3546
3684
  var __spreadProps$5 = (a, b) => __defProps$5(a, __getOwnPropDescs$5(b));
3547
3685
  class TextBaseColumn extends ColumnType {
3548
- constructor(schema, schemaType = schema.string) {
3686
+ constructor(schema, schemaType = schema.stringSchema) {
3549
3687
  super(schema, schemaType);
3550
3688
  this.operators = Operators.text;
3551
3689
  }
3552
3690
  }
3553
3691
  class LimitedTextBaseColumn extends TextBaseColumn {
3554
3692
  constructor(schema, limit) {
3555
- super(schema, limit ? schema.stringMax(limit) : schema.string);
3693
+ super(schema, limit ? schema.stringMax(limit) : schema.stringSchema);
3556
3694
  this.data.maxChars = limit;
3557
3695
  }
3558
3696
  toSQL() {
@@ -3635,7 +3773,7 @@ const textColumnToCode = (column, t) => {
3635
3773
  `${column.dataType}(${args})${stringDataToCode(data)}`
3636
3774
  );
3637
3775
  };
3638
- const minMaxToSchema = (schema, min, max) => min ? max ? schema.stringMinMax(min, max) : schema.stringMin(min) : schema.string;
3776
+ const minMaxToSchema = (schema, min, max) => min ? max ? schema.stringMinMax(min, max) : schema.stringMin(min) : schema.stringSchema;
3639
3777
  class TextColumn extends TextBaseColumn {
3640
3778
  constructor(schema, min, max) {
3641
3779
  super(schema, minMaxToSchema(schema, min, max));
@@ -3658,7 +3796,7 @@ class ByteaColumn extends ColumnType {
3658
3796
  }
3659
3797
  class PointColumn extends ColumnType {
3660
3798
  constructor(schema) {
3661
- super(schema, schema.string);
3799
+ super(schema, schema.stringSchema);
3662
3800
  this.dataType = "point";
3663
3801
  this.operators = Operators.text;
3664
3802
  }
@@ -3668,7 +3806,7 @@ class PointColumn extends ColumnType {
3668
3806
  }
3669
3807
  class LineColumn extends ColumnType {
3670
3808
  constructor(schema) {
3671
- super(schema, schema.string);
3809
+ super(schema, schema.stringSchema);
3672
3810
  this.dataType = "line";
3673
3811
  this.operators = Operators.text;
3674
3812
  }
@@ -3678,7 +3816,7 @@ class LineColumn extends ColumnType {
3678
3816
  }
3679
3817
  class LsegColumn extends ColumnType {
3680
3818
  constructor(schema) {
3681
- super(schema, schema.string);
3819
+ super(schema, schema.stringSchema);
3682
3820
  this.dataType = "lseg";
3683
3821
  this.operators = Operators.text;
3684
3822
  }
@@ -3688,7 +3826,7 @@ class LsegColumn extends ColumnType {
3688
3826
  }
3689
3827
  class BoxColumn extends ColumnType {
3690
3828
  constructor(schema) {
3691
- super(schema, schema.string);
3829
+ super(schema, schema.stringSchema);
3692
3830
  this.dataType = "box";
3693
3831
  this.operators = Operators.text;
3694
3832
  }
@@ -3698,7 +3836,7 @@ class BoxColumn extends ColumnType {
3698
3836
  }
3699
3837
  class PathColumn extends ColumnType {
3700
3838
  constructor(schema) {
3701
- super(schema, schema.string);
3839
+ super(schema, schema.stringSchema);
3702
3840
  this.dataType = "path";
3703
3841
  this.operators = Operators.text;
3704
3842
  }
@@ -3708,7 +3846,7 @@ class PathColumn extends ColumnType {
3708
3846
  }
3709
3847
  class PolygonColumn extends ColumnType {
3710
3848
  constructor(schema) {
3711
- super(schema, schema.string);
3849
+ super(schema, schema.stringSchema);
3712
3850
  this.dataType = "polygon";
3713
3851
  this.operators = Operators.text;
3714
3852
  }
@@ -3718,7 +3856,7 @@ class PolygonColumn extends ColumnType {
3718
3856
  }
3719
3857
  class CircleColumn extends ColumnType {
3720
3858
  constructor(schema) {
3721
- super(schema, schema.string);
3859
+ super(schema, schema.stringSchema);
3722
3860
  this.dataType = "circle";
3723
3861
  this.operators = Operators.text;
3724
3862
  }
@@ -3728,7 +3866,7 @@ class CircleColumn extends ColumnType {
3728
3866
  }
3729
3867
  class MoneyColumn extends NumberBaseColumn {
3730
3868
  constructor(schema) {
3731
- super(schema, schema.string);
3869
+ super(schema, schema.stringSchema);
3732
3870
  this.dataType = "money";
3733
3871
  this.parseFn = Object.assign(
3734
3872
  function(input) {
@@ -3745,7 +3883,7 @@ class MoneyColumn extends NumberBaseColumn {
3745
3883
  }
3746
3884
  class CidrColumn extends ColumnType {
3747
3885
  constructor(schema) {
3748
- super(schema, schema.string);
3886
+ super(schema, schema.stringSchema);
3749
3887
  this.dataType = "cidr";
3750
3888
  this.operators = Operators.text;
3751
3889
  }
@@ -3755,7 +3893,7 @@ class CidrColumn extends ColumnType {
3755
3893
  }
3756
3894
  class InetColumn extends ColumnType {
3757
3895
  constructor(schema) {
3758
- super(schema, schema.string);
3896
+ super(schema, schema.stringSchema);
3759
3897
  this.dataType = "inet";
3760
3898
  this.operators = Operators.text;
3761
3899
  }
@@ -3765,7 +3903,7 @@ class InetColumn extends ColumnType {
3765
3903
  }
3766
3904
  class MacAddrColumn extends ColumnType {
3767
3905
  constructor(schema) {
3768
- super(schema, schema.string);
3906
+ super(schema, schema.stringSchema);
3769
3907
  this.dataType = "macaddr";
3770
3908
  this.operators = Operators.text;
3771
3909
  }
@@ -3775,7 +3913,7 @@ class MacAddrColumn extends ColumnType {
3775
3913
  }
3776
3914
  class MacAddr8Column extends ColumnType {
3777
3915
  constructor(schema) {
3778
- super(schema, schema.string);
3916
+ super(schema, schema.stringSchema);
3779
3917
  this.dataType = "macaddr8";
3780
3918
  this.operators = Operators.text;
3781
3919
  }
@@ -3821,7 +3959,7 @@ class BitVaryingColumn extends ColumnType {
3821
3959
  }
3822
3960
  class TsVectorColumn extends ColumnType {
3823
3961
  constructor(schema, defaultLanguage = getDefaultLanguage()) {
3824
- super(schema, schema.string);
3962
+ super(schema, schema.stringSchema);
3825
3963
  this.defaultLanguage = defaultLanguage;
3826
3964
  this.dataType = "tsvector";
3827
3965
  this.operators = Operators.text;
@@ -3875,7 +4013,7 @@ class TsVectorColumn extends ColumnType {
3875
4013
  }
3876
4014
  class TsQueryColumn extends ColumnType {
3877
4015
  constructor(schema) {
3878
- super(schema, schema.string);
4016
+ super(schema, schema.stringSchema);
3879
4017
  this.dataType = "tsquery";
3880
4018
  this.operators = Operators.text;
3881
4019
  }
@@ -3910,7 +4048,7 @@ class UUIDColumn extends ColumnType {
3910
4048
  }
3911
4049
  class XMLColumn extends ColumnType {
3912
4050
  constructor(schema) {
3913
- super(schema, schema.string);
4051
+ super(schema, schema.stringSchema);
3914
4052
  this.dataType = "xml";
3915
4053
  this.operators = Operators.text;
3916
4054
  }
@@ -3929,166 +4067,43 @@ class CitextColumn extends TextBaseColumn {
3929
4067
  }
3930
4068
  }
3931
4069
 
3932
- const dateTimeEncode = (input) => {
3933
- return typeof input === "number" ? new Date(input) : input;
3934
- };
3935
- const skipDateMethodsFromToCode = { encodeFn: dateTimeEncode };
3936
- class DateBaseColumn extends ColumnType {
4070
+ class BooleanColumn extends ColumnType {
3937
4071
  constructor(schema) {
3938
- super(schema, schema.stringNumberDate);
3939
- this.operators = Operators.date;
3940
- this.encodeFn = dateTimeEncode;
3941
- this.asNumber = schema.dateAsNumber;
3942
- this.asDate = schema.dateAsDate;
3943
- }
3944
- }
3945
- class DateColumn extends DateBaseColumn {
3946
- constructor() {
3947
- super(...arguments);
3948
- this.dataType = "date";
4072
+ super(schema, schema.boolean);
4073
+ this.dataType = "boolean";
4074
+ this.operators = Operators.boolean;
4075
+ this.parseItem = (input) => input[0] === "t";
3949
4076
  }
3950
4077
  toCode(t) {
3951
- return columnCode(
3952
- this,
3953
- t,
3954
- `date()${dateDataToCode(this.data)}`,
3955
- this.data,
3956
- skipDateMethodsFromToCode
3957
- );
4078
+ return columnCode(this, t, "boolean()");
3958
4079
  }
3959
4080
  }
3960
- class DateTimeBaseClass extends DateBaseColumn {
3961
- constructor(schema, dateTimePrecision) {
3962
- super(schema);
3963
- this.data.dateTimePrecision = dateTimePrecision;
4081
+
4082
+ class CustomTypeColumn extends ColumnType {
4083
+ constructor(schema, dataType) {
4084
+ super(schema, schema.unknown, schema.unknown, schema.unknown);
4085
+ this.dataType = dataType;
4086
+ this.operators = Operators.any;
4087
+ this.data.isOfCustomType = true;
3964
4088
  }
3965
- toSQL() {
3966
- return joinTruthy(
3967
- this.dataType,
3968
- this.data.dateTimePrecision !== void 0 && `(${this.data.dateTimePrecision})`
3969
- );
4089
+ toCode(t) {
4090
+ return columnCode(this, t, `type(${singleQuote(this.dataType)})`);
3970
4091
  }
3971
- }
3972
- class DateTimeTzBaseClass extends DateTimeBaseClass {
3973
- toSQL() {
3974
- return joinTruthy(
3975
- this.baseDataType,
3976
- this.data.dateTimePrecision !== void 0 && `(${this.data.dateTimePrecision})`,
3977
- " with time zone"
4092
+ as(column) {
4093
+ const c = setColumnData(
4094
+ this,
4095
+ "as",
4096
+ column
3978
4097
  );
4098
+ c.inputSchema = column.inputSchema;
4099
+ c.outputSchema = column.outputSchema;
4100
+ c.querySchema = column.querySchema;
4101
+ return c;
3979
4102
  }
3980
4103
  }
3981
- const timestampToCode = (self, t) => {
3982
- const { dateTimePrecision: p } = self.data;
3983
- return columnCode(
3984
- self,
3985
- t,
3986
- `${self instanceof TimestampColumn ? "timestampNoTZ" : "timestamp"}(${p && p !== 6 ? p : ""})${dateDataToCode(self.data)}`,
3987
- self.data,
3988
- skipDateMethodsFromToCode
3989
- );
3990
- };
3991
- class TimestampColumn extends DateTimeBaseClass {
3992
- constructor() {
3993
- super(...arguments);
3994
- this.dataType = "timestamp";
3995
- }
3996
- toCode(t) {
3997
- return timestampToCode(this, t);
3998
- }
3999
- }
4000
- class TimestampTZColumn extends DateTimeTzBaseClass {
4001
- constructor() {
4002
- super(...arguments);
4003
- this.dataType = "timestamptz";
4004
- this.baseDataType = "timestamp";
4005
- }
4104
+ class DomainColumn extends CustomTypeColumn {
4006
4105
  toCode(t) {
4007
- return timestampToCode(this, t);
4008
- }
4009
- }
4010
- class TimeColumn extends ColumnType {
4011
- constructor(schema, dateTimePrecision) {
4012
- super(schema, schema.string);
4013
- this.dataType = "time";
4014
- this.operators = Operators.time;
4015
- this.data.dateTimePrecision = dateTimePrecision;
4016
- }
4017
- toCode(t) {
4018
- const { dateTimePrecision } = this.data;
4019
- return columnCode(
4020
- this,
4021
- t,
4022
- `time(${dateTimePrecision || ""})${dateDataToCode(this.data)}`,
4023
- this.data,
4024
- skipDateMethodsFromToCode
4025
- );
4026
- }
4027
- }
4028
- class IntervalColumn extends ColumnType {
4029
- constructor(schema, fields, precision) {
4030
- super(schema, schema.timeInterval);
4031
- this.dataType = "interval";
4032
- this.operators = Operators.date;
4033
- this.data.fields = fields;
4034
- this.data.precision = precision;
4035
- }
4036
- toCode(t) {
4037
- const { fields, precision } = this.data;
4038
- return columnCode(
4039
- this,
4040
- t,
4041
- `interval(${[fields && `'${fields}'`, precision && String(precision)].filter((part) => part).join(", ")})`,
4042
- this.data,
4043
- skipDateMethodsFromToCode
4044
- );
4045
- }
4046
- toSQL() {
4047
- return joinTruthy(
4048
- this.dataType,
4049
- this.data.fields && ` ${this.data.fields}`,
4050
- this.data.precision !== void 0 && ` (${this.data.precision})`
4051
- );
4052
- }
4053
- }
4054
-
4055
- class BooleanColumn extends ColumnType {
4056
- constructor(schema) {
4057
- super(schema, schema.boolean);
4058
- this.dataType = "boolean";
4059
- this.operators = Operators.boolean;
4060
- this.parseItem = (input) => input[0] === "t";
4061
- }
4062
- toCode(t) {
4063
- return columnCode(this, t, "boolean()");
4064
- }
4065
- }
4066
-
4067
- class CustomTypeColumn extends ColumnType {
4068
- constructor(schema, dataType) {
4069
- super(schema, schema.unknown, schema.unknown, schema.unknown);
4070
- this.dataType = dataType;
4071
- this.operators = Operators.any;
4072
- this.data.isOfCustomType = true;
4073
- }
4074
- toCode(t) {
4075
- return columnCode(this, t, `type(${singleQuote(this.dataType)})`);
4076
- }
4077
- as(column) {
4078
- const c = setColumnData(
4079
- this,
4080
- "as",
4081
- column
4082
- );
4083
- c.inputSchema = column.inputSchema;
4084
- c.outputSchema = column.outputSchema;
4085
- c.querySchema = column.querySchema;
4086
- return c;
4087
- }
4088
- }
4089
- class DomainColumn extends CustomTypeColumn {
4090
- toCode(t) {
4091
- return columnCode(this, t, `domain(${singleQuote(this.dataType)})`);
4106
+ return columnCode(this, t, `domain(${singleQuote(this.dataType)})`);
4092
4107
  }
4093
4108
  }
4094
4109
 
@@ -4126,19 +4141,6 @@ const getColumnTypes = (types, fn, nowSQL, language, data = newTableData()) => {
4126
4141
  return fn(types);
4127
4142
  };
4128
4143
  const makeColumnTypes = (schema) => {
4129
- const columnsWithMethods = {};
4130
- function columnWithMethods(klass, methods, ...args) {
4131
- if (columnsWithMethods[klass.name]) {
4132
- return new columnsWithMethods[klass.name](...args);
4133
- }
4134
- const withMethods = class extends klass {
4135
- };
4136
- Object.assign(withMethods.prototype, methods);
4137
- return new (columnsWithMethods[klass.name] = withMethods)(...args);
4138
- }
4139
- const numberMethods = schema.numberMethods;
4140
- const stringMethods = schema.stringMethods;
4141
- const dateMethods = schema.dateMethods;
4142
4144
  return __spreadValues$8({
4143
4145
  schema,
4144
4146
  enum: schema.enum,
@@ -4161,90 +4163,33 @@ const makeColumnTypes = (schema) => {
4161
4163
  }
4162
4164
  return (...args2) => new RawSQL(args2, arg);
4163
4165
  },
4164
- smallint() {
4165
- return columnWithMethods(SmallIntColumn, numberMethods, schema);
4166
- },
4167
- integer() {
4168
- return columnWithMethods(IntegerColumn, numberMethods, schema);
4169
- },
4170
- bigint() {
4171
- return columnWithMethods(BigIntColumn, stringMethods, schema);
4172
- },
4173
- numeric(precision, scale) {
4174
- return columnWithMethods(
4175
- DecimalColumn,
4176
- stringMethods,
4177
- schema,
4178
- precision,
4179
- scale
4180
- );
4181
- },
4182
- decimal(precision, scale) {
4183
- return columnWithMethods(
4184
- DecimalColumn,
4185
- stringMethods,
4186
- schema,
4187
- precision,
4188
- scale
4189
- );
4190
- },
4191
- real() {
4192
- return columnWithMethods(RealColumn, numberMethods, schema);
4193
- },
4194
- doublePrecision() {
4195
- return columnWithMethods(DoublePrecisionColumn, stringMethods, schema);
4196
- },
4166
+ smallint: schema.smallint,
4167
+ integer: schema.integer,
4168
+ bigint: schema.bigint,
4169
+ numeric: schema.decimal,
4170
+ decimal: schema.decimal,
4171
+ real: schema.real,
4172
+ doublePrecision: schema.doublePrecision,
4197
4173
  identity(options) {
4198
- return columnWithMethods(
4199
- IntegerColumn,
4200
- numberMethods,
4201
- schema
4202
- ).identity(options);
4203
- },
4204
- smallSerial() {
4205
- return columnWithMethods(SmallSerialColumn, numberMethods, schema);
4206
- },
4207
- serial() {
4208
- return columnWithMethods(SerialColumn, numberMethods, schema);
4209
- },
4210
- bigSerial() {
4211
- return columnWithMethods(BigSerialColumn, stringMethods, schema);
4212
- },
4213
- money() {
4214
- return columnWithMethods(MoneyColumn, stringMethods, schema);
4215
- },
4216
- varchar(limit) {
4217
- return columnWithMethods(VarCharColumn, stringMethods, schema, limit);
4218
- },
4219
- char(limit) {
4220
- return columnWithMethods(CharColumn, stringMethods, schema, limit);
4221
- },
4222
- text(min, max) {
4223
- return columnWithMethods(TextColumn, stringMethods, schema, min, max);
4224
- },
4225
- string(limit = 255) {
4226
- return columnWithMethods(StringColumn, stringMethods, schema, limit);
4227
- },
4228
- citext(min, max) {
4229
- return columnWithMethods(CitextColumn, stringMethods, schema, min, max);
4174
+ return schema.integer().identity(
4175
+ options
4176
+ );
4230
4177
  },
4178
+ smallSerial: schema.smallSerial,
4179
+ serial: schema.serial,
4180
+ bigSerial: schema.bigSerial,
4181
+ money: schema.money,
4182
+ varchar: schema.varchar,
4183
+ char: schema.char,
4184
+ text: schema.text,
4185
+ string: schema.string,
4186
+ citext: schema.citext,
4231
4187
  bytea() {
4232
4188
  return new ByteaColumn(schema);
4233
4189
  },
4234
- date() {
4235
- return columnWithMethods(DateColumn, dateMethods, schema);
4236
- },
4237
- timestampNoTZ(precision) {
4238
- return columnWithMethods(TimestampColumn, dateMethods, schema, precision);
4239
- },
4240
- timestamp(precision) {
4241
- return columnWithMethods(
4242
- TimestampTZColumn,
4243
- dateMethods,
4244
- schema,
4245
- precision
4246
- );
4247
- },
4190
+ date: schema.date,
4191
+ timestampNoTZ: schema.timestampNoTZ,
4192
+ timestamp: schema.timestamp,
4248
4193
  time(precision) {
4249
4194
  return new TimeColumn(schema, precision);
4250
4195
  },
@@ -4818,7 +4763,10 @@ class AggregateMethods {
4818
4763
  * ```
4819
4764
  */
4820
4765
  exists() {
4821
- const q = _queryGetOptional(this.clone(), new RawSQL("true"));
4766
+ const q = _queryGetOptional(
4767
+ this.clone(),
4768
+ new RawSQL("true")
4769
+ );
4822
4770
  q.q.notFoundDefault = false;
4823
4771
  q.q.coalesceValue = new RawSQL("false");
4824
4772
  return q;
@@ -4848,13 +4796,7 @@ class AggregateMethods {
4848
4796
  * @param options - aggregation options
4849
4797
  */
4850
4798
  count(arg = "*", options) {
4851
- return makeFnExpression(
4852
- this,
4853
- int,
4854
- "count",
4855
- [arg],
4856
- options
4857
- );
4799
+ return makeFnExpression(this, int, "count", [arg], options);
4858
4800
  }
4859
4801
  /**
4860
4802
  * Get the minimum value for the specified numeric column, returns number or `null` if there are no records.
@@ -6072,16 +6014,17 @@ class OnConflictQueryBuilder {
6072
6014
  }
6073
6015
  }
6074
6016
 
6075
- const _queryDelete = (q) => {
6076
- if (!q.q.select) {
6077
- if (q.q.returnType === "oneOrThrow" || q.q.returnType === "valueOrThrow") {
6078
- q.q.throwOnNotFound = true;
6017
+ const _queryDelete = (query) => {
6018
+ const q = query.q;
6019
+ if (!q.select) {
6020
+ if (q.returnType === "oneOrThrow" || q.returnType === "valueOrThrow") {
6021
+ q.throwOnNotFound = true;
6079
6022
  }
6080
- q.q.returnType = "rowCount";
6023
+ q.returnType = "rowCount";
6081
6024
  }
6082
- throwIfNoWhere(q, "delete");
6083
- q.q.type = "delete";
6084
- return q;
6025
+ throwIfNoWhere(query, "delete");
6026
+ q.type = "delete";
6027
+ return query;
6085
6028
  };
6086
6029
  class Delete {
6087
6030
  /**
@@ -6154,8 +6097,8 @@ const forMethods = {
6154
6097
  return q;
6155
6098
  }
6156
6099
  };
6157
- const forQueryBuilder = (q, type, tableNames) => {
6158
- q = extendQuery(q, forMethods);
6100
+ const forQueryBuilder = (arg, type, tableNames) => {
6101
+ const q = extendQuery(arg, forMethods);
6159
6102
  q.q.for = {
6160
6103
  type,
6161
6104
  tableNames
@@ -6334,7 +6277,7 @@ const _queryHookAfterDelete = (q, select, cb) => {
6334
6277
  const _queryHookAfterDeleteCommit = (q, select, cb) => {
6335
6278
  return after(q, "Delete", select, cb, true);
6336
6279
  };
6337
- class QueryHooks extends QueryBase {
6280
+ class QueryHooks {
6338
6281
  /**
6339
6282
  * Run the function before any kind of query.
6340
6283
  *
@@ -6371,7 +6314,11 @@ class QueryHooks extends QueryBase {
6371
6314
  * @param cb - function to call, first argument is the query result with selected columns, second argument is a query object
6372
6315
  */
6373
6316
  afterCreate(select, cb) {
6374
- return _queryHookAfterCreate(this.clone(), select, cb);
6317
+ return _queryHookAfterCreate(
6318
+ this.clone(),
6319
+ select,
6320
+ cb
6321
+ );
6375
6322
  }
6376
6323
  /**
6377
6324
  * Run the function after transaction for a `create` kind of query will be committed.
@@ -6381,7 +6328,11 @@ class QueryHooks extends QueryBase {
6381
6328
  * @param cb - function to call, first argument is the query result with selected columns, second argument is a query object
6382
6329
  */
6383
6330
  afterCreateCommit(select, cb) {
6384
- return _queryHookAfterCreateCommit(this.clone(), select, cb);
6331
+ return _queryHookAfterCreateCommit(
6332
+ this.clone(),
6333
+ select,
6334
+ cb
6335
+ );
6385
6336
  }
6386
6337
  /**
6387
6338
  * Run the function before an `update` kind of query.
@@ -6402,7 +6353,11 @@ class QueryHooks extends QueryBase {
6402
6353
  * @param cb - function to call, first argument is the query result with selected columns, second argument is a query object
6403
6354
  */
6404
6355
  afterUpdate(select, cb) {
6405
- return _queryHookAfterUpdate(this.clone(), select, cb);
6356
+ return _queryHookAfterUpdate(
6357
+ this.clone(),
6358
+ select,
6359
+ cb
6360
+ );
6406
6361
  }
6407
6362
  /**
6408
6363
  * Run the function after transaction for an `update` kind of query will be committed.
@@ -6413,7 +6368,11 @@ class QueryHooks extends QueryBase {
6413
6368
  * @param cb - function to call, first argument is the query result with selected columns, second argument is a query object
6414
6369
  */
6415
6370
  afterUpdateCommit(select, cb) {
6416
- return _queryHookAfterUpdateCommit(this.clone(), select, cb);
6371
+ return _queryHookAfterUpdateCommit(
6372
+ this.clone(),
6373
+ select,
6374
+ cb
6375
+ );
6417
6376
  }
6418
6377
  /**
6419
6378
  * Run the function before a `create` or an `update` kind of query.
@@ -6434,7 +6393,11 @@ class QueryHooks extends QueryBase {
6434
6393
  * @param cb - function to call, first argument is the query result with selected columns, second argument is a query object
6435
6394
  */
6436
6395
  afterSave(select, cb) {
6437
- return _queryHookAfterSave(this.clone(), select, cb);
6396
+ return _queryHookAfterSave(
6397
+ this.clone(),
6398
+ select,
6399
+ cb
6400
+ );
6438
6401
  }
6439
6402
  /**
6440
6403
  * Run the function after transaction for a `create` or an `update` kind of query will be committed.
@@ -6445,7 +6408,11 @@ class QueryHooks extends QueryBase {
6445
6408
  * @param cb - function to call, first argument is the query result with selected columns, second argument is a query object
6446
6409
  */
6447
6410
  afterSaveCommit(select, cb) {
6448
- return _queryAfterSaveCommit(this.clone(), select, cb);
6411
+ return _queryAfterSaveCommit(
6412
+ this.clone(),
6413
+ select,
6414
+ cb
6415
+ );
6449
6416
  }
6450
6417
  /**
6451
6418
  * Run the function before a `delete` kind of query.
@@ -6466,7 +6433,11 @@ class QueryHooks extends QueryBase {
6466
6433
  * @param cb - function to call, first argument is the query result with selected columns, second argument is a query object
6467
6434
  */
6468
6435
  afterDelete(select, cb) {
6469
- return _queryHookAfterDelete(this.clone(), select, cb);
6436
+ return _queryHookAfterDelete(
6437
+ this.clone(),
6438
+ select,
6439
+ cb
6440
+ );
6470
6441
  }
6471
6442
  /**
6472
6443
  * Run the function after transaction for a `delete` kind of query will be committed.
@@ -6477,7 +6448,27 @@ class QueryHooks extends QueryBase {
6477
6448
  * @param cb - function to call, first argument is the query result with selected columns, second argument is a query object
6478
6449
  */
6479
6450
  afterDeleteCommit(select, cb) {
6480
- return _queryHookAfterDeleteCommit(this.clone(), select, cb);
6451
+ return _queryHookAfterDeleteCommit(
6452
+ this.clone(),
6453
+ select,
6454
+ cb
6455
+ );
6456
+ }
6457
+ }
6458
+
6459
+ class QueryBase {
6460
+ constructor() {
6461
+ this.q = {};
6462
+ }
6463
+ /**
6464
+ * Clones the current query chain, useful for re-using partial query snippets in other queries without mutating the original.
6465
+ *
6466
+ * Used under the hood, and not really needed on the app side.
6467
+ */
6468
+ clone() {
6469
+ const cloned = Object.create(this.baseQuery);
6470
+ cloned.q = getClonedQueryData(this.q);
6471
+ return cloned;
6481
6472
  }
6482
6473
  }
6483
6474
 
@@ -6489,7 +6480,11 @@ const _queryWhere = (q, args) => {
6489
6480
  new RawSQL(args)
6490
6481
  );
6491
6482
  }
6492
- return pushQueryArray(q, "and", args);
6483
+ return pushQueryArray(
6484
+ q,
6485
+ "and",
6486
+ args
6487
+ );
6493
6488
  };
6494
6489
  const _queryWhereNot = (q, args) => {
6495
6490
  if (Array.isArray(args[0])) {
@@ -6543,14 +6538,13 @@ const _queryWhereIn = (q, and, arg, values, not) => {
6543
6538
  }
6544
6539
  return q;
6545
6540
  };
6546
- const existsArgs = (args) => {
6547
- const q = args[0];
6541
+ const existsArgs = (q, args) => {
6548
6542
  let isSubQuery;
6549
6543
  if (typeof q === "object") {
6550
6544
  isSubQuery = getIsJoinSubQuery(q.q, q.baseQuery.q);
6551
6545
  if (isSubQuery) {
6552
- args[0] = q.clone();
6553
- args[0].shape = getShapeFromSelect(q, true);
6546
+ q = q.clone();
6547
+ q.shape = getShapeFromSelect(q, true);
6554
6548
  }
6555
6549
  } else {
6556
6550
  isSubQuery = false;
@@ -6558,6 +6552,7 @@ const existsArgs = (args) => {
6558
6552
  return [
6559
6553
  {
6560
6554
  EXISTS: {
6555
+ first: q,
6561
6556
  args,
6562
6557
  isSubQuery
6563
6558
  }
@@ -6954,7 +6949,10 @@ class Where {
6954
6949
  * @param args - {@link WhereArgs}
6955
6950
  */
6956
6951
  where(...args) {
6957
- return _queryWhere(this.clone(), args);
6952
+ return _queryWhere(
6953
+ this.clone(),
6954
+ args
6955
+ );
6958
6956
  }
6959
6957
  /**
6960
6958
  * `whereNot` takes the same argument as `where`,
@@ -6972,7 +6970,10 @@ class Where {
6972
6970
  * @param args - {@link WhereArgs}
6973
6971
  */
6974
6972
  whereNot(...args) {
6975
- return _queryWhereNot(this.clone(), args);
6973
+ return _queryWhereNot(
6974
+ this.clone(),
6975
+ args
6976
+ );
6976
6977
  }
6977
6978
  /**
6978
6979
  * `orWhere` is accepting the same arguments as {@link where}, joining arguments with `OR`.
@@ -7006,35 +7007,172 @@ class Where {
7006
7007
  * @param args - {@link WhereArgs} will be prefixed with `NOT` and joined with `OR`
7007
7008
  */
7008
7009
  orWhereNot(...args) {
7009
- return _queryOrNot(this.clone(), args);
7010
+ return _queryOrNot(
7011
+ this.clone(),
7012
+ args
7013
+ );
7010
7014
  }
7011
- whereIn(arg, values) {
7012
- return _queryWhereIn(this.clone(), true, arg, values);
7015
+ /**
7016
+ * `whereIn` and related methods are for the `IN` operator to check for inclusion in a list of values.
7017
+ *
7018
+ * When used with a single column it works equivalent to the `in` column operator:
7019
+ *
7020
+ * ```ts
7021
+ * db.table.whereIn('column', [1, 2, 3]);
7022
+ * // the same as:
7023
+ * db.table.where({ column: [1, 2, 3] });
7024
+ * ```
7025
+ *
7026
+ * `whereIn` can support a tuple of columns, that's what the `in` operator cannot support:
7027
+ *
7028
+ * ```ts
7029
+ * db.table.whereIn(
7030
+ * ['id', 'name'],
7031
+ * [
7032
+ * [1, 'Alice'],
7033
+ * [2, 'Bob'],
7034
+ * ],
7035
+ * );
7036
+ * ```
7037
+ *
7038
+ * It supports sub query which should return records with columns of the same type:
7039
+ *
7040
+ * ```ts
7041
+ * db.table.whereIn(['id', 'name'], OtherTable.select('id', 'name'));
7042
+ * ```
7043
+ *
7044
+ * It supports raw SQL expression:
7045
+ *
7046
+ * ```ts
7047
+ * db.table.whereIn(['id', 'name'], db.table.sql`((1, 'one'), (2, 'two'))`);
7048
+ * ```
7049
+ */
7050
+ whereIn(...args) {
7051
+ return _queryWhereIn(
7052
+ this.clone(),
7053
+ true,
7054
+ args[0],
7055
+ args[1]
7056
+ );
7013
7057
  }
7014
- orWhereIn(arg, values) {
7015
- return _queryWhereIn(this.clone(), false, arg, values);
7058
+ /**
7059
+ * Takes the same arguments as {@link whereIn}.
7060
+ * Add a `WHERE IN` condition prefixed with `OR` to the query:
7061
+ *
7062
+ * ```ts
7063
+ * db.table.whereIn('a', [1, 2, 3]).orWhereIn('b', ['one', 'two']);
7064
+ * ```
7065
+ */
7066
+ orWhereIn(...args) {
7067
+ return _queryWhereIn(
7068
+ this.clone(),
7069
+ false,
7070
+ args[0],
7071
+ args[1]
7072
+ );
7016
7073
  }
7017
- whereNotIn(arg, values) {
7018
- return _queryWhereIn(this.clone(), true, arg, values, true);
7074
+ /**
7075
+ * Acts as `whereIn`, but negates the condition with `NOT`:
7076
+ *
7077
+ * ```ts
7078
+ * db.table.whereNotIn('color', ['red', 'green', 'blue']);
7079
+ * ```
7080
+ */
7081
+ whereNotIn(...args) {
7082
+ return _queryWhereIn(
7083
+ this.clone(),
7084
+ true,
7085
+ args[0],
7086
+ args[1],
7087
+ true
7088
+ );
7019
7089
  }
7020
- orWhereNotIn(arg, values) {
7021
- return _queryWhereIn(this.clone(), false, arg, values, true);
7090
+ /**
7091
+ * Acts as `whereIn`, but prepends `OR` to the condition and negates it with `NOT`:
7092
+ *
7093
+ * ```ts
7094
+ * db.table.whereNotIn('a', [1, 2, 3]).orWhereNoIn('b', ['one', 'two']);
7095
+ * ```
7096
+ */
7097
+ orWhereNotIn(...args) {
7098
+ return _queryWhereIn(
7099
+ this.clone(),
7100
+ false,
7101
+ args[0],
7102
+ args[1],
7103
+ true
7104
+ );
7022
7105
  }
7023
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
7024
- whereExists(...args) {
7025
- return _queryWhere(this.clone(), existsArgs(args));
7106
+ /**
7107
+ * `whereExists` is for support of the `WHERE EXISTS (query)` clause.
7108
+ *
7109
+ * This method is accepting the same arguments as `join`, see the {@link Join.join} section for more details.
7110
+ *
7111
+ * ```ts
7112
+ * // find users who have accounts
7113
+ * // find by a relation name if it's defined
7114
+ * db.user.whereExists('account');
7115
+ *
7116
+ * // find using a table and a join conditions
7117
+ * db.user.whereExists(db.account, 'account.id', 'user.id');
7118
+ *
7119
+ * // find using a query builder in a callback:
7120
+ * db.user.whereExists(db.account, (q) => q.on('account.id', '=', 'user.id'));
7121
+ * ```
7122
+ */
7123
+ whereExists(arg, ...args) {
7124
+ return _queryWhere(
7125
+ this.clone(),
7126
+ existsArgs(arg, args)
7127
+ );
7026
7128
  }
7027
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
7028
- orWhereExists(...args) {
7029
- return _queryOr(this.clone(), existsArgs(args));
7129
+ /**
7130
+ * Acts as `whereExists`, but prepends the condition with `OR`:
7131
+ *
7132
+ * ```ts
7133
+ * // find users who have an account or a profile,
7134
+ * // imagine that the user has both `account` and `profile` relations defined.
7135
+ * db.user.whereExist('account').orWhereExists('profile');
7136
+ * ```
7137
+ */
7138
+ orWhereExists(arg, ...args) {
7139
+ return _queryOr(
7140
+ this.clone(),
7141
+ existsArgs(arg, args)
7142
+ );
7030
7143
  }
7031
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
7032
- whereNotExists(...args) {
7033
- return _queryWhereNot(this.clone(), existsArgs(args));
7144
+ /**
7145
+ * Acts as `whereExists`, but negates the condition with `NOT`:
7146
+ *
7147
+ * ```ts
7148
+ * // find users who don't have an account,
7149
+ * // image that the user `belongsTo` or `hasOne` account.
7150
+ * db.user.whereNotExist('account');
7151
+ * ```
7152
+ *
7153
+ * @param arg - relation name, or a query object, or a `with` table alias, or a callback returning a query object.
7154
+ * @param args - no arguments needed when the first argument is a relation name, or conditions to join the table with.
7155
+ */
7156
+ whereNotExists(arg, ...args) {
7157
+ return _queryWhereNot(
7158
+ this.clone(),
7159
+ existsArgs(arg, args)
7160
+ );
7034
7161
  }
7035
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
7036
- orWhereNotExists(...args) {
7037
- return _queryOrNot(this.clone(), existsArgs(args));
7162
+ /**
7163
+ * Acts as `whereExists`, but prepends the condition with `OR` and negates it with `NOT`:
7164
+ *
7165
+ * ```ts
7166
+ * // find users who don't have an account OR who don't have a profile
7167
+ * // imagine that the user has both `account` and `profile` relations defined.
7168
+ * db.user.whereNotExists('account').orWhereNotExists('profile');
7169
+ * ```
7170
+ */
7171
+ orWhereNotExists(arg, ...args) {
7172
+ return _queryOrNot(
7173
+ this.clone(),
7174
+ existsArgs(arg, args)
7175
+ );
7038
7176
  }
7039
7177
  }
7040
7178
  class WhereQueryBase extends QueryBase {
@@ -7042,21 +7180,447 @@ class WhereQueryBase extends QueryBase {
7042
7180
  applyMixins(WhereQueryBase, [Where]);
7043
7181
 
7044
7182
  class Join {
7045
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
7046
- join(...args) {
7047
- return _join(this.clone(), true, "JOIN", args);
7183
+ /**
7184
+ * ## Select relation
7185
+ *
7186
+ * Before joining a table, consider if selecting a relation is enough for your case:
7187
+ *
7188
+ * ```ts
7189
+ * // select users with profiles
7190
+ * // result type is Array<{ name: string, profile: Profile }>
7191
+ * await db.user.select('name', {
7192
+ * profile: (q) => q.profile,
7193
+ * });
7194
+ *
7195
+ * // select posts with counts of comments, order by comments count
7196
+ * // result type is Array<Post & { commentsCount: number }>
7197
+ * await db.post
7198
+ * .select('*', {
7199
+ * commentsCount: (q) => q.comments.count(),
7200
+ * })
7201
+ * .order({
7202
+ * commentsCount: 'DESC',
7203
+ * });
7204
+ *
7205
+ * // select authors with array of their book titles
7206
+ * // result type is Array<Author & { books: string[] }>
7207
+ * await db.author.select('*', {
7208
+ * books: (q) => q.books.pluck('title'),
7209
+ * });
7210
+ * ```
7211
+ *
7212
+ * Internally, such selects will use `LEFT JOIN LATERAL` to join a relation.
7213
+ * If you're loading users with profiles (one-to-one relation), and some users don't have a profile, `profile` property will have `NULL` for such users.
7214
+ * If you want to load only users that have profiles, and filter out the rest, add `.join()` method to the relation without arguments:
7215
+ *
7216
+ * ```ts
7217
+ * // load only users who have a profile
7218
+ * await db.user.select('*', {
7219
+ * profile: (q) => q.profile.join(),
7220
+ * });
7221
+ *
7222
+ * // load only users who have a specific profile
7223
+ * await db.user.select('*', {
7224
+ * profile: (q) => q.profile.join().where({ age: { gt: 20 } }),
7225
+ * });
7226
+ * ```
7227
+ *
7228
+ * You can also use this `.join()` method on the one-to-many relations, and records with empty array will be filtered out:
7229
+ *
7230
+ * ```ts
7231
+ * // posts that have no tags won't be loaded
7232
+ * // result type is Array<Post & { tags: Tag[] }>
7233
+ * db.post.select('*', {
7234
+ * tags: (q) => q.tags.join(),
7235
+ * });
7236
+ * ```
7237
+ *
7238
+ * # Joins
7239
+ *
7240
+ * `join` methods allows to join other tables, relations by name, [with](/guide/advanced-queries#with) statements, sub queries.
7241
+ *
7242
+ * All the `join` methods accept the same arguments, but returning type is different because with `join` it's guaranteed to load joined table, and with `leftJoin` the joined table columns may be `NULL` when no matching record was found.
7243
+ *
7244
+ * For the following examples, imagine we have a `User` table with `id` and `name`, and `Message` table with `id`, `text`, messages belongs to user via `userId` column:
7245
+ *
7246
+ * ```ts
7247
+ * export class UserTable extends BaseTable {
7248
+ * readonly table = 'user';
7249
+ * columns = this.setColumns((t) => ({
7250
+ * id: t.identity().primaryKey(),
7251
+ * name: t.text(),
7252
+ * }));
7253
+ *
7254
+ * relations = {
7255
+ * messages: this.hasMany(() => MessageTable, {
7256
+ * primaryKey: 'id',
7257
+ * foreignKey: 'userId',
7258
+ * }),
7259
+ * };
7260
+ * }
7261
+ *
7262
+ * export class MessageTable extends BaseTable {
7263
+ * readonly table = 'message';
7264
+ * columns = this.setColumns((t) => ({
7265
+ * id: t.identity().primaryKey(),
7266
+ * text: t.text(),
7267
+ * ...t.timestamps(),
7268
+ * }));
7269
+ *
7270
+ * relations = {
7271
+ * user: this.belongsTo(() => UserTable, {
7272
+ * primaryKey: 'id',
7273
+ * foreignKey: 'userId',
7274
+ * }),
7275
+ * };
7276
+ * }
7277
+ * ```
7278
+ *
7279
+ * ## join
7280
+ *
7281
+ * `join` is a method for SQL `JOIN`, which is equivalent to `INNER JOIN`, `LEFT INNERT JOIN`.
7282
+ *
7283
+ * When no matching record is found, it will skip records of the main table.
7284
+ *
7285
+ * ### join relation
7286
+ *
7287
+ * When relations are defined between the tables, you can join them by a relation name.
7288
+ * Joined table can be references from `where` and `select` by a relation name.
7289
+ *
7290
+ * ```ts
7291
+ * const result = await db.user
7292
+ * .join('messages')
7293
+ * // after joining a table, we can use it in `where` conditions:
7294
+ * .where({ 'messages.text': { startsWith: 'Hi' } })
7295
+ * .select(
7296
+ * 'name', // name is User column, table name may be omitted
7297
+ * 'messages.text', // text is the Message column, and the table name is required
7298
+ * );
7299
+ *
7300
+ * // result has the following type:
7301
+ * const ok: { name: string; text: string }[] = result;
7302
+ * ```
7303
+ *
7304
+ * The first argument can also be a callback, where instead of relation name as a string we're picking it as a property of `q`.
7305
+ * In such a way, we can alias the relation with `as`, add `where` conditions, use other query methods.
7306
+ *
7307
+ * ```ts
7308
+ * const result = await db.user.join((q) =>
7309
+ * q.messages.as('m').where({ text: 'some text' }),
7310
+ * );
7311
+ * ```
7312
+ *
7313
+ * Optionally, you can pass a second callback argument, it makes `on` and `orOn` methods available.
7314
+ *
7315
+ * But remember that when joining a relation, the needed `ON` conditions are already handled automatically.
7316
+ *
7317
+ * ```ts
7318
+ * const result = await db.user.join(
7319
+ * (q) => q.messages.as('m'),
7320
+ * (q) =>
7321
+ * q
7322
+ * .on('text', 'name') // additionally, match message with user name
7323
+ * .where({ text: 'some text' }), // you can add `where` in a second callback as well.
7324
+ * );
7325
+ * ```
7326
+ *
7327
+ * ### Selecting full joined records
7328
+ *
7329
+ * `select` supports selecting a full record of a previously joined table by passing a table name with `.*` at the end:
7330
+ *
7331
+ * ```ts
7332
+ * const result = await db.book.join('author').select('title', {
7333
+ * author: 'author.*',
7334
+ * });
7335
+ *
7336
+ * // result has the following type:
7337
+ * const ok: {
7338
+ * // title of the book
7339
+ * title: string;
7340
+ * // a full author record is included:
7341
+ * author: { id: number; name: string; updatedAt: Date; createdAt: Date };
7342
+ * }[] = result;
7343
+ * ```
7344
+ *
7345
+ * It works fine for `1:1` (`belongsTo`, `hasOne`) relations, but it may have an unexpected result for `1:M` or `M:M` (`hasMany`, `hasAndBelongsToMany`) relations.
7346
+ * For any kind of relation, it results in one main table record with data of exactly one joined table record, i.e. when selecting in this way, the records **won't** be collected into arrays.
7347
+ *
7348
+ * ```ts
7349
+ * const result = await db.user
7350
+ * .join('messages')
7351
+ * .where({ 'messages.text': { startsWith: 'Hi' } })
7352
+ * .select('name', { messages: 'messages.*' });
7353
+ *
7354
+ * // result has the following type:
7355
+ * const ok: {
7356
+ * name: string;
7357
+ * // full message is included:
7358
+ * messages: { id: number; text: string; updatedAt: Date; createdAt: Date };
7359
+ * }[] = result;
7360
+ * ```
7361
+ *
7362
+ * Because it's a one-to-many relation, one user has many messages, the user data will be duplicated for different messages data:
7363
+ *
7364
+ * | name | msg |
7365
+ * | ------ | ------------------------------ |
7366
+ * | user 1 | `{ id: 1, text: 'message 1' }` |
7367
+ * | user 1 | `{ id: 2, text: 'message 2' }` |
7368
+ * | user 1 | `{ id: 3, text: 'message 3' }` |
7369
+ *
7370
+ * ### join table
7371
+ *
7372
+ * If relation wasn't defined, provide a `db.table` instance and specify columns for the join.
7373
+ * Joined table can be references from `where` and `select` by a table name.
7374
+ *
7375
+ * ```ts
7376
+ * // Join message where userId = id:
7377
+ * db.user
7378
+ * .join(db.message, 'userId', 'id')
7379
+ * .where({ 'message.text': { startsWith: 'Hi' } })
7380
+ * .select('name', 'message.text');
7381
+ * ```
7382
+ *
7383
+ * Columns in the join list may be prefixed with table names for clarity:
7384
+ *
7385
+ * ```ts
7386
+ * db.user.join(db.message, 'message.userId', 'user.id');
7387
+ * ```
7388
+ *
7389
+ * Joined table can have an alias for referencing it further:
7390
+ *
7391
+ * ```ts
7392
+ * db.user
7393
+ * .join(db.message.as('m'), 'message.userId', 'user.id')
7394
+ * .where({ 'm.text': { startsWith: 'Hi' } })
7395
+ * .select('name', 'm.text');
7396
+ * ```
7397
+ *
7398
+ * Joined table can be selected as an object as well as the relation join above:
7399
+ *
7400
+ * ```ts
7401
+ * const result = await db.user
7402
+ * .join(db.message.as('m'), 'message.userId', 'user.id')
7403
+ * .where({ 'm.text': { startsWith: 'Hi' } })
7404
+ * .select('name', { msg: 'm.*' });
7405
+ *
7406
+ * // result has the following type:
7407
+ * const ok: {
7408
+ * name: string;
7409
+ * // full message is included as msg:
7410
+ * msg: { id: number; text: string; updatedAt: Date; createdAt: Date };
7411
+ * }[] = result;
7412
+ * ```
7413
+ *
7414
+ * You can provide a custom comparison operator
7415
+ *
7416
+ * ```ts
7417
+ * db.user.join(db.message, 'userId', '!=', 'id');
7418
+ * ```
7419
+ *
7420
+ * Join can accept raw SQL for the `ON` part of join:
7421
+ *
7422
+ * ```ts
7423
+ * db.user.join(
7424
+ * db.message,
7425
+ * db.user.sql`lower("message"."text") = lower("user"."name")`,
7426
+ * );
7427
+ * ```
7428
+ *
7429
+ * Join can accept raw SQL instead of columns:
7430
+ *
7431
+ * ```ts
7432
+ * db.user.join(
7433
+ * db.message,
7434
+ * db.user.sql`lower("message"."text")`,
7435
+ * db.user.sql`lower("user"."name")`,
7436
+ * );
7437
+ *
7438
+ * // with operator:
7439
+ * db.user.join(
7440
+ * db.message,
7441
+ * db.user.sql`lower("message"."text")`,
7442
+ * '!=',
7443
+ * db.user.sql`lower("user"."name")`,
7444
+ * );
7445
+ * ```
7446
+ *
7447
+ * To join based on multiple columns, you can provide an object where keys are joining table columns, and values are main table columns or a raw SQL:
7448
+ *
7449
+ * ```ts
7450
+ * db.user.join(db.message, {
7451
+ * userId: 'id',
7452
+ *
7453
+ * // with table names:
7454
+ * 'message.userId': 'user.id',
7455
+ *
7456
+ * // value can be a raw SQL expression:
7457
+ * text: db.user.sql`lower("user"."name")`,
7458
+ * });
7459
+ * ```
7460
+ *
7461
+ * Join all records without conditions by providing `true`:
7462
+ *
7463
+ * ```ts
7464
+ * db.user.join(db.message, true);
7465
+ * ```
7466
+ *
7467
+ * Join methods can accept a callback with a special query builder that has `on` and `orOn` methods for handling advanced cases:
7468
+ *
7469
+ * ```ts
7470
+ * db.user.join(
7471
+ * db.message,
7472
+ * (q) =>
7473
+ * q
7474
+ * // left column is the db.message column, right column is the db.user column
7475
+ * .on('userId', 'id')
7476
+ * // table names can be provided:
7477
+ * .on('message.userId', 'user.id')
7478
+ * // operator can be specified:
7479
+ * .on('userId', '!=', 'id')
7480
+ * // operator can be specified with table names as well:
7481
+ * .on('message.userId', '!=', 'user.id')
7482
+ * // `.orOn` takes the same arguments as `.on` and acts like `.or`:
7483
+ * .on('userId', 'id') // where message.userId = user.id
7484
+ * .orOn('text', 'name'), // or message.text = user.name
7485
+ * );
7486
+ * ```
7487
+ *
7488
+ * Join query builder supports all `where` methods: `.where`, `.whereIn`, `.whereExists`, and all `.or`, `.not`, and `.orNot` forms.
7489
+ *
7490
+ * Column names in the where conditions are applied for the joined table, but you can specify a table name to add a condition for the main table.
7491
+ *
7492
+ * ```ts
7493
+ * db.user.join(db.message, (q) =>
7494
+ * q
7495
+ * .on('userId', 'id')
7496
+ * .where({
7497
+ * // not prefixed column name is for joined table:
7498
+ * text: { startsWith: 'hello' },
7499
+ * // specify a table name to set condition on the main table:
7500
+ * 'user.name': 'Bob',
7501
+ * })
7502
+ * // id is a column of a joined table Message
7503
+ * .whereIn('id', [1, 2, 3])
7504
+ * // condition for id of a user
7505
+ * .whereIn('user.id', [4, 5, 6]),
7506
+ * );
7507
+ * ```
7508
+ *
7509
+ * The query above will generate the following SQL (simplified):
7510
+ *
7511
+ * ```sql
7512
+ * SELECT * FROM "user"
7513
+ * JOIN "message"
7514
+ * ON "message"."userId" = "user"."id"
7515
+ * AND "message"."text" ILIKE 'hello%'
7516
+ * AND "user"."name" = 'Bob'
7517
+ * AND "message"."id" IN (1, 2, 3)
7518
+ * AND "user"."id" IN (4, 5, 6)
7519
+ * ```
7520
+ *
7521
+ * The join argument can be a query with `select`, `where`, and other methods. In such case, it will be handled as a sub query:
7522
+ *
7523
+ * ```ts
7524
+ * db.user.join(
7525
+ * db.message
7526
+ * .select('id', 'userId', 'text')
7527
+ * .where({ text: { startsWith: 'Hi' } })
7528
+ * .as('t'),
7529
+ * 'userId',
7530
+ * 'id',
7531
+ * );
7532
+ * ```
7533
+ *
7534
+ * It will produce such SQL:
7535
+ *
7536
+ * ```sql
7537
+ * SELECT * FROM "user"
7538
+ * JOIN (
7539
+ * SELECT "t"."id", "t"."userId", "t"."text"
7540
+ * FROM "message" AS "t"
7541
+ * ) "t" ON "t"."userId" = "user"."id"
7542
+ * ```
7543
+ *
7544
+ * @param arg - {@link JoinFirstArg}
7545
+ * @param args - {@link JoinArgs}
7546
+ */
7547
+ join(arg, ...args) {
7548
+ return _join(this.clone(), true, "JOIN", arg, args);
7048
7549
  }
7049
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
7050
- leftJoin(...args) {
7051
- return _join(this.clone(), false, "LEFT JOIN", args);
7550
+ /**
7551
+ * `leftJoin` is a method for SQL `LEFT JOIN`, which is equivalent to `OUTER JOIN`, `LEFT OUTER JOIN`.
7552
+ *
7553
+ * When no matching record is found, it will fill joined table columns with `NULL` values in the result rows.
7554
+ *
7555
+ * Works just like `join`, except for result type that may have `null`:
7556
+ *
7557
+ * ```ts
7558
+ * const result = await db.user
7559
+ * .leftJoin('messages')
7560
+ * .select('name', 'messages.text');
7561
+ *
7562
+ * // the same query, but joining table explicitly
7563
+ * const result2: typeof result = await db.user
7564
+ * .leftJoin(db.message, 'userId', 'id')
7565
+ * .select('name', 'message.text');
7566
+ *
7567
+ * // result has the following type:
7568
+ * const ok: { name: string; text: string | null }[] = result;
7569
+ * ```
7570
+ *
7571
+ * @param arg - {@link JoinFirstArg}
7572
+ * @param args - {@link JoinArgs}
7573
+ */
7574
+ leftJoin(arg, ...args) {
7575
+ return _join(this.clone(), false, "LEFT JOIN", arg, args);
7052
7576
  }
7053
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
7054
- rightJoin(...args) {
7055
- return _join(this.clone(), true, "RIGHT JOIN", args);
7577
+ /**
7578
+ * `rightJoin` is a method for SQL `RIGHT JOIN`, which is equivalent to `RIGHT OUTER JOIN`.
7579
+ *
7580
+ * Takes the same arguments as `json`.
7581
+ *
7582
+ * It will load all records from the joining table, and fill the main table columns with `null` when no match is found.
7583
+ *
7584
+ * The columns of the table you're joining to are becoming nullable when using `rightJoin`.
7585
+ *
7586
+ * ```ts
7587
+ * const result = await db.user
7588
+ * .rightJoin('messages')
7589
+ * .select('name', 'messages.text');
7590
+ *
7591
+ * // even though name is not a nullable column, it becomes nullable after using rightJoin
7592
+ * const ok: { name: string | null; text: string }[] = result;
7593
+ * ```
7594
+ *
7595
+ * @param arg - {@link JoinFirstArg}
7596
+ * @param args - {@link JoinArgs}
7597
+ */
7598
+ rightJoin(arg, ...args) {
7599
+ return _join(this.clone(), true, "RIGHT JOIN", arg, args);
7056
7600
  }
7057
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
7058
- fullJoin(...args) {
7059
- return _join(this.clone(), false, "FULL JOIN", args);
7601
+ /**
7602
+ * `fullJoin` is a method for SQL `FULL JOIN`, which is equivalent to `FULL OUTER JOIN`.
7603
+ *
7604
+ * Takes the same arguments as `json`.
7605
+ *
7606
+ * It will load all records from the joining table, both sides of the join may result in `null` values when there is no match.
7607
+ *
7608
+ * All columns become nullable after using `fullJoin`.
7609
+ *
7610
+ * ```ts
7611
+ * const result = await db.user
7612
+ * .rightJoin('messages')
7613
+ * .select('name', 'messages.text');
7614
+ *
7615
+ * // all columns can be null
7616
+ * const ok: { name: string | null; text: string | null }[] = result;
7617
+ * ```
7618
+ *
7619
+ * @param arg - {@link JoinFirstArg}
7620
+ * @param args - {@link JoinArgs}
7621
+ */
7622
+ fullJoin(arg, ...args) {
7623
+ return _join(this.clone(), false, "FULL JOIN", arg, args);
7060
7624
  }
7061
7625
  /**
7062
7626
  * `joinLateral` allows joining a table with a sub-query that can reference the main table of current query and the other joined tables.
@@ -7245,7 +7809,7 @@ class OnQueryBuilder extends WhereQueryBase {
7245
7809
  }
7246
7810
  }
7247
7811
 
7248
- class JsonModifiers extends QueryBase {
7812
+ class JsonModifiers {
7249
7813
  /**
7250
7814
  * Return a JSON value/object/array where a given value is set at the given path.
7251
7815
  * The path is an array of keys to access the value.
@@ -7448,7 +8012,10 @@ class JsonMethods {
7448
8012
  * @param coalesce
7449
8013
  */
7450
8014
  json(coalesce) {
7451
- return queryJson(this.clone(), coalesce);
8015
+ return queryJson(
8016
+ this.clone(),
8017
+ coalesce
8018
+ );
7452
8019
  }
7453
8020
  }
7454
8021
 
@@ -8032,12 +8599,7 @@ class With {
8032
8599
  });
8033
8600
  }
8034
8601
  pushQueryValue(q, "with", [args[0], options || emptyObject, query]);
8035
- return setQueryObjectValue(
8036
- q,
8037
- "withShapes",
8038
- args[0],
8039
- shape
8040
- );
8602
+ return setQueryObjectValue(q, "withShapes", args[0], shape);
8041
8603
  }
8042
8604
  }
8043
8605
 
@@ -8150,12 +8712,13 @@ var __spreadValues$3 = (a, b) => {
8150
8712
  return a;
8151
8713
  };
8152
8714
  const _queryChangeCounter = (self, op, data) => {
8153
- self.q.type = "update";
8154
- if (!self.q.select) {
8155
- if (self.q.returnType === "oneOrThrow" || self.q.returnType === "valueOrThrow") {
8156
- self.q.throwOnNotFound = true;
8715
+ const q = self.q;
8716
+ q.type = "update";
8717
+ if (!q.select) {
8718
+ if (q.returnType === "oneOrThrow" || q.returnType === "valueOrThrow") {
8719
+ q.throwOnNotFound = true;
8157
8720
  }
8158
- self.q.returnType = "rowCount";
8721
+ q.returnType = "rowCount";
8159
8722
  }
8160
8723
  let map;
8161
8724
  if (typeof data === "object") {
@@ -8169,13 +8732,14 @@ const _queryChangeCounter = (self, op, data) => {
8169
8732
  pushQueryValue(self, "updateData", map);
8170
8733
  return self;
8171
8734
  };
8172
- const update = (q) => {
8173
- q.q.type = "update";
8174
- if (!q.q.select) {
8175
- q.q.returnType = "rowCount";
8735
+ const update = (self) => {
8736
+ const q = self.q;
8737
+ q.type = "update";
8738
+ if (!q.select) {
8739
+ q.returnType = "rowCount";
8176
8740
  }
8177
- throwIfNoWhere(q, "update");
8178
- return q;
8741
+ throwIfNoWhere(self, "update");
8742
+ return self;
8179
8743
  };
8180
8744
  const _queryUpdate = (query, arg) => {
8181
8745
  const { q } = query;
@@ -8208,8 +8772,16 @@ const _queryUpdate = (query, arg) => {
8208
8772
  if (value !== null && value !== void 0 && !isExpression(value)) {
8209
8773
  if (value instanceof Db) {
8210
8774
  if (value.q.type) {
8211
- const as = saveSearchAlias(query, "q", "withShapes");
8212
- pushQueryValue(query, "with", [as, emptyObject, value]);
8775
+ const as = saveSearchAlias(
8776
+ query,
8777
+ "q",
8778
+ "withShapes"
8779
+ );
8780
+ pushQueryValue(query, "with", [
8781
+ as,
8782
+ emptyObject,
8783
+ value
8784
+ ]);
8213
8785
  set[key] = new RawSQL(`(SELECT * FROM "${as}")`);
8214
8786
  }
8215
8787
  } else {
@@ -8415,7 +8987,10 @@ class Update {
8415
8987
  * @param arg - data to update records with, may have specific values, raw SQL, queries, or callbacks with sub-queries.
8416
8988
  */
8417
8989
  update(arg) {
8418
- return _queryUpdate(this.clone(), arg);
8990
+ return _queryUpdate(
8991
+ this.clone(),
8992
+ arg
8993
+ );
8419
8994
  }
8420
8995
  /**
8421
8996
  * `updateRaw` is for updating records with raw expression.
@@ -8471,7 +9046,10 @@ class Update {
8471
9046
  * @param arg - data to update records with, may have specific values, raw SQL, queries, or callbacks with sub-queries.
8472
9047
  */
8473
9048
  updateOrThrow(arg) {
8474
- return _queryUpdateOrThrow(this.clone(), arg);
9049
+ return _queryUpdateOrThrow(
9050
+ this.clone(),
9051
+ arg
9052
+ );
8475
9053
  }
8476
9054
  /**
8477
9055
  * Increments a column by `1`, returns a count of updated records by default.
@@ -8512,7 +9090,11 @@ class Update {
8512
9090
  * @param data - name of the column to increment, or an object with columns and values to add
8513
9091
  */
8514
9092
  increment(data) {
8515
- return _queryChangeCounter(this.clone(), "+", data);
9093
+ return _queryChangeCounter(
9094
+ this.clone(),
9095
+ "+",
9096
+ data
9097
+ );
8516
9098
  }
8517
9099
  /**
8518
9100
  * Decrements a column by `1`, returns a count of updated records by default.
@@ -8553,7 +9135,11 @@ class Update {
8553
9135
  * @param data - name of the column to decrement, or an object with columns and values to subtract
8554
9136
  */
8555
9137
  decrement(data) {
8556
- return _queryChangeCounter(this.clone(), "-", data);
9138
+ return _queryChangeCounter(
9139
+ this.clone(),
9140
+ "-",
9141
+ data
9142
+ );
8557
9143
  }
8558
9144
  }
8559
9145
 
@@ -8694,14 +9280,12 @@ class Headline extends Expression {
8694
9280
  }
8695
9281
  AggregateMethods.prototype.headline = function(search, params) {
8696
9282
  var _a;
8697
- const source = (_a = this.q.sources) == null ? void 0 : _a[search];
9283
+ const q = this;
9284
+ const source = (_a = q.q.sources) == null ? void 0 : _a[search];
8698
9285
  if (!source)
8699
- throw new OrchidOrmInternalError(
8700
- this,
8701
- `Search \`${search}\` is not defined`
8702
- );
9286
+ throw new OrchidOrmInternalError(q, `Search \`${search}\` is not defined`);
8703
9287
  return new Headline(
8704
- this.q,
9288
+ q.q,
8705
9289
  source,
8706
9290
  params
8707
9291
  );
@@ -9206,7 +9790,7 @@ class ScopeMethods {
9206
9790
  var _a;
9207
9791
  const q = this.clone();
9208
9792
  if (!((_a = q.q.scopes) == null ? void 0 : _a[scope])) {
9209
- const s = this.internal.scopes[scope];
9793
+ const s = q.internal.scopes[scope];
9210
9794
  if (s.and)
9211
9795
  pushQueryArray(q, "and", s.and);
9212
9796
  if (s.or)
@@ -9295,7 +9879,9 @@ class SoftDeleteMethods {
9295
9879
  * ```
9296
9880
  */
9297
9881
  hardDelete(..._args) {
9298
- return _queryDelete(this.clone().unscope("nonDeleted"));
9882
+ return _queryDelete(
9883
+ this.clone().unscope("nonDeleted")
9884
+ );
9299
9885
  }
9300
9886
  }
9301
9887
 
@@ -9463,7 +10049,11 @@ class QueryMethods {
9463
10049
  * @param columns - column names or a raw SQL
9464
10050
  */
9465
10051
  distinct(...columns) {
9466
- return pushQueryArray(this.clone(), "distinct", columns);
10052
+ return pushQueryArray(
10053
+ this.clone(),
10054
+ "distinct",
10055
+ columns
10056
+ );
9467
10057
  }
9468
10058
  /**
9469
10059
  * The `find` method is available only for tables which has exactly one primary key.
@@ -9532,7 +10122,10 @@ class QueryMethods {
9532
10122
  * @param args - `where` conditions
9533
10123
  */
9534
10124
  findBy(...args) {
9535
- return _queryFindBy(this.clone(), args);
10125
+ return _queryFindBy(
10126
+ this.clone(),
10127
+ args
10128
+ );
9536
10129
  }
9537
10130
  /**
9538
10131
  * The same as `where(conditions).takeOptional()`, it will filter records and add a `LIMIT 1`.
@@ -9547,7 +10140,10 @@ class QueryMethods {
9547
10140
  * @param args - `where` conditions
9548
10141
  */
9549
10142
  findByOptional(...args) {
9550
- return _queryFindByOptional(this.clone(), args);
10143
+ return _queryFindByOptional(
10144
+ this.clone(),
10145
+ args
10146
+ );
9551
10147
  }
9552
10148
  /**
9553
10149
  * Specifies the schema to be used as a prefix of a table name.
@@ -9603,7 +10199,11 @@ class QueryMethods {
9603
10199
  * @param columns - column names or a raw SQL
9604
10200
  */
9605
10201
  group(...columns) {
9606
- return pushQueryArray(this.clone(), "group", columns);
10202
+ return pushQueryArray(
10203
+ this.clone(),
10204
+ "group",
10205
+ columns
10206
+ );
9607
10207
  }
9608
10208
  /**
9609
10209
  * Add a window with `window` and use it later by its name for aggregate or window functions:
@@ -9689,7 +10289,11 @@ class QueryMethods {
9689
10289
  new RawSQL(args)
9690
10290
  );
9691
10291
  }
9692
- return pushQueryArray(this.clone(), "order", args);
10292
+ return pushQueryArray(
10293
+ this.clone(),
10294
+ "order",
10295
+ args
10296
+ );
9693
10297
  }
9694
10298
  /**
9695
10299
  * Adds a limit clause to the query.
@@ -9867,7 +10471,11 @@ class QueryMethods {
9867
10471
  * @param fn - helper function
9868
10472
  */
9869
10473
  makeHelper(fn) {
9870
- return fn;
10474
+ return (query, ...args) => {
10475
+ const q = query.clone();
10476
+ q.q.as = void 0;
10477
+ return fn(q, ...args);
10478
+ };
9871
10479
  }
9872
10480
  /**
9873
10481
  * Use `column` method to interpolate column names inside SQL templates.