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