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