pqb 0.23.5 → 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.d.ts +3891 -3878
- package/dist/index.js +1047 -445
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1048 -446
- package/dist/index.mjs.map +1 -1
- package/package.json +3 -3
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.
|
|
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[
|
|
1133
|
-
const arg = args[
|
|
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 ===
|
|
1211
|
-
const arg = args[
|
|
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 >=
|
|
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 [
|
|
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
|
|
1391
|
-
|
|
1392
|
-
|
|
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
|
-
|
|
1403
|
-
|
|
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 = (
|
|
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(
|
|
1874
|
+
selectAs[key] = addParserForSelectItem(
|
|
1875
|
+
q,
|
|
1876
|
+
as,
|
|
1877
|
+
key,
|
|
1878
|
+
value
|
|
1879
|
+
);
|
|
1738
1880
|
}
|
|
1739
1881
|
return { selectAs };
|
|
1740
1882
|
};
|
|
@@ -1896,40 +2038,46 @@ class SelectItemExpression extends orchidCore.Expression {
|
|
|
1896
2038
|
}
|
|
1897
2039
|
}
|
|
1898
2040
|
|
|
1899
|
-
const _get = (
|
|
2041
|
+
const _get = (query, returnType, arg) => {
|
|
1900
2042
|
var _a, _b;
|
|
1901
|
-
q
|
|
2043
|
+
const q = query.q;
|
|
2044
|
+
q.returnType = returnType;
|
|
1902
2045
|
let type;
|
|
1903
2046
|
if (typeof arg === "string") {
|
|
1904
|
-
type = q.
|
|
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.
|
|
1911
|
-
type = q.
|
|
2053
|
+
if (table === (q.as || query.table)) {
|
|
2054
|
+
type = q.shape[column];
|
|
1912
2055
|
} else {
|
|
1913
|
-
type = (_b = (_a = q.
|
|
2056
|
+
type = (_b = (_a = q.joinedShapes) == null ? void 0 : _a[table]) == null ? void 0 : _b[column];
|
|
1914
2057
|
}
|
|
1915
2058
|
}
|
|
1916
2059
|
}
|
|
1917
|
-
q
|
|
1918
|
-
setParserForSelectedString(
|
|
1919
|
-
|
|
1920
|
-
|
|
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
|
|
1927
|
-
addParserForRawExpression(
|
|
1928
|
-
q.
|
|
2074
|
+
q[orchidCore.getValueKey] = type;
|
|
2075
|
+
addParserForRawExpression(query, orchidCore.getValueKey, arg);
|
|
2076
|
+
q.expr = arg;
|
|
1929
2077
|
}
|
|
1930
|
-
q.
|
|
2078
|
+
q.select = [q.expr];
|
|
1931
2079
|
return setQueryOperators(
|
|
1932
|
-
|
|
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
|
|
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
|
-
|
|
2121
|
+
data.as || (data.as = args[0]);
|
|
1990
2122
|
} else if (!orchidCore.isExpression(args[0])) {
|
|
1991
2123
|
const q = args[0];
|
|
1992
|
-
|
|
1993
|
-
|
|
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
|
-
|
|
2129
|
+
data.parsers = q.q.parsers;
|
|
1998
2130
|
} else {
|
|
1999
|
-
|
|
2131
|
+
data.as || (data.as = "t");
|
|
2000
2132
|
}
|
|
2001
2133
|
const options = args[1];
|
|
2002
2134
|
if (options == null ? void 0 : options.only) {
|
|
2003
|
-
|
|
2135
|
+
data.fromOnly = options.only;
|
|
2004
2136
|
}
|
|
2005
|
-
|
|
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(
|
|
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(
|
|
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(
|
|
3246
|
-
|
|
3247
|
-
|
|
3248
|
-
|
|
3249
|
-
|
|
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.
|
|
3387
|
+
q.originalQuery = query.baseQuery;
|
|
3252
3388
|
}
|
|
3253
|
-
q.
|
|
3254
|
-
return extendQuery(
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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
|
-
|
|
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.
|
|
3943
|
-
this.
|
|
3944
|
-
this.
|
|
3945
|
-
this.
|
|
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
|
-
|
|
3965
|
-
|
|
3966
|
-
|
|
3967
|
-
|
|
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
|
-
|
|
3970
|
-
return orchidCore.
|
|
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
|
-
|
|
3977
|
-
|
|
3978
|
-
|
|
3979
|
-
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
4170
|
-
|
|
4171
|
-
|
|
4172
|
-
|
|
4173
|
-
|
|
4174
|
-
|
|
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
|
|
4203
|
-
|
|
4204
|
-
|
|
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
|
-
|
|
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(
|
|
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 = (
|
|
6080
|
-
|
|
6081
|
-
|
|
6082
|
-
|
|
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.
|
|
6025
|
+
q.returnType = "rowCount";
|
|
6085
6026
|
}
|
|
6086
|
-
throwIfNoWhere(
|
|
6087
|
-
q.
|
|
6088
|
-
return
|
|
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 = (
|
|
6162
|
-
q = extendQuery(
|
|
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
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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
|
-
|
|
6557
|
-
|
|
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(
|
|
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(
|
|
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(
|
|
7012
|
+
return _queryOrNot(
|
|
7013
|
+
this.clone(),
|
|
7014
|
+
args
|
|
7015
|
+
);
|
|
7014
7016
|
}
|
|
7015
|
-
|
|
7016
|
-
|
|
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
|
-
|
|
7019
|
-
|
|
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
|
-
|
|
7022
|
-
|
|
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
|
-
|
|
7025
|
-
|
|
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
|
-
|
|
7028
|
-
|
|
7029
|
-
|
|
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
|
-
|
|
7032
|
-
|
|
7033
|
-
|
|
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
|
-
|
|
7036
|
-
|
|
7037
|
-
|
|
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
|
-
|
|
7040
|
-
|
|
7041
|
-
|
|
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
|
-
|
|
7050
|
-
|
|
7051
|
-
|
|
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
|
-
|
|
7054
|
-
|
|
7055
|
-
|
|
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
|
-
|
|
7058
|
-
|
|
7059
|
-
|
|
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
|
-
|
|
7062
|
-
|
|
7063
|
-
|
|
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
|
|
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(
|
|
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
|
-
|
|
8158
|
-
|
|
8159
|
-
|
|
8160
|
-
|
|
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
|
-
|
|
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 = (
|
|
8177
|
-
q
|
|
8178
|
-
|
|
8179
|
-
|
|
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(
|
|
8182
|
-
return
|
|
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(
|
|
8216
|
-
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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
|
|
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
|
-
|
|
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 =
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
10294
|
+
return pushQueryArray(
|
|
10295
|
+
this.clone(),
|
|
10296
|
+
"order",
|
|
10297
|
+
args
|
|
10298
|
+
);
|
|
9697
10299
|
}
|
|
9698
10300
|
/**
|
|
9699
10301
|
* Adds a limit clause to the query.
|