@carbonorm/carbonnode 3.9.6 → 3.11.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/api/C6Constants.d.ts +20 -0
- package/dist/api/orm/builders/ConditionBuilder.d.ts +5 -0
- package/dist/api/orm/builders/JoinBuilder.d.ts +9 -0
- package/dist/index.cjs.js +309 -3
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.esm.js +309 -3
- package/dist/index.esm.js.map +1 -1
- package/package.json +1 -1
- package/src/__tests__/fixtures/c6.fixture.ts +3 -0
- package/src/__tests__/sakila-db/C6.js +1 -1
- package/src/__tests__/sakila-db/C6.ts +1 -1
- package/src/__tests__/sqlBuilders.complex.test.ts +85 -0
- package/src/__tests__/sqlBuilders.expressions.test.ts +30 -1
- package/src/api/C6Constants.ts +12 -2
- package/src/api/orm/builders/ConditionBuilder.ts +184 -1
- package/src/api/orm/builders/JoinBuilder.ts +150 -1
- package/src/api/orm/queries/SelectQueryBuilder.ts +5 -0
|
@@ -27,10 +27,12 @@ export declare const C6Constants: {
|
|
|
27
27
|
DATE_FORMAT: string;
|
|
28
28
|
DESC: string;
|
|
29
29
|
DISTINCT: string;
|
|
30
|
+
EXISTS: string;
|
|
30
31
|
EXTRACT: string;
|
|
31
32
|
EQUAL: string;
|
|
32
33
|
EQUAL_NULL_SAFE: string;
|
|
33
34
|
FALSE: string;
|
|
35
|
+
FORCE: string;
|
|
34
36
|
FULL_OUTER: string;
|
|
35
37
|
FROM_DAYS: string;
|
|
36
38
|
FROM_UNIXTIME: string;
|
|
@@ -46,6 +48,7 @@ export declare const C6Constants: {
|
|
|
46
48
|
HOUR_SECOND: string;
|
|
47
49
|
HOUR_MINUTE: string;
|
|
48
50
|
IN: string;
|
|
51
|
+
INDEX: string;
|
|
49
52
|
IS: string;
|
|
50
53
|
IS_NOT: string;
|
|
51
54
|
INNER: string;
|
|
@@ -63,6 +66,7 @@ export declare const C6Constants: {
|
|
|
63
66
|
MAKEDATE: string;
|
|
64
67
|
MAKETIME: string;
|
|
65
68
|
MATCH_AGAINST: string;
|
|
69
|
+
MBRCONTAINS: string;
|
|
66
70
|
MONTHNAME: string;
|
|
67
71
|
MICROSECOND: string;
|
|
68
72
|
MINUTE: string;
|
|
@@ -78,8 +82,14 @@ export declare const C6Constants: {
|
|
|
78
82
|
NULL: string;
|
|
79
83
|
ORDER: string;
|
|
80
84
|
OR: string;
|
|
85
|
+
INDEX_HINTS: string;
|
|
86
|
+
FORCE_INDEX: string;
|
|
87
|
+
USE_INDEX: string;
|
|
88
|
+
IGNORE_INDEX: string;
|
|
81
89
|
PAGE: string;
|
|
82
90
|
PAGINATION: string;
|
|
91
|
+
POLYGON: string;
|
|
92
|
+
POINT: string;
|
|
83
93
|
RIGHT_OUTER: string;
|
|
84
94
|
SECOND: string;
|
|
85
95
|
SECOND_MICROSECOND: string;
|
|
@@ -188,10 +198,12 @@ export declare const C6C: {
|
|
|
188
198
|
DATE_FORMAT: string;
|
|
189
199
|
DESC: string;
|
|
190
200
|
DISTINCT: string;
|
|
201
|
+
EXISTS: string;
|
|
191
202
|
EXTRACT: string;
|
|
192
203
|
EQUAL: string;
|
|
193
204
|
EQUAL_NULL_SAFE: string;
|
|
194
205
|
FALSE: string;
|
|
206
|
+
FORCE: string;
|
|
195
207
|
FULL_OUTER: string;
|
|
196
208
|
FROM_DAYS: string;
|
|
197
209
|
FROM_UNIXTIME: string;
|
|
@@ -207,6 +219,7 @@ export declare const C6C: {
|
|
|
207
219
|
HOUR_SECOND: string;
|
|
208
220
|
HOUR_MINUTE: string;
|
|
209
221
|
IN: string;
|
|
222
|
+
INDEX: string;
|
|
210
223
|
IS: string;
|
|
211
224
|
IS_NOT: string;
|
|
212
225
|
INNER: string;
|
|
@@ -224,6 +237,7 @@ export declare const C6C: {
|
|
|
224
237
|
MAKEDATE: string;
|
|
225
238
|
MAKETIME: string;
|
|
226
239
|
MATCH_AGAINST: string;
|
|
240
|
+
MBRCONTAINS: string;
|
|
227
241
|
MONTHNAME: string;
|
|
228
242
|
MICROSECOND: string;
|
|
229
243
|
MINUTE: string;
|
|
@@ -239,8 +253,14 @@ export declare const C6C: {
|
|
|
239
253
|
NULL: string;
|
|
240
254
|
ORDER: string;
|
|
241
255
|
OR: string;
|
|
256
|
+
INDEX_HINTS: string;
|
|
257
|
+
FORCE_INDEX: string;
|
|
258
|
+
USE_INDEX: string;
|
|
259
|
+
IGNORE_INDEX: string;
|
|
242
260
|
PAGE: string;
|
|
243
261
|
PAGINATION: string;
|
|
262
|
+
POLYGON: string;
|
|
263
|
+
POINT: string;
|
|
244
264
|
RIGHT_OUTER: string;
|
|
245
265
|
SECOND: string;
|
|
246
266
|
SECOND_MICROSECOND: string;
|
|
@@ -13,6 +13,7 @@ export declare abstract class ConditionBuilder<G extends OrmGenerics> extends Ag
|
|
|
13
13
|
execute(): Promise<DetermineResponseDataType<G['RequestMethod'], G['RestTableInterface']>>;
|
|
14
14
|
private readonly BOOLEAN_OPERATORS;
|
|
15
15
|
private readonly OPERATOR_ALIASES;
|
|
16
|
+
private readonly BOOLEAN_FUNCTION_KEYS;
|
|
16
17
|
private isTableReference;
|
|
17
18
|
addParam(params: any[] | Record<string, any>, column: string, value: any): string;
|
|
18
19
|
private normalizeOperatorKey;
|
|
@@ -24,6 +25,10 @@ export declare abstract class ConditionBuilder<G extends OrmGenerics> extends Ag
|
|
|
24
25
|
private normalizeFunctionField;
|
|
25
26
|
private buildFunctionCall;
|
|
26
27
|
private serializeOperand;
|
|
28
|
+
private ensurePlainObject;
|
|
29
|
+
private resolveExistsInnerColumn;
|
|
30
|
+
private normalizeExistsSpec;
|
|
31
|
+
private buildExistsExpression;
|
|
27
32
|
private buildOperatorExpression;
|
|
28
33
|
private buildLegacyColumnCondition;
|
|
29
34
|
private buildBooleanExpression;
|
|
@@ -1,12 +1,21 @@
|
|
|
1
1
|
import { OrmGenerics } from "../../types/ormGenerics";
|
|
2
2
|
import { ConditionBuilder } from "./ConditionBuilder";
|
|
3
3
|
export declare abstract class JoinBuilder<G extends OrmGenerics> extends ConditionBuilder<G> {
|
|
4
|
+
private indexHintCache?;
|
|
4
5
|
protected createSelectBuilder(_request: any): {
|
|
5
6
|
build(table: string, isSubSelect: boolean): {
|
|
6
7
|
sql: string;
|
|
7
8
|
params: any[] | Record<string, any>;
|
|
8
9
|
};
|
|
9
10
|
};
|
|
11
|
+
protected resetIndexHints(): void;
|
|
12
|
+
private normalizeIndexHintKey;
|
|
13
|
+
private normalizeHintTargetKey;
|
|
14
|
+
private hasIndexHintKeys;
|
|
15
|
+
private normalizeHintSpec;
|
|
16
|
+
private formatIndexHintClause;
|
|
17
|
+
private normalizeIndexHints;
|
|
18
|
+
protected getIndexHintClause(table: string, alias?: string): string;
|
|
10
19
|
buildJoinClauses(joinArgs: any, params: any[] | Record<string, any>): string;
|
|
11
20
|
protected integrateSubSelectParams(subSql: string, subParams: any[] | Record<string, any>, target: any[] | Record<string, any>): string;
|
|
12
21
|
protected buildScalarSubSelect(subRequest: any, params: any[] | Record<string, any>): string;
|
package/dist/index.cjs.js
CHANGED
|
@@ -38,10 +38,12 @@ var C6Constants = {
|
|
|
38
38
|
DATE_FORMAT: 'DATE_FORMAT',
|
|
39
39
|
DESC: 'DESC',
|
|
40
40
|
DISTINCT: 'DISTINCT',
|
|
41
|
+
EXISTS: 'EXISTS',
|
|
41
42
|
EXTRACT: 'EXTRACT',
|
|
42
43
|
EQUAL: '=',
|
|
43
44
|
EQUAL_NULL_SAFE: '<=>',
|
|
44
45
|
FALSE: 'FALSE',
|
|
46
|
+
FORCE: 'FORCE',
|
|
45
47
|
FULL_OUTER: 'FULL_OUTER',
|
|
46
48
|
FROM_DAYS: 'FROM_DAYS',
|
|
47
49
|
FROM_UNIXTIME: 'FROM_UNIXTIME',
|
|
@@ -57,6 +59,7 @@ var C6Constants = {
|
|
|
57
59
|
HOUR_SECOND: 'HOUR_SECOND',
|
|
58
60
|
HOUR_MINUTE: 'HOUR_MINUTE',
|
|
59
61
|
IN: 'IN',
|
|
62
|
+
INDEX: 'INDEX',
|
|
60
63
|
IS: 'IS',
|
|
61
64
|
IS_NOT: 'IS_NOT',
|
|
62
65
|
INNER: 'INNER',
|
|
@@ -74,6 +77,7 @@ var C6Constants = {
|
|
|
74
77
|
MAKEDATE: 'MAKEDATE',
|
|
75
78
|
MAKETIME: 'MAKETIME',
|
|
76
79
|
MATCH_AGAINST: 'MATCH_AGAINST',
|
|
80
|
+
MBRCONTAINS: 'MBRContains',
|
|
77
81
|
MONTHNAME: 'MONTHNAME',
|
|
78
82
|
MICROSECOND: 'MICROSECOND',
|
|
79
83
|
MINUTE: 'MINUTE',
|
|
@@ -89,8 +93,14 @@ var C6Constants = {
|
|
|
89
93
|
NULL: 'NULL',
|
|
90
94
|
ORDER: 'ORDER',
|
|
91
95
|
OR: 'OR',
|
|
96
|
+
INDEX_HINTS: 'INDEX_HINTS',
|
|
97
|
+
FORCE_INDEX: 'FORCE INDEX',
|
|
98
|
+
USE_INDEX: 'USE INDEX',
|
|
99
|
+
IGNORE_INDEX: 'IGNORE INDEX',
|
|
92
100
|
PAGE: 'PAGE',
|
|
93
101
|
PAGINATION: 'PAGINATION',
|
|
102
|
+
POLYGON: 'POLYGON',
|
|
103
|
+
POINT: 'POINT',
|
|
94
104
|
RIGHT_OUTER: 'RIGHT_OUTER',
|
|
95
105
|
SECOND: 'SECOND',
|
|
96
106
|
SECOND_MICROSECOND: 'SECOND_MICROSECOND',
|
|
@@ -1451,7 +1461,8 @@ var stContains = function (envelope, shape) {
|
|
|
1451
1461
|
var ConditionBuilder = /** @class */ (function (_super) {
|
|
1452
1462
|
tslib.__extends(ConditionBuilder, _super);
|
|
1453
1463
|
function ConditionBuilder() {
|
|
1454
|
-
var
|
|
1464
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j;
|
|
1465
|
+
var _this = _super.apply(this, arguments) || this;
|
|
1455
1466
|
_this.aliasMap = {};
|
|
1456
1467
|
_this.derivedAliases = new Set();
|
|
1457
1468
|
_this.BOOLEAN_OPERATORS = new Map([
|
|
@@ -1490,8 +1501,16 @@ var ConditionBuilder = /** @class */ (function (_super) {
|
|
|
1490
1501
|
[C6C.BETWEEN, C6C.BETWEEN],
|
|
1491
1502
|
['BETWEEN', C6C.BETWEEN],
|
|
1492
1503
|
['NOT BETWEEN', 'NOT BETWEEN'],
|
|
1504
|
+
[C6C.EXISTS, C6C.EXISTS],
|
|
1505
|
+
['EXISTS', C6C.EXISTS],
|
|
1506
|
+
['NOT EXISTS', 'NOT EXISTS'],
|
|
1493
1507
|
[C6C.MATCH_AGAINST, C6C.MATCH_AGAINST],
|
|
1494
1508
|
]);
|
|
1509
|
+
_this.BOOLEAN_FUNCTION_KEYS = new Set([
|
|
1510
|
+
(_c = (_b = (_a = C6C.ST_CONTAINS) === null || _a === void 0 ? void 0 : _a.toUpperCase) === null || _b === void 0 ? void 0 : _b.call(_a)) !== null && _c !== void 0 ? _c : 'ST_CONTAINS',
|
|
1511
|
+
(_f = (_e = (_d = C6C.ST_WITHIN) === null || _d === void 0 ? void 0 : _d.toUpperCase) === null || _e === void 0 ? void 0 : _e.call(_d)) !== null && _f !== void 0 ? _f : 'ST_WITHIN',
|
|
1512
|
+
(_j = (_h = (_g = C6C.MBRCONTAINS) === null || _g === void 0 ? void 0 : _g.toUpperCase) === null || _h === void 0 ? void 0 : _h.call(_g)) !== null && _j !== void 0 ? _j : 'MBRCONTAINS',
|
|
1513
|
+
]);
|
|
1495
1514
|
return _this;
|
|
1496
1515
|
}
|
|
1497
1516
|
ConditionBuilder.prototype.initAlias = function (baseTable, joins) {
|
|
@@ -1726,6 +1745,9 @@ var ConditionBuilder = /** @class */ (function (_super) {
|
|
|
1726
1745
|
if (operand === null || typeof operand === 'number' || typeof operand === 'boolean') {
|
|
1727
1746
|
return { sql: asParam(operand), isReference: false, isExpression: false, isSubSelect: false };
|
|
1728
1747
|
}
|
|
1748
|
+
if (typeof Buffer !== 'undefined' && Buffer.isBuffer && Buffer.isBuffer(operand)) {
|
|
1749
|
+
return { sql: asParam(operand), isReference: false, isExpression: false, isSubSelect: false };
|
|
1750
|
+
}
|
|
1729
1751
|
if (typeof operand === 'string') {
|
|
1730
1752
|
if (this.isTableReference(operand) || this.isColumnRef(operand)) {
|
|
1731
1753
|
return { sql: operand, isReference: true, isExpression: false, isSubSelect: false };
|
|
@@ -1769,10 +1791,129 @@ var ConditionBuilder = /** @class */ (function (_super) {
|
|
|
1769
1791
|
}
|
|
1770
1792
|
throw new Error('Unsupported operand type in SQL expression.');
|
|
1771
1793
|
};
|
|
1794
|
+
ConditionBuilder.prototype.ensurePlainObject = function (value) {
|
|
1795
|
+
if (value instanceof Map) {
|
|
1796
|
+
return Object.fromEntries(value);
|
|
1797
|
+
}
|
|
1798
|
+
return value;
|
|
1799
|
+
};
|
|
1800
|
+
ConditionBuilder.prototype.resolveExistsInnerColumn = function (subRequest, provided) {
|
|
1801
|
+
var _a, _b;
|
|
1802
|
+
if (provided) {
|
|
1803
|
+
if (typeof provided !== 'string' || provided.trim() === '') {
|
|
1804
|
+
throw new Error('EXISTS correlation column must be a non-empty string.');
|
|
1805
|
+
}
|
|
1806
|
+
return provided;
|
|
1807
|
+
}
|
|
1808
|
+
var selectClause = this.ensurePlainObject(subRequest === null || subRequest === void 0 ? void 0 : subRequest[C6C.SELECT]);
|
|
1809
|
+
if (Array.isArray(selectClause) && selectClause.length > 0) {
|
|
1810
|
+
var candidate = selectClause[0];
|
|
1811
|
+
if (typeof candidate === 'string' && candidate.trim() !== '') {
|
|
1812
|
+
return candidate;
|
|
1813
|
+
}
|
|
1814
|
+
}
|
|
1815
|
+
var fromTable = subRequest === null || subRequest === void 0 ? void 0 : subRequest[C6C.FROM];
|
|
1816
|
+
if (typeof fromTable === 'string' && fromTable.trim() !== '') {
|
|
1817
|
+
var table = (_b = (_a = this.config.C6) === null || _a === void 0 ? void 0 : _a.TABLES) === null || _b === void 0 ? void 0 : _b[fromTable.trim()];
|
|
1818
|
+
var primary = table === null || table === void 0 ? void 0 : table.PRIMARY;
|
|
1819
|
+
if (Array.isArray(primary) && primary.length > 0) {
|
|
1820
|
+
return String(primary[0]);
|
|
1821
|
+
}
|
|
1822
|
+
}
|
|
1823
|
+
throw new Error('EXISTS requires a correlation column to be provided or inferable from the subselect.');
|
|
1824
|
+
};
|
|
1825
|
+
ConditionBuilder.prototype.normalizeExistsSpec = function (spec) {
|
|
1826
|
+
var normalized = this.ensurePlainObject(spec);
|
|
1827
|
+
if (!Array.isArray(normalized) || normalized.length < 2) {
|
|
1828
|
+
throw new Error('EXISTS expects an array like [outerColumn, subselect, innerColumn?].');
|
|
1829
|
+
}
|
|
1830
|
+
var outerRaw = normalized[0], payloadRaw = normalized[1], innerRaw = normalized[2];
|
|
1831
|
+
if (typeof outerRaw !== 'string' || outerRaw.trim() === '') {
|
|
1832
|
+
throw new Error('EXISTS requires the first element to be an outer column reference string.');
|
|
1833
|
+
}
|
|
1834
|
+
var payload = this.ensurePlainObject(payloadRaw);
|
|
1835
|
+
var subSelect;
|
|
1836
|
+
if (payload && typeof payload === 'object' && C6C.SUBSELECT in payload) {
|
|
1837
|
+
subSelect = this.ensurePlainObject(payload[C6C.SUBSELECT]);
|
|
1838
|
+
}
|
|
1839
|
+
else if (payload && typeof payload === 'object') {
|
|
1840
|
+
subSelect = payload;
|
|
1841
|
+
}
|
|
1842
|
+
else {
|
|
1843
|
+
throw new Error('EXISTS requires a subselect payload as the second element.');
|
|
1844
|
+
}
|
|
1845
|
+
if (!subSelect || typeof subSelect !== 'object') {
|
|
1846
|
+
throw new Error('EXISTS subselect payload must be an object.');
|
|
1847
|
+
}
|
|
1848
|
+
var innerColumn = typeof innerRaw === 'string' ? innerRaw : undefined;
|
|
1849
|
+
return {
|
|
1850
|
+
outerColumn: outerRaw,
|
|
1851
|
+
subRequest: tslib.__assign({}, subSelect),
|
|
1852
|
+
innerColumn: innerColumn,
|
|
1853
|
+
};
|
|
1854
|
+
};
|
|
1855
|
+
ConditionBuilder.prototype.buildExistsExpression = function (spec, operator, params) {
|
|
1856
|
+
var _a, _b, _c, _d;
|
|
1857
|
+
var _this = this;
|
|
1858
|
+
var _e;
|
|
1859
|
+
var _f = this.normalizeExistsSpec(spec), outerColumn = _f.outerColumn, subRequest = _f.subRequest, innerColumn = _f.innerColumn;
|
|
1860
|
+
var fromTableRaw = subRequest[C6C.FROM];
|
|
1861
|
+
if (typeof fromTableRaw !== 'string' || fromTableRaw.trim() === '') {
|
|
1862
|
+
throw new Error('EXISTS subselect requires a table specified with C6C.FROM.');
|
|
1863
|
+
}
|
|
1864
|
+
var fromTable = fromTableRaw.trim();
|
|
1865
|
+
this.assertValidIdentifier(outerColumn, 'EXISTS correlation column');
|
|
1866
|
+
var correlationColumn = this.resolveExistsInnerColumn(subRequest, innerColumn);
|
|
1867
|
+
if (!this.isColumnRef(correlationColumn) && !this.isTableReference(correlationColumn)) {
|
|
1868
|
+
throw new Error("Unknown column reference '".concat(correlationColumn, "' used in EXISTS subquery correlation column."));
|
|
1869
|
+
}
|
|
1870
|
+
var existingWhereRaw = this.ensurePlainObject(subRequest[C6C.WHERE]);
|
|
1871
|
+
var correlationCondition = (_a = {}, _a[correlationColumn] = [C6C.EQUAL, outerColumn], _a);
|
|
1872
|
+
var normalizedExistingWhere = existingWhereRaw && typeof existingWhereRaw === 'object'
|
|
1873
|
+
? Array.isArray(existingWhereRaw)
|
|
1874
|
+
? existingWhereRaw.slice()
|
|
1875
|
+
: tslib.__assign({}, existingWhereRaw)
|
|
1876
|
+
: existingWhereRaw;
|
|
1877
|
+
var hasExistingWhere = Array.isArray(normalizedExistingWhere)
|
|
1878
|
+
? normalizedExistingWhere.length > 0
|
|
1879
|
+
: normalizedExistingWhere && typeof normalizedExistingWhere === 'object'
|
|
1880
|
+
? Object.keys(normalizedExistingWhere).length > 0
|
|
1881
|
+
: normalizedExistingWhere != null;
|
|
1882
|
+
var whereClause;
|
|
1883
|
+
if (!hasExistingWhere) {
|
|
1884
|
+
whereClause = correlationCondition;
|
|
1885
|
+
}
|
|
1886
|
+
else if (normalizedExistingWhere && typeof normalizedExistingWhere === 'object' &&
|
|
1887
|
+
Object.keys(normalizedExistingWhere).some(function (key) { return _this.BOOLEAN_OPERATORS.has(key); })) {
|
|
1888
|
+
whereClause = (_b = {}, _b[C6C.AND] = [normalizedExistingWhere, correlationCondition], _b);
|
|
1889
|
+
}
|
|
1890
|
+
else if (normalizedExistingWhere && typeof normalizedExistingWhere === 'object') {
|
|
1891
|
+
whereClause = tslib.__assign(tslib.__assign({}, normalizedExistingWhere), correlationCondition);
|
|
1892
|
+
}
|
|
1893
|
+
else {
|
|
1894
|
+
whereClause = (_c = {}, _c[C6C.AND] = [normalizedExistingWhere, correlationCondition], _c);
|
|
1895
|
+
}
|
|
1896
|
+
var subRequestWithCorrelation = tslib.__assign(tslib.__assign({}, subRequest), (_d = {}, _d[C6C.FROM] = fromTable, _d[C6C.WHERE] = whereClause, _d[C6C.SELECT] = (_e = subRequest[C6C.SELECT]) !== null && _e !== void 0 ? _e : ['1'], _d));
|
|
1897
|
+
var buildScalarSubSelect = this.buildScalarSubSelect;
|
|
1898
|
+
if (typeof buildScalarSubSelect !== 'function') {
|
|
1899
|
+
throw new Error('EXISTS operator requires SelectQueryBuilder context.');
|
|
1900
|
+
}
|
|
1901
|
+
var scalar = buildScalarSubSelect.call(this, subRequestWithCorrelation, params);
|
|
1902
|
+
var keyword = operator === 'NOT EXISTS' ? 'NOT EXISTS' : C6C.EXISTS;
|
|
1903
|
+
return "".concat(keyword, " ").concat(scalar);
|
|
1904
|
+
};
|
|
1772
1905
|
ConditionBuilder.prototype.buildOperatorExpression = function (op, rawOperands, params, contextColumn) {
|
|
1773
1906
|
var _a, _b;
|
|
1774
1907
|
var _this = this;
|
|
1775
1908
|
var operator = this.formatOperator(op);
|
|
1909
|
+
if (operator === C6C.EXISTS || operator === 'NOT EXISTS') {
|
|
1910
|
+
var operands_1 = Array.isArray(rawOperands) ? rawOperands : [rawOperands];
|
|
1911
|
+
if (!operands_1.length) {
|
|
1912
|
+
throw new Error("".concat(operator, " requires at least one subselect specification."));
|
|
1913
|
+
}
|
|
1914
|
+
var clauses = operands_1.map(function (spec) { return _this.buildExistsExpression(spec, operator, params); });
|
|
1915
|
+
return this.joinBooleanParts(clauses, 'AND');
|
|
1916
|
+
}
|
|
1776
1917
|
if (operator === C6C.MATCH_AGAINST) {
|
|
1777
1918
|
if (!Array.isArray(rawOperands) || rawOperands.length !== 2) {
|
|
1778
1919
|
throw new Error('MATCH_AGAINST requires an array of two operands.');
|
|
@@ -1882,6 +2023,18 @@ var ConditionBuilder = /** @class */ (function (_super) {
|
|
|
1882
2023
|
if (value instanceof Map) {
|
|
1883
2024
|
value = Object.fromEntries(value);
|
|
1884
2025
|
}
|
|
2026
|
+
if (typeof column === 'string') {
|
|
2027
|
+
var normalizedColumn = column.trim().toUpperCase();
|
|
2028
|
+
if (this.BOOLEAN_FUNCTION_KEYS.has(normalizedColumn)) {
|
|
2029
|
+
if (!Array.isArray(value)) {
|
|
2030
|
+
throw new Error("".concat(column, " expects an array of arguments."));
|
|
2031
|
+
}
|
|
2032
|
+
return this.buildFunctionCall(column, value, params);
|
|
2033
|
+
}
|
|
2034
|
+
}
|
|
2035
|
+
if (typeof Buffer !== 'undefined' && Buffer.isBuffer && Buffer.isBuffer(value)) {
|
|
2036
|
+
return this.buildOperatorExpression(C6C.EQUAL, [column, value], params, column);
|
|
2037
|
+
}
|
|
1885
2038
|
if (Array.isArray(value)) {
|
|
1886
2039
|
if (value.length >= 2 && typeof value[0] === 'string') {
|
|
1887
2040
|
var op = value[0], rest = value.slice(1);
|
|
@@ -1923,8 +2076,17 @@ var ConditionBuilder = /** @class */ (function (_super) {
|
|
|
1923
2076
|
if (Array.isArray(node)) {
|
|
1924
2077
|
if (node.length === 0)
|
|
1925
2078
|
return '';
|
|
2079
|
+
// Support both [left, operator, right] and [operator, left, right]
|
|
1926
2080
|
if (node.length === 3 && typeof node[0] === 'string' && typeof node[1] === 'string') {
|
|
1927
|
-
|
|
2081
|
+
var opAsSecond = this.isOperator(node[1]);
|
|
2082
|
+
var opAsFirst = this.isOperator(node[0]);
|
|
2083
|
+
if (opAsSecond) {
|
|
2084
|
+
return this.buildOperatorExpression(node[1], [node[0], node[2]], params, node[0]);
|
|
2085
|
+
}
|
|
2086
|
+
if (opAsFirst) {
|
|
2087
|
+
return this.buildOperatorExpression(node[0], [node[1], node[2]], params, node[1]);
|
|
2088
|
+
}
|
|
2089
|
+
// fall-through to treat as grouped expressions
|
|
1928
2090
|
}
|
|
1929
2091
|
var parts_1 = node
|
|
1930
2092
|
.map(function (item) { return _this.buildBooleanExpression(item, params, 'OR'); })
|
|
@@ -2045,6 +2207,143 @@ var JoinBuilder = /** @class */ (function (_super) {
|
|
|
2045
2207
|
JoinBuilder.prototype.createSelectBuilder = function (_request) {
|
|
2046
2208
|
throw new Error('Subclasses must implement createSelectBuilder to support derived table serialization.');
|
|
2047
2209
|
};
|
|
2210
|
+
JoinBuilder.prototype.resetIndexHints = function () {
|
|
2211
|
+
this.indexHintCache = undefined;
|
|
2212
|
+
};
|
|
2213
|
+
JoinBuilder.prototype.normalizeIndexHintKey = function (key) {
|
|
2214
|
+
return key
|
|
2215
|
+
.replace(/`/g, '')
|
|
2216
|
+
.replace(/_/g, ' ')
|
|
2217
|
+
.trim()
|
|
2218
|
+
.replace(/\s+/g, ' ')
|
|
2219
|
+
.toUpperCase();
|
|
2220
|
+
};
|
|
2221
|
+
JoinBuilder.prototype.normalizeHintTargetKey = function (target) {
|
|
2222
|
+
return target.replace(/`/g, '').trim();
|
|
2223
|
+
};
|
|
2224
|
+
JoinBuilder.prototype.hasIndexHintKeys = function (obj) {
|
|
2225
|
+
var _this = this;
|
|
2226
|
+
var keys = Object.keys(obj !== null && obj !== void 0 ? obj : {});
|
|
2227
|
+
if (!keys.length)
|
|
2228
|
+
return false;
|
|
2229
|
+
var forceKey = this.normalizeIndexHintKey(C6C.FORCE_INDEX);
|
|
2230
|
+
var useKey = this.normalizeIndexHintKey(C6C.USE_INDEX);
|
|
2231
|
+
var ignoreKey = this.normalizeIndexHintKey(C6C.IGNORE_INDEX);
|
|
2232
|
+
return keys.some(function (key) {
|
|
2233
|
+
var normalized = _this.normalizeIndexHintKey(key);
|
|
2234
|
+
return normalized === forceKey || normalized === useKey || normalized === ignoreKey;
|
|
2235
|
+
});
|
|
2236
|
+
};
|
|
2237
|
+
JoinBuilder.prototype.normalizeHintSpec = function (spec) {
|
|
2238
|
+
var _a;
|
|
2239
|
+
if (spec instanceof Map) {
|
|
2240
|
+
spec = Object.fromEntries(spec);
|
|
2241
|
+
}
|
|
2242
|
+
if (Array.isArray(spec) || typeof spec === 'string') {
|
|
2243
|
+
return _a = {}, _a[C6C.FORCE_INDEX] = spec, _a;
|
|
2244
|
+
}
|
|
2245
|
+
if (!spec || typeof spec !== 'object') {
|
|
2246
|
+
return undefined;
|
|
2247
|
+
}
|
|
2248
|
+
if (!this.hasIndexHintKeys(spec)) {
|
|
2249
|
+
return undefined;
|
|
2250
|
+
}
|
|
2251
|
+
return spec;
|
|
2252
|
+
};
|
|
2253
|
+
JoinBuilder.prototype.formatIndexHintClause = function (spec) {
|
|
2254
|
+
var normalizedSpec = this.normalizeHintSpec(spec);
|
|
2255
|
+
if (!normalizedSpec)
|
|
2256
|
+
return '';
|
|
2257
|
+
var clauses = [];
|
|
2258
|
+
var forceKey = this.normalizeIndexHintKey(C6C.FORCE_INDEX);
|
|
2259
|
+
var useKey = this.normalizeIndexHintKey(C6C.USE_INDEX);
|
|
2260
|
+
var ignoreKey = this.normalizeIndexHintKey(C6C.IGNORE_INDEX);
|
|
2261
|
+
var pushClause = function (keyword, rawValue) {
|
|
2262
|
+
var values = Array.isArray(rawValue) ? rawValue : [rawValue];
|
|
2263
|
+
var indexes = values
|
|
2264
|
+
.map(function (value) { return String(value !== null && value !== void 0 ? value : '').trim(); })
|
|
2265
|
+
.filter(Boolean)
|
|
2266
|
+
.map(function (value) { return "`".concat(value.replace(/`/g, '``'), "`"); });
|
|
2267
|
+
if (!indexes.length)
|
|
2268
|
+
return;
|
|
2269
|
+
clauses.push("".concat(keyword, " (").concat(indexes.join(', '), ")"));
|
|
2270
|
+
};
|
|
2271
|
+
for (var _i = 0, _a = Object.entries(normalizedSpec); _i < _a.length; _i++) {
|
|
2272
|
+
var _b = _a[_i], key = _b[0], rawValue = _b[1];
|
|
2273
|
+
var normalizedKey = this.normalizeIndexHintKey(key);
|
|
2274
|
+
if (normalizedKey === forceKey) {
|
|
2275
|
+
pushClause('FORCE INDEX', rawValue);
|
|
2276
|
+
}
|
|
2277
|
+
else if (normalizedKey === useKey) {
|
|
2278
|
+
pushClause('USE INDEX', rawValue);
|
|
2279
|
+
}
|
|
2280
|
+
else if (normalizedKey === ignoreKey) {
|
|
2281
|
+
pushClause('IGNORE INDEX', rawValue);
|
|
2282
|
+
}
|
|
2283
|
+
}
|
|
2284
|
+
return clauses.join(' ');
|
|
2285
|
+
};
|
|
2286
|
+
JoinBuilder.prototype.normalizeIndexHints = function (raw) {
|
|
2287
|
+
var _this = this;
|
|
2288
|
+
if (raw instanceof Map) {
|
|
2289
|
+
raw = Object.fromEntries(raw);
|
|
2290
|
+
}
|
|
2291
|
+
var cache = new Map();
|
|
2292
|
+
var addEntry = function (target, spec) {
|
|
2293
|
+
var clause = _this.formatIndexHintClause(spec);
|
|
2294
|
+
if (!clause)
|
|
2295
|
+
return;
|
|
2296
|
+
var normalizedTarget = target === '__base__'
|
|
2297
|
+
? '__base__'
|
|
2298
|
+
: _this.normalizeHintTargetKey(target);
|
|
2299
|
+
cache.set(normalizedTarget, clause);
|
|
2300
|
+
};
|
|
2301
|
+
if (Array.isArray(raw) || typeof raw === 'string') {
|
|
2302
|
+
addEntry('__base__', raw);
|
|
2303
|
+
}
|
|
2304
|
+
else if (raw && typeof raw === 'object') {
|
|
2305
|
+
if (this.hasIndexHintKeys(raw)) {
|
|
2306
|
+
addEntry('__base__', raw);
|
|
2307
|
+
}
|
|
2308
|
+
else {
|
|
2309
|
+
for (var _i = 0, _a = Object.entries(raw); _i < _a.length; _i++) {
|
|
2310
|
+
var _b = _a[_i], key = _b[0], value = _b[1];
|
|
2311
|
+
var normalizedKey = this.normalizeHintTargetKey(key);
|
|
2312
|
+
if (!normalizedKey)
|
|
2313
|
+
continue;
|
|
2314
|
+
addEntry(normalizedKey, value);
|
|
2315
|
+
}
|
|
2316
|
+
}
|
|
2317
|
+
}
|
|
2318
|
+
return cache.size ? cache : undefined;
|
|
2319
|
+
};
|
|
2320
|
+
JoinBuilder.prototype.getIndexHintClause = function (table, alias) {
|
|
2321
|
+
var _a;
|
|
2322
|
+
if (!this.indexHintCache) {
|
|
2323
|
+
var rawHints = (_a = this.request) === null || _a === void 0 ? void 0 : _a[C6C.INDEX_HINTS];
|
|
2324
|
+
this.indexHintCache = this.normalizeIndexHints(rawHints);
|
|
2325
|
+
}
|
|
2326
|
+
var hints = this.indexHintCache;
|
|
2327
|
+
if (!hints || hints.size === 0)
|
|
2328
|
+
return '';
|
|
2329
|
+
var normalizedTable = this.normalizeHintTargetKey(table);
|
|
2330
|
+
var normalizedAlias = alias ? this.normalizeHintTargetKey(alias) : undefined;
|
|
2331
|
+
var candidates = [
|
|
2332
|
+
normalizedAlias,
|
|
2333
|
+
normalizedAlias ? "".concat(normalizedTable, " ").concat(normalizedAlias) : undefined,
|
|
2334
|
+
normalizedTable,
|
|
2335
|
+
'__base__',
|
|
2336
|
+
];
|
|
2337
|
+
for (var _i = 0, candidates_1 = candidates; _i < candidates_1.length; _i++) {
|
|
2338
|
+
var candidate = candidates_1[_i];
|
|
2339
|
+
if (!candidate)
|
|
2340
|
+
continue;
|
|
2341
|
+
var clause = hints.get(candidate);
|
|
2342
|
+
if (clause)
|
|
2343
|
+
return clause;
|
|
2344
|
+
}
|
|
2345
|
+
return '';
|
|
2346
|
+
};
|
|
2048
2347
|
JoinBuilder.prototype.buildJoinClauses = function (joinArgs, params) {
|
|
2049
2348
|
var sql = '';
|
|
2050
2349
|
var joinTypeEntries = joinArgs instanceof Map
|
|
@@ -2108,7 +2407,9 @@ var JoinBuilder = /** @class */ (function (_super) {
|
|
|
2108
2407
|
if (alias) {
|
|
2109
2408
|
this_1.registerAlias(alias, table);
|
|
2110
2409
|
}
|
|
2111
|
-
var
|
|
2410
|
+
var hintClause = this_1.getIndexHintClause(table, alias);
|
|
2411
|
+
var baseJoinSql = alias ? "`".concat(table, "` AS `").concat(alias, "`") : "`".concat(table, "`");
|
|
2412
|
+
var joinSql = hintClause ? "".concat(baseJoinSql, " ").concat(hintClause) : baseJoinSql;
|
|
2112
2413
|
var onClause = this_1.buildBooleanJoinedConditions(conditions, true, params);
|
|
2113
2414
|
sql += " ".concat(joinKind, " JOIN ").concat(joinSql);
|
|
2114
2415
|
if (onClause) {
|
|
@@ -2262,6 +2563,7 @@ var SelectQueryBuilder = /** @class */ (function (_super) {
|
|
|
2262
2563
|
// @ts-ignore
|
|
2263
2564
|
if (this.selectAliases && this.selectAliases.clear)
|
|
2264
2565
|
this.selectAliases.clear();
|
|
2566
|
+
this.resetIndexHints();
|
|
2265
2567
|
var args = this.request;
|
|
2266
2568
|
this.initAlias(table, args.JOIN);
|
|
2267
2569
|
var params = this.useNamedParams ? {} : [];
|
|
@@ -2270,6 +2572,10 @@ var SelectQueryBuilder = /** @class */ (function (_super) {
|
|
|
2270
2572
|
.map(function (f) { return _this.buildAggregateField(f, params); })
|
|
2271
2573
|
.join(', ');
|
|
2272
2574
|
var sql = "SELECT ".concat(selectFields, " FROM `").concat(table, "`");
|
|
2575
|
+
var baseIndexHint = this.getIndexHintClause(table);
|
|
2576
|
+
if (baseIndexHint) {
|
|
2577
|
+
sql += " ".concat(baseIndexHint);
|
|
2578
|
+
}
|
|
2273
2579
|
if (args.JOIN) {
|
|
2274
2580
|
sql += this.buildJoinClauses(args.JOIN, params);
|
|
2275
2581
|
}
|