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