metal-orm 1.1.22 → 1.1.23
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.cjs +267 -400
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +95 -151
- package/dist/index.d.ts +95 -151
- package/dist/index.js +262 -400
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/core/dialect/abstract.ts +94 -417
- package/src/core/dialect/base/expression-compiler-registry.ts +254 -0
- package/src/core/dialect/base/function-table-formatter.ts +40 -78
- package/src/core/dialect/base/select-ast-normalizer.ts +61 -0
- package/src/core/dialect/base/sql-dialect.ts +36 -59
- package/src/core/dialect/capabilities/procedure-compiler.ts +30 -0
- package/src/core/dialect/dialect-factory.ts +3 -4
- package/src/core/dialect/mssql/index.ts +3 -2
- package/src/core/dialect/mysql/index.ts +3 -2
- package/src/core/dialect/postgres/index.ts +3 -2
- package/src/core/dialect/sqlite/index.ts +1 -7
- package/src/index.ts +4 -1
- package/src/orm/execute-procedure.ts +3 -2
- package/src/query-builder/procedure-call.ts +4 -18
package/dist/index.js
CHANGED
|
@@ -1314,268 +1314,40 @@ var StandardTableFunctionStrategy = class {
|
|
|
1314
1314
|
}
|
|
1315
1315
|
};
|
|
1316
1316
|
|
|
1317
|
-
// src/core/dialect/
|
|
1318
|
-
var
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
* @param ast - Query AST to compile
|
|
1322
|
-
* @returns Compiled query with SQL and parameters
|
|
1323
|
-
*/
|
|
1324
|
-
compileSelect(ast) {
|
|
1325
|
-
const ctx = this.createCompilerContext();
|
|
1326
|
-
const normalized = this.normalizeSelectAst(ast);
|
|
1327
|
-
const rawSql = this.compileSelectAst(normalized, ctx).trim();
|
|
1328
|
-
const sql = rawSql.endsWith(";") ? rawSql : `${rawSql};`;
|
|
1329
|
-
return {
|
|
1330
|
-
sql,
|
|
1331
|
-
params: [...ctx.params]
|
|
1332
|
-
};
|
|
1333
|
-
}
|
|
1334
|
-
compileInsert(ast) {
|
|
1335
|
-
const ctx = this.createCompilerContext();
|
|
1336
|
-
const rawSql = this.compileInsertAst(ast, ctx).trim();
|
|
1337
|
-
const sql = rawSql.endsWith(";") ? rawSql : `${rawSql};`;
|
|
1338
|
-
return {
|
|
1339
|
-
sql,
|
|
1340
|
-
params: [...ctx.params]
|
|
1341
|
-
};
|
|
1342
|
-
}
|
|
1343
|
-
compileUpdate(ast) {
|
|
1344
|
-
const ctx = this.createCompilerContext();
|
|
1345
|
-
const rawSql = this.compileUpdateAst(ast, ctx).trim();
|
|
1346
|
-
const sql = rawSql.endsWith(";") ? rawSql : `${rawSql};`;
|
|
1347
|
-
return {
|
|
1348
|
-
sql,
|
|
1349
|
-
params: [...ctx.params]
|
|
1350
|
-
};
|
|
1351
|
-
}
|
|
1352
|
-
compileDelete(ast) {
|
|
1353
|
-
const ctx = this.createCompilerContext();
|
|
1354
|
-
const rawSql = this.compileDeleteAst(ast, ctx).trim();
|
|
1355
|
-
const sql = rawSql.endsWith(";") ? rawSql : `${rawSql};`;
|
|
1356
|
-
return {
|
|
1357
|
-
sql,
|
|
1358
|
-
params: [...ctx.params]
|
|
1359
|
-
};
|
|
1360
|
-
}
|
|
1361
|
-
supportsDmlReturningClause() {
|
|
1362
|
-
return false;
|
|
1363
|
-
}
|
|
1364
|
-
/**
|
|
1365
|
-
* Compiles a WHERE clause
|
|
1366
|
-
* @param where - WHERE expression
|
|
1367
|
-
* @param ctx - Compiler context
|
|
1368
|
-
* @returns SQL WHERE clause or empty string
|
|
1369
|
-
*/
|
|
1370
|
-
compileWhere(where, ctx) {
|
|
1371
|
-
if (!where) return "";
|
|
1372
|
-
return ` WHERE ${this.compileExpression(where, ctx)}`;
|
|
1373
|
-
}
|
|
1374
|
-
compileReturning(returning, _ctx) {
|
|
1375
|
-
void _ctx;
|
|
1376
|
-
if (!returning || returning.length === 0) return "";
|
|
1377
|
-
throw new Error("RETURNING is not supported by this dialect.");
|
|
1378
|
-
}
|
|
1379
|
-
/**
|
|
1380
|
-
* Generates subquery for EXISTS expressions
|
|
1381
|
-
* Rule: Always forces SELECT 1, ignoring column list
|
|
1382
|
-
* Maintains FROM, JOINs, WHERE, GROUP BY, ORDER BY, LIMIT/OFFSET
|
|
1383
|
-
* Does not add ';' at the end
|
|
1384
|
-
* @param ast - Query AST
|
|
1385
|
-
* @param ctx - Compiler context
|
|
1386
|
-
* @returns SQL for EXISTS subquery
|
|
1387
|
-
*/
|
|
1388
|
-
compileSelectForExists(ast, ctx) {
|
|
1389
|
-
const normalized = this.normalizeSelectAst(ast);
|
|
1390
|
-
const full = this.compileSelectAst(normalized, ctx).trim().replace(/;$/, "");
|
|
1391
|
-
if (normalized.setOps && normalized.setOps.length > 0) {
|
|
1392
|
-
return `SELECT 1 FROM (${full}) AS _exists`;
|
|
1393
|
-
}
|
|
1394
|
-
const upper2 = full.toUpperCase();
|
|
1395
|
-
const fromIndex = upper2.indexOf(" FROM ");
|
|
1396
|
-
if (fromIndex === -1) {
|
|
1397
|
-
return full;
|
|
1398
|
-
}
|
|
1399
|
-
const tail = full.slice(fromIndex);
|
|
1400
|
-
return `SELECT 1${tail}`;
|
|
1401
|
-
}
|
|
1402
|
-
/**
|
|
1403
|
-
* Creates a new compiler context
|
|
1404
|
-
* @returns Compiler context with parameter management
|
|
1405
|
-
*/
|
|
1406
|
-
createCompilerContext() {
|
|
1407
|
-
const params = [];
|
|
1408
|
-
let counter = 0;
|
|
1409
|
-
return {
|
|
1410
|
-
params,
|
|
1411
|
-
addParameter: (value) => {
|
|
1412
|
-
counter += 1;
|
|
1413
|
-
params.push(value);
|
|
1414
|
-
return this.formatPlaceholder(counter);
|
|
1415
|
-
}
|
|
1416
|
-
};
|
|
1417
|
-
}
|
|
1418
|
-
/**
|
|
1419
|
-
* Formats a parameter placeholder
|
|
1420
|
-
* @param index - Parameter index
|
|
1421
|
-
* @returns Formatted placeholder string
|
|
1422
|
-
*/
|
|
1423
|
-
formatPlaceholder(_index) {
|
|
1424
|
-
void _index;
|
|
1425
|
-
return "?";
|
|
1426
|
-
}
|
|
1427
|
-
/**
|
|
1428
|
-
* Whether the current dialect supports a given set operation.
|
|
1429
|
-
* Override in concrete dialects to restrict support.
|
|
1430
|
-
*/
|
|
1431
|
-
supportsSetOperation(_kind) {
|
|
1432
|
-
void _kind;
|
|
1433
|
-
return true;
|
|
1434
|
-
}
|
|
1435
|
-
/**
|
|
1436
|
-
* Validates set-operation semantics:
|
|
1437
|
-
* - Ensures the dialect supports requested operators.
|
|
1438
|
-
* - Enforces that only the outermost compound query may have ORDER/LIMIT/OFFSET.
|
|
1439
|
-
* @param ast - Query to validate
|
|
1440
|
-
* @param isOutermost - Whether this node is the outermost compound query
|
|
1441
|
-
*/
|
|
1442
|
-
validateSetOperations(ast, isOutermost = true) {
|
|
1443
|
-
const hasSetOps = !!(ast.setOps && ast.setOps.length);
|
|
1444
|
-
if (!isOutermost && (ast.orderBy || ast.limit !== void 0 || ast.offset !== void 0)) {
|
|
1445
|
-
throw new Error("ORDER BY / LIMIT / OFFSET are only allowed on the outermost compound query.");
|
|
1446
|
-
}
|
|
1447
|
-
if (hasSetOps) {
|
|
1448
|
-
for (const op of ast.setOps) {
|
|
1449
|
-
if (!this.supportsSetOperation(op.operator)) {
|
|
1450
|
-
throw new Error(`Set operation ${op.operator} is not supported by this dialect.`);
|
|
1451
|
-
}
|
|
1452
|
-
this.validateSetOperations(op.query, false);
|
|
1453
|
-
}
|
|
1454
|
-
}
|
|
1455
|
-
}
|
|
1456
|
-
/**
|
|
1457
|
-
* Hoists CTEs from set-operation operands to the outermost query so WITH appears once.
|
|
1458
|
-
* @param ast - Query AST
|
|
1459
|
-
* @returns Normalized AST without inner CTEs and a list of hoisted CTEs
|
|
1460
|
-
*/
|
|
1461
|
-
hoistCtes(ast) {
|
|
1462
|
-
let hoisted = [];
|
|
1463
|
-
const normalizedSetOps = ast.setOps?.map((op) => {
|
|
1464
|
-
const { normalized: child, hoistedCtes: childHoisted } = this.hoistCtes(op.query);
|
|
1465
|
-
const childCtes = child.ctes ?? [];
|
|
1466
|
-
if (childCtes.length) {
|
|
1467
|
-
hoisted = hoisted.concat(childCtes);
|
|
1468
|
-
}
|
|
1469
|
-
hoisted = hoisted.concat(childHoisted);
|
|
1470
|
-
const queryWithoutCtes = childCtes.length ? { ...child, ctes: void 0 } : child;
|
|
1471
|
-
return { ...op, query: queryWithoutCtes };
|
|
1472
|
-
});
|
|
1473
|
-
const normalized = normalizedSetOps ? { ...ast, setOps: normalizedSetOps } : ast;
|
|
1474
|
-
return { normalized, hoistedCtes: hoisted };
|
|
1475
|
-
}
|
|
1476
|
-
/**
|
|
1477
|
-
* Normalizes a SELECT AST before compilation (validation + CTE hoisting).
|
|
1478
|
-
* @param ast - Query AST
|
|
1479
|
-
* @returns Normalized query AST
|
|
1480
|
-
*/
|
|
1481
|
-
normalizeSelectAst(ast) {
|
|
1482
|
-
this.validateSetOperations(ast, true);
|
|
1483
|
-
const { normalized, hoistedCtes } = this.hoistCtes(ast);
|
|
1484
|
-
const combinedCtes = [...normalized.ctes ?? [], ...hoistedCtes];
|
|
1485
|
-
return combinedCtes.length ? { ...normalized, ctes: combinedCtes } : normalized;
|
|
1486
|
-
}
|
|
1487
|
-
expressionCompilers;
|
|
1488
|
-
operandCompilers;
|
|
1489
|
-
functionStrategy;
|
|
1490
|
-
tableFunctionStrategy;
|
|
1491
|
-
constructor(functionStrategy, tableFunctionStrategy) {
|
|
1492
|
-
this.expressionCompilers = /* @__PURE__ */ new Map();
|
|
1493
|
-
this.operandCompilers = /* @__PURE__ */ new Map();
|
|
1494
|
-
this.functionStrategy = functionStrategy || new StandardFunctionStrategy();
|
|
1495
|
-
this.tableFunctionStrategy = tableFunctionStrategy || new StandardTableFunctionStrategy();
|
|
1317
|
+
// src/core/dialect/base/expression-compiler-registry.ts
|
|
1318
|
+
var ExpressionCompilerRegistry = class {
|
|
1319
|
+
constructor(host) {
|
|
1320
|
+
this.host = host;
|
|
1496
1321
|
this.registerDefaultOperandCompilers();
|
|
1497
1322
|
this.registerDefaultExpressionCompilers();
|
|
1498
1323
|
}
|
|
1499
|
-
|
|
1500
|
-
|
|
1501
|
-
* @param functionStrategy - Optional function strategy
|
|
1502
|
-
* @returns New Dialect instance
|
|
1503
|
-
*/
|
|
1504
|
-
static create(functionStrategy, tableFunctionStrategy) {
|
|
1505
|
-
class TestDialect extends _Dialect {
|
|
1506
|
-
dialect = "sqlite";
|
|
1507
|
-
quoteIdentifier(id) {
|
|
1508
|
-
return `"${id}"`;
|
|
1509
|
-
}
|
|
1510
|
-
compileSelectAst() {
|
|
1511
|
-
throw new Error("Not implemented");
|
|
1512
|
-
}
|
|
1513
|
-
compileInsertAst() {
|
|
1514
|
-
throw new Error("Not implemented");
|
|
1515
|
-
}
|
|
1516
|
-
compileUpdateAst() {
|
|
1517
|
-
throw new Error("Not implemented");
|
|
1518
|
-
}
|
|
1519
|
-
compileDeleteAst() {
|
|
1520
|
-
throw new Error("Not implemented");
|
|
1521
|
-
}
|
|
1522
|
-
compileProcedureCall() {
|
|
1523
|
-
throw new Error("Not implemented");
|
|
1524
|
-
}
|
|
1525
|
-
}
|
|
1526
|
-
return new TestDialect(functionStrategy, tableFunctionStrategy);
|
|
1527
|
-
}
|
|
1528
|
-
/**
|
|
1529
|
-
* Registers an expression compiler for a specific node type
|
|
1530
|
-
* @param type - Expression node type
|
|
1531
|
-
* @param compiler - Compiler function
|
|
1532
|
-
*/
|
|
1324
|
+
expressionCompilers = /* @__PURE__ */ new Map();
|
|
1325
|
+
operandCompilers = /* @__PURE__ */ new Map();
|
|
1533
1326
|
registerExpressionCompiler(type, compiler) {
|
|
1534
1327
|
this.expressionCompilers.set(type, compiler);
|
|
1535
1328
|
}
|
|
1536
|
-
/**
|
|
1537
|
-
* Registers an operand compiler for a specific node type
|
|
1538
|
-
* @param type - Operand node type
|
|
1539
|
-
* @param compiler - Compiler function
|
|
1540
|
-
*/
|
|
1541
1329
|
registerOperandCompiler(type, compiler) {
|
|
1542
1330
|
this.operandCompilers.set(type, compiler);
|
|
1543
1331
|
}
|
|
1544
|
-
/**
|
|
1545
|
-
* Compiles an expression node
|
|
1546
|
-
* @param node - Expression node to compile
|
|
1547
|
-
* @param ctx - Compiler context
|
|
1548
|
-
* @returns Compiled SQL expression
|
|
1549
|
-
*/
|
|
1550
1332
|
compileExpression(node, ctx) {
|
|
1551
1333
|
const compiler = this.expressionCompilers.get(node.type);
|
|
1552
1334
|
if (!compiler) {
|
|
1553
|
-
throw new Error(`Unsupported expression node type "${node.type}" for ${this.
|
|
1335
|
+
throw new Error(`Unsupported expression node type "${node.type}" for ${this.host.describe()}`);
|
|
1554
1336
|
}
|
|
1555
1337
|
return compiler(node, ctx);
|
|
1556
1338
|
}
|
|
1557
|
-
/**
|
|
1558
|
-
* Compiles an operand node
|
|
1559
|
-
* @param node - Operand node to compile
|
|
1560
|
-
* @param ctx - Compiler context
|
|
1561
|
-
* @returns Compiled SQL operand
|
|
1562
|
-
*/
|
|
1563
1339
|
compileOperand(node, ctx) {
|
|
1564
1340
|
const compiler = this.operandCompilers.get(node.type);
|
|
1565
1341
|
if (!compiler) {
|
|
1566
|
-
throw new Error(`Unsupported operand node type "${node.type}" for ${this.
|
|
1342
|
+
throw new Error(`Unsupported operand node type "${node.type}" for ${this.host.describe()}`);
|
|
1567
1343
|
}
|
|
1568
1344
|
return compiler(node, ctx);
|
|
1569
1345
|
}
|
|
1570
|
-
/**
|
|
1571
|
-
* Compiles an ordering term (operand, expression, or alias reference).
|
|
1572
|
-
*/
|
|
1573
1346
|
compileOrderingTerm(term, ctx) {
|
|
1574
1347
|
if (isOperandNode(term)) {
|
|
1575
1348
|
return this.compileOperand(term, ctx);
|
|
1576
1349
|
}
|
|
1577
|
-
|
|
1578
|
-
return `(${expr})`;
|
|
1350
|
+
return `(${this.compileExpression(term, ctx)})`;
|
|
1579
1351
|
}
|
|
1580
1352
|
registerDefaultExpressionCompilers() {
|
|
1581
1353
|
this.registerExpressionCompiler("BinaryExpression", (binary, ctx) => {
|
|
@@ -1610,11 +1382,11 @@ var Dialect = class _Dialect {
|
|
|
1610
1382
|
const values = inExpr.right.map((v) => this.compileOperand(v, ctx)).join(", ");
|
|
1611
1383
|
return `${left2} ${inExpr.operator} (${values})`;
|
|
1612
1384
|
}
|
|
1613
|
-
const subquerySql = this.compileSelectAst(inExpr.right.query, ctx).trim().replace(/;$/, "");
|
|
1385
|
+
const subquerySql = this.host.compileSelectAst(inExpr.right.query, ctx).trim().replace(/;$/, "");
|
|
1614
1386
|
return `${left2} ${inExpr.operator} (${subquerySql})`;
|
|
1615
1387
|
});
|
|
1616
1388
|
this.registerExpressionCompiler("ExistsExpression", (existsExpr, ctx) => {
|
|
1617
|
-
const subquerySql = this.compileSelectForExists(existsExpr.subquery, ctx);
|
|
1389
|
+
const subquerySql = this.host.compileSelectForExists(existsExpr.subquery, ctx);
|
|
1618
1390
|
return `${existsExpr.operator} (${subquerySql})`;
|
|
1619
1391
|
});
|
|
1620
1392
|
this.registerExpressionCompiler("BetweenExpression", (betweenExpr, ctx) => {
|
|
@@ -1640,25 +1412,28 @@ var Dialect = class _Dialect {
|
|
|
1640
1412
|
});
|
|
1641
1413
|
}
|
|
1642
1414
|
registerDefaultOperandCompilers() {
|
|
1643
|
-
this.registerOperandCompiler(
|
|
1644
|
-
|
|
1645
|
-
|
|
1646
|
-
|
|
1647
|
-
|
|
1648
|
-
|
|
1649
|
-
|
|
1650
|
-
|
|
1651
|
-
|
|
1415
|
+
this.registerOperandCompiler(
|
|
1416
|
+
"Literal",
|
|
1417
|
+
(literal, ctx) => ctx.addParameter(literal.value)
|
|
1418
|
+
);
|
|
1419
|
+
this.registerOperandCompiler(
|
|
1420
|
+
"AliasRef",
|
|
1421
|
+
(alias) => this.host.quoteIdentifier(alias.name)
|
|
1422
|
+
);
|
|
1423
|
+
this.registerOperandCompiler(
|
|
1424
|
+
"Column",
|
|
1425
|
+
(column) => `${this.host.quoteIdentifier(column.table)}.${this.host.quoteIdentifier(column.name)}`
|
|
1426
|
+
);
|
|
1652
1427
|
this.registerOperandCompiler(
|
|
1653
1428
|
"Function",
|
|
1654
|
-
(fnNode, ctx) => this.compileFunctionOperand(fnNode, ctx)
|
|
1429
|
+
(fnNode, ctx) => this.host.compileFunctionOperand(fnNode, ctx)
|
|
1430
|
+
);
|
|
1431
|
+
this.registerOperandCompiler(
|
|
1432
|
+
"JsonPath",
|
|
1433
|
+
(path) => this.host.compileJsonPath(path)
|
|
1655
1434
|
);
|
|
1656
|
-
this.registerOperandCompiler("JsonPath", (path, _ctx) => {
|
|
1657
|
-
void _ctx;
|
|
1658
|
-
return this.compileJsonPath(path);
|
|
1659
|
-
});
|
|
1660
1435
|
this.registerOperandCompiler("ScalarSubquery", (node, ctx) => {
|
|
1661
|
-
const sql = this.compileSelectAst(node.query, ctx).trim().replace(/;$/, "");
|
|
1436
|
+
const sql = this.host.compileSelectAst(node.query, ctx).trim().replace(/;$/, "");
|
|
1662
1437
|
return `(${sql})`;
|
|
1663
1438
|
});
|
|
1664
1439
|
this.registerOperandCompiler("CaseExpression", (node, ctx) => {
|
|
@@ -1685,7 +1460,7 @@ var Dialect = class _Dialect {
|
|
|
1685
1460
|
const parts = [];
|
|
1686
1461
|
if (node.partitionBy && node.partitionBy.length > 0) {
|
|
1687
1462
|
const partitionClause = "PARTITION BY " + node.partitionBy.map(
|
|
1688
|
-
(col2) => `${this.quoteIdentifier(col2.table)}.${this.quoteIdentifier(col2.name)}`
|
|
1463
|
+
(col2) => `${this.host.quoteIdentifier(col2.table)}.${this.host.quoteIdentifier(col2.name)}`
|
|
1689
1464
|
).join(", ");
|
|
1690
1465
|
parts.push(partitionClause);
|
|
1691
1466
|
}
|
|
@@ -1717,14 +1492,164 @@ var Dialect = class _Dialect {
|
|
|
1717
1492
|
return `${expr} COLLATE ${node.collation}`;
|
|
1718
1493
|
});
|
|
1719
1494
|
}
|
|
1720
|
-
|
|
1495
|
+
};
|
|
1496
|
+
|
|
1497
|
+
// src/core/dialect/base/select-ast-normalizer.ts
|
|
1498
|
+
var SelectAstNormalizer = class {
|
|
1499
|
+
constructor(supportsSetOperation) {
|
|
1500
|
+
this.supportsSetOperation = supportsSetOperation;
|
|
1501
|
+
}
|
|
1502
|
+
normalize(ast) {
|
|
1503
|
+
this.validateSetOperations(ast, true);
|
|
1504
|
+
const { normalized, hoistedCtes } = this.hoistCtes(ast);
|
|
1505
|
+
const combinedCtes = [...normalized.ctes ?? [], ...hoistedCtes];
|
|
1506
|
+
return combinedCtes.length ? { ...normalized, ctes: combinedCtes } : normalized;
|
|
1507
|
+
}
|
|
1508
|
+
validateSetOperations(ast, isOutermost) {
|
|
1509
|
+
const hasSetOps = !!(ast.setOps && ast.setOps.length);
|
|
1510
|
+
if (!isOutermost && (ast.orderBy || ast.limit !== void 0 || ast.offset !== void 0)) {
|
|
1511
|
+
throw new Error("ORDER BY / LIMIT / OFFSET are only allowed on the outermost compound query.");
|
|
1512
|
+
}
|
|
1513
|
+
if (!hasSetOps) return;
|
|
1514
|
+
for (const op of ast.setOps) {
|
|
1515
|
+
if (!this.supportsSetOperation(op.operator)) {
|
|
1516
|
+
throw new Error(`Set operation ${op.operator} is not supported by this dialect.`);
|
|
1517
|
+
}
|
|
1518
|
+
this.validateSetOperations(op.query, false);
|
|
1519
|
+
}
|
|
1520
|
+
}
|
|
1521
|
+
hoistCtes(ast) {
|
|
1522
|
+
let hoisted = [];
|
|
1523
|
+
const normalizedSetOps = ast.setOps?.map((op) => {
|
|
1524
|
+
const { normalized: child, hoistedCtes: childHoisted } = this.hoistCtes(op.query);
|
|
1525
|
+
const childCtes = child.ctes ?? [];
|
|
1526
|
+
if (childCtes.length) hoisted = hoisted.concat(childCtes);
|
|
1527
|
+
hoisted = hoisted.concat(childHoisted);
|
|
1528
|
+
const queryWithoutCtes = childCtes.length ? { ...child, ctes: void 0 } : child;
|
|
1529
|
+
return { ...op, query: queryWithoutCtes };
|
|
1530
|
+
});
|
|
1531
|
+
const normalized = normalizedSetOps ? { ...ast, setOps: normalizedSetOps } : ast;
|
|
1532
|
+
return { normalized, hoistedCtes: hoisted };
|
|
1533
|
+
}
|
|
1534
|
+
};
|
|
1535
|
+
|
|
1536
|
+
// src/core/dialect/abstract.ts
|
|
1537
|
+
var DialectBase = class _DialectBase {
|
|
1538
|
+
expressionCompilerRegistry;
|
|
1539
|
+
selectAstNormalizer;
|
|
1540
|
+
functionStrategy;
|
|
1541
|
+
tableFunctionStrategy;
|
|
1542
|
+
constructor(functionStrategy, tableFunctionStrategy) {
|
|
1543
|
+
this.functionStrategy = functionStrategy ?? new StandardFunctionStrategy();
|
|
1544
|
+
this.tableFunctionStrategy = tableFunctionStrategy ?? new StandardTableFunctionStrategy();
|
|
1545
|
+
this.selectAstNormalizer = new SelectAstNormalizer((kind) => this.supportsSetOperation(kind));
|
|
1546
|
+
this.expressionCompilerRegistry = new ExpressionCompilerRegistry({
|
|
1547
|
+
quoteIdentifier: (id) => this.quoteIdentifier(id),
|
|
1548
|
+
compileSelectAst: (ast, ctx) => this.compileSelectAst(ast, ctx),
|
|
1549
|
+
compileSelectForExists: (ast, ctx) => this.compileSelectForExists(ast, ctx),
|
|
1550
|
+
compileJsonPath: (node) => this.compileJsonPath(node),
|
|
1551
|
+
compileFunctionOperand: (node, ctx) => this.compileFunctionOperand(node, ctx),
|
|
1552
|
+
describe: () => this.constructor.name
|
|
1553
|
+
});
|
|
1554
|
+
}
|
|
1555
|
+
compileSelect(ast) {
|
|
1556
|
+
const ctx = this.createCompilerContext();
|
|
1557
|
+
const normalized = this.normalizeSelectAst(ast);
|
|
1558
|
+
const rawSql = this.compileSelectAst(normalized, ctx).trim();
|
|
1559
|
+
return {
|
|
1560
|
+
sql: rawSql.endsWith(";") ? rawSql : `${rawSql};`,
|
|
1561
|
+
params: [...ctx.params]
|
|
1562
|
+
};
|
|
1563
|
+
}
|
|
1564
|
+
compileInsert(ast) {
|
|
1565
|
+
const ctx = this.createCompilerContext();
|
|
1566
|
+
const rawSql = this.compileInsertAst(ast, ctx).trim();
|
|
1567
|
+
return {
|
|
1568
|
+
sql: rawSql.endsWith(";") ? rawSql : `${rawSql};`,
|
|
1569
|
+
params: [...ctx.params]
|
|
1570
|
+
};
|
|
1571
|
+
}
|
|
1572
|
+
compileUpdate(ast) {
|
|
1573
|
+
const ctx = this.createCompilerContext();
|
|
1574
|
+
const rawSql = this.compileUpdateAst(ast, ctx).trim();
|
|
1575
|
+
return {
|
|
1576
|
+
sql: rawSql.endsWith(";") ? rawSql : `${rawSql};`,
|
|
1577
|
+
params: [...ctx.params]
|
|
1578
|
+
};
|
|
1579
|
+
}
|
|
1580
|
+
compileDelete(ast) {
|
|
1581
|
+
const ctx = this.createCompilerContext();
|
|
1582
|
+
const rawSql = this.compileDeleteAst(ast, ctx).trim();
|
|
1583
|
+
return {
|
|
1584
|
+
sql: rawSql.endsWith(";") ? rawSql : `${rawSql};`,
|
|
1585
|
+
params: [...ctx.params]
|
|
1586
|
+
};
|
|
1587
|
+
}
|
|
1588
|
+
supportsDmlReturningClause() {
|
|
1589
|
+
return false;
|
|
1590
|
+
}
|
|
1591
|
+
compileWhere(where, ctx) {
|
|
1592
|
+
if (!where) return "";
|
|
1593
|
+
return ` WHERE ${this.compileExpression(where, ctx)}`;
|
|
1594
|
+
}
|
|
1595
|
+
compileReturning(returning, _ctx) {
|
|
1596
|
+
void _ctx;
|
|
1597
|
+
if (!returning || returning.length === 0) return "";
|
|
1598
|
+
throw new Error("RETURNING is not supported by this dialect.");
|
|
1599
|
+
}
|
|
1600
|
+
compileSelectForExists(ast, ctx) {
|
|
1601
|
+
const normalized = this.normalizeSelectAst(ast);
|
|
1602
|
+
const full = this.compileSelectAst(normalized, ctx).trim().replace(/;$/, "");
|
|
1603
|
+
if (normalized.setOps && normalized.setOps.length > 0) {
|
|
1604
|
+
return `SELECT 1 FROM (${full}) AS _exists`;
|
|
1605
|
+
}
|
|
1606
|
+
const upper2 = full.toUpperCase();
|
|
1607
|
+
const fromIndex = upper2.indexOf(" FROM ");
|
|
1608
|
+
if (fromIndex === -1) return full;
|
|
1609
|
+
return `SELECT 1${full.slice(fromIndex)}`;
|
|
1610
|
+
}
|
|
1611
|
+
createCompilerContext() {
|
|
1612
|
+
const params = [];
|
|
1613
|
+
let counter = 0;
|
|
1614
|
+
return {
|
|
1615
|
+
params,
|
|
1616
|
+
addParameter: (value) => {
|
|
1617
|
+
counter += 1;
|
|
1618
|
+
params.push(value);
|
|
1619
|
+
return this.formatPlaceholder(counter);
|
|
1620
|
+
}
|
|
1621
|
+
};
|
|
1622
|
+
}
|
|
1623
|
+
formatPlaceholder(_index) {
|
|
1624
|
+
void _index;
|
|
1625
|
+
return "?";
|
|
1626
|
+
}
|
|
1627
|
+
supportsSetOperation(_kind) {
|
|
1628
|
+
void _kind;
|
|
1629
|
+
return true;
|
|
1630
|
+
}
|
|
1631
|
+
normalizeSelectAst(ast) {
|
|
1632
|
+
return this.selectAstNormalizer.normalize(ast);
|
|
1633
|
+
}
|
|
1634
|
+
registerExpressionCompiler(type, compiler) {
|
|
1635
|
+
this.expressionCompilerRegistry.registerExpressionCompiler(type, compiler);
|
|
1636
|
+
}
|
|
1637
|
+
registerOperandCompiler(type, compiler) {
|
|
1638
|
+
this.expressionCompilerRegistry.registerOperandCompiler(type, compiler);
|
|
1639
|
+
}
|
|
1640
|
+
compileExpression(node, ctx) {
|
|
1641
|
+
return this.expressionCompilerRegistry.compileExpression(node, ctx);
|
|
1642
|
+
}
|
|
1643
|
+
compileOperand(node, ctx) {
|
|
1644
|
+
return this.expressionCompilerRegistry.compileOperand(node, ctx);
|
|
1645
|
+
}
|
|
1646
|
+
compileOrderingTerm(term, ctx) {
|
|
1647
|
+
return this.expressionCompilerRegistry.compileOrderingTerm(term, ctx);
|
|
1648
|
+
}
|
|
1721
1649
|
compileJsonPath(_node) {
|
|
1722
1650
|
void _node;
|
|
1723
1651
|
throw new Error("JSON Path not supported by this dialect");
|
|
1724
1652
|
}
|
|
1725
|
-
/**
|
|
1726
|
-
* Compiles a function operand, using the dialect's function strategy.
|
|
1727
|
-
*/
|
|
1728
1653
|
compileFunctionOperand(fnNode, ctx) {
|
|
1729
1654
|
const compiledArgs = fnNode.args.map((arg) => this.compileOperand(arg, ctx));
|
|
1730
1655
|
const renderer = this.functionStrategy.getRenderer(fnNode.name);
|
|
@@ -1737,98 +1662,62 @@ var Dialect = class _Dialect {
|
|
|
1737
1662
|
}
|
|
1738
1663
|
return `${fnNode.name}(${compiledArgs.join(", ")})`;
|
|
1739
1664
|
}
|
|
1665
|
+
/** Creates a minimal dialect implementation for isolated compiler tests. */
|
|
1666
|
+
static create(functionStrategy, tableFunctionStrategy) {
|
|
1667
|
+
class TestDialect extends _DialectBase {
|
|
1668
|
+
dialect = "sqlite";
|
|
1669
|
+
quoteIdentifier(id) {
|
|
1670
|
+
return `"${id}"`;
|
|
1671
|
+
}
|
|
1672
|
+
compileSelectAst() {
|
|
1673
|
+
throw new Error("Not implemented");
|
|
1674
|
+
}
|
|
1675
|
+
compileInsertAst() {
|
|
1676
|
+
throw new Error("Not implemented");
|
|
1677
|
+
}
|
|
1678
|
+
compileUpdateAst() {
|
|
1679
|
+
throw new Error("Not implemented");
|
|
1680
|
+
}
|
|
1681
|
+
compileDeleteAst() {
|
|
1682
|
+
throw new Error("Not implemented");
|
|
1683
|
+
}
|
|
1684
|
+
}
|
|
1685
|
+
return new TestDialect(functionStrategy, tableFunctionStrategy);
|
|
1686
|
+
}
|
|
1740
1687
|
};
|
|
1741
1688
|
|
|
1742
1689
|
// src/core/dialect/base/function-table-formatter.ts
|
|
1743
1690
|
var FunctionTableFormatter = class {
|
|
1744
|
-
|
|
1745
|
-
|
|
1746
|
-
|
|
1747
|
-
* @param ctx - Optional compiler context for operand compilation.
|
|
1748
|
-
* @param dialect - The dialect instance for compiling operands.
|
|
1749
|
-
* @returns SQL function table expression (e.g., "LATERAL schema.func(args) WITH ORDINALITY AS alias(col1, col2)").
|
|
1750
|
-
*/
|
|
1751
|
-
static format(fn9, ctx, dialect) {
|
|
1752
|
-
const schemaPart = this.formatSchema(fn9, dialect);
|
|
1753
|
-
const args = this.formatArgs(fn9, ctx, dialect);
|
|
1691
|
+
static format(fn9, ctx, formatter) {
|
|
1692
|
+
const schemaPart = this.formatSchema(fn9, formatter);
|
|
1693
|
+
const args = this.formatArgs(fn9, ctx, formatter);
|
|
1754
1694
|
const base = this.formatBase(fn9, schemaPart, args);
|
|
1755
1695
|
const lateral = this.formatLateral(fn9);
|
|
1756
|
-
const alias = this.formatAlias(fn9,
|
|
1757
|
-
const colAliases = this.formatColumnAliases(fn9,
|
|
1696
|
+
const alias = this.formatAlias(fn9, formatter);
|
|
1697
|
+
const colAliases = this.formatColumnAliases(fn9, formatter);
|
|
1758
1698
|
return `${lateral}${base}${alias}${colAliases}`;
|
|
1759
1699
|
}
|
|
1760
|
-
|
|
1761
|
-
* Formats the schema prefix for the function name.
|
|
1762
|
-
* @param fn - The function table node.
|
|
1763
|
-
* @param dialect - The dialect instance for quoting identifiers.
|
|
1764
|
-
* @returns Schema prefix (e.g., "schema.") or empty string.
|
|
1765
|
-
* @internal
|
|
1766
|
-
*/
|
|
1767
|
-
static formatSchema(fn9, dialect) {
|
|
1700
|
+
static formatSchema(fn9, formatter) {
|
|
1768
1701
|
if (!fn9.schema) return "";
|
|
1769
|
-
|
|
1770
|
-
return `${quoted}.`;
|
|
1702
|
+
return `${formatter.quoteIdentifier(fn9.schema)}.`;
|
|
1771
1703
|
}
|
|
1772
|
-
|
|
1773
|
-
|
|
1774
|
-
* @param fn - The function table node containing arguments.
|
|
1775
|
-
* @param ctx - Optional compiler context for operand compilation.
|
|
1776
|
-
* @param dialect - The dialect instance for compiling operands.
|
|
1777
|
-
* @returns Comma-separated function arguments.
|
|
1778
|
-
* @internal
|
|
1779
|
-
*/
|
|
1780
|
-
static formatArgs(fn9, ctx, dialect) {
|
|
1781
|
-
return (fn9.args || []).map((a) => {
|
|
1782
|
-
if (ctx && dialect) {
|
|
1783
|
-
return dialect.compileOperand(a, ctx);
|
|
1784
|
-
}
|
|
1785
|
-
return String(a);
|
|
1786
|
-
}).join(", ");
|
|
1704
|
+
static formatArgs(fn9, ctx, formatter) {
|
|
1705
|
+
return (fn9.args || []).map((arg) => ctx ? formatter.compileOperand(arg, ctx) : String(arg)).join(", ");
|
|
1787
1706
|
}
|
|
1788
|
-
/**
|
|
1789
|
-
* Formats the base function call with WITH ORDINALITY if present.
|
|
1790
|
-
* @param fn - The function table node.
|
|
1791
|
-
* @param schemaPart - Formatted schema prefix.
|
|
1792
|
-
* @param args - Formatted function arguments.
|
|
1793
|
-
* @param dialect - The dialect instance for quoting identifiers.
|
|
1794
|
-
* @returns Base function call expression (e.g., "schema.func(args) WITH ORDINALITY").
|
|
1795
|
-
* @internal
|
|
1796
|
-
*/
|
|
1797
1707
|
static formatBase(fn9, schemaPart, args) {
|
|
1798
1708
|
const ordinality = fn9.withOrdinality ? " WITH ORDINALITY" : "";
|
|
1799
1709
|
return `${schemaPart}${fn9.name}(${args})${ordinality}`;
|
|
1800
1710
|
}
|
|
1801
|
-
/**
|
|
1802
|
-
* Formats the LATERAL keyword if present.
|
|
1803
|
-
* @param fn - The function table node.
|
|
1804
|
-
* @returns "LATERAL " or empty string.
|
|
1805
|
-
* @internal
|
|
1806
|
-
*/
|
|
1807
1711
|
static formatLateral(fn9) {
|
|
1808
1712
|
return fn9.lateral ? "LATERAL " : "";
|
|
1809
1713
|
}
|
|
1810
|
-
|
|
1811
|
-
* Formats the table alias for the function table.
|
|
1812
|
-
* @param fn - The function table node.
|
|
1813
|
-
* @param dialect - The dialect instance for quoting identifiers.
|
|
1814
|
-
* @returns " AS alias" or empty string.
|
|
1815
|
-
* @internal
|
|
1816
|
-
*/
|
|
1817
|
-
static formatAlias(fn9, dialect) {
|
|
1714
|
+
static formatAlias(fn9, formatter) {
|
|
1818
1715
|
if (!fn9.alias) return "";
|
|
1819
|
-
|
|
1820
|
-
return ` AS ${quoted}`;
|
|
1716
|
+
return ` AS ${formatter.quoteIdentifier(fn9.alias)}`;
|
|
1821
1717
|
}
|
|
1822
|
-
|
|
1823
|
-
* Formats column aliases for the function table result columns.
|
|
1824
|
-
* @param fn - The function table node containing column aliases.
|
|
1825
|
-
* @param dialect - The dialect instance for quoting identifiers.
|
|
1826
|
-
* @returns "(col1, col2, ...)" or empty string.
|
|
1827
|
-
* @internal
|
|
1828
|
-
*/
|
|
1829
|
-
static formatColumnAliases(fn9, dialect) {
|
|
1718
|
+
static formatColumnAliases(fn9, formatter) {
|
|
1830
1719
|
if (!fn9.columnAliases || !fn9.columnAliases.length) return "";
|
|
1831
|
-
const aliases = fn9.columnAliases.map((col2) =>
|
|
1720
|
+
const aliases = fn9.columnAliases.map((col2) => formatter.quoteIdentifier(col2)).join(", ");
|
|
1832
1721
|
return `(${aliases})`;
|
|
1833
1722
|
}
|
|
1834
1723
|
};
|
|
@@ -1954,7 +1843,7 @@ var OrderByCompiler = class {
|
|
|
1954
1843
|
};
|
|
1955
1844
|
|
|
1956
1845
|
// src/core/dialect/base/sql-dialect.ts
|
|
1957
|
-
var SqlDialectBase = class extends
|
|
1846
|
+
var SqlDialectBase = class extends DialectBase {
|
|
1958
1847
|
paginationStrategy = new StandardLimitOffsetPagination();
|
|
1959
1848
|
returningStrategy = new NoReturningStrategy();
|
|
1960
1849
|
compileSelectAst(ast, ctx) {
|
|
@@ -1964,14 +1853,12 @@ var SqlDialectBase = class extends Dialect {
|
|
|
1964
1853
|
ctx,
|
|
1965
1854
|
this.quoteIdentifier.bind(this),
|
|
1966
1855
|
this.compileSelectAst.bind(this),
|
|
1967
|
-
this.normalizeSelectAst
|
|
1856
|
+
this.normalizeSelectAst.bind(this),
|
|
1968
1857
|
this.stripTrailingSemicolon.bind(this)
|
|
1969
1858
|
);
|
|
1970
1859
|
const baseAst = hasSetOps ? { ...ast, setOps: void 0, orderBy: void 0, limit: void 0, offset: void 0 } : ast;
|
|
1971
1860
|
const baseSelect = this.compileSelectCore(baseAst, ctx);
|
|
1972
|
-
if (!hasSetOps) {
|
|
1973
|
-
return `${ctes}${baseSelect}`;
|
|
1974
|
-
}
|
|
1861
|
+
if (!hasSetOps) return `${ctes}${baseSelect}`;
|
|
1975
1862
|
return this.compileSelectWithSetOps(ast, baseSelect, ctes, ctx);
|
|
1976
1863
|
}
|
|
1977
1864
|
compileSelectWithSetOps(ast, baseSelect, ctes, ctx) {
|
|
@@ -2020,9 +1907,7 @@ var SqlDialectBase = class extends Dialect {
|
|
|
2020
1907
|
return columns.map((column) => this.quoteIdentifier(column.name)).join(", ");
|
|
2021
1908
|
}
|
|
2022
1909
|
ensureConflictColumns(clause, message) {
|
|
2023
|
-
if (!clause.target.columns.length)
|
|
2024
|
-
throw new Error(message);
|
|
2025
|
-
}
|
|
1910
|
+
if (!clause.target.columns.length) throw new Error(message);
|
|
2026
1911
|
}
|
|
2027
1912
|
compileSelectCore(ast, ctx) {
|
|
2028
1913
|
const columns = this.compileSelectColumns(ast, ctx);
|
|
@@ -2055,8 +1940,7 @@ var SqlDialectBase = class extends Dialect {
|
|
|
2055
1940
|
}
|
|
2056
1941
|
compileUpdateAssignments(assignments, table, ctx) {
|
|
2057
1942
|
return assignments.map((assignment) => {
|
|
2058
|
-
const
|
|
2059
|
-
const target = this.compileSetTarget(col2, table);
|
|
1943
|
+
const target = this.compileSetTarget(assignment.column, table);
|
|
2060
1944
|
const value = this.compileOperand(assignment.value, ctx);
|
|
2061
1945
|
return `${target} = ${value}`;
|
|
2062
1946
|
}).join(", ");
|
|
@@ -2069,9 +1953,7 @@ var SqlDialectBase = class extends Dialect {
|
|
|
2069
1953
|
const alias = table.alias;
|
|
2070
1954
|
const columnTable = column.table ?? alias ?? baseTableName;
|
|
2071
1955
|
const tableQualifier = alias && column.table === baseTableName ? alias : columnTable;
|
|
2072
|
-
if (!tableQualifier)
|
|
2073
|
-
return this.quoteIdentifier(column.name);
|
|
2074
|
-
}
|
|
1956
|
+
if (!tableQualifier) return this.quoteIdentifier(column.name);
|
|
2075
1957
|
return `${this.quoteIdentifier(tableQualifier)}.${this.quoteIdentifier(column.name)}`;
|
|
2076
1958
|
}
|
|
2077
1959
|
compileDeleteAst(ast, ctx) {
|
|
@@ -2088,27 +1970,20 @@ var SqlDialectBase = class extends Dialect {
|
|
|
2088
1970
|
return ast.distinct ? "DISTINCT " : "";
|
|
2089
1971
|
}
|
|
2090
1972
|
compileSelectColumns(ast, ctx) {
|
|
2091
|
-
if (!ast.columns || ast.columns.length === 0)
|
|
2092
|
-
|
|
2093
|
-
|
|
2094
|
-
|
|
2095
|
-
|
|
2096
|
-
|
|
2097
|
-
if (c.alias.includes("(")) return c.alias;
|
|
2098
|
-
return `${expr} AS ${this.quoteIdentifier(c.alias)}`;
|
|
1973
|
+
if (!ast.columns || ast.columns.length === 0) return "*";
|
|
1974
|
+
return ast.columns.map((column) => {
|
|
1975
|
+
const expr = this.compileOperand(column, ctx);
|
|
1976
|
+
if (column.alias) {
|
|
1977
|
+
if (column.alias.includes("(")) return column.alias;
|
|
1978
|
+
return `${expr} AS ${this.quoteIdentifier(column.alias)}`;
|
|
2099
1979
|
}
|
|
2100
1980
|
return expr;
|
|
2101
1981
|
}).join(", ");
|
|
2102
1982
|
}
|
|
2103
1983
|
compileFrom(ast, ctx) {
|
|
2104
|
-
|
|
2105
|
-
if (
|
|
2106
|
-
|
|
2107
|
-
}
|
|
2108
|
-
if (tableSource.type === "DerivedTable") {
|
|
2109
|
-
return this.compileDerivedTable(tableSource, ctx);
|
|
2110
|
-
}
|
|
2111
|
-
return this.compileTableSource(tableSource);
|
|
1984
|
+
if (ast.type === "FunctionTable") return this.compileFunctionTable(ast, ctx);
|
|
1985
|
+
if (ast.type === "DerivedTable") return this.compileDerivedTable(ast, ctx);
|
|
1986
|
+
return this.compileTableSource(ast);
|
|
2112
1987
|
}
|
|
2113
1988
|
compileFunctionTable(fn9, ctx) {
|
|
2114
1989
|
const key = fn9.key ?? fn9.name;
|
|
@@ -2127,23 +2002,20 @@ var SqlDialectBase = class extends Dialect {
|
|
|
2127
2002
|
throw new Error(`Table function "${key}" is not supported by dialect "${this.dialect}".`);
|
|
2128
2003
|
}
|
|
2129
2004
|
}
|
|
2130
|
-
return FunctionTableFormatter.format(fn9, ctx,
|
|
2005
|
+
return FunctionTableFormatter.format(fn9, ctx, {
|
|
2006
|
+
quoteIdentifier: (id) => this.quoteIdentifier(id),
|
|
2007
|
+
compileOperand: (node, compilerContext) => this.compileOperand(node, compilerContext)
|
|
2008
|
+
});
|
|
2131
2009
|
}
|
|
2132
2010
|
compileDerivedTable(table, ctx) {
|
|
2133
|
-
if (!table.alias)
|
|
2134
|
-
throw new Error("Derived tables must have an alias.");
|
|
2135
|
-
}
|
|
2011
|
+
if (!table.alias) throw new Error("Derived tables must have an alias.");
|
|
2136
2012
|
const subquery = this.compileSelectAst(this.normalizeSelectAst(table.query), ctx).trim().replace(/;$/, "");
|
|
2137
2013
|
const columns = table.columnAliases?.length ? ` (${table.columnAliases.map((c) => this.quoteIdentifier(c)).join(", ")})` : "";
|
|
2138
2014
|
return `(${subquery}) AS ${this.quoteIdentifier(table.alias)}${columns}`;
|
|
2139
2015
|
}
|
|
2140
2016
|
compileTableSource(table) {
|
|
2141
|
-
if (table.type === "FunctionTable")
|
|
2142
|
-
|
|
2143
|
-
}
|
|
2144
|
-
if (table.type === "DerivedTable") {
|
|
2145
|
-
return this.compileDerivedTable(table);
|
|
2146
|
-
}
|
|
2017
|
+
if (table.type === "FunctionTable") return this.compileFunctionTable(table);
|
|
2018
|
+
if (table.type === "DerivedTable") return this.compileDerivedTable(table);
|
|
2147
2019
|
const base = this.compileTableName(table);
|
|
2148
2020
|
return table.alias ? `${base} AS ${this.quoteIdentifier(table.alias)}` : base;
|
|
2149
2021
|
}
|
|
@@ -2159,9 +2031,7 @@ var SqlDialectBase = class extends Dialect {
|
|
|
2159
2031
|
}
|
|
2160
2032
|
compileUpdateFromClause(ast, ctx) {
|
|
2161
2033
|
if (!ast.from && (!ast.joins || ast.joins.length === 0)) return "";
|
|
2162
|
-
if (!ast.from)
|
|
2163
|
-
throw new Error("UPDATE with JOINs requires an explicit FROM clause.");
|
|
2164
|
-
}
|
|
2034
|
+
if (!ast.from) throw new Error("UPDATE with JOINs requires an explicit FROM clause.");
|
|
2165
2035
|
const from = this.compileFrom(ast.from, ctx);
|
|
2166
2036
|
const joins = JoinCompiler.compileJoins(
|
|
2167
2037
|
ast.joins,
|
|
@@ -2173,9 +2043,7 @@ var SqlDialectBase = class extends Dialect {
|
|
|
2173
2043
|
}
|
|
2174
2044
|
compileDeleteUsingClause(ast, ctx) {
|
|
2175
2045
|
if (!ast.using && (!ast.joins || ast.joins.length === 0)) return "";
|
|
2176
|
-
if (!ast.using)
|
|
2177
|
-
throw new Error("DELETE with JOINs requires a USING clause.");
|
|
2178
|
-
}
|
|
2046
|
+
if (!ast.using) throw new Error("DELETE with JOINs requires a USING clause.");
|
|
2179
2047
|
const usingTable = this.compileFrom(ast.using, ctx);
|
|
2180
2048
|
const joins = JoinCompiler.compileJoins(
|
|
2181
2049
|
ast.joins,
|
|
@@ -2193,8 +2061,7 @@ var SqlDialectBase = class extends Dialect {
|
|
|
2193
2061
|
return sql.trim().replace(/;$/, "");
|
|
2194
2062
|
}
|
|
2195
2063
|
wrapSetOperand(sql) {
|
|
2196
|
-
|
|
2197
|
-
return `(${trimmed})`;
|
|
2064
|
+
return `(${this.stripTrailingSemicolon(sql)})`;
|
|
2198
2065
|
}
|
|
2199
2066
|
renderOrderByNulls(order) {
|
|
2200
2067
|
return order.nulls ? ` NULLS ${order.nulls}` : "";
|
|
@@ -2903,10 +2770,6 @@ var SqliteDialect = class extends SqlDialectBase {
|
|
|
2903
2770
|
supportsDmlReturningClause() {
|
|
2904
2771
|
return true;
|
|
2905
2772
|
}
|
|
2906
|
-
compileProcedureCall(_ast) {
|
|
2907
|
-
void _ast;
|
|
2908
|
-
throw new Error("Stored procedures are not supported by the SQLite dialect.");
|
|
2909
|
-
}
|
|
2910
2773
|
};
|
|
2911
2774
|
|
|
2912
2775
|
// src/core/dialect/mssql/functions.ts
|
|
@@ -3341,9 +3204,8 @@ var DialectFactory = class {
|
|
|
3341
3204
|
/**
|
|
3342
3205
|
* Register (or override) a dialect factory for a key.
|
|
3343
3206
|
*
|
|
3344
|
-
*
|
|
3345
|
-
*
|
|
3346
|
-
* DialectFactory.register('my-tenant-dialect', () => new CustomDialect());
|
|
3207
|
+
* Implementations are structural: extending DialectBase/SqlDialectBase is
|
|
3208
|
+
* optional. A composed object satisfying Dialect is a valid registration.
|
|
3347
3209
|
*/
|
|
3348
3210
|
static register(key, factory) {
|
|
3349
3211
|
this.registry.set(key, factory);
|
|
@@ -10916,6 +10778,15 @@ var DeleteQueryBuilder = class _DeleteQueryBuilder {
|
|
|
10916
10778
|
};
|
|
10917
10779
|
var isTableSourceNode2 = (source) => typeof source.type === "string";
|
|
10918
10780
|
|
|
10781
|
+
// src/core/dialect/capabilities/procedure-compiler.ts
|
|
10782
|
+
var isProcedureCompiler = (value) => typeof value?.compileProcedureCall === "function";
|
|
10783
|
+
var requireProcedureCompiler = (value) => {
|
|
10784
|
+
if (!isProcedureCompiler(value)) {
|
|
10785
|
+
throw new Error("Stored procedures are not supported by this dialect.");
|
|
10786
|
+
}
|
|
10787
|
+
return value;
|
|
10788
|
+
};
|
|
10789
|
+
|
|
10919
10790
|
// src/orm/execute-procedure.ts
|
|
10920
10791
|
var resolveColumnIndex = (columns, expectedName) => {
|
|
10921
10792
|
const exact = columns.findIndex((column) => column === expectedName);
|
|
@@ -10954,7 +10825,7 @@ var extractOutValues = (compiled, resultSets) => {
|
|
|
10954
10825
|
};
|
|
10955
10826
|
var executeProcedureAst = async (session, ast) => {
|
|
10956
10827
|
const execCtx = session.getExecutionContext();
|
|
10957
|
-
const compiled = execCtx.dialect.compileProcedureCall(ast);
|
|
10828
|
+
const compiled = requireProcedureCompiler(execCtx.dialect).compileProcedureCall(ast);
|
|
10958
10829
|
const payload = await execCtx.interceptors.run(
|
|
10959
10830
|
{ sql: compiled.sql, params: compiled.params },
|
|
10960
10831
|
execCtx.executor
|
|
@@ -11027,8 +10898,7 @@ var ProcedureCallBuilder = class _ProcedureCallBuilder {
|
|
|
11027
10898
|
}
|
|
11028
10899
|
compile(dialect) {
|
|
11029
10900
|
const resolved = resolveDialectInput(dialect);
|
|
11030
|
-
this.
|
|
11031
|
-
return resolved.compileProcedureCall(this.getAST());
|
|
10901
|
+
return requireProcedureCompiler(resolved).compileProcedureCall(this.getAST());
|
|
11032
10902
|
}
|
|
11033
10903
|
toSql(dialect) {
|
|
11034
10904
|
return this.compile(dialect).sql;
|
|
@@ -11041,21 +10911,8 @@ var ProcedureCallBuilder = class _ProcedureCallBuilder {
|
|
|
11041
10911
|
};
|
|
11042
10912
|
}
|
|
11043
10913
|
async execute(session) {
|
|
11044
|
-
this.validateMssqlOutDbType(session.getExecutionContext().dialect);
|
|
11045
10914
|
return executeProcedureAst(session, this.getAST());
|
|
11046
10915
|
}
|
|
11047
|
-
validateMssqlOutDbType(dialect) {
|
|
11048
|
-
const isMssqlDialect = dialect.constructor.name === "SqlServerDialect";
|
|
11049
|
-
if (!isMssqlDialect) return;
|
|
11050
|
-
for (const param of this.ast.params) {
|
|
11051
|
-
const needsDbType = param.direction === "out" || param.direction === "inout";
|
|
11052
|
-
if (needsDbType && !param.dbType) {
|
|
11053
|
-
throw new Error(
|
|
11054
|
-
`MSSQL requires "dbType" for procedure parameter "${param.name}" with direction "${param.direction}".`
|
|
11055
|
-
);
|
|
11056
|
-
}
|
|
11057
|
-
}
|
|
11058
|
-
}
|
|
11059
10916
|
};
|
|
11060
10917
|
var callProcedure = (name, options) => new ProcedureCallBuilder(name, options);
|
|
11061
10918
|
|
|
@@ -21783,6 +21640,8 @@ export {
|
|
|
21783
21640
|
DefaultMorphToReference,
|
|
21784
21641
|
DefaultTypeStrategy,
|
|
21785
21642
|
DeleteQueryBuilder,
|
|
21643
|
+
DialectBase,
|
|
21644
|
+
DialectFactory,
|
|
21786
21645
|
DomainEventBus,
|
|
21787
21646
|
Email,
|
|
21788
21647
|
Entity,
|
|
@@ -22010,6 +21869,7 @@ export {
|
|
|
22010
21869
|
isNull,
|
|
22011
21870
|
isNullableColumn,
|
|
22012
21871
|
isOperandNode,
|
|
21872
|
+
isProcedureCompiler,
|
|
22013
21873
|
isSingleTargetRelation,
|
|
22014
21874
|
isTableDef2 as isTableDef,
|
|
22015
21875
|
isTreeConfig,
|
|
@@ -22107,6 +21967,8 @@ export {
|
|
|
22107
21967
|
repeat,
|
|
22108
21968
|
replace,
|
|
22109
21969
|
replaceWithRefs,
|
|
21970
|
+
requireProcedureCompiler,
|
|
21971
|
+
resolveDialectInput,
|
|
22110
21972
|
resolveTreeConfig,
|
|
22111
21973
|
resolveValidator,
|
|
22112
21974
|
responseToRef,
|