metal-orm 1.1.22 → 1.1.24
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 +564 -575
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +196 -164
- package/dist/index.d.ts +196 -164
- package/dist/index.js +554 -575
- 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 +84 -245
- package/src/core/dialect/base/standard-delete-compiler.ts +37 -0
- package/src/core/dialect/base/standard-insert-compiler.ts +49 -0
- package/src/core/dialect/base/standard-select-compiler.ts +82 -0
- package/src/core/dialect/base/standard-sql-services.ts +44 -0
- package/src/core/dialect/base/standard-sql-source-compiler.ts +88 -0
- package/src/core/dialect/base/standard-update-compiler.ts +53 -0
- 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 +10 -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,115 +1662,175 @@ 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
|
-
// src/core/dialect/base/
|
|
1743
|
-
var
|
|
1689
|
+
// src/core/dialect/base/pagination-strategy.ts
|
|
1690
|
+
var StandardLimitOffsetPagination = class {
|
|
1744
1691
|
/**
|
|
1745
|
-
*
|
|
1746
|
-
* @param
|
|
1747
|
-
* @param
|
|
1748
|
-
* @
|
|
1749
|
-
* @returns SQL function table expression (e.g., "LATERAL schema.func(args) WITH ORDINALITY AS alias(col1, col2)").
|
|
1692
|
+
* Compiles LIMIT/OFFSET pagination clause.
|
|
1693
|
+
* @param limit - The maximum number of rows to return.
|
|
1694
|
+
* @param offset - The number of rows to skip.
|
|
1695
|
+
* @returns SQL pagination clause with LIMIT and/or OFFSET.
|
|
1750
1696
|
*/
|
|
1751
|
-
|
|
1752
|
-
const
|
|
1753
|
-
|
|
1754
|
-
|
|
1755
|
-
|
|
1756
|
-
const alias = this.formatAlias(fn9, dialect);
|
|
1757
|
-
const colAliases = this.formatColumnAliases(fn9, dialect);
|
|
1758
|
-
return `${lateral}${base}${alias}${colAliases}`;
|
|
1697
|
+
compilePagination(limit, offset) {
|
|
1698
|
+
const parts = [];
|
|
1699
|
+
if (limit !== void 0) parts.push(`LIMIT ${limit}`);
|
|
1700
|
+
if (offset !== void 0) parts.push(`OFFSET ${offset}`);
|
|
1701
|
+
return parts.length ? ` ${parts.join(" ")}` : "";
|
|
1759
1702
|
}
|
|
1703
|
+
};
|
|
1704
|
+
|
|
1705
|
+
// src/core/dialect/base/returning-strategy.ts
|
|
1706
|
+
var NoReturningStrategy = class {
|
|
1760
1707
|
/**
|
|
1761
|
-
*
|
|
1762
|
-
* @param
|
|
1763
|
-
* @param
|
|
1764
|
-
* @
|
|
1765
|
-
* @internal
|
|
1708
|
+
* Throws an error as RETURNING is not supported.
|
|
1709
|
+
* @param returning - Columns to return (causes error if non-empty).
|
|
1710
|
+
* @param _ctx - Compiler context (unused).
|
|
1711
|
+
* @throws Error indicating RETURNING is not supported.
|
|
1766
1712
|
*/
|
|
1767
|
-
|
|
1768
|
-
|
|
1769
|
-
|
|
1770
|
-
|
|
1713
|
+
compileReturning(returning, _ctx) {
|
|
1714
|
+
void _ctx;
|
|
1715
|
+
if (!returning || returning.length === 0) return "";
|
|
1716
|
+
throw new Error("RETURNING is not supported by this dialect.");
|
|
1771
1717
|
}
|
|
1772
1718
|
/**
|
|
1773
|
-
* Formats
|
|
1774
|
-
* @param
|
|
1775
|
-
* @param
|
|
1776
|
-
* @
|
|
1777
|
-
* @returns Comma-separated function arguments.
|
|
1778
|
-
* @internal
|
|
1719
|
+
* Formats column names for RETURNING clause.
|
|
1720
|
+
* @param returning - Columns to format.
|
|
1721
|
+
* @param quoteIdentifier - Function to quote identifiers according to dialect rules.
|
|
1722
|
+
* @returns Simple comma-separated column names.
|
|
1779
1723
|
*/
|
|
1780
|
-
|
|
1781
|
-
return
|
|
1782
|
-
|
|
1783
|
-
|
|
1784
|
-
}
|
|
1785
|
-
return String(a);
|
|
1724
|
+
formatReturningColumns(returning, quoteIdentifier) {
|
|
1725
|
+
return returning.map((column) => {
|
|
1726
|
+
const tablePart = column.table ? `${quoteIdentifier(column.table)}.` : "";
|
|
1727
|
+
const aliasPart = column.alias ? ` AS ${quoteIdentifier(column.alias)}` : "";
|
|
1728
|
+
return `${tablePart}${quoteIdentifier(column.name)}${aliasPart}`;
|
|
1786
1729
|
}).join(", ");
|
|
1787
1730
|
}
|
|
1788
|
-
|
|
1789
|
-
|
|
1790
|
-
|
|
1791
|
-
|
|
1792
|
-
|
|
1793
|
-
|
|
1794
|
-
|
|
1795
|
-
|
|
1796
|
-
|
|
1731
|
+
};
|
|
1732
|
+
|
|
1733
|
+
// src/core/dialect/base/function-table-formatter.ts
|
|
1734
|
+
var FunctionTableFormatter = class {
|
|
1735
|
+
static format(fn9, ctx, formatter) {
|
|
1736
|
+
const schemaPart = this.formatSchema(fn9, formatter);
|
|
1737
|
+
const args = this.formatArgs(fn9, ctx, formatter);
|
|
1738
|
+
const base = this.formatBase(fn9, schemaPart, args);
|
|
1739
|
+
const lateral = this.formatLateral(fn9);
|
|
1740
|
+
const alias = this.formatAlias(fn9, formatter);
|
|
1741
|
+
const colAliases = this.formatColumnAliases(fn9, formatter);
|
|
1742
|
+
return `${lateral}${base}${alias}${colAliases}`;
|
|
1743
|
+
}
|
|
1744
|
+
static formatSchema(fn9, formatter) {
|
|
1745
|
+
if (!fn9.schema) return "";
|
|
1746
|
+
return `${formatter.quoteIdentifier(fn9.schema)}.`;
|
|
1747
|
+
}
|
|
1748
|
+
static formatArgs(fn9, ctx, formatter) {
|
|
1749
|
+
return (fn9.args || []).map((arg) => ctx ? formatter.compileOperand(arg, ctx) : String(arg)).join(", ");
|
|
1750
|
+
}
|
|
1797
1751
|
static formatBase(fn9, schemaPart, args) {
|
|
1798
1752
|
const ordinality = fn9.withOrdinality ? " WITH ORDINALITY" : "";
|
|
1799
1753
|
return `${schemaPart}${fn9.name}(${args})${ordinality}`;
|
|
1800
1754
|
}
|
|
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
1755
|
static formatLateral(fn9) {
|
|
1808
1756
|
return fn9.lateral ? "LATERAL " : "";
|
|
1809
1757
|
}
|
|
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) {
|
|
1758
|
+
static formatAlias(fn9, formatter) {
|
|
1818
1759
|
if (!fn9.alias) return "";
|
|
1819
|
-
|
|
1820
|
-
|
|
1821
|
-
|
|
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) {
|
|
1760
|
+
return ` AS ${formatter.quoteIdentifier(fn9.alias)}`;
|
|
1761
|
+
}
|
|
1762
|
+
static formatColumnAliases(fn9, formatter) {
|
|
1830
1763
|
if (!fn9.columnAliases || !fn9.columnAliases.length) return "";
|
|
1831
|
-
const aliases = fn9.columnAliases.map((col2) =>
|
|
1764
|
+
const aliases = fn9.columnAliases.map((col2) => formatter.quoteIdentifier(col2)).join(", ");
|
|
1832
1765
|
return `(${aliases})`;
|
|
1833
1766
|
}
|
|
1834
1767
|
};
|
|
1835
1768
|
|
|
1836
|
-
// src/core/dialect/base/
|
|
1837
|
-
var
|
|
1838
|
-
|
|
1839
|
-
|
|
1840
|
-
|
|
1841
|
-
|
|
1842
|
-
|
|
1843
|
-
|
|
1844
|
-
|
|
1845
|
-
|
|
1846
|
-
|
|
1847
|
-
|
|
1848
|
-
|
|
1769
|
+
// src/core/dialect/base/standard-sql-source-compiler.ts
|
|
1770
|
+
var StandardSqlSourceCompiler = class {
|
|
1771
|
+
constructor(services) {
|
|
1772
|
+
this.services = services;
|
|
1773
|
+
}
|
|
1774
|
+
compileFrom(source, ctx) {
|
|
1775
|
+
if (source.type === "FunctionTable") return this.compileFunctionTable(source, ctx);
|
|
1776
|
+
if (source.type === "DerivedTable") return this.compileDerivedTable(source, ctx);
|
|
1777
|
+
return this.compileTableSource(source);
|
|
1778
|
+
}
|
|
1779
|
+
compileFunctionTable(fn9, ctx) {
|
|
1780
|
+
const key = fn9.key ?? fn9.name;
|
|
1781
|
+
if (ctx) {
|
|
1782
|
+
const renderer = this.services.getTableFunctionStrategy().getRenderer(key);
|
|
1783
|
+
if (renderer) {
|
|
1784
|
+
const compiledArgs = (fn9.args ?? []).map((arg) => this.services.compileOperand(arg, ctx));
|
|
1785
|
+
return renderer({
|
|
1786
|
+
node: fn9,
|
|
1787
|
+
compiledArgs,
|
|
1788
|
+
compileOperand: (operand) => this.services.compileOperand(operand, ctx),
|
|
1789
|
+
quoteIdentifier: (id) => this.services.quoteIdentifier(id)
|
|
1790
|
+
});
|
|
1791
|
+
}
|
|
1792
|
+
if (fn9.key) {
|
|
1793
|
+
throw new Error(
|
|
1794
|
+
`Table function "${key}" is not supported by dialect "${this.services.getDialectName()}".`
|
|
1795
|
+
);
|
|
1796
|
+
}
|
|
1797
|
+
}
|
|
1798
|
+
return FunctionTableFormatter.format(fn9, ctx, {
|
|
1799
|
+
quoteIdentifier: (id) => this.services.quoteIdentifier(id),
|
|
1800
|
+
compileOperand: (node, compilerContext) => this.services.compileOperand(node, compilerContext)
|
|
1801
|
+
});
|
|
1802
|
+
}
|
|
1803
|
+
compileDerivedTable(table, ctx) {
|
|
1804
|
+
if (!table.alias) throw new Error("Derived tables must have an alias.");
|
|
1805
|
+
if (!ctx) throw new Error("Derived table compilation requires a compiler context.");
|
|
1806
|
+
const normalized = this.services.normalizeSelectAst(table.query);
|
|
1807
|
+
const subquery = this.services.compileSelectAst(normalized, ctx).trim().replace(/;$/, "");
|
|
1808
|
+
const columns = table.columnAliases?.length ? ` (${table.columnAliases.map((column) => this.services.quoteIdentifier(column)).join(", ")})` : "";
|
|
1809
|
+
return `(${subquery}) AS ${this.services.quoteIdentifier(table.alias)}${columns}`;
|
|
1810
|
+
}
|
|
1811
|
+
compileTableSource(table) {
|
|
1812
|
+
if (table.type === "FunctionTable") return this.compileFunctionTable(table);
|
|
1813
|
+
if (table.type === "DerivedTable") {
|
|
1814
|
+
throw new Error("Derived table compilation requires a compiler context.");
|
|
1815
|
+
}
|
|
1816
|
+
const base = this.compileTableName(table);
|
|
1817
|
+
return table.alias ? `${base} AS ${this.services.quoteIdentifier(table.alias)}` : base;
|
|
1818
|
+
}
|
|
1819
|
+
compileTableName(table) {
|
|
1820
|
+
if (table.schema) {
|
|
1821
|
+
return `${this.services.quoteIdentifier(table.schema)}.${this.services.quoteIdentifier(table.name)}`;
|
|
1822
|
+
}
|
|
1823
|
+
return this.services.quoteIdentifier(table.name);
|
|
1824
|
+
}
|
|
1825
|
+
compileTableReference(table) {
|
|
1826
|
+
const base = this.compileTableName(table);
|
|
1827
|
+
return table.alias ? `${base} AS ${this.services.quoteIdentifier(table.alias)}` : base;
|
|
1828
|
+
}
|
|
1829
|
+
stripTrailingSemicolon(sql) {
|
|
1830
|
+
return sql.trim().replace(/;$/, "");
|
|
1831
|
+
}
|
|
1832
|
+
wrapSetOperand(sql) {
|
|
1833
|
+
return `(${this.stripTrailingSemicolon(sql)})`;
|
|
1849
1834
|
}
|
|
1850
1835
|
};
|
|
1851
1836
|
|
|
@@ -1875,34 +1860,6 @@ var CteCompiler = class {
|
|
|
1875
1860
|
}
|
|
1876
1861
|
};
|
|
1877
1862
|
|
|
1878
|
-
// src/core/dialect/base/returning-strategy.ts
|
|
1879
|
-
var NoReturningStrategy = class {
|
|
1880
|
-
/**
|
|
1881
|
-
* Throws an error as RETURNING is not supported.
|
|
1882
|
-
* @param returning - Columns to return (causes error if non-empty).
|
|
1883
|
-
* @param _ctx - Compiler context (unused).
|
|
1884
|
-
* @throws Error indicating RETURNING is not supported.
|
|
1885
|
-
*/
|
|
1886
|
-
compileReturning(returning, _ctx) {
|
|
1887
|
-
void _ctx;
|
|
1888
|
-
if (!returning || returning.length === 0) return "";
|
|
1889
|
-
throw new Error("RETURNING is not supported by this dialect.");
|
|
1890
|
-
}
|
|
1891
|
-
/**
|
|
1892
|
-
* Formats column names for RETURNING clause.
|
|
1893
|
-
* @param returning - Columns to format.
|
|
1894
|
-
* @param quoteIdentifier - Function to quote identifiers according to dialect rules.
|
|
1895
|
-
* @returns Simple comma-separated column names.
|
|
1896
|
-
*/
|
|
1897
|
-
formatReturningColumns(returning, quoteIdentifier) {
|
|
1898
|
-
return returning.map((column) => {
|
|
1899
|
-
const tablePart = column.table ? `${quoteIdentifier(column.table)}.` : "";
|
|
1900
|
-
const aliasPart = column.alias ? ` AS ${quoteIdentifier(column.alias)}` : "";
|
|
1901
|
-
return `${tablePart}${quoteIdentifier(column.name)}${aliasPart}`;
|
|
1902
|
-
}).join(", ");
|
|
1903
|
-
}
|
|
1904
|
-
};
|
|
1905
|
-
|
|
1906
1863
|
// src/core/dialect/base/join-compiler.ts
|
|
1907
1864
|
var JoinCompiler = class {
|
|
1908
1865
|
static compileJoins(joins, ctx, compileFrom, compileExpression) {
|
|
@@ -1953,113 +1910,229 @@ var OrderByCompiler = class {
|
|
|
1953
1910
|
}
|
|
1954
1911
|
};
|
|
1955
1912
|
|
|
1956
|
-
// src/core/dialect/base/
|
|
1957
|
-
var
|
|
1958
|
-
|
|
1959
|
-
|
|
1960
|
-
|
|
1913
|
+
// src/core/dialect/base/standard-select-compiler.ts
|
|
1914
|
+
var StandardSelectCompiler = class {
|
|
1915
|
+
constructor(services, sources) {
|
|
1916
|
+
this.services = services;
|
|
1917
|
+
this.sources = sources;
|
|
1918
|
+
}
|
|
1919
|
+
compile(ast, ctx) {
|
|
1961
1920
|
const hasSetOps = !!(ast.setOps && ast.setOps.length);
|
|
1962
1921
|
const ctes = CteCompiler.compileCtes(
|
|
1963
1922
|
ast,
|
|
1964
1923
|
ctx,
|
|
1965
|
-
this.quoteIdentifier
|
|
1966
|
-
this.compileSelectAst
|
|
1967
|
-
|
|
1968
|
-
this.stripTrailingSemicolon
|
|
1924
|
+
(id) => this.services.quoteIdentifier(id),
|
|
1925
|
+
(query, compilerContext) => this.services.compileSelectAst(query, compilerContext),
|
|
1926
|
+
(query) => this.services.normalizeSelectAst(query),
|
|
1927
|
+
(sql) => this.sources.stripTrailingSemicolon(sql)
|
|
1969
1928
|
);
|
|
1970
1929
|
const baseAst = hasSetOps ? { ...ast, setOps: void 0, orderBy: void 0, limit: void 0, offset: void 0 } : ast;
|
|
1971
|
-
const baseSelect = this.
|
|
1972
|
-
if (!hasSetOps) {
|
|
1973
|
-
|
|
1974
|
-
|
|
1975
|
-
|
|
1930
|
+
const baseSelect = this.compileCore(baseAst, ctx);
|
|
1931
|
+
if (!hasSetOps) return `${ctes}${baseSelect}`;
|
|
1932
|
+
const compound = ast.setOps.map((op) => `${op.operator} ${this.sources.wrapSetOperand(this.services.compileSelectAst(op.query, ctx))}`).join(" ");
|
|
1933
|
+
const orderBy = this.compileOrderBy(ast, ctx);
|
|
1934
|
+
const pagination = this.services.getPaginationStrategy().compilePagination(ast.limit, ast.offset);
|
|
1935
|
+
const combined = `${this.sources.wrapSetOperand(baseSelect)} ${compound}`;
|
|
1936
|
+
return `${ctes}${combined}${orderBy}${pagination}`;
|
|
1976
1937
|
}
|
|
1977
|
-
|
|
1978
|
-
const
|
|
1979
|
-
const
|
|
1938
|
+
compileCore(ast, ctx) {
|
|
1939
|
+
const columns = this.compileColumns(ast, ctx);
|
|
1940
|
+
const from = this.sources.compileFrom(ast.from, ctx);
|
|
1941
|
+
const joins = JoinCompiler.compileJoins(
|
|
1942
|
+
ast.joins,
|
|
1943
|
+
ctx,
|
|
1944
|
+
(source, compilerContext) => this.sources.compileFrom(source, compilerContext),
|
|
1945
|
+
(expression, compilerContext) => this.services.compileExpression(expression, compilerContext)
|
|
1946
|
+
);
|
|
1947
|
+
const where = ast.where ? ` WHERE ${this.services.compileExpression(ast.where, ctx)}` : "";
|
|
1948
|
+
const groupBy = GroupByCompiler.compileGroupBy(
|
|
1980
1949
|
ast,
|
|
1981
|
-
(term) => this.compileOrderingTerm(term, ctx)
|
|
1982
|
-
this.renderOrderByNulls.bind(this),
|
|
1983
|
-
this.renderOrderByCollation.bind(this)
|
|
1950
|
+
(term) => this.services.compileOrderingTerm(term, ctx)
|
|
1984
1951
|
);
|
|
1985
|
-
const
|
|
1986
|
-
const
|
|
1987
|
-
|
|
1952
|
+
const having = ast.having ? ` HAVING ${this.services.compileExpression(ast.having, ctx)}` : "";
|
|
1953
|
+
const orderBy = this.compileOrderBy(ast, ctx);
|
|
1954
|
+
const pagination = this.services.getPaginationStrategy().compilePagination(ast.limit, ast.offset);
|
|
1955
|
+
return `SELECT ${ast.distinct ? "DISTINCT " : ""}${columns} FROM ${from}${joins}${where}${groupBy}${having}${orderBy}${pagination}`;
|
|
1956
|
+
}
|
|
1957
|
+
compileColumns(ast, ctx) {
|
|
1958
|
+
if (!ast.columns || ast.columns.length === 0) return "*";
|
|
1959
|
+
return ast.columns.map((column) => {
|
|
1960
|
+
const expr = this.services.compileOperand(column, ctx);
|
|
1961
|
+
if (!column.alias) return expr;
|
|
1962
|
+
if (column.alias.includes("(")) return column.alias;
|
|
1963
|
+
return `${expr} AS ${this.services.quoteIdentifier(column.alias)}`;
|
|
1964
|
+
}).join(", ");
|
|
1988
1965
|
}
|
|
1989
|
-
|
|
1966
|
+
compileOrderBy(ast, ctx) {
|
|
1967
|
+
return OrderByCompiler.compileOrderBy(
|
|
1968
|
+
ast,
|
|
1969
|
+
(term) => this.services.compileOrderingTerm(term, ctx),
|
|
1970
|
+
(order) => this.services.renderOrderByNulls(order),
|
|
1971
|
+
(order) => this.services.renderOrderByCollation(order)
|
|
1972
|
+
);
|
|
1973
|
+
}
|
|
1974
|
+
};
|
|
1975
|
+
|
|
1976
|
+
// src/core/dialect/base/standard-insert-compiler.ts
|
|
1977
|
+
var StandardInsertCompiler = class {
|
|
1978
|
+
constructor(services, sources) {
|
|
1979
|
+
this.services = services;
|
|
1980
|
+
this.sources = sources;
|
|
1981
|
+
}
|
|
1982
|
+
compile(ast, ctx) {
|
|
1990
1983
|
if (!ast.columns.length) {
|
|
1991
1984
|
throw new Error("INSERT queries must specify columns.");
|
|
1992
1985
|
}
|
|
1993
|
-
const table = this.compileTableName(ast.into);
|
|
1994
|
-
const columnList = this.
|
|
1995
|
-
const source = this.
|
|
1996
|
-
const upsert = this.compileUpsertClause(ast, ctx);
|
|
1997
|
-
const returning = this.compileReturning(ast.returning, ctx);
|
|
1986
|
+
const table = this.sources.compileTableName(ast.into);
|
|
1987
|
+
const columnList = this.compileColumnList(ast.columns);
|
|
1988
|
+
const source = this.compileSource(ast.source, ctx);
|
|
1989
|
+
const upsert = this.services.compileUpsertClause(ast, ctx);
|
|
1990
|
+
const returning = this.services.compileReturning(ast.returning, ctx);
|
|
1998
1991
|
return `INSERT INTO ${table} (${columnList}) ${source}${upsert}${returning}`;
|
|
1999
1992
|
}
|
|
2000
|
-
|
|
2001
|
-
void _ctx;
|
|
2002
|
-
if (!ast.onConflict) return "";
|
|
2003
|
-
throw new Error(`UPSERT/ON CONFLICT is not supported by dialect "${this.dialect}".`);
|
|
2004
|
-
}
|
|
2005
|
-
compileReturning(returning, ctx) {
|
|
2006
|
-
return this.returningStrategy.compileReturning(returning, ctx);
|
|
2007
|
-
}
|
|
2008
|
-
compileInsertSource(source, ctx) {
|
|
1993
|
+
compileSource(source, ctx) {
|
|
2009
1994
|
if (source.type === "InsertValues") {
|
|
2010
1995
|
if (!source.rows.length) {
|
|
2011
1996
|
throw new Error("INSERT ... VALUES requires at least one row.");
|
|
2012
1997
|
}
|
|
2013
|
-
const values = source.rows.map((row) => `(${row.map((value) => this.compileOperand(value, ctx)).join(", ")})`).join(", ");
|
|
1998
|
+
const values = source.rows.map((row) => `(${row.map((value) => this.services.compileOperand(value, ctx)).join(", ")})`).join(", ");
|
|
2014
1999
|
return `VALUES ${values}`;
|
|
2015
2000
|
}
|
|
2016
|
-
const normalized = this.normalizeSelectAst(source.query);
|
|
2017
|
-
return this.compileSelectAst(normalized, ctx).trim();
|
|
2001
|
+
const normalized = this.services.normalizeSelectAst(source.query);
|
|
2002
|
+
return this.services.compileSelectAst(normalized, ctx).trim();
|
|
2018
2003
|
}
|
|
2019
|
-
|
|
2020
|
-
return columns.map((column) => this.quoteIdentifier(column.name)).join(", ");
|
|
2004
|
+
compileColumnList(columns) {
|
|
2005
|
+
return columns.map((column) => this.services.quoteIdentifier(column.name)).join(", ");
|
|
2021
2006
|
}
|
|
2022
2007
|
ensureConflictColumns(clause, message) {
|
|
2023
|
-
if (!clause.target.columns.length)
|
|
2024
|
-
throw new Error(message);
|
|
2025
|
-
}
|
|
2008
|
+
if (!clause.target.columns.length) throw new Error(message);
|
|
2026
2009
|
}
|
|
2027
|
-
|
|
2028
|
-
|
|
2029
|
-
|
|
2010
|
+
};
|
|
2011
|
+
|
|
2012
|
+
// src/core/dialect/base/standard-update-compiler.ts
|
|
2013
|
+
var StandardUpdateCompiler = class {
|
|
2014
|
+
constructor(services, sources) {
|
|
2015
|
+
this.services = services;
|
|
2016
|
+
this.sources = sources;
|
|
2017
|
+
}
|
|
2018
|
+
compile(ast, ctx) {
|
|
2019
|
+
const target = this.sources.compileTableReference(ast.table);
|
|
2020
|
+
const assignments = this.compileAssignments(ast.set, ast.table, ctx);
|
|
2021
|
+
const from = this.compileFromClause(ast, ctx);
|
|
2022
|
+
const where = ast.where ? ` WHERE ${this.services.compileExpression(ast.where, ctx)}` : "";
|
|
2023
|
+
const returning = this.services.compileReturning(ast.returning, ctx);
|
|
2024
|
+
return `UPDATE ${target} SET ${assignments}${from}${where}${returning}`;
|
|
2025
|
+
}
|
|
2026
|
+
compileAssignments(assignments, table, ctx) {
|
|
2027
|
+
return assignments.map((assignment) => {
|
|
2028
|
+
const target = this.services.compileSetTarget(assignment.column, table);
|
|
2029
|
+
const value = this.services.compileOperand(assignment.value, ctx);
|
|
2030
|
+
return `${target} = ${value}`;
|
|
2031
|
+
}).join(", ");
|
|
2032
|
+
}
|
|
2033
|
+
compileFromClause(ast, ctx) {
|
|
2034
|
+
if (!ast.from && (!ast.joins || ast.joins.length === 0)) return "";
|
|
2035
|
+
if (!ast.from) {
|
|
2036
|
+
throw new Error("UPDATE with JOINs requires an explicit FROM clause.");
|
|
2037
|
+
}
|
|
2038
|
+
const from = this.sources.compileFrom(ast.from, ctx);
|
|
2030
2039
|
const joins = JoinCompiler.compileJoins(
|
|
2031
2040
|
ast.joins,
|
|
2032
2041
|
ctx,
|
|
2033
|
-
this.compileFrom
|
|
2034
|
-
this.compileExpression
|
|
2042
|
+
(source, compilerContext) => this.sources.compileFrom(source, compilerContext),
|
|
2043
|
+
(expression, compilerContext) => this.services.compileExpression(expression, compilerContext)
|
|
2035
2044
|
);
|
|
2036
|
-
|
|
2037
|
-
|
|
2038
|
-
|
|
2039
|
-
|
|
2040
|
-
|
|
2041
|
-
|
|
2042
|
-
|
|
2043
|
-
|
|
2045
|
+
return ` FROM ${from}${joins}`;
|
|
2046
|
+
}
|
|
2047
|
+
};
|
|
2048
|
+
|
|
2049
|
+
// src/core/dialect/base/standard-delete-compiler.ts
|
|
2050
|
+
var StandardDeleteCompiler = class {
|
|
2051
|
+
constructor(services, sources) {
|
|
2052
|
+
this.services = services;
|
|
2053
|
+
this.sources = sources;
|
|
2054
|
+
}
|
|
2055
|
+
compile(ast, ctx) {
|
|
2056
|
+
const target = this.sources.compileTableReference(ast.from);
|
|
2057
|
+
const using = this.compileUsingClause(ast, ctx);
|
|
2058
|
+
const where = ast.where ? ` WHERE ${this.services.compileExpression(ast.where, ctx)}` : "";
|
|
2059
|
+
const returning = this.services.compileReturning(ast.returning, ctx);
|
|
2060
|
+
return `DELETE FROM ${target}${using}${where}${returning}`;
|
|
2061
|
+
}
|
|
2062
|
+
compileUsingClause(ast, ctx) {
|
|
2063
|
+
if (!ast.using && (!ast.joins || ast.joins.length === 0)) return "";
|
|
2064
|
+
if (!ast.using) {
|
|
2065
|
+
throw new Error("DELETE with JOINs requires a USING clause.");
|
|
2066
|
+
}
|
|
2067
|
+
const usingTable = this.sources.compileFrom(ast.using, ctx);
|
|
2068
|
+
const joins = JoinCompiler.compileJoins(
|
|
2069
|
+
ast.joins,
|
|
2070
|
+
ctx,
|
|
2071
|
+
(source, compilerContext) => this.sources.compileFrom(source, compilerContext),
|
|
2072
|
+
(expression, compilerContext) => this.services.compileExpression(expression, compilerContext)
|
|
2044
2073
|
);
|
|
2045
|
-
|
|
2046
|
-
|
|
2074
|
+
return ` USING ${usingTable}${joins}`;
|
|
2075
|
+
}
|
|
2076
|
+
};
|
|
2077
|
+
|
|
2078
|
+
// src/core/dialect/base/sql-dialect.ts
|
|
2079
|
+
var SqlDialectBase = class extends DialectBase {
|
|
2080
|
+
paginationStrategy = new StandardLimitOffsetPagination();
|
|
2081
|
+
returningStrategy = new NoReturningStrategy();
|
|
2082
|
+
sourceCompiler;
|
|
2083
|
+
selectCompiler;
|
|
2084
|
+
insertCompiler;
|
|
2085
|
+
updateCompiler;
|
|
2086
|
+
deleteCompiler;
|
|
2087
|
+
constructor(functionStrategy, tableFunctionStrategy) {
|
|
2088
|
+
super(functionStrategy, tableFunctionStrategy);
|
|
2089
|
+
const services = {
|
|
2090
|
+
getDialectName: () => this.dialect,
|
|
2091
|
+
getPaginationStrategy: () => this.paginationStrategy,
|
|
2092
|
+
getTableFunctionStrategy: () => this.tableFunctionStrategy,
|
|
2093
|
+
quoteIdentifier: (id) => this.quoteIdentifier(id),
|
|
2094
|
+
compileOperand: (node, ctx) => this.compileOperand(node, ctx),
|
|
2095
|
+
compileExpression: (node, ctx) => this.compileExpression(node, ctx),
|
|
2096
|
+
compileOrderingTerm: (term, ctx) => this.compileOrderingTerm(term, ctx),
|
|
2097
|
+
normalizeSelectAst: (ast) => this.normalizeSelectAst(ast),
|
|
2098
|
+
compileSelectAst: (ast, ctx) => this.compileSelectAst(ast, ctx),
|
|
2099
|
+
compileReturning: (returning, ctx) => this.compileReturning(returning, ctx),
|
|
2100
|
+
compileUpsertClause: (ast, ctx) => this.compileUpsertClause(ast, ctx),
|
|
2101
|
+
compileSetTarget: (column, table) => this.compileSetTarget(column, table),
|
|
2102
|
+
renderOrderByNulls: (order) => this.renderOrderByNulls(order),
|
|
2103
|
+
renderOrderByCollation: (order) => this.renderOrderByCollation(order)
|
|
2104
|
+
};
|
|
2105
|
+
this.sourceCompiler = new StandardSqlSourceCompiler(services);
|
|
2106
|
+
this.selectCompiler = new StandardSelectCompiler(services, this.sourceCompiler);
|
|
2107
|
+
this.insertCompiler = new StandardInsertCompiler(services, this.sourceCompiler);
|
|
2108
|
+
this.updateCompiler = new StandardUpdateCompiler(services, this.sourceCompiler);
|
|
2109
|
+
this.deleteCompiler = new StandardDeleteCompiler(services, this.sourceCompiler);
|
|
2110
|
+
}
|
|
2111
|
+
compileSelectAst(ast, ctx) {
|
|
2112
|
+
return this.selectCompiler.compile(ast, ctx);
|
|
2113
|
+
}
|
|
2114
|
+
compileInsertAst(ast, ctx) {
|
|
2115
|
+
return this.insertCompiler.compile(ast, ctx);
|
|
2047
2116
|
}
|
|
2048
2117
|
compileUpdateAst(ast, ctx) {
|
|
2049
|
-
|
|
2050
|
-
|
|
2051
|
-
|
|
2052
|
-
|
|
2053
|
-
|
|
2054
|
-
|
|
2118
|
+
return this.updateCompiler.compile(ast, ctx);
|
|
2119
|
+
}
|
|
2120
|
+
compileDeleteAst(ast, ctx) {
|
|
2121
|
+
return this.deleteCompiler.compile(ast, ctx);
|
|
2122
|
+
}
|
|
2123
|
+
compileUpsertClause(ast, _ctx) {
|
|
2124
|
+
void _ctx;
|
|
2125
|
+
if (!ast.onConflict) return "";
|
|
2126
|
+
throw new Error(`UPSERT/ON CONFLICT is not supported by dialect "${this.dialect}".`);
|
|
2127
|
+
}
|
|
2128
|
+
compileReturning(returning, ctx) {
|
|
2129
|
+
return this.returningStrategy.compileReturning(returning, ctx);
|
|
2130
|
+
}
|
|
2131
|
+
ensureConflictColumns(clause, message) {
|
|
2132
|
+
this.insertCompiler.ensureConflictColumns(clause, message);
|
|
2055
2133
|
}
|
|
2056
2134
|
compileUpdateAssignments(assignments, table, ctx) {
|
|
2057
|
-
return
|
|
2058
|
-
const col2 = assignment.column;
|
|
2059
|
-
const target = this.compileSetTarget(col2, table);
|
|
2060
|
-
const value = this.compileOperand(assignment.value, ctx);
|
|
2061
|
-
return `${target} = ${value}`;
|
|
2062
|
-
}).join(", ");
|
|
2135
|
+
return this.updateCompiler.compileAssignments(assignments, table, ctx);
|
|
2063
2136
|
}
|
|
2064
2137
|
compileSetTarget(column, table) {
|
|
2065
2138
|
return this.compileQualifiedColumn(column, table);
|
|
@@ -2069,132 +2142,38 @@ var SqlDialectBase = class extends Dialect {
|
|
|
2069
2142
|
const alias = table.alias;
|
|
2070
2143
|
const columnTable = column.table ?? alias ?? baseTableName;
|
|
2071
2144
|
const tableQualifier = alias && column.table === baseTableName ? alias : columnTable;
|
|
2072
|
-
if (!tableQualifier)
|
|
2073
|
-
return this.quoteIdentifier(column.name);
|
|
2074
|
-
}
|
|
2145
|
+
if (!tableQualifier) return this.quoteIdentifier(column.name);
|
|
2075
2146
|
return `${this.quoteIdentifier(tableQualifier)}.${this.quoteIdentifier(column.name)}`;
|
|
2076
2147
|
}
|
|
2077
|
-
compileDeleteAst(ast, ctx) {
|
|
2078
|
-
const target = this.compileTableReference(ast.from);
|
|
2079
|
-
const usingClause = this.compileDeleteUsingClause(ast, ctx);
|
|
2080
|
-
const whereClause = this.compileWhere(ast.where, ctx);
|
|
2081
|
-
const returning = this.compileReturning(ast.returning, ctx);
|
|
2082
|
-
return `DELETE FROM ${target}${usingClause}${whereClause}${returning}`;
|
|
2083
|
-
}
|
|
2084
2148
|
formatReturningColumns(returning) {
|
|
2085
|
-
return this.returningStrategy.formatReturningColumns(
|
|
2086
|
-
|
|
2087
|
-
|
|
2088
|
-
|
|
2089
|
-
}
|
|
2090
|
-
compileSelectColumns(ast, ctx) {
|
|
2091
|
-
if (!ast.columns || ast.columns.length === 0) {
|
|
2092
|
-
return "*";
|
|
2093
|
-
}
|
|
2094
|
-
return ast.columns.map((c) => {
|
|
2095
|
-
const expr = this.compileOperand(c, ctx);
|
|
2096
|
-
if (c.alias) {
|
|
2097
|
-
if (c.alias.includes("(")) return c.alias;
|
|
2098
|
-
return `${expr} AS ${this.quoteIdentifier(c.alias)}`;
|
|
2099
|
-
}
|
|
2100
|
-
return expr;
|
|
2101
|
-
}).join(", ");
|
|
2149
|
+
return this.returningStrategy.formatReturningColumns(
|
|
2150
|
+
returning,
|
|
2151
|
+
(id) => this.quoteIdentifier(id)
|
|
2152
|
+
);
|
|
2102
2153
|
}
|
|
2103
|
-
compileFrom(
|
|
2104
|
-
|
|
2105
|
-
if (tableSource.type === "FunctionTable") {
|
|
2106
|
-
return this.compileFunctionTable(tableSource, ctx);
|
|
2107
|
-
}
|
|
2108
|
-
if (tableSource.type === "DerivedTable") {
|
|
2109
|
-
return this.compileDerivedTable(tableSource, ctx);
|
|
2110
|
-
}
|
|
2111
|
-
return this.compileTableSource(tableSource);
|
|
2154
|
+
compileFrom(source, ctx) {
|
|
2155
|
+
return this.sourceCompiler.compileFrom(source, ctx);
|
|
2112
2156
|
}
|
|
2113
2157
|
compileFunctionTable(fn9, ctx) {
|
|
2114
|
-
|
|
2115
|
-
if (ctx) {
|
|
2116
|
-
const renderer = this.tableFunctionStrategy.getRenderer(key);
|
|
2117
|
-
if (renderer) {
|
|
2118
|
-
const compiledArgs = (fn9.args ?? []).map((arg) => this.compileOperand(arg, ctx));
|
|
2119
|
-
return renderer({
|
|
2120
|
-
node: fn9,
|
|
2121
|
-
compiledArgs,
|
|
2122
|
-
compileOperand: (operand) => this.compileOperand(operand, ctx),
|
|
2123
|
-
quoteIdentifier: this.quoteIdentifier.bind(this)
|
|
2124
|
-
});
|
|
2125
|
-
}
|
|
2126
|
-
if (fn9.key) {
|
|
2127
|
-
throw new Error(`Table function "${key}" is not supported by dialect "${this.dialect}".`);
|
|
2128
|
-
}
|
|
2129
|
-
}
|
|
2130
|
-
return FunctionTableFormatter.format(fn9, ctx, this);
|
|
2158
|
+
return this.sourceCompiler.compileFunctionTable(fn9, ctx);
|
|
2131
2159
|
}
|
|
2132
2160
|
compileDerivedTable(table, ctx) {
|
|
2133
|
-
|
|
2134
|
-
throw new Error("Derived tables must have an alias.");
|
|
2135
|
-
}
|
|
2136
|
-
const subquery = this.compileSelectAst(this.normalizeSelectAst(table.query), ctx).trim().replace(/;$/, "");
|
|
2137
|
-
const columns = table.columnAliases?.length ? ` (${table.columnAliases.map((c) => this.quoteIdentifier(c)).join(", ")})` : "";
|
|
2138
|
-
return `(${subquery}) AS ${this.quoteIdentifier(table.alias)}${columns}`;
|
|
2161
|
+
return this.sourceCompiler.compileDerivedTable(table, ctx);
|
|
2139
2162
|
}
|
|
2140
2163
|
compileTableSource(table) {
|
|
2141
|
-
|
|
2142
|
-
return this.compileFunctionTable(table);
|
|
2143
|
-
}
|
|
2144
|
-
if (table.type === "DerivedTable") {
|
|
2145
|
-
return this.compileDerivedTable(table);
|
|
2146
|
-
}
|
|
2147
|
-
const base = this.compileTableName(table);
|
|
2148
|
-
return table.alias ? `${base} AS ${this.quoteIdentifier(table.alias)}` : base;
|
|
2164
|
+
return this.sourceCompiler.compileTableSource(table);
|
|
2149
2165
|
}
|
|
2150
2166
|
compileTableName(table) {
|
|
2151
|
-
|
|
2152
|
-
return `${this.quoteIdentifier(table.schema)}.${this.quoteIdentifier(table.name)}`;
|
|
2153
|
-
}
|
|
2154
|
-
return this.quoteIdentifier(table.name);
|
|
2167
|
+
return this.sourceCompiler.compileTableName(table);
|
|
2155
2168
|
}
|
|
2156
2169
|
compileTableReference(table) {
|
|
2157
|
-
|
|
2158
|
-
return table.alias ? `${base} AS ${this.quoteIdentifier(table.alias)}` : base;
|
|
2159
|
-
}
|
|
2160
|
-
compileUpdateFromClause(ast, ctx) {
|
|
2161
|
-
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
|
-
}
|
|
2165
|
-
const from = this.compileFrom(ast.from, ctx);
|
|
2166
|
-
const joins = JoinCompiler.compileJoins(
|
|
2167
|
-
ast.joins,
|
|
2168
|
-
ctx,
|
|
2169
|
-
this.compileFrom.bind(this),
|
|
2170
|
-
this.compileExpression.bind(this)
|
|
2171
|
-
);
|
|
2172
|
-
return ` FROM ${from}${joins}`;
|
|
2173
|
-
}
|
|
2174
|
-
compileDeleteUsingClause(ast, ctx) {
|
|
2175
|
-
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
|
-
}
|
|
2179
|
-
const usingTable = this.compileFrom(ast.using, ctx);
|
|
2180
|
-
const joins = JoinCompiler.compileJoins(
|
|
2181
|
-
ast.joins,
|
|
2182
|
-
ctx,
|
|
2183
|
-
this.compileFrom.bind(this),
|
|
2184
|
-
this.compileExpression.bind(this)
|
|
2185
|
-
);
|
|
2186
|
-
return ` USING ${usingTable}${joins}`;
|
|
2187
|
-
}
|
|
2188
|
-
compileHaving(ast, ctx) {
|
|
2189
|
-
if (!ast.having) return "";
|
|
2190
|
-
return ` HAVING ${this.compileExpression(ast.having, ctx)}`;
|
|
2170
|
+
return this.sourceCompiler.compileTableReference(table);
|
|
2191
2171
|
}
|
|
2192
2172
|
stripTrailingSemicolon(sql) {
|
|
2193
|
-
return
|
|
2173
|
+
return this.sourceCompiler.stripTrailingSemicolon(sql);
|
|
2194
2174
|
}
|
|
2195
2175
|
wrapSetOperand(sql) {
|
|
2196
|
-
|
|
2197
|
-
return `(${trimmed})`;
|
|
2176
|
+
return this.sourceCompiler.wrapSetOperand(sql);
|
|
2198
2177
|
}
|
|
2199
2178
|
renderOrderByNulls(order) {
|
|
2200
2179
|
return order.nulls ? ` NULLS ${order.nulls}` : "";
|
|
@@ -2903,10 +2882,6 @@ var SqliteDialect = class extends SqlDialectBase {
|
|
|
2903
2882
|
supportsDmlReturningClause() {
|
|
2904
2883
|
return true;
|
|
2905
2884
|
}
|
|
2906
|
-
compileProcedureCall(_ast) {
|
|
2907
|
-
void _ast;
|
|
2908
|
-
throw new Error("Stored procedures are not supported by the SQLite dialect.");
|
|
2909
|
-
}
|
|
2910
2885
|
};
|
|
2911
2886
|
|
|
2912
2887
|
// src/core/dialect/mssql/functions.ts
|
|
@@ -3341,9 +3316,8 @@ var DialectFactory = class {
|
|
|
3341
3316
|
/**
|
|
3342
3317
|
* Register (or override) a dialect factory for a key.
|
|
3343
3318
|
*
|
|
3344
|
-
*
|
|
3345
|
-
*
|
|
3346
|
-
* DialectFactory.register('my-tenant-dialect', () => new CustomDialect());
|
|
3319
|
+
* Implementations are structural: extending DialectBase/SqlDialectBase is
|
|
3320
|
+
* optional. A composed object satisfying Dialect is a valid registration.
|
|
3347
3321
|
*/
|
|
3348
3322
|
static register(key, factory) {
|
|
3349
3323
|
this.registry.set(key, factory);
|
|
@@ -10916,6 +10890,15 @@ var DeleteQueryBuilder = class _DeleteQueryBuilder {
|
|
|
10916
10890
|
};
|
|
10917
10891
|
var isTableSourceNode2 = (source) => typeof source.type === "string";
|
|
10918
10892
|
|
|
10893
|
+
// src/core/dialect/capabilities/procedure-compiler.ts
|
|
10894
|
+
var isProcedureCompiler = (value) => typeof value?.compileProcedureCall === "function";
|
|
10895
|
+
var requireProcedureCompiler = (value) => {
|
|
10896
|
+
if (!isProcedureCompiler(value)) {
|
|
10897
|
+
throw new Error("Stored procedures are not supported by this dialect.");
|
|
10898
|
+
}
|
|
10899
|
+
return value;
|
|
10900
|
+
};
|
|
10901
|
+
|
|
10919
10902
|
// src/orm/execute-procedure.ts
|
|
10920
10903
|
var resolveColumnIndex = (columns, expectedName) => {
|
|
10921
10904
|
const exact = columns.findIndex((column) => column === expectedName);
|
|
@@ -10954,7 +10937,7 @@ var extractOutValues = (compiled, resultSets) => {
|
|
|
10954
10937
|
};
|
|
10955
10938
|
var executeProcedureAst = async (session, ast) => {
|
|
10956
10939
|
const execCtx = session.getExecutionContext();
|
|
10957
|
-
const compiled = execCtx.dialect.compileProcedureCall(ast);
|
|
10940
|
+
const compiled = requireProcedureCompiler(execCtx.dialect).compileProcedureCall(ast);
|
|
10958
10941
|
const payload = await execCtx.interceptors.run(
|
|
10959
10942
|
{ sql: compiled.sql, params: compiled.params },
|
|
10960
10943
|
execCtx.executor
|
|
@@ -11027,8 +11010,7 @@ var ProcedureCallBuilder = class _ProcedureCallBuilder {
|
|
|
11027
11010
|
}
|
|
11028
11011
|
compile(dialect) {
|
|
11029
11012
|
const resolved = resolveDialectInput(dialect);
|
|
11030
|
-
this.
|
|
11031
|
-
return resolved.compileProcedureCall(this.getAST());
|
|
11013
|
+
return requireProcedureCompiler(resolved).compileProcedureCall(this.getAST());
|
|
11032
11014
|
}
|
|
11033
11015
|
toSql(dialect) {
|
|
11034
11016
|
return this.compile(dialect).sql;
|
|
@@ -11041,21 +11023,8 @@ var ProcedureCallBuilder = class _ProcedureCallBuilder {
|
|
|
11041
11023
|
};
|
|
11042
11024
|
}
|
|
11043
11025
|
async execute(session) {
|
|
11044
|
-
this.validateMssqlOutDbType(session.getExecutionContext().dialect);
|
|
11045
11026
|
return executeProcedureAst(session, this.getAST());
|
|
11046
11027
|
}
|
|
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
11028
|
};
|
|
11060
11029
|
var callProcedure = (name, options) => new ProcedureCallBuilder(name, options);
|
|
11061
11030
|
|
|
@@ -21783,6 +21752,8 @@ export {
|
|
|
21783
21752
|
DefaultMorphToReference,
|
|
21784
21753
|
DefaultTypeStrategy,
|
|
21785
21754
|
DeleteQueryBuilder,
|
|
21755
|
+
DialectBase,
|
|
21756
|
+
DialectFactory,
|
|
21786
21757
|
DomainEventBus,
|
|
21787
21758
|
Email,
|
|
21788
21759
|
Entity,
|
|
@@ -21816,6 +21787,11 @@ export {
|
|
|
21816
21787
|
SelectQueryBuilder,
|
|
21817
21788
|
SqlServerDialect,
|
|
21818
21789
|
SqliteDialect,
|
|
21790
|
+
StandardDeleteCompiler,
|
|
21791
|
+
StandardInsertCompiler,
|
|
21792
|
+
StandardSelectCompiler,
|
|
21793
|
+
StandardSqlSourceCompiler,
|
|
21794
|
+
StandardUpdateCompiler,
|
|
21819
21795
|
StringTypeStrategy,
|
|
21820
21796
|
TagIndex,
|
|
21821
21797
|
Title,
|
|
@@ -22010,6 +21986,7 @@ export {
|
|
|
22010
21986
|
isNull,
|
|
22011
21987
|
isNullableColumn,
|
|
22012
21988
|
isOperandNode,
|
|
21989
|
+
isProcedureCompiler,
|
|
22013
21990
|
isSingleTargetRelation,
|
|
22014
21991
|
isTableDef2 as isTableDef,
|
|
22015
21992
|
isTreeConfig,
|
|
@@ -22107,6 +22084,8 @@ export {
|
|
|
22107
22084
|
repeat,
|
|
22108
22085
|
replace,
|
|
22109
22086
|
replaceWithRefs,
|
|
22087
|
+
requireProcedureCompiler,
|
|
22088
|
+
resolveDialectInput,
|
|
22110
22089
|
resolveTreeConfig,
|
|
22111
22090
|
resolveValidator,
|
|
22112
22091
|
responseToRef,
|