@carbonorm/carbonnode 3.8.4 → 3.9.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/README.md +48 -1
- package/dist/api/C6Constants.d.ts +4 -0
- package/dist/api/orm/builders/AggregateBuilder.d.ts +2 -1
- package/dist/api/orm/builders/ConditionBuilder.d.ts +3 -0
- package/dist/api/orm/builders/JoinBuilder.d.ts +8 -0
- package/dist/api/orm/builders/PaginationBuilder.d.ts +1 -1
- package/dist/api/orm/queries/DeleteQueryBuilder.d.ts +2 -0
- package/dist/api/orm/queries/SelectQueryBuilder.d.ts +1 -0
- package/dist/api/orm/queries/UpdateQueryBuilder.d.ts +2 -0
- package/dist/api/orm/queryHelpers.d.ts +5 -0
- package/dist/index.cjs.js +364 -112
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.esm.js +362 -113
- package/dist/index.esm.js.map +1 -1
- package/package.json +1 -1
- package/src/__tests__/fixtures/c6.fixture.ts +39 -0
- package/src/__tests__/fixtures/pu.fixture.ts +72 -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 +199 -1
- package/src/api/C6Constants.ts +2 -0
- package/src/api/orm/builders/AggregateBuilder.ts +39 -2
- package/src/api/orm/builders/ConditionBuilder.ts +66 -4
- package/src/api/orm/builders/JoinBuilder.ts +117 -6
- package/src/api/orm/builders/PaginationBuilder.ts +12 -2
- package/src/api/orm/queries/DeleteQueryBuilder.ts +5 -0
- package/src/api/orm/queries/SelectQueryBuilder.ts +6 -2
- package/src/api/orm/queries/UpdateQueryBuilder.ts +6 -1
- package/src/api/orm/queryHelpers.ts +59 -0
package/dist/index.esm.js
CHANGED
|
@@ -58,6 +58,7 @@ var C6Constants = {
|
|
|
58
58
|
INNER: 'INNER',
|
|
59
59
|
INTERVAL: 'INTERVAL',
|
|
60
60
|
JOIN: 'JOIN',
|
|
61
|
+
FROM: 'FROM',
|
|
61
62
|
LEFT: 'LEFT',
|
|
62
63
|
LEFT_OUTER: 'LEFT_OUTER',
|
|
63
64
|
LESS_THAN: '<',
|
|
@@ -89,6 +90,7 @@ var C6Constants = {
|
|
|
89
90
|
SECOND: 'SECOND',
|
|
90
91
|
SECOND_MICROSECOND: 'SECOND_MICROSECOND',
|
|
91
92
|
SELECT: 'SELECT',
|
|
93
|
+
SUBSELECT: 'SUBSELECT',
|
|
92
94
|
// MySQL Spatial Functions
|
|
93
95
|
ST_AREA: 'ST_Area',
|
|
94
96
|
ST_ASBINARY: 'ST_AsBinary',
|
|
@@ -1251,9 +1253,16 @@ var AggregateBuilder = /** @class */ (function (_super) {
|
|
|
1251
1253
|
_this.selectAliases = new Set();
|
|
1252
1254
|
return _this;
|
|
1253
1255
|
}
|
|
1254
|
-
|
|
1256
|
+
// Overridden in ConditionBuilder where alias tracking is available.
|
|
1257
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
1258
|
+
AggregateBuilder.prototype.assertValidIdentifier = function (_identifier, _context) {
|
|
1259
|
+
// no-op placeholder for subclasses that do not implement alias validation
|
|
1260
|
+
};
|
|
1261
|
+
AggregateBuilder.prototype.buildAggregateField = function (field, params) {
|
|
1255
1262
|
var _this = this;
|
|
1263
|
+
var _a, _b;
|
|
1256
1264
|
if (typeof field === 'string') {
|
|
1265
|
+
this.assertValidIdentifier(field, 'SELECT field');
|
|
1257
1266
|
return field;
|
|
1258
1267
|
}
|
|
1259
1268
|
if (!Array.isArray(field) || field.length === 0) {
|
|
@@ -1266,8 +1275,33 @@ var AggregateBuilder = /** @class */ (function (_super) {
|
|
|
1266
1275
|
args.pop();
|
|
1267
1276
|
}
|
|
1268
1277
|
var F = String(fn).toUpperCase();
|
|
1278
|
+
if (F === C6C.SUBSELECT) {
|
|
1279
|
+
if (!params) {
|
|
1280
|
+
throw new Error('Scalar subselects in SELECT require parameter tracking.');
|
|
1281
|
+
}
|
|
1282
|
+
var subRequest = args[0];
|
|
1283
|
+
var subSql = (_b = (_a = this).buildScalarSubSelect) === null || _b === void 0 ? void 0 : _b.call(_a, subRequest, params);
|
|
1284
|
+
if (!subSql) {
|
|
1285
|
+
throw new Error('Failed to build scalar subselect.');
|
|
1286
|
+
}
|
|
1287
|
+
var expr_1 = subSql;
|
|
1288
|
+
if (alias) {
|
|
1289
|
+
this.selectAliases.add(alias);
|
|
1290
|
+
expr_1 += " AS ".concat(alias);
|
|
1291
|
+
}
|
|
1292
|
+
this.config.verbose && console.log("[SELECT] ".concat(expr_1));
|
|
1293
|
+
return expr_1;
|
|
1294
|
+
}
|
|
1269
1295
|
var argList = args
|
|
1270
|
-
.map(function (arg) {
|
|
1296
|
+
.map(function (arg) {
|
|
1297
|
+
if (Array.isArray(arg))
|
|
1298
|
+
return _this.buildAggregateField(arg, params);
|
|
1299
|
+
if (typeof arg === 'string') {
|
|
1300
|
+
_this.assertValidIdentifier(arg, 'SELECT expression');
|
|
1301
|
+
return arg;
|
|
1302
|
+
}
|
|
1303
|
+
return String(arg);
|
|
1304
|
+
})
|
|
1271
1305
|
.join(', ');
|
|
1272
1306
|
var expr;
|
|
1273
1307
|
if (F === 'DISTINCT') {
|
|
@@ -1286,11 +1320,91 @@ var AggregateBuilder = /** @class */ (function (_super) {
|
|
|
1286
1320
|
return AggregateBuilder;
|
|
1287
1321
|
}(Executor));
|
|
1288
1322
|
|
|
1323
|
+
// Alias a table name with a given alias
|
|
1324
|
+
var DERIVED_TABLE_PREFIX = '__c6DerivedTable__';
|
|
1325
|
+
var DERIVED_ID_SYMBOL = Symbol('c6DerivedTableId');
|
|
1326
|
+
var derivedTableLookup = new Map();
|
|
1327
|
+
var derivedTableReverseLookup = new WeakMap();
|
|
1328
|
+
var derivedTableCounter = 0;
|
|
1329
|
+
var isDerivedTableKey = function (key) {
|
|
1330
|
+
return typeof key === 'string' && key.startsWith(DERIVED_TABLE_PREFIX);
|
|
1331
|
+
};
|
|
1332
|
+
var resolveDerivedTable = function (key) {
|
|
1333
|
+
return derivedTableLookup.get(key);
|
|
1334
|
+
};
|
|
1335
|
+
var derivedTable = function (spec) {
|
|
1336
|
+
if (!spec || typeof spec !== 'object') {
|
|
1337
|
+
throw new Error('Derived table definition must be an object.');
|
|
1338
|
+
}
|
|
1339
|
+
var aliasRaw = spec[C6C.AS];
|
|
1340
|
+
if (typeof aliasRaw !== 'string' || aliasRaw.trim() === '') {
|
|
1341
|
+
throw new Error('Derived tables require a non-empty alias via C6C.AS.');
|
|
1342
|
+
}
|
|
1343
|
+
if (!spec[C6C.SUBSELECT] || typeof spec[C6C.SUBSELECT] !== 'object') {
|
|
1344
|
+
throw new Error('Derived tables require a nested SELECT payload under C6C.SUBSELECT.');
|
|
1345
|
+
}
|
|
1346
|
+
var id = derivedTableReverseLookup.get(spec);
|
|
1347
|
+
if (!id) {
|
|
1348
|
+
id = "".concat(DERIVED_TABLE_PREFIX).concat(++derivedTableCounter);
|
|
1349
|
+
derivedTableReverseLookup.set(spec, id);
|
|
1350
|
+
derivedTableLookup.set(id, spec);
|
|
1351
|
+
Object.defineProperty(spec, DERIVED_ID_SYMBOL, {
|
|
1352
|
+
value: id,
|
|
1353
|
+
configurable: false,
|
|
1354
|
+
enumerable: false,
|
|
1355
|
+
writable: false
|
|
1356
|
+
});
|
|
1357
|
+
}
|
|
1358
|
+
var alias = aliasRaw.trim();
|
|
1359
|
+
derivedTableLookup.set(id, spec);
|
|
1360
|
+
Object.defineProperty(spec, 'toString', {
|
|
1361
|
+
value: function () { return "".concat(id, " ").concat(alias); },
|
|
1362
|
+
configurable: true,
|
|
1363
|
+
enumerable: false,
|
|
1364
|
+
writable: true
|
|
1365
|
+
});
|
|
1366
|
+
return spec;
|
|
1367
|
+
};
|
|
1368
|
+
var A = function (tableName, alias) {
|
|
1369
|
+
return "".concat(tableName, " ").concat(alias);
|
|
1370
|
+
};
|
|
1371
|
+
// Qualify a column constant (e.g. 'property_units.parcel_id') to an alias
|
|
1372
|
+
var F = function (qualifiedCol, alias) {
|
|
1373
|
+
return "".concat(alias, ".").concat(qualifiedCol.split('.').pop());
|
|
1374
|
+
};
|
|
1375
|
+
// Equal join condition using full-qualified column constants
|
|
1376
|
+
var fieldEq = function (leftCol, rightCol, leftAlias, rightAlias) {
|
|
1377
|
+
var _a;
|
|
1378
|
+
return (_a = {},
|
|
1379
|
+
_a[F(leftCol, leftAlias)] = F(rightCol, rightAlias),
|
|
1380
|
+
_a);
|
|
1381
|
+
};
|
|
1382
|
+
// ST_Distance_Sphere for aliased fields
|
|
1383
|
+
var distSphere = function (fromCol, toCol, fromAlias, toAlias) {
|
|
1384
|
+
return [C6C.ST_DISTANCE_SPHERE, F(fromCol, fromAlias), F(toCol, toAlias)];
|
|
1385
|
+
};
|
|
1386
|
+
// Build a bounding-box expression.
|
|
1387
|
+
//
|
|
1388
|
+
// Arguments must be provided in `(minLng, minLat, maxLng, maxLat)` order. The
|
|
1389
|
+
// helper does not attempt to swap or validate coordinates; if a minimum value
|
|
1390
|
+
// is greater than its corresponding maximum value, MySQL's `ST_MakeEnvelope`
|
|
1391
|
+
// returns `NULL`.
|
|
1392
|
+
var bbox = function (minLng, minLat, maxLng, maxLat) {
|
|
1393
|
+
return [C6C.ST_SRID, [C6C.ST_MAKEENVELOPE,
|
|
1394
|
+
[C6C.ST_POINT, minLng, minLat],
|
|
1395
|
+
[C6C.ST_POINT, maxLng, maxLat]], 4326];
|
|
1396
|
+
};
|
|
1397
|
+
// ST_Contains for map envelope/shape queries
|
|
1398
|
+
var stContains = function (envelope, shape) {
|
|
1399
|
+
return [C6C.ST_CONTAINS, envelope, shape];
|
|
1400
|
+
};
|
|
1401
|
+
|
|
1289
1402
|
var ConditionBuilder = /** @class */ (function (_super) {
|
|
1290
1403
|
__extends(ConditionBuilder, _super);
|
|
1291
1404
|
function ConditionBuilder() {
|
|
1292
1405
|
var _this = _super !== null && _super.apply(this, arguments) || this;
|
|
1293
1406
|
_this.aliasMap = {};
|
|
1407
|
+
_this.derivedAliases = new Set();
|
|
1294
1408
|
_this.OPERATORS = new Set([
|
|
1295
1409
|
C6C.EQUAL, C6C.NOT_EQUAL, C6C.LESS_THAN, C6C.LESS_THAN_OR_EQUAL_TO,
|
|
1296
1410
|
C6C.GREATER_THAN, C6C.GREATER_THAN_OR_EQUAL_TO,
|
|
@@ -1315,21 +1429,43 @@ var ConditionBuilder = /** @class */ (function (_super) {
|
|
|
1315
1429
|
ConditionBuilder.prototype.initAlias = function (baseTable, joins) {
|
|
1316
1430
|
var _a;
|
|
1317
1431
|
this.aliasMap = (_a = {}, _a[baseTable] = baseTable, _a);
|
|
1432
|
+
this.derivedAliases = new Set();
|
|
1318
1433
|
if (!joins)
|
|
1319
1434
|
return;
|
|
1320
1435
|
for (var joinType in joins) {
|
|
1321
1436
|
for (var raw in joins[joinType]) {
|
|
1322
|
-
var _b = raw.split(
|
|
1323
|
-
|
|
1437
|
+
var _b = raw.trim().split(/\s+/, 2), table = _b[0], alias = _b[1];
|
|
1438
|
+
if (!table)
|
|
1439
|
+
continue;
|
|
1440
|
+
this.registerAlias(alias || table, table);
|
|
1324
1441
|
}
|
|
1325
1442
|
}
|
|
1326
1443
|
};
|
|
1444
|
+
ConditionBuilder.prototype.registerAlias = function (alias, table) {
|
|
1445
|
+
this.aliasMap[alias] = table;
|
|
1446
|
+
if (isDerivedTableKey(table)) {
|
|
1447
|
+
this.derivedAliases.add(alias);
|
|
1448
|
+
}
|
|
1449
|
+
};
|
|
1450
|
+
ConditionBuilder.prototype.assertValidIdentifier = function (identifier, context) {
|
|
1451
|
+
if (typeof identifier !== 'string')
|
|
1452
|
+
return;
|
|
1453
|
+
if (!identifier.includes('.'))
|
|
1454
|
+
return;
|
|
1455
|
+
var alias = identifier.split('.', 2)[0];
|
|
1456
|
+
if (!(alias in this.aliasMap)) {
|
|
1457
|
+
throw new Error("Unknown table or alias '".concat(alias, "' referenced in ").concat(context, ": '").concat(identifier, "'."));
|
|
1458
|
+
}
|
|
1459
|
+
};
|
|
1327
1460
|
ConditionBuilder.prototype.isColumnRef = function (ref) {
|
|
1328
1461
|
var _a, _b;
|
|
1329
1462
|
if (typeof ref !== 'string' || !ref.includes('.'))
|
|
1330
1463
|
return false;
|
|
1331
1464
|
var _c = ref.split('.', 2), prefix = _c[0], column = _c[1];
|
|
1332
1465
|
var tableName = this.aliasMap[prefix] || prefix;
|
|
1466
|
+
if (isDerivedTableKey(tableName) || this.derivedAliases.has(prefix)) {
|
|
1467
|
+
return true;
|
|
1468
|
+
}
|
|
1333
1469
|
var table = (_b = (_a = this.config.C6) === null || _a === void 0 ? void 0 : _a.TABLES) === null || _b === void 0 ? void 0 : _b[tableName];
|
|
1334
1470
|
if (!table)
|
|
1335
1471
|
return false;
|
|
@@ -1358,6 +1494,9 @@ var ConditionBuilder = /** @class */ (function (_super) {
|
|
|
1358
1494
|
}
|
|
1359
1495
|
var _e = val.split('.'), prefix = _e[0], column = _e[1];
|
|
1360
1496
|
var tableName = (_b = this.aliasMap[prefix]) !== null && _b !== void 0 ? _b : prefix;
|
|
1497
|
+
if (isDerivedTableKey(tableName) || this.derivedAliases.has(prefix)) {
|
|
1498
|
+
return true;
|
|
1499
|
+
}
|
|
1361
1500
|
var table = (_d = (_c = this.config.C6) === null || _c === void 0 ? void 0 : _c.TABLES) === null || _d === void 0 ? void 0 : _d[tableName];
|
|
1362
1501
|
if (!table || !table.COLUMNS)
|
|
1363
1502
|
return false;
|
|
@@ -1400,6 +1539,26 @@ var ConditionBuilder = /** @class */ (function (_super) {
|
|
|
1400
1539
|
// Normalize common variants
|
|
1401
1540
|
var valueNorm = (value === C6C.NULL) ? null : value;
|
|
1402
1541
|
var displayOp = typeof op === 'string' ? op.replace('_', ' ') : op;
|
|
1542
|
+
var extractSubSelect = function (input) {
|
|
1543
|
+
if (Array.isArray(input) && input.length >= 2 && input[0] === C6C.SUBSELECT) {
|
|
1544
|
+
return input[1];
|
|
1545
|
+
}
|
|
1546
|
+
if (input && typeof input === 'object' && C6C.SUBSELECT in input) {
|
|
1547
|
+
return input[C6C.SUBSELECT];
|
|
1548
|
+
}
|
|
1549
|
+
return undefined;
|
|
1550
|
+
};
|
|
1551
|
+
var rightSubSelectPayload = extractSubSelect(valueNorm);
|
|
1552
|
+
var buildSubSelect = function (payload) {
|
|
1553
|
+
if (!payload)
|
|
1554
|
+
return undefined;
|
|
1555
|
+
var builder = _this.buildScalarSubSelect;
|
|
1556
|
+
if (typeof builder !== 'function') {
|
|
1557
|
+
throw new Error('Scalar subselect handling requires JoinBuilder context.');
|
|
1558
|
+
}
|
|
1559
|
+
return builder.call(_this, payload, params);
|
|
1560
|
+
};
|
|
1561
|
+
var rightSubSelectSql = buildSubSelect(rightSubSelectPayload);
|
|
1403
1562
|
// Support function-based expressions like [C6C.ST_DISTANCE_SPHERE, col1, col2]
|
|
1404
1563
|
if (typeof column === 'string' &&
|
|
1405
1564
|
_this.OPERATORS.has(column) &&
|
|
@@ -1426,7 +1585,7 @@ var ConditionBuilder = /** @class */ (function (_super) {
|
|
|
1426
1585
|
var leftIsCol = _this.isColumnRef(column);
|
|
1427
1586
|
var leftIsRef = _this.isTableReference(column);
|
|
1428
1587
|
var rightIsCol = typeof value === 'string' && _this.isColumnRef(value);
|
|
1429
|
-
if (!leftIsCol && !leftIsRef && !rightIsCol) {
|
|
1588
|
+
if (!leftIsCol && !leftIsRef && !rightIsCol && !rightSubSelectSql) {
|
|
1430
1589
|
throw new Error("Potential SQL injection detected: '".concat(column, " ").concat(op, " ").concat(value, "'"));
|
|
1431
1590
|
}
|
|
1432
1591
|
_this.validateOperator(op);
|
|
@@ -1459,6 +1618,13 @@ var ConditionBuilder = /** @class */ (function (_super) {
|
|
|
1459
1618
|
return matchClause;
|
|
1460
1619
|
}
|
|
1461
1620
|
if ((op === C6C.IN || op === C6C.NOT_IN) && Array.isArray(value)) {
|
|
1621
|
+
if (rightSubSelectSql) {
|
|
1622
|
+
if (!leftIsRef) {
|
|
1623
|
+
throw new Error("IN operator requires a table reference as the left operand. Column '".concat(column, "' is not a valid table reference."));
|
|
1624
|
+
}
|
|
1625
|
+
var normalized_1 = op.replace('_', ' ');
|
|
1626
|
+
return "( ".concat(column, " ").concat(normalized_1, " ").concat(rightSubSelectSql, " )");
|
|
1627
|
+
}
|
|
1462
1628
|
var placeholders = value.map(function (v) {
|
|
1463
1629
|
return _this.isColumnRef(v) ? v : _this.addParam(params, column, v);
|
|
1464
1630
|
}).join(', ');
|
|
@@ -1478,10 +1644,13 @@ var ConditionBuilder = /** @class */ (function (_super) {
|
|
|
1478
1644
|
}
|
|
1479
1645
|
return "(".concat(column, ") ").concat(op.replace('_', ' '), " ").concat(_this.addParam(params, column, start), " AND ").concat(_this.addParam(params, column, end));
|
|
1480
1646
|
}
|
|
1481
|
-
var rightIsRef = _this.isTableReference(value);
|
|
1647
|
+
var rightIsRef = rightSubSelectSql ? false : _this.isTableReference(value);
|
|
1482
1648
|
if (leftIsRef && rightIsRef) {
|
|
1483
1649
|
return "(".concat(column, ") ").concat(displayOp, " ").concat(value);
|
|
1484
1650
|
}
|
|
1651
|
+
if (leftIsRef && rightSubSelectSql) {
|
|
1652
|
+
return "(".concat(column, ") ").concat(displayOp, " ").concat(rightSubSelectSql);
|
|
1653
|
+
}
|
|
1485
1654
|
if (leftIsRef && !rightIsRef) {
|
|
1486
1655
|
return "(".concat(column, ") ").concat(displayOp, " ").concat(_this.addParam(params, column, valueNorm));
|
|
1487
1656
|
}
|
|
@@ -1577,85 +1746,117 @@ var JoinBuilder = /** @class */ (function (_super) {
|
|
|
1577
1746
|
function JoinBuilder() {
|
|
1578
1747
|
return _super !== null && _super.apply(this, arguments) || this;
|
|
1579
1748
|
}
|
|
1749
|
+
JoinBuilder.prototype.createSelectBuilder = function (_request) {
|
|
1750
|
+
throw new Error('Subclasses must implement createSelectBuilder to support derived table serialization.');
|
|
1751
|
+
};
|
|
1580
1752
|
JoinBuilder.prototype.buildJoinClauses = function (joinArgs, params) {
|
|
1581
1753
|
var sql = '';
|
|
1582
|
-
|
|
1754
|
+
var _loop_1 = function (joinType) {
|
|
1583
1755
|
var joinKind = joinType.replace('_', ' ').toUpperCase();
|
|
1584
|
-
|
|
1585
|
-
|
|
1586
|
-
|
|
1587
|
-
|
|
1588
|
-
|
|
1589
|
-
|
|
1756
|
+
var entries = [];
|
|
1757
|
+
var joinSection = joinArgs[joinType];
|
|
1758
|
+
if (joinSection instanceof Map) {
|
|
1759
|
+
joinSection.forEach(function (value, key) {
|
|
1760
|
+
entries.push([key, value]);
|
|
1761
|
+
});
|
|
1762
|
+
}
|
|
1763
|
+
else {
|
|
1764
|
+
for (var raw in joinSection) {
|
|
1765
|
+
entries.push([raw, joinSection[raw]]);
|
|
1766
|
+
}
|
|
1767
|
+
}
|
|
1768
|
+
for (var _i = 0, entries_1 = entries; _i < entries_1.length; _i++) {
|
|
1769
|
+
var _a = entries_1[_i], rawKey = _a[0], conditions = _a[1];
|
|
1770
|
+
var raw = typeof rawKey === 'string' ? rawKey : String(rawKey);
|
|
1771
|
+
var _b = raw.trim().split(/\s+/, 2), table = _b[0], aliasCandidate = _b[1];
|
|
1772
|
+
if (!table)
|
|
1773
|
+
continue;
|
|
1774
|
+
if (isDerivedTableKey(table)) {
|
|
1775
|
+
var derived = resolveDerivedTable(table);
|
|
1776
|
+
if (!derived) {
|
|
1777
|
+
throw new Error("Derived table '".concat(table, "' was not registered. Wrap the object with derivedTable(...) before using it in JOIN."));
|
|
1778
|
+
}
|
|
1779
|
+
var configuredAliasRaw = derived[C6C.AS];
|
|
1780
|
+
var configuredAlias = typeof configuredAliasRaw === 'string' ? configuredAliasRaw.trim() : '';
|
|
1781
|
+
var alias = (aliasCandidate !== null && aliasCandidate !== void 0 ? aliasCandidate : configuredAlias).trim();
|
|
1782
|
+
if (!alias) {
|
|
1783
|
+
throw new Error('Derived tables require an alias via C6C.AS.');
|
|
1784
|
+
}
|
|
1785
|
+
this_1.registerAlias(alias, table);
|
|
1786
|
+
var subRequest = derived[C6C.SUBSELECT];
|
|
1787
|
+
if (!subRequest || typeof subRequest !== 'object') {
|
|
1788
|
+
throw new Error('Derived tables must include a C6C.SUBSELECT payload.');
|
|
1789
|
+
}
|
|
1790
|
+
var fromTable = subRequest[C6C.FROM];
|
|
1791
|
+
if (typeof fromTable !== 'string' || fromTable.trim() === '') {
|
|
1792
|
+
throw new Error('Derived table subselects require a base table defined with C6C.FROM.');
|
|
1793
|
+
}
|
|
1794
|
+
var subBuilder = this_1.createSelectBuilder(subRequest);
|
|
1795
|
+
var _c = subBuilder.build(fromTable, true), subSql = _c.sql, subParams = _c.params;
|
|
1796
|
+
var normalizedSql = this_1.integrateSubSelectParams(subSql, subParams, params);
|
|
1797
|
+
var formatted = normalizedSql.trim().split('\n').map(function (line) { return " ".concat(line); }).join('\n');
|
|
1798
|
+
var joinSql = "(\n".concat(formatted, "\n) AS `").concat(alias, "`");
|
|
1799
|
+
var onClause = this_1.buildBooleanJoinedConditions(conditions, true, params);
|
|
1800
|
+
sql += " ".concat(joinKind, " JOIN ").concat(joinSql);
|
|
1801
|
+
if (onClause) {
|
|
1802
|
+
sql += " ON ".concat(onClause);
|
|
1803
|
+
}
|
|
1804
|
+
}
|
|
1805
|
+
else {
|
|
1806
|
+
var alias = aliasCandidate;
|
|
1807
|
+
if (alias) {
|
|
1808
|
+
this_1.registerAlias(alias, table);
|
|
1809
|
+
}
|
|
1810
|
+
var joinSql = alias ? "`".concat(table, "` AS `").concat(alias, "`") : "`".concat(table, "`");
|
|
1811
|
+
var onClause = this_1.buildBooleanJoinedConditions(conditions, true, params);
|
|
1812
|
+
sql += " ".concat(joinKind, " JOIN ").concat(joinSql);
|
|
1813
|
+
if (onClause) {
|
|
1814
|
+
sql += " ON ".concat(onClause);
|
|
1815
|
+
}
|
|
1816
|
+
}
|
|
1590
1817
|
}
|
|
1818
|
+
};
|
|
1819
|
+
var this_1 = this;
|
|
1820
|
+
for (var joinType in joinArgs) {
|
|
1821
|
+
_loop_1(joinType);
|
|
1591
1822
|
}
|
|
1592
1823
|
this.config.verbose && console.log("[JOIN] ".concat(sql.trim()));
|
|
1593
1824
|
return sql;
|
|
1594
1825
|
};
|
|
1595
|
-
|
|
1596
|
-
|
|
1597
|
-
|
|
1598
|
-
|
|
1599
|
-
|
|
1600
|
-
|
|
1601
|
-
|
|
1602
|
-
|
|
1603
|
-
|
|
1604
|
-
|
|
1605
|
-
|
|
1606
|
-
|
|
1607
|
-
|
|
1608
|
-
|
|
1609
|
-
|
|
1610
|
-
|
|
1611
|
-
if (this.request.WHERE) {
|
|
1612
|
-
sql += this.buildWhereClause(this.request.WHERE, params);
|
|
1613
|
-
}
|
|
1614
|
-
return { sql: sql, params: params };
|
|
1615
|
-
};
|
|
1616
|
-
return DeleteQueryBuilder;
|
|
1617
|
-
}(JoinBuilder));
|
|
1618
|
-
|
|
1619
|
-
var PostQueryBuilder = /** @class */ (function (_super) {
|
|
1620
|
-
__extends(PostQueryBuilder, _super);
|
|
1621
|
-
function PostQueryBuilder() {
|
|
1622
|
-
return _super !== null && _super.apply(this, arguments) || this;
|
|
1623
|
-
}
|
|
1624
|
-
PostQueryBuilder.prototype.trimTablePrefix = function (table, column) {
|
|
1625
|
-
if (!column.includes('.'))
|
|
1626
|
-
return column;
|
|
1627
|
-
var _a = column.split('.', 2), prefix = _a[0], col = _a[1];
|
|
1628
|
-
if (prefix !== table) {
|
|
1629
|
-
throw new Error("Invalid prefixed column: '".concat(column, "'. Expected prefix '").concat(table, ".'"));
|
|
1826
|
+
JoinBuilder.prototype.integrateSubSelectParams = function (subSql, subParams, target) {
|
|
1827
|
+
var _a;
|
|
1828
|
+
if (!subParams)
|
|
1829
|
+
return subSql;
|
|
1830
|
+
if (this.useNamedParams) {
|
|
1831
|
+
var normalized = subSql;
|
|
1832
|
+
var extras = subParams;
|
|
1833
|
+
for (var _i = 0, _b = Object.keys(extras); _i < _b.length; _i++) {
|
|
1834
|
+
var key = _b[_i];
|
|
1835
|
+
var placeholder = this.addParam(target, '', extras[key]);
|
|
1836
|
+
var original = ":".concat(key);
|
|
1837
|
+
if (original !== placeholder) {
|
|
1838
|
+
normalized = normalized.split(original).join(placeholder);
|
|
1839
|
+
}
|
|
1840
|
+
}
|
|
1841
|
+
return normalized;
|
|
1630
1842
|
}
|
|
1631
|
-
|
|
1843
|
+
(_a = target).push.apply(_a, subParams);
|
|
1844
|
+
return subSql;
|
|
1632
1845
|
};
|
|
1633
|
-
|
|
1634
|
-
|
|
1635
|
-
|
|
1636
|
-
var verb = C6C.REPLACE in this.request ? C6C.REPLACE : C6C.INSERT;
|
|
1637
|
-
var body = verb in this.request ? this.request[verb] : this.request;
|
|
1638
|
-
var keys = Object.keys(body);
|
|
1639
|
-
var params = [];
|
|
1640
|
-
var placeholders = [];
|
|
1641
|
-
for (var _i = 0, keys_1 = keys; _i < keys_1.length; _i++) {
|
|
1642
|
-
var key = keys_1[_i];
|
|
1643
|
-
var value = body[key];
|
|
1644
|
-
var placeholder = this.addParam(params, key, value);
|
|
1645
|
-
placeholders.push(placeholder);
|
|
1846
|
+
JoinBuilder.prototype.buildScalarSubSelect = function (subRequest, params) {
|
|
1847
|
+
if (!subRequest || typeof subRequest !== 'object') {
|
|
1848
|
+
throw new Error('Scalar subselect requires a C6C.SUBSELECT object payload.');
|
|
1646
1849
|
}
|
|
1647
|
-
var
|
|
1648
|
-
if (
|
|
1649
|
-
|
|
1650
|
-
if (!Array.isArray(updateData)) {
|
|
1651
|
-
throw new Error("Update data must be an array of keys to update, got: ".concat(JSON.stringify(updateData)));
|
|
1652
|
-
}
|
|
1653
|
-
var updateClause = updateData.map(function (k) { return "`".concat(k, "` = VALUES(`").concat(k, "`)"); }).join(', ');
|
|
1654
|
-
sql += " ON DUPLICATE KEY UPDATE ".concat(updateClause);
|
|
1850
|
+
var fromTable = subRequest[C6C.FROM];
|
|
1851
|
+
if (typeof fromTable !== 'string' || fromTable.trim() === '') {
|
|
1852
|
+
throw new Error('Scalar subselects require a base table specified with C6C.FROM.');
|
|
1655
1853
|
}
|
|
1656
|
-
|
|
1854
|
+
var subBuilder = this.createSelectBuilder(subRequest);
|
|
1855
|
+
var _a = subBuilder.build(fromTable, true), subSql = _a.sql, subParams = _a.params;
|
|
1856
|
+
var normalized = this.integrateSubSelectParams(subSql, subParams, params).trim();
|
|
1857
|
+
return "(".concat(normalized, ")");
|
|
1657
1858
|
};
|
|
1658
|
-
return
|
|
1859
|
+
return JoinBuilder;
|
|
1659
1860
|
}(ConditionBuilder));
|
|
1660
1861
|
|
|
1661
1862
|
var PaginationBuilder = /** @class */ (function (_super) {
|
|
@@ -1676,7 +1877,7 @@ var PaginationBuilder = /** @class */ (function (_super) {
|
|
|
1676
1877
|
* }
|
|
1677
1878
|
* ```
|
|
1678
1879
|
*/
|
|
1679
|
-
PaginationBuilder.prototype.buildPaginationClause = function (pagination) {
|
|
1880
|
+
PaginationBuilder.prototype.buildPaginationClause = function (pagination, params) {
|
|
1680
1881
|
var _this = this;
|
|
1681
1882
|
var sql = "";
|
|
1682
1883
|
/* -------- ORDER BY -------- */
|
|
@@ -1684,10 +1885,21 @@ var PaginationBuilder = /** @class */ (function (_super) {
|
|
|
1684
1885
|
var orderParts = [];
|
|
1685
1886
|
for (var _i = 0, _a = Object.entries(pagination[C6Constants.ORDER]); _i < _a.length; _i++) {
|
|
1686
1887
|
var _b = _a[_i], key = _b[0], val = _b[1];
|
|
1888
|
+
if (typeof key === 'string' && key.includes('.')) {
|
|
1889
|
+
this.assertValidIdentifier(key, 'ORDER BY');
|
|
1890
|
+
}
|
|
1687
1891
|
// FUNCTION CALL: val is an array of args
|
|
1688
1892
|
if (Array.isArray(val)) {
|
|
1689
1893
|
var args = val
|
|
1690
|
-
.map(function (arg) {
|
|
1894
|
+
.map(function (arg) {
|
|
1895
|
+
if (Array.isArray(arg))
|
|
1896
|
+
return _this.buildAggregateField(arg, params);
|
|
1897
|
+
if (typeof arg === 'string' && arg.includes('.')) {
|
|
1898
|
+
_this.assertValidIdentifier(arg, 'ORDER BY argument');
|
|
1899
|
+
return arg;
|
|
1900
|
+
}
|
|
1901
|
+
return String(arg);
|
|
1902
|
+
})
|
|
1691
1903
|
.join(", ");
|
|
1692
1904
|
orderParts.push("".concat(key, "(").concat(args, ")"));
|
|
1693
1905
|
}
|
|
@@ -1724,6 +1936,9 @@ var SelectQueryBuilder = /** @class */ (function (_super) {
|
|
|
1724
1936
|
function SelectQueryBuilder() {
|
|
1725
1937
|
return _super !== null && _super.apply(this, arguments) || this;
|
|
1726
1938
|
}
|
|
1939
|
+
SelectQueryBuilder.prototype.createSelectBuilder = function (request) {
|
|
1940
|
+
return new SelectQueryBuilder(this.config, request, this.useNamedParams);
|
|
1941
|
+
};
|
|
1727
1942
|
SelectQueryBuilder.prototype.build = function (table, isSubSelect) {
|
|
1728
1943
|
var _this = this;
|
|
1729
1944
|
var _a;
|
|
@@ -1738,7 +1953,7 @@ var SelectQueryBuilder = /** @class */ (function (_super) {
|
|
|
1738
1953
|
var params = this.useNamedParams ? {} : [];
|
|
1739
1954
|
var selectList = (_a = args.SELECT) !== null && _a !== void 0 ? _a : ['*'];
|
|
1740
1955
|
var selectFields = selectList
|
|
1741
|
-
.map(function (f) { return _this.buildAggregateField(f); })
|
|
1956
|
+
.map(function (f) { return _this.buildAggregateField(f, params); })
|
|
1742
1957
|
.join(', ');
|
|
1743
1958
|
var sql = "SELECT ".concat(selectFields, " FROM `").concat(table, "`");
|
|
1744
1959
|
if (args.JOIN) {
|
|
@@ -1757,7 +1972,7 @@ var SelectQueryBuilder = /** @class */ (function (_super) {
|
|
|
1757
1972
|
sql += " HAVING ".concat(this.buildBooleanJoinedConditions(args.HAVING, true, params));
|
|
1758
1973
|
}
|
|
1759
1974
|
if (args.PAGINATION) {
|
|
1760
|
-
sql += this.buildPaginationClause(args.PAGINATION);
|
|
1975
|
+
sql += this.buildPaginationClause(args.PAGINATION, params);
|
|
1761
1976
|
}
|
|
1762
1977
|
else if (!isSubSelect) {
|
|
1763
1978
|
sql += " LIMIT 100";
|
|
@@ -1768,11 +1983,80 @@ var SelectQueryBuilder = /** @class */ (function (_super) {
|
|
|
1768
1983
|
return SelectQueryBuilder;
|
|
1769
1984
|
}(PaginationBuilder));
|
|
1770
1985
|
|
|
1986
|
+
var DeleteQueryBuilder = /** @class */ (function (_super) {
|
|
1987
|
+
__extends(DeleteQueryBuilder, _super);
|
|
1988
|
+
function DeleteQueryBuilder() {
|
|
1989
|
+
return _super !== null && _super.apply(this, arguments) || this;
|
|
1990
|
+
}
|
|
1991
|
+
DeleteQueryBuilder.prototype.createSelectBuilder = function (request) {
|
|
1992
|
+
return new SelectQueryBuilder(this.config, request, this.useNamedParams);
|
|
1993
|
+
};
|
|
1994
|
+
DeleteQueryBuilder.prototype.build = function (table) {
|
|
1995
|
+
this.aliasMap = {};
|
|
1996
|
+
var params = this.useNamedParams ? {} : [];
|
|
1997
|
+
this.initAlias(table, this.request.JOIN);
|
|
1998
|
+
var sql = "DELETE `".concat(table, "` FROM `").concat(table, "`");
|
|
1999
|
+
if (this.request.JOIN) {
|
|
2000
|
+
sql += this.buildJoinClauses(this.request.JOIN, params);
|
|
2001
|
+
}
|
|
2002
|
+
if (this.request.WHERE) {
|
|
2003
|
+
sql += this.buildWhereClause(this.request.WHERE, params);
|
|
2004
|
+
}
|
|
2005
|
+
return { sql: sql, params: params };
|
|
2006
|
+
};
|
|
2007
|
+
return DeleteQueryBuilder;
|
|
2008
|
+
}(JoinBuilder));
|
|
2009
|
+
|
|
2010
|
+
var PostQueryBuilder = /** @class */ (function (_super) {
|
|
2011
|
+
__extends(PostQueryBuilder, _super);
|
|
2012
|
+
function PostQueryBuilder() {
|
|
2013
|
+
return _super !== null && _super.apply(this, arguments) || this;
|
|
2014
|
+
}
|
|
2015
|
+
PostQueryBuilder.prototype.trimTablePrefix = function (table, column) {
|
|
2016
|
+
if (!column.includes('.'))
|
|
2017
|
+
return column;
|
|
2018
|
+
var _a = column.split('.', 2), prefix = _a[0], col = _a[1];
|
|
2019
|
+
if (prefix !== table) {
|
|
2020
|
+
throw new Error("Invalid prefixed column: '".concat(column, "'. Expected prefix '").concat(table, ".'"));
|
|
2021
|
+
}
|
|
2022
|
+
return col;
|
|
2023
|
+
};
|
|
2024
|
+
PostQueryBuilder.prototype.build = function (table) {
|
|
2025
|
+
var _this = this;
|
|
2026
|
+
this.aliasMap = {};
|
|
2027
|
+
var verb = C6C.REPLACE in this.request ? C6C.REPLACE : C6C.INSERT;
|
|
2028
|
+
var body = verb in this.request ? this.request[verb] : this.request;
|
|
2029
|
+
var keys = Object.keys(body);
|
|
2030
|
+
var params = [];
|
|
2031
|
+
var placeholders = [];
|
|
2032
|
+
for (var _i = 0, keys_1 = keys; _i < keys_1.length; _i++) {
|
|
2033
|
+
var key = keys_1[_i];
|
|
2034
|
+
var value = body[key];
|
|
2035
|
+
var placeholder = this.addParam(params, key, value);
|
|
2036
|
+
placeholders.push(placeholder);
|
|
2037
|
+
}
|
|
2038
|
+
var sql = "".concat(verb, " INTO `").concat(table, "` (\n ").concat(keys.map(function (k) { return "`".concat(_this.trimTablePrefix(table, k), "`"); }).join(', '), "\n ) VALUES (\n ").concat(placeholders.join(', '), "\n )");
|
|
2039
|
+
if (C6C.UPDATE in this.request) {
|
|
2040
|
+
var updateData = this.request[C6C.UPDATE];
|
|
2041
|
+
if (!Array.isArray(updateData)) {
|
|
2042
|
+
throw new Error("Update data must be an array of keys to update, got: ".concat(JSON.stringify(updateData)));
|
|
2043
|
+
}
|
|
2044
|
+
var updateClause = updateData.map(function (k) { return "`".concat(k, "` = VALUES(`").concat(k, "`)"); }).join(', ');
|
|
2045
|
+
sql += " ON DUPLICATE KEY UPDATE ".concat(updateClause);
|
|
2046
|
+
}
|
|
2047
|
+
return { sql: sql, params: params };
|
|
2048
|
+
};
|
|
2049
|
+
return PostQueryBuilder;
|
|
2050
|
+
}(ConditionBuilder));
|
|
2051
|
+
|
|
1771
2052
|
var UpdateQueryBuilder = /** @class */ (function (_super) {
|
|
1772
2053
|
__extends(UpdateQueryBuilder, _super);
|
|
1773
2054
|
function UpdateQueryBuilder() {
|
|
1774
2055
|
return _super !== null && _super.apply(this, arguments) || this;
|
|
1775
2056
|
}
|
|
2057
|
+
UpdateQueryBuilder.prototype.createSelectBuilder = function (request) {
|
|
2058
|
+
return new SelectQueryBuilder(this.config, request, this.useNamedParams);
|
|
2059
|
+
};
|
|
1776
2060
|
UpdateQueryBuilder.prototype.trimTablePrefix = function (table, column) {
|
|
1777
2061
|
if (!column.includes('.'))
|
|
1778
2062
|
return column;
|
|
@@ -1807,7 +2091,7 @@ var UpdateQueryBuilder = /** @class */ (function (_super) {
|
|
|
1807
2091
|
sql += this.buildWhereClause(args.WHERE, params);
|
|
1808
2092
|
}
|
|
1809
2093
|
if (args.PAGINATION) {
|
|
1810
|
-
sql += this.buildPaginationClause(args.PAGINATION);
|
|
2094
|
+
sql += this.buildPaginationClause(args.PAGINATION, params);
|
|
1811
2095
|
}
|
|
1812
2096
|
return { sql: sql, params: params };
|
|
1813
2097
|
};
|
|
@@ -2203,41 +2487,6 @@ function ExpressHandler(_a) {
|
|
|
2203
2487
|
}); };
|
|
2204
2488
|
}
|
|
2205
2489
|
|
|
2206
|
-
// Alias a table name with a given alias
|
|
2207
|
-
var A = function (tableName, alias) {
|
|
2208
|
-
return "".concat(tableName, " ").concat(alias);
|
|
2209
|
-
};
|
|
2210
|
-
// Qualify a column constant (e.g. 'property_units.parcel_id') to an alias
|
|
2211
|
-
var F = function (qualifiedCol, alias) {
|
|
2212
|
-
return "".concat(alias, ".").concat(qualifiedCol.split('.').pop());
|
|
2213
|
-
};
|
|
2214
|
-
// Equal join condition using full-qualified column constants
|
|
2215
|
-
var fieldEq = function (leftCol, rightCol, leftAlias, rightAlias) {
|
|
2216
|
-
var _a;
|
|
2217
|
-
return (_a = {},
|
|
2218
|
-
_a[F(leftCol, leftAlias)] = F(rightCol, rightAlias),
|
|
2219
|
-
_a);
|
|
2220
|
-
};
|
|
2221
|
-
// ST_Distance_Sphere for aliased fields
|
|
2222
|
-
var distSphere = function (fromCol, toCol, fromAlias, toAlias) {
|
|
2223
|
-
return [C6C.ST_DISTANCE_SPHERE, F(fromCol, fromAlias), F(toCol, toAlias)];
|
|
2224
|
-
};
|
|
2225
|
-
// Build a bounding-box expression.
|
|
2226
|
-
//
|
|
2227
|
-
// Arguments must be provided in `(minLng, minLat, maxLng, maxLat)` order. The
|
|
2228
|
-
// helper does not attempt to swap or validate coordinates; if a minimum value
|
|
2229
|
-
// is greater than its corresponding maximum value, MySQL's `ST_MakeEnvelope`
|
|
2230
|
-
// returns `NULL`.
|
|
2231
|
-
var bbox = function (minLng, minLat, maxLng, maxLat) {
|
|
2232
|
-
return [C6C.ST_SRID, [C6C.ST_MAKEENVELOPE,
|
|
2233
|
-
[C6C.ST_POINT, minLng, minLat],
|
|
2234
|
-
[C6C.ST_POINT, maxLng, maxLat]], 4326];
|
|
2235
|
-
};
|
|
2236
|
-
// ST_Contains for map envelope/shape queries
|
|
2237
|
-
var stContains = function (envelope, shape) {
|
|
2238
|
-
return [C6C.ST_CONTAINS, envelope, shape];
|
|
2239
|
-
};
|
|
2240
|
-
|
|
2241
2490
|
function determineRuntimeJsType(mysqlType) {
|
|
2242
2491
|
var base = mysqlType.toLowerCase().split('(')[0];
|
|
2243
2492
|
if ([
|
|
@@ -2337,5 +2586,5 @@ function isVerbose () {
|
|
|
2337
2586
|
return ['true', '1', 'yes', 'on'].includes(envVerbose.toLowerCase());
|
|
2338
2587
|
}
|
|
2339
2588
|
|
|
2340
|
-
export { A, AggregateBuilder, C6C, C6Constants, ConditionBuilder, DELETE, DeleteQueryBuilder, Executor, ExpressHandler, F, GET, HttpExecutor, JoinBuilder, POST, PUT, PaginationBuilder, PostQueryBuilder, SelectQueryBuilder, SqlExecutor, TestRestfulResponse, UpdateQueryBuilder, apiRequestCache, axiosInstance, bbox, carbonNodeQsStringify, checkAllRequestsComplete, checkCache, clearCache, convertForRequestBody, convertHexIfBinary, determineRuntimeJsType, distSphere, eFetchDependencies, error, fieldEq, getEnvVar, getPrimaryKeyTypes, group, info, isLocal, isNode, isTest, isVerbose, normalizeSingularRequest, onError, onSuccess, removeInvalidKeys, removePrefixIfExists, restOrm, restRequest, sortAndSerializeQueryObject, stContains, timeout, toastOptions, toastOptionsDevs, userCustomClearCache, warn };
|
|
2589
|
+
export { A, AggregateBuilder, C6C, C6Constants, ConditionBuilder, DELETE, DeleteQueryBuilder, Executor, ExpressHandler, F, GET, HttpExecutor, JoinBuilder, POST, PUT, PaginationBuilder, PostQueryBuilder, SelectQueryBuilder, SqlExecutor, TestRestfulResponse, UpdateQueryBuilder, apiRequestCache, axiosInstance, bbox, carbonNodeQsStringify, checkAllRequestsComplete, checkCache, clearCache, convertForRequestBody, convertHexIfBinary, derivedTable, determineRuntimeJsType, distSphere, eFetchDependencies, error, fieldEq, getEnvVar, getPrimaryKeyTypes, group, info, isDerivedTableKey, isLocal, isNode, isTest, isVerbose, normalizeSingularRequest, onError, onSuccess, removeInvalidKeys, removePrefixIfExists, resolveDerivedTable, restOrm, restRequest, sortAndSerializeQueryObject, stContains, timeout, toastOptions, toastOptionsDevs, userCustomClearCache, warn };
|
|
2341
2590
|
//# sourceMappingURL=index.esm.js.map
|