pqb 0.23.5 → 0.24.1

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
  }
@@ -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) => {
@@ -1734,7 +1871,12 @@ const processSelectArg = (q, as, arg, columnAs) => {
1734
1871
  value = value.q.expr;
1735
1872
  }
1736
1873
  }
1737
- selectAs[key] = addParserForSelectItem(q, as, key, value);
1874
+ selectAs[key] = addParserForSelectItem(
1875
+ q,
1876
+ as,
1877
+ key,
1878
+ value
1879
+ );
1738
1880
  }
1739
1881
  return { selectAs };
1740
1882
  };
@@ -1843,7 +1985,7 @@ const addColumnToShapeFromSelect = (q, arg, shape, query, result, isSubQuery, ke
1843
1985
  }
1844
1986
  };
1845
1987
  const maybeUnNameColumn = (column, isSubQuery) => {
1846
- return isSubQuery && column.data.name ? orchidCore.setColumnData(column, "name", void 0) : column;
1988
+ return isSubQuery && (column == null ? void 0 : column.data.name) ? orchidCore.setColumnData(column, "name", void 0) : column;
1847
1989
  };
1848
1990
  function _querySelect(q, args) {
1849
1991
  if (!args.length) {
@@ -1896,40 +2038,46 @@ class SelectItemExpression extends orchidCore.Expression {
1896
2038
  }
1897
2039
  }
1898
2040
 
1899
- const _get = (q, returnType, arg) => {
2041
+ const _get = (query, returnType, arg) => {
1900
2042
  var _a, _b;
1901
- q.q.returnType = returnType;
2043
+ const q = query.q;
2044
+ q.returnType = returnType;
1902
2045
  let type;
1903
2046
  if (typeof arg === "string") {
1904
- type = q.q.shape[arg];
2047
+ type = q.shape[arg];
1905
2048
  if (!type) {
1906
2049
  const index = arg.indexOf(".");
1907
2050
  if (index !== -1) {
1908
2051
  const table = arg.slice(0, index);
1909
2052
  const column = arg.slice(index + 1);
1910
- if (table === (q.q.as || q.table)) {
1911
- type = q.q.shape[column];
2053
+ if (table === (q.as || query.table)) {
2054
+ type = q.shape[column];
1912
2055
  } else {
1913
- 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];
1914
2057
  }
1915
2058
  }
1916
2059
  }
1917
- q.q[orchidCore.getValueKey] = type;
1918
- setParserForSelectedString(q, arg, getQueryAs(q), orchidCore.getValueKey);
1919
- q.q.expr = new SelectItemExpression(
1920
- 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,
1921
2069
  arg,
1922
2070
  type || orchidCore.emptyObject
1923
2071
  );
1924
2072
  } else {
1925
2073
  type = arg._type;
1926
- q.q[orchidCore.getValueKey] = type;
1927
- addParserForRawExpression(q, orchidCore.getValueKey, arg);
1928
- q.q.expr = arg;
2074
+ q[orchidCore.getValueKey] = type;
2075
+ addParserForRawExpression(query, orchidCore.getValueKey, arg);
2076
+ q.expr = arg;
1929
2077
  }
1930
- q.q.select = [q.q.expr];
2078
+ q.select = [q.expr];
1931
2079
  return setQueryOperators(
1932
- q,
2080
+ query,
1933
2081
  (type == null ? void 0 : type.operators) || Operators.any
1934
2082
  );
1935
2083
  };
@@ -1940,27 +2088,11 @@ function _queryGetOptional(self, arg) {
1940
2088
  return _get(self, "value", arg);
1941
2089
  }
1942
2090
 
1943
- class QueryBase {
1944
- constructor() {
1945
- this.q = {};
1946
- }
1947
- /**
1948
- * Clones the current query chain, useful for re-using partial query snippets in other queries without mutating the original.
1949
- *
1950
- * Used under the hood, and not really needed on the app side.
1951
- */
1952
- clone() {
1953
- const cloned = Object.create(this.baseQuery);
1954
- cloned.q = getClonedQueryData(this.q);
1955
- return cloned;
1956
- }
1957
- }
1958
-
1959
2091
  const _queryAs = (self, as) => {
1960
2092
  self.q.as = as;
1961
2093
  return self;
1962
2094
  };
1963
- class AsMethods extends QueryBase {
2095
+ class AsMethods {
1964
2096
  /**
1965
2097
  * Sets table alias:
1966
2098
  *
@@ -1979,30 +2111,30 @@ class AsMethods extends QueryBase {
1979
2111
  }
1980
2112
 
1981
2113
  function queryFrom(self, args) {
1982
- var _a, _b, _c;
1983
2114
  if (Array.isArray(args[0])) {
1984
2115
  return queryFrom(self, [
1985
2116
  new RawSQL(args)
1986
2117
  ]);
1987
2118
  }
2119
+ const data = self.q;
1988
2120
  if (typeof args[0] === "string") {
1989
- (_a = self.q).as || (_a.as = args[0]);
2121
+ data.as || (data.as = args[0]);
1990
2122
  } else if (!orchidCore.isExpression(args[0])) {
1991
2123
  const q = args[0];
1992
- (_b = self.q).as || (_b.as = q.q.as || q.table || "t");
1993
- self.q.shape = getShapeFromSelect(
2124
+ data.as || (data.as = q.q.as || q.table || "t");
2125
+ data.shape = getShapeFromSelect(
1994
2126
  args[0],
1995
2127
  true
1996
2128
  );
1997
- self.q.parsers = q.q.parsers;
2129
+ data.parsers = q.q.parsers;
1998
2130
  } else {
1999
- (_c = self.q).as || (_c.as = "t");
2131
+ data.as || (data.as = "t");
2000
2132
  }
2001
2133
  const options = args[1];
2002
2134
  if (options == null ? void 0 : options.only) {
2003
- self.q.fromOnly = options.only;
2135
+ data.fromOnly = options.only;
2004
2136
  }
2005
- self.q.from = args[0];
2137
+ data.from = args[0];
2006
2138
  return self;
2007
2139
  }
2008
2140
  class From {
@@ -2035,19 +2167,22 @@ class From {
2035
2167
  * @param args - query, raw SQL, name of CTE table, or a template string
2036
2168
  */
2037
2169
  from(...args) {
2038
- return queryFrom(this.clone(), args);
2170
+ return queryFrom(
2171
+ this.clone(),
2172
+ args
2173
+ );
2039
2174
  }
2040
2175
  }
2041
2176
 
2042
2177
  function queryWrap(self, query, as = "t") {
2043
- return _queryAs(
2044
- queryFrom(query, [self]),
2045
- as
2046
- );
2178
+ return _queryAs(queryFrom(query, [self]), as);
2047
2179
  }
2048
2180
 
2049
2181
  function queryJson(self, coalesce) {
2050
- const q = queryWrap(self, self.baseQuery.clone());
2182
+ const q = queryWrap(
2183
+ self,
2184
+ self.baseQuery.clone()
2185
+ );
2051
2186
  _queryGetOptional(
2052
2187
  q,
2053
2188
  new RawSQL(
@@ -3242,16 +3377,17 @@ var __spreadValues$a = (a, b) => {
3242
3377
  return a;
3243
3378
  };
3244
3379
  var __spreadProps$6 = (a, b) => __defProps$6(a, __getOwnPropDescs$6(b));
3245
- function setQueryOperators(q, operators) {
3246
- if (q.q.operators) {
3247
- if (q.q.operators === operators)
3248
- return q;
3249
- 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;
3250
3386
  } else {
3251
- q.q.originalQuery = q.baseQuery;
3387
+ q.originalQuery = query.baseQuery;
3252
3388
  }
3253
- q.q.operators = operators;
3254
- return extendQuery(q, operators);
3389
+ q.operators = operators;
3390
+ return extendQuery(query, operators);
3255
3391
  }
3256
3392
  const make = (_op) => {
3257
3393
  return Object.assign(
@@ -3384,13 +3520,13 @@ class IntegerBaseColumn extends NumberBaseColumn {
3384
3520
  }
3385
3521
  class NumberAsStringBaseColumn extends ColumnType {
3386
3522
  constructor(schema) {
3387
- super(schema, schema.string);
3523
+ super(schema, schema.stringSchema);
3388
3524
  this.operators = Operators.number;
3389
3525
  }
3390
3526
  }
3391
3527
  class DecimalColumn extends ColumnType {
3392
3528
  constructor(schema, numericPrecision, numericScale) {
3393
- super(schema, schema.string);
3529
+ super(schema, schema.stringSchema);
3394
3530
  this.operators = Operators.number;
3395
3531
  this.dataType = "decimal";
3396
3532
  this.data.numericPrecision = numericPrecision;
@@ -3549,14 +3685,14 @@ var __spreadValues$9 = (a, b) => {
3549
3685
  };
3550
3686
  var __spreadProps$5 = (a, b) => __defProps$5(a, __getOwnPropDescs$5(b));
3551
3687
  class TextBaseColumn extends ColumnType {
3552
- constructor(schema, schemaType = schema.string) {
3688
+ constructor(schema, schemaType = schema.stringSchema) {
3553
3689
  super(schema, schemaType);
3554
3690
  this.operators = Operators.text;
3555
3691
  }
3556
3692
  }
3557
3693
  class LimitedTextBaseColumn extends TextBaseColumn {
3558
3694
  constructor(schema, limit) {
3559
- super(schema, limit ? schema.stringMax(limit) : schema.string);
3695
+ super(schema, limit ? schema.stringMax(limit) : schema.stringSchema);
3560
3696
  this.data.maxChars = limit;
3561
3697
  }
3562
3698
  toSQL() {
@@ -3639,7 +3775,7 @@ const textColumnToCode = (column, t) => {
3639
3775
  `${column.dataType}(${args})${orchidCore.stringDataToCode(data)}`
3640
3776
  );
3641
3777
  };
3642
- 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;
3643
3779
  class TextColumn extends TextBaseColumn {
3644
3780
  constructor(schema, min, max) {
3645
3781
  super(schema, minMaxToSchema(schema, min, max));
@@ -3662,7 +3798,7 @@ class ByteaColumn extends ColumnType {
3662
3798
  }
3663
3799
  class PointColumn extends ColumnType {
3664
3800
  constructor(schema) {
3665
- super(schema, schema.string);
3801
+ super(schema, schema.stringSchema);
3666
3802
  this.dataType = "point";
3667
3803
  this.operators = Operators.text;
3668
3804
  }
@@ -3672,7 +3808,7 @@ class PointColumn extends ColumnType {
3672
3808
  }
3673
3809
  class LineColumn extends ColumnType {
3674
3810
  constructor(schema) {
3675
- super(schema, schema.string);
3811
+ super(schema, schema.stringSchema);
3676
3812
  this.dataType = "line";
3677
3813
  this.operators = Operators.text;
3678
3814
  }
@@ -3682,7 +3818,7 @@ class LineColumn extends ColumnType {
3682
3818
  }
3683
3819
  class LsegColumn extends ColumnType {
3684
3820
  constructor(schema) {
3685
- super(schema, schema.string);
3821
+ super(schema, schema.stringSchema);
3686
3822
  this.dataType = "lseg";
3687
3823
  this.operators = Operators.text;
3688
3824
  }
@@ -3692,7 +3828,7 @@ class LsegColumn extends ColumnType {
3692
3828
  }
3693
3829
  class BoxColumn extends ColumnType {
3694
3830
  constructor(schema) {
3695
- super(schema, schema.string);
3831
+ super(schema, schema.stringSchema);
3696
3832
  this.dataType = "box";
3697
3833
  this.operators = Operators.text;
3698
3834
  }
@@ -3702,7 +3838,7 @@ class BoxColumn extends ColumnType {
3702
3838
  }
3703
3839
  class PathColumn extends ColumnType {
3704
3840
  constructor(schema) {
3705
- super(schema, schema.string);
3841
+ super(schema, schema.stringSchema);
3706
3842
  this.dataType = "path";
3707
3843
  this.operators = Operators.text;
3708
3844
  }
@@ -3712,7 +3848,7 @@ class PathColumn extends ColumnType {
3712
3848
  }
3713
3849
  class PolygonColumn extends ColumnType {
3714
3850
  constructor(schema) {
3715
- super(schema, schema.string);
3851
+ super(schema, schema.stringSchema);
3716
3852
  this.dataType = "polygon";
3717
3853
  this.operators = Operators.text;
3718
3854
  }
@@ -3722,7 +3858,7 @@ class PolygonColumn extends ColumnType {
3722
3858
  }
3723
3859
  class CircleColumn extends ColumnType {
3724
3860
  constructor(schema) {
3725
- super(schema, schema.string);
3861
+ super(schema, schema.stringSchema);
3726
3862
  this.dataType = "circle";
3727
3863
  this.operators = Operators.text;
3728
3864
  }
@@ -3732,7 +3868,7 @@ class CircleColumn extends ColumnType {
3732
3868
  }
3733
3869
  class MoneyColumn extends NumberBaseColumn {
3734
3870
  constructor(schema) {
3735
- super(schema, schema.string);
3871
+ super(schema, schema.stringSchema);
3736
3872
  this.dataType = "money";
3737
3873
  this.parseFn = Object.assign(
3738
3874
  function(input) {
@@ -3749,7 +3885,7 @@ class MoneyColumn extends NumberBaseColumn {
3749
3885
  }
3750
3886
  class CidrColumn extends ColumnType {
3751
3887
  constructor(schema) {
3752
- super(schema, schema.string);
3888
+ super(schema, schema.stringSchema);
3753
3889
  this.dataType = "cidr";
3754
3890
  this.operators = Operators.text;
3755
3891
  }
@@ -3759,7 +3895,7 @@ class CidrColumn extends ColumnType {
3759
3895
  }
3760
3896
  class InetColumn extends ColumnType {
3761
3897
  constructor(schema) {
3762
- super(schema, schema.string);
3898
+ super(schema, schema.stringSchema);
3763
3899
  this.dataType = "inet";
3764
3900
  this.operators = Operators.text;
3765
3901
  }
@@ -3769,7 +3905,7 @@ class InetColumn extends ColumnType {
3769
3905
  }
3770
3906
  class MacAddrColumn extends ColumnType {
3771
3907
  constructor(schema) {
3772
- super(schema, schema.string);
3908
+ super(schema, schema.stringSchema);
3773
3909
  this.dataType = "macaddr";
3774
3910
  this.operators = Operators.text;
3775
3911
  }
@@ -3779,7 +3915,7 @@ class MacAddrColumn extends ColumnType {
3779
3915
  }
3780
3916
  class MacAddr8Column extends ColumnType {
3781
3917
  constructor(schema) {
3782
- super(schema, schema.string);
3918
+ super(schema, schema.stringSchema);
3783
3919
  this.dataType = "macaddr8";
3784
3920
  this.operators = Operators.text;
3785
3921
  }
@@ -3825,7 +3961,7 @@ class BitVaryingColumn extends ColumnType {
3825
3961
  }
3826
3962
  class TsVectorColumn extends ColumnType {
3827
3963
  constructor(schema, defaultLanguage = orchidCore.getDefaultLanguage()) {
3828
- super(schema, schema.string);
3964
+ super(schema, schema.stringSchema);
3829
3965
  this.defaultLanguage = defaultLanguage;
3830
3966
  this.dataType = "tsvector";
3831
3967
  this.operators = Operators.text;
@@ -3879,7 +4015,7 @@ class TsVectorColumn extends ColumnType {
3879
4015
  }
3880
4016
  class TsQueryColumn extends ColumnType {
3881
4017
  constructor(schema) {
3882
- super(schema, schema.string);
4018
+ super(schema, schema.stringSchema);
3883
4019
  this.dataType = "tsquery";
3884
4020
  this.operators = Operators.text;
3885
4021
  }
@@ -3914,7 +4050,7 @@ class UUIDColumn extends ColumnType {
3914
4050
  }
3915
4051
  class XMLColumn extends ColumnType {
3916
4052
  constructor(schema) {
3917
- super(schema, schema.string);
4053
+ super(schema, schema.stringSchema);
3918
4054
  this.dataType = "xml";
3919
4055
  this.operators = Operators.text;
3920
4056
  }
@@ -3933,166 +4069,43 @@ class CitextColumn extends TextBaseColumn {
3933
4069
  }
3934
4070
  }
3935
4071
 
3936
- const dateTimeEncode = (input) => {
3937
- return typeof input === "number" ? new Date(input) : input;
3938
- };
3939
- const skipDateMethodsFromToCode = { encodeFn: dateTimeEncode };
3940
- class DateBaseColumn extends ColumnType {
4072
+ class BooleanColumn extends ColumnType {
3941
4073
  constructor(schema) {
3942
- super(schema, schema.stringNumberDate);
3943
- this.operators = Operators.date;
3944
- this.encodeFn = dateTimeEncode;
3945
- this.asNumber = schema.dateAsNumber;
3946
- this.asDate = schema.dateAsDate;
3947
- }
3948
- }
3949
- class DateColumn extends DateBaseColumn {
3950
- constructor() {
3951
- super(...arguments);
3952
- this.dataType = "date";
4074
+ super(schema, schema.boolean);
4075
+ this.dataType = "boolean";
4076
+ this.operators = Operators.boolean;
4077
+ this.parseItem = (input) => input[0] === "t";
3953
4078
  }
3954
4079
  toCode(t) {
3955
- return columnCode(
3956
- this,
3957
- t,
3958
- `date()${orchidCore.dateDataToCode(this.data)}`,
3959
- this.data,
3960
- skipDateMethodsFromToCode
3961
- );
4080
+ return columnCode(this, t, "boolean()");
3962
4081
  }
3963
4082
  }
3964
- class DateTimeBaseClass extends DateBaseColumn {
3965
- constructor(schema, dateTimePrecision) {
3966
- super(schema);
3967
- 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;
3968
4090
  }
3969
- toSQL() {
3970
- return orchidCore.joinTruthy(
3971
- this.dataType,
3972
- this.data.dateTimePrecision !== void 0 && `(${this.data.dateTimePrecision})`
3973
- );
4091
+ toCode(t) {
4092
+ return columnCode(this, t, `type(${orchidCore.singleQuote(this.dataType)})`);
3974
4093
  }
3975
- }
3976
- class DateTimeTzBaseClass extends DateTimeBaseClass {
3977
- toSQL() {
3978
- return orchidCore.joinTruthy(
3979
- this.baseDataType,
3980
- this.data.dateTimePrecision !== void 0 && `(${this.data.dateTimePrecision})`,
3981
- " with time zone"
4094
+ as(column) {
4095
+ const c = orchidCore.setColumnData(
4096
+ this,
4097
+ "as",
4098
+ column
3982
4099
  );
4100
+ c.inputSchema = column.inputSchema;
4101
+ c.outputSchema = column.outputSchema;
4102
+ c.querySchema = column.querySchema;
4103
+ return c;
3983
4104
  }
3984
4105
  }
3985
- const timestampToCode = (self, t) => {
3986
- const { dateTimePrecision: p } = self.data;
3987
- return columnCode(
3988
- self,
3989
- t,
3990
- `${self instanceof TimestampColumn ? "timestampNoTZ" : "timestamp"}(${p && p !== 6 ? p : ""})${orchidCore.dateDataToCode(self.data)}`,
3991
- self.data,
3992
- skipDateMethodsFromToCode
3993
- );
3994
- };
3995
- class TimestampColumn extends DateTimeBaseClass {
3996
- constructor() {
3997
- super(...arguments);
3998
- this.dataType = "timestamp";
3999
- }
4000
- toCode(t) {
4001
- return timestampToCode(this, t);
4002
- }
4003
- }
4004
- class TimestampTZColumn extends DateTimeTzBaseClass {
4005
- constructor() {
4006
- super(...arguments);
4007
- this.dataType = "timestamptz";
4008
- this.baseDataType = "timestamp";
4009
- }
4106
+ class DomainColumn extends CustomTypeColumn {
4010
4107
  toCode(t) {
4011
- return timestampToCode(this, t);
4012
- }
4013
- }
4014
- class TimeColumn extends ColumnType {
4015
- constructor(schema, dateTimePrecision) {
4016
- super(schema, schema.string);
4017
- this.dataType = "time";
4018
- this.operators = Operators.time;
4019
- this.data.dateTimePrecision = dateTimePrecision;
4020
- }
4021
- toCode(t) {
4022
- const { dateTimePrecision } = this.data;
4023
- return columnCode(
4024
- this,
4025
- t,
4026
- `time(${dateTimePrecision || ""})${orchidCore.dateDataToCode(this.data)}`,
4027
- this.data,
4028
- skipDateMethodsFromToCode
4029
- );
4030
- }
4031
- }
4032
- class IntervalColumn extends ColumnType {
4033
- constructor(schema, fields, precision) {
4034
- super(schema, schema.timeInterval);
4035
- this.dataType = "interval";
4036
- this.operators = Operators.date;
4037
- this.data.fields = fields;
4038
- this.data.precision = precision;
4039
- }
4040
- toCode(t) {
4041
- const { fields, precision } = this.data;
4042
- return columnCode(
4043
- this,
4044
- t,
4045
- `interval(${[fields && `'${fields}'`, precision && String(precision)].filter((part) => part).join(", ")})`,
4046
- this.data,
4047
- skipDateMethodsFromToCode
4048
- );
4049
- }
4050
- toSQL() {
4051
- return orchidCore.joinTruthy(
4052
- this.dataType,
4053
- this.data.fields && ` ${this.data.fields}`,
4054
- this.data.precision !== void 0 && ` (${this.data.precision})`
4055
- );
4056
- }
4057
- }
4058
-
4059
- class BooleanColumn extends ColumnType {
4060
- constructor(schema) {
4061
- super(schema, schema.boolean);
4062
- this.dataType = "boolean";
4063
- this.operators = Operators.boolean;
4064
- this.parseItem = (input) => input[0] === "t";
4065
- }
4066
- toCode(t) {
4067
- return columnCode(this, t, "boolean()");
4068
- }
4069
- }
4070
-
4071
- class CustomTypeColumn extends ColumnType {
4072
- constructor(schema, dataType) {
4073
- super(schema, schema.unknown, schema.unknown, schema.unknown);
4074
- this.dataType = dataType;
4075
- this.operators = Operators.any;
4076
- this.data.isOfCustomType = true;
4077
- }
4078
- toCode(t) {
4079
- return columnCode(this, t, `type(${orchidCore.singleQuote(this.dataType)})`);
4080
- }
4081
- as(column) {
4082
- const c = orchidCore.setColumnData(
4083
- this,
4084
- "as",
4085
- column
4086
- );
4087
- c.inputSchema = column.inputSchema;
4088
- c.outputSchema = column.outputSchema;
4089
- c.querySchema = column.querySchema;
4090
- return c;
4091
- }
4092
- }
4093
- class DomainColumn extends CustomTypeColumn {
4094
- toCode(t) {
4095
- return columnCode(this, t, `domain(${orchidCore.singleQuote(this.dataType)})`);
4108
+ return columnCode(this, t, `domain(${orchidCore.singleQuote(this.dataType)})`);
4096
4109
  }
4097
4110
  }
4098
4111
 
@@ -4130,19 +4143,6 @@ const getColumnTypes = (types, fn, nowSQL, language, data = newTableData()) => {
4130
4143
  return fn(types);
4131
4144
  };
4132
4145
  const makeColumnTypes = (schema) => {
4133
- const columnsWithMethods = {};
4134
- function columnWithMethods(klass, methods, ...args) {
4135
- if (columnsWithMethods[klass.name]) {
4136
- return new columnsWithMethods[klass.name](...args);
4137
- }
4138
- const withMethods = class extends klass {
4139
- };
4140
- Object.assign(withMethods.prototype, methods);
4141
- return new (columnsWithMethods[klass.name] = withMethods)(...args);
4142
- }
4143
- const numberMethods = schema.numberMethods;
4144
- const stringMethods = schema.stringMethods;
4145
- const dateMethods = schema.dateMethods;
4146
4146
  return __spreadValues$8({
4147
4147
  schema,
4148
4148
  enum: schema.enum,
@@ -4165,90 +4165,33 @@ const makeColumnTypes = (schema) => {
4165
4165
  }
4166
4166
  return (...args2) => new RawSQL(args2, arg);
4167
4167
  },
4168
- smallint() {
4169
- return columnWithMethods(SmallIntColumn, numberMethods, schema);
4170
- },
4171
- integer() {
4172
- return columnWithMethods(IntegerColumn, numberMethods, schema);
4173
- },
4174
- bigint() {
4175
- return columnWithMethods(BigIntColumn, stringMethods, schema);
4176
- },
4177
- numeric(precision, scale) {
4178
- return columnWithMethods(
4179
- DecimalColumn,
4180
- stringMethods,
4181
- schema,
4182
- precision,
4183
- scale
4184
- );
4185
- },
4186
- decimal(precision, scale) {
4187
- return columnWithMethods(
4188
- DecimalColumn,
4189
- stringMethods,
4190
- schema,
4191
- precision,
4192
- scale
4193
- );
4194
- },
4195
- real() {
4196
- return columnWithMethods(RealColumn, numberMethods, schema);
4197
- },
4198
- doublePrecision() {
4199
- return columnWithMethods(DoublePrecisionColumn, stringMethods, schema);
4200
- },
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,
4201
4175
  identity(options) {
4202
- return columnWithMethods(
4203
- IntegerColumn,
4204
- numberMethods,
4205
- schema
4206
- ).identity(options);
4207
- },
4208
- smallSerial() {
4209
- return columnWithMethods(SmallSerialColumn, numberMethods, schema);
4210
- },
4211
- serial() {
4212
- return columnWithMethods(SerialColumn, numberMethods, schema);
4213
- },
4214
- bigSerial() {
4215
- return columnWithMethods(BigSerialColumn, stringMethods, schema);
4216
- },
4217
- money() {
4218
- return columnWithMethods(MoneyColumn, stringMethods, schema);
4219
- },
4220
- varchar(limit) {
4221
- return columnWithMethods(VarCharColumn, stringMethods, schema, limit);
4222
- },
4223
- char(limit) {
4224
- return columnWithMethods(CharColumn, stringMethods, schema, limit);
4225
- },
4226
- text(min, max) {
4227
- return columnWithMethods(TextColumn, stringMethods, schema, min, max);
4228
- },
4229
- string(limit = 255) {
4230
- return columnWithMethods(StringColumn, stringMethods, schema, limit);
4231
- },
4232
- citext(min, max) {
4233
- return columnWithMethods(CitextColumn, stringMethods, schema, min, max);
4176
+ return schema.integer().identity(
4177
+ options
4178
+ );
4234
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,
4235
4189
  bytea() {
4236
4190
  return new ByteaColumn(schema);
4237
4191
  },
4238
- date() {
4239
- return columnWithMethods(DateColumn, dateMethods, schema);
4240
- },
4241
- timestampNoTZ(precision) {
4242
- return columnWithMethods(TimestampColumn, dateMethods, schema, precision);
4243
- },
4244
- timestamp(precision) {
4245
- return columnWithMethods(
4246
- TimestampTZColumn,
4247
- dateMethods,
4248
- schema,
4249
- precision
4250
- );
4251
- },
4192
+ date: schema.date,
4193
+ timestampNoTZ: schema.timestampNoTZ,
4194
+ timestamp: schema.timestamp,
4252
4195
  time(precision) {
4253
4196
  return new TimeColumn(schema, precision);
4254
4197
  },
@@ -4822,7 +4765,10 @@ class AggregateMethods {
4822
4765
  * ```
4823
4766
  */
4824
4767
  exists() {
4825
- const q = _queryGetOptional(this.clone(), new RawSQL("true"));
4768
+ const q = _queryGetOptional(
4769
+ this.clone(),
4770
+ new RawSQL("true")
4771
+ );
4826
4772
  q.q.notFoundDefault = false;
4827
4773
  q.q.coalesceValue = new RawSQL("false");
4828
4774
  return q;
@@ -4852,13 +4798,7 @@ class AggregateMethods {
4852
4798
  * @param options - aggregation options
4853
4799
  */
4854
4800
  count(arg = "*", options) {
4855
- return makeFnExpression(
4856
- this,
4857
- int,
4858
- "count",
4859
- [arg],
4860
- options
4861
- );
4801
+ return makeFnExpression(this, int, "count", [arg], options);
4862
4802
  }
4863
4803
  /**
4864
4804
  * Get the minimum value for the specified numeric column, returns number or `null` if there are no records.
@@ -6076,16 +6016,17 @@ class OnConflictQueryBuilder {
6076
6016
  }
6077
6017
  }
6078
6018
 
6079
- const _queryDelete = (q) => {
6080
- if (!q.q.select) {
6081
- if (q.q.returnType === "oneOrThrow" || q.q.returnType === "valueOrThrow") {
6082
- 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;
6083
6024
  }
6084
- q.q.returnType = "rowCount";
6025
+ q.returnType = "rowCount";
6085
6026
  }
6086
- throwIfNoWhere(q, "delete");
6087
- q.q.type = "delete";
6088
- return q;
6027
+ throwIfNoWhere(query, "delete");
6028
+ q.type = "delete";
6029
+ return query;
6089
6030
  };
6090
6031
  class Delete {
6091
6032
  /**
@@ -6158,8 +6099,8 @@ const forMethods = {
6158
6099
  return q;
6159
6100
  }
6160
6101
  };
6161
- const forQueryBuilder = (q, type, tableNames) => {
6162
- q = extendQuery(q, forMethods);
6102
+ const forQueryBuilder = (arg, type, tableNames) => {
6103
+ const q = extendQuery(arg, forMethods);
6163
6104
  q.q.for = {
6164
6105
  type,
6165
6106
  tableNames
@@ -6338,7 +6279,7 @@ const _queryHookAfterDelete = (q, select, cb) => {
6338
6279
  const _queryHookAfterDeleteCommit = (q, select, cb) => {
6339
6280
  return after(q, "Delete", select, cb, true);
6340
6281
  };
6341
- class QueryHooks extends QueryBase {
6282
+ class QueryHooks {
6342
6283
  /**
6343
6284
  * Run the function before any kind of query.
6344
6285
  *
@@ -6375,7 +6316,11 @@ class QueryHooks extends QueryBase {
6375
6316
  * @param cb - function to call, first argument is the query result with selected columns, second argument is a query object
6376
6317
  */
6377
6318
  afterCreate(select, cb) {
6378
- return _queryHookAfterCreate(this.clone(), select, cb);
6319
+ return _queryHookAfterCreate(
6320
+ this.clone(),
6321
+ select,
6322
+ cb
6323
+ );
6379
6324
  }
6380
6325
  /**
6381
6326
  * Run the function after transaction for a `create` kind of query will be committed.
@@ -6385,7 +6330,11 @@ class QueryHooks extends QueryBase {
6385
6330
  * @param cb - function to call, first argument is the query result with selected columns, second argument is a query object
6386
6331
  */
6387
6332
  afterCreateCommit(select, cb) {
6388
- return _queryHookAfterCreateCommit(this.clone(), select, cb);
6333
+ return _queryHookAfterCreateCommit(
6334
+ this.clone(),
6335
+ select,
6336
+ cb
6337
+ );
6389
6338
  }
6390
6339
  /**
6391
6340
  * Run the function before an `update` kind of query.
@@ -6406,7 +6355,11 @@ class QueryHooks extends QueryBase {
6406
6355
  * @param cb - function to call, first argument is the query result with selected columns, second argument is a query object
6407
6356
  */
6408
6357
  afterUpdate(select, cb) {
6409
- return _queryHookAfterUpdate(this.clone(), select, cb);
6358
+ return _queryHookAfterUpdate(
6359
+ this.clone(),
6360
+ select,
6361
+ cb
6362
+ );
6410
6363
  }
6411
6364
  /**
6412
6365
  * Run the function after transaction for an `update` kind of query will be committed.
@@ -6417,7 +6370,11 @@ class QueryHooks extends QueryBase {
6417
6370
  * @param cb - function to call, first argument is the query result with selected columns, second argument is a query object
6418
6371
  */
6419
6372
  afterUpdateCommit(select, cb) {
6420
- return _queryHookAfterUpdateCommit(this.clone(), select, cb);
6373
+ return _queryHookAfterUpdateCommit(
6374
+ this.clone(),
6375
+ select,
6376
+ cb
6377
+ );
6421
6378
  }
6422
6379
  /**
6423
6380
  * Run the function before a `create` or an `update` kind of query.
@@ -6438,7 +6395,11 @@ class QueryHooks extends QueryBase {
6438
6395
  * @param cb - function to call, first argument is the query result with selected columns, second argument is a query object
6439
6396
  */
6440
6397
  afterSave(select, cb) {
6441
- return _queryHookAfterSave(this.clone(), select, cb);
6398
+ return _queryHookAfterSave(
6399
+ this.clone(),
6400
+ select,
6401
+ cb
6402
+ );
6442
6403
  }
6443
6404
  /**
6444
6405
  * Run the function after transaction for a `create` or an `update` kind of query will be committed.
@@ -6449,7 +6410,11 @@ class QueryHooks extends QueryBase {
6449
6410
  * @param cb - function to call, first argument is the query result with selected columns, second argument is a query object
6450
6411
  */
6451
6412
  afterSaveCommit(select, cb) {
6452
- return _queryAfterSaveCommit(this.clone(), select, cb);
6413
+ return _queryAfterSaveCommit(
6414
+ this.clone(),
6415
+ select,
6416
+ cb
6417
+ );
6453
6418
  }
6454
6419
  /**
6455
6420
  * Run the function before a `delete` kind of query.
@@ -6470,7 +6435,11 @@ class QueryHooks extends QueryBase {
6470
6435
  * @param cb - function to call, first argument is the query result with selected columns, second argument is a query object
6471
6436
  */
6472
6437
  afterDelete(select, cb) {
6473
- return _queryHookAfterDelete(this.clone(), select, cb);
6438
+ return _queryHookAfterDelete(
6439
+ this.clone(),
6440
+ select,
6441
+ cb
6442
+ );
6474
6443
  }
6475
6444
  /**
6476
6445
  * Run the function after transaction for a `delete` kind of query will be committed.
@@ -6481,7 +6450,27 @@ class QueryHooks extends QueryBase {
6481
6450
  * @param cb - function to call, first argument is the query result with selected columns, second argument is a query object
6482
6451
  */
6483
6452
  afterDeleteCommit(select, cb) {
6484
- 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;
6485
6474
  }
6486
6475
  }
6487
6476
 
@@ -6493,7 +6482,11 @@ const _queryWhere = (q, args) => {
6493
6482
  new RawSQL(args)
6494
6483
  );
6495
6484
  }
6496
- return pushQueryArray(q, "and", args);
6485
+ return pushQueryArray(
6486
+ q,
6487
+ "and",
6488
+ args
6489
+ );
6497
6490
  };
6498
6491
  const _queryWhereNot = (q, args) => {
6499
6492
  if (Array.isArray(args[0])) {
@@ -6547,14 +6540,13 @@ const _queryWhereIn = (q, and, arg, values, not) => {
6547
6540
  }
6548
6541
  return q;
6549
6542
  };
6550
- const existsArgs = (args) => {
6551
- const q = args[0];
6543
+ const existsArgs = (q, args) => {
6552
6544
  let isSubQuery;
6553
6545
  if (typeof q === "object") {
6554
6546
  isSubQuery = getIsJoinSubQuery(q.q, q.baseQuery.q);
6555
6547
  if (isSubQuery) {
6556
- args[0] = q.clone();
6557
- args[0].shape = getShapeFromSelect(q, true);
6548
+ q = q.clone();
6549
+ q.shape = getShapeFromSelect(q, true);
6558
6550
  }
6559
6551
  } else {
6560
6552
  isSubQuery = false;
@@ -6562,6 +6554,7 @@ const existsArgs = (args) => {
6562
6554
  return [
6563
6555
  {
6564
6556
  EXISTS: {
6557
+ first: q,
6565
6558
  args,
6566
6559
  isSubQuery
6567
6560
  }
@@ -6958,7 +6951,10 @@ class Where {
6958
6951
  * @param args - {@link WhereArgs}
6959
6952
  */
6960
6953
  where(...args) {
6961
- return _queryWhere(this.clone(), args);
6954
+ return _queryWhere(
6955
+ this.clone(),
6956
+ args
6957
+ );
6962
6958
  }
6963
6959
  /**
6964
6960
  * `whereNot` takes the same argument as `where`,
@@ -6976,7 +6972,10 @@ class Where {
6976
6972
  * @param args - {@link WhereArgs}
6977
6973
  */
6978
6974
  whereNot(...args) {
6979
- return _queryWhereNot(this.clone(), args);
6975
+ return _queryWhereNot(
6976
+ this.clone(),
6977
+ args
6978
+ );
6980
6979
  }
6981
6980
  /**
6982
6981
  * `orWhere` is accepting the same arguments as {@link where}, joining arguments with `OR`.
@@ -7010,35 +7009,172 @@ class Where {
7010
7009
  * @param args - {@link WhereArgs} will be prefixed with `NOT` and joined with `OR`
7011
7010
  */
7012
7011
  orWhereNot(...args) {
7013
- return _queryOrNot(this.clone(), args);
7012
+ return _queryOrNot(
7013
+ this.clone(),
7014
+ args
7015
+ );
7014
7016
  }
7015
- whereIn(arg, values) {
7016
- 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
+ );
7017
7059
  }
7018
- orWhereIn(arg, values) {
7019
- 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
+ );
7020
7075
  }
7021
- whereNotIn(arg, values) {
7022
- 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
+ );
7023
7091
  }
7024
- orWhereNotIn(arg, values) {
7025
- 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
+ );
7026
7107
  }
7027
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
7028
- whereExists(...args) {
7029
- 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
+ );
7030
7130
  }
7031
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
7032
- orWhereExists(...args) {
7033
- 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
+ );
7034
7145
  }
7035
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
7036
- whereNotExists(...args) {
7037
- 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
+ );
7038
7163
  }
7039
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
7040
- orWhereNotExists(...args) {
7041
- 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
+ );
7042
7178
  }
7043
7179
  }
7044
7180
  class WhereQueryBase extends QueryBase {
@@ -7046,21 +7182,447 @@ class WhereQueryBase extends QueryBase {
7046
7182
  orchidCore.applyMixins(WhereQueryBase, [Where]);
7047
7183
 
7048
7184
  class Join {
7049
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
7050
- join(...args) {
7051
- 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);
7052
7551
  }
7053
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
7054
- leftJoin(...args) {
7055
- 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);
7056
7578
  }
7057
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
7058
- rightJoin(...args) {
7059
- 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);
7060
7602
  }
7061
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
7062
- fullJoin(...args) {
7063
- 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);
7064
7626
  }
7065
7627
  /**
7066
7628
  * `joinLateral` allows joining a table with a sub-query that can reference the main table of current query and the other joined tables.
@@ -7249,7 +7811,7 @@ class OnQueryBuilder extends WhereQueryBase {
7249
7811
  }
7250
7812
  }
7251
7813
 
7252
- class JsonModifiers extends QueryBase {
7814
+ class JsonModifiers {
7253
7815
  /**
7254
7816
  * Return a JSON value/object/array where a given value is set at the given path.
7255
7817
  * The path is an array of keys to access the value.
@@ -7452,7 +8014,10 @@ class JsonMethods {
7452
8014
  * @param coalesce
7453
8015
  */
7454
8016
  json(coalesce) {
7455
- return queryJson(this.clone(), coalesce);
8017
+ return queryJson(
8018
+ this.clone(),
8019
+ coalesce
8020
+ );
7456
8021
  }
7457
8022
  }
7458
8023
 
@@ -8036,12 +8601,7 @@ class With {
8036
8601
  });
8037
8602
  }
8038
8603
  pushQueryValue(q, "with", [args[0], options || orchidCore.emptyObject, query]);
8039
- return setQueryObjectValue(
8040
- q,
8041
- "withShapes",
8042
- args[0],
8043
- shape
8044
- );
8604
+ return setQueryObjectValue(q, "withShapes", args[0], shape);
8045
8605
  }
8046
8606
  }
8047
8607
 
@@ -8154,12 +8714,13 @@ var __spreadValues$3 = (a, b) => {
8154
8714
  return a;
8155
8715
  };
8156
8716
  const _queryChangeCounter = (self, op, data) => {
8157
- self.q.type = "update";
8158
- if (!self.q.select) {
8159
- if (self.q.returnType === "oneOrThrow" || self.q.returnType === "valueOrThrow") {
8160
- 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;
8161
8722
  }
8162
- self.q.returnType = "rowCount";
8723
+ q.returnType = "rowCount";
8163
8724
  }
8164
8725
  let map;
8165
8726
  if (typeof data === "object") {
@@ -8173,13 +8734,14 @@ const _queryChangeCounter = (self, op, data) => {
8173
8734
  pushQueryValue(self, "updateData", map);
8174
8735
  return self;
8175
8736
  };
8176
- const update = (q) => {
8177
- q.q.type = "update";
8178
- if (!q.q.select) {
8179
- 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";
8180
8742
  }
8181
- throwIfNoWhere(q, "update");
8182
- return q;
8743
+ throwIfNoWhere(self, "update");
8744
+ return self;
8183
8745
  };
8184
8746
  const _queryUpdate = (query, arg) => {
8185
8747
  const { q } = query;
@@ -8212,8 +8774,16 @@ const _queryUpdate = (query, arg) => {
8212
8774
  if (value !== null && value !== void 0 && !orchidCore.isExpression(value)) {
8213
8775
  if (value instanceof Db) {
8214
8776
  if (value.q.type) {
8215
- const as = saveSearchAlias(query, "q", "withShapes");
8216
- 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
+ ]);
8217
8787
  set[key] = new RawSQL(`(SELECT * FROM "${as}")`);
8218
8788
  }
8219
8789
  } else {
@@ -8419,7 +8989,10 @@ class Update {
8419
8989
  * @param arg - data to update records with, may have specific values, raw SQL, queries, or callbacks with sub-queries.
8420
8990
  */
8421
8991
  update(arg) {
8422
- return _queryUpdate(this.clone(), arg);
8992
+ return _queryUpdate(
8993
+ this.clone(),
8994
+ arg
8995
+ );
8423
8996
  }
8424
8997
  /**
8425
8998
  * `updateRaw` is for updating records with raw expression.
@@ -8475,7 +9048,10 @@ class Update {
8475
9048
  * @param arg - data to update records with, may have specific values, raw SQL, queries, or callbacks with sub-queries.
8476
9049
  */
8477
9050
  updateOrThrow(arg) {
8478
- return _queryUpdateOrThrow(this.clone(), arg);
9051
+ return _queryUpdateOrThrow(
9052
+ this.clone(),
9053
+ arg
9054
+ );
8479
9055
  }
8480
9056
  /**
8481
9057
  * Increments a column by `1`, returns a count of updated records by default.
@@ -8516,7 +9092,11 @@ class Update {
8516
9092
  * @param data - name of the column to increment, or an object with columns and values to add
8517
9093
  */
8518
9094
  increment(data) {
8519
- return _queryChangeCounter(this.clone(), "+", data);
9095
+ return _queryChangeCounter(
9096
+ this.clone(),
9097
+ "+",
9098
+ data
9099
+ );
8520
9100
  }
8521
9101
  /**
8522
9102
  * Decrements a column by `1`, returns a count of updated records by default.
@@ -8557,7 +9137,11 @@ class Update {
8557
9137
  * @param data - name of the column to decrement, or an object with columns and values to subtract
8558
9138
  */
8559
9139
  decrement(data) {
8560
- return _queryChangeCounter(this.clone(), "-", data);
9140
+ return _queryChangeCounter(
9141
+ this.clone(),
9142
+ "-",
9143
+ data
9144
+ );
8561
9145
  }
8562
9146
  }
8563
9147
 
@@ -8698,14 +9282,12 @@ class Headline extends orchidCore.Expression {
8698
9282
  }
8699
9283
  AggregateMethods.prototype.headline = function(search, params) {
8700
9284
  var _a;
8701
- 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];
8702
9287
  if (!source)
8703
- throw new OrchidOrmInternalError(
8704
- this,
8705
- `Search \`${search}\` is not defined`
8706
- );
9288
+ throw new OrchidOrmInternalError(q, `Search \`${search}\` is not defined`);
8707
9289
  return new Headline(
8708
- this.q,
9290
+ q.q,
8709
9291
  source,
8710
9292
  params
8711
9293
  );
@@ -9210,7 +9792,7 @@ class ScopeMethods {
9210
9792
  var _a;
9211
9793
  const q = this.clone();
9212
9794
  if (!((_a = q.q.scopes) == null ? void 0 : _a[scope])) {
9213
- const s = this.internal.scopes[scope];
9795
+ const s = q.internal.scopes[scope];
9214
9796
  if (s.and)
9215
9797
  pushQueryArray(q, "and", s.and);
9216
9798
  if (s.or)
@@ -9299,7 +9881,9 @@ class SoftDeleteMethods {
9299
9881
  * ```
9300
9882
  */
9301
9883
  hardDelete(..._args) {
9302
- return _queryDelete(this.clone().unscope("nonDeleted"));
9884
+ return _queryDelete(
9885
+ this.clone().unscope("nonDeleted")
9886
+ );
9303
9887
  }
9304
9888
  }
9305
9889
 
@@ -9467,7 +10051,11 @@ class QueryMethods {
9467
10051
  * @param columns - column names or a raw SQL
9468
10052
  */
9469
10053
  distinct(...columns) {
9470
- return pushQueryArray(this.clone(), "distinct", columns);
10054
+ return pushQueryArray(
10055
+ this.clone(),
10056
+ "distinct",
10057
+ columns
10058
+ );
9471
10059
  }
9472
10060
  /**
9473
10061
  * The `find` method is available only for tables which has exactly one primary key.
@@ -9536,7 +10124,10 @@ class QueryMethods {
9536
10124
  * @param args - `where` conditions
9537
10125
  */
9538
10126
  findBy(...args) {
9539
- return _queryFindBy(this.clone(), args);
10127
+ return _queryFindBy(
10128
+ this.clone(),
10129
+ args
10130
+ );
9540
10131
  }
9541
10132
  /**
9542
10133
  * The same as `where(conditions).takeOptional()`, it will filter records and add a `LIMIT 1`.
@@ -9551,7 +10142,10 @@ class QueryMethods {
9551
10142
  * @param args - `where` conditions
9552
10143
  */
9553
10144
  findByOptional(...args) {
9554
- return _queryFindByOptional(this.clone(), args);
10145
+ return _queryFindByOptional(
10146
+ this.clone(),
10147
+ args
10148
+ );
9555
10149
  }
9556
10150
  /**
9557
10151
  * Specifies the schema to be used as a prefix of a table name.
@@ -9607,7 +10201,11 @@ class QueryMethods {
9607
10201
  * @param columns - column names or a raw SQL
9608
10202
  */
9609
10203
  group(...columns) {
9610
- return pushQueryArray(this.clone(), "group", columns);
10204
+ return pushQueryArray(
10205
+ this.clone(),
10206
+ "group",
10207
+ columns
10208
+ );
9611
10209
  }
9612
10210
  /**
9613
10211
  * Add a window with `window` and use it later by its name for aggregate or window functions:
@@ -9693,7 +10291,11 @@ class QueryMethods {
9693
10291
  new RawSQL(args)
9694
10292
  );
9695
10293
  }
9696
- return pushQueryArray(this.clone(), "order", args);
10294
+ return pushQueryArray(
10295
+ this.clone(),
10296
+ "order",
10297
+ args
10298
+ );
9697
10299
  }
9698
10300
  /**
9699
10301
  * Adds a limit clause to the query.
@@ -10094,7 +10696,7 @@ class Db {
10094
10696
  }
10095
10697
  }
10096
10698
  [node_util.inspect.custom]() {
10097
- return `QueryObject<${this.table}>`;
10699
+ return `Query<${this.table}>`;
10098
10700
  }
10099
10701
  /**
10100
10702
  * Use `query` to perform raw SQL queries.