metal-orm 1.1.24 → 1.1.26

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.
Files changed (35) hide show
  1. package/dist/index.cjs +770 -710
  2. package/dist/index.cjs.map +1 -1
  3. package/dist/index.d.cts +294 -318
  4. package/dist/index.d.ts +294 -318
  5. package/dist/index.js +745 -709
  6. package/dist/index.js.map +1 -1
  7. package/package.json +1 -1
  8. package/src/core/dialect/abstract.ts +7 -229
  9. package/src/core/dialect/base/returning-strategy.ts +40 -39
  10. package/src/core/dialect/base/sql-compiler-set.ts +33 -0
  11. package/src/core/dialect/base/sql-dialect-composer.ts +294 -0
  12. package/src/core/dialect/base/standard-sql-services.ts +2 -6
  13. package/src/core/dialect/base/upsert-strategy.ts +44 -0
  14. package/src/core/dialect/capabilities/procedure-compiler.ts +10 -8
  15. package/src/core/dialect/dialect-factory.ts +17 -49
  16. package/src/core/dialect/mssql/compiler-factory.ts +12 -0
  17. package/src/core/dialect/mssql/delete-compiler.ts +40 -0
  18. package/src/core/dialect/mssql/index.ts +52 -370
  19. package/src/core/dialect/mssql/insert-compiler.ts +112 -0
  20. package/src/core/dialect/mssql/output.ts +46 -0
  21. package/src/core/dialect/mssql/procedure-compiler.ts +81 -0
  22. package/src/core/dialect/mssql/select-compiler.ts +116 -0
  23. package/src/core/dialect/mssql/update-compiler.ts +37 -0
  24. package/src/core/dialect/mysql/index.ts +66 -126
  25. package/src/core/dialect/mysql/procedure-compiler.ts +67 -0
  26. package/src/core/dialect/mysql/upsert.ts +42 -0
  27. package/src/core/dialect/postgres/index.ts +75 -114
  28. package/src/core/dialect/postgres/procedure-compiler.ts +41 -0
  29. package/src/core/dialect/postgres/returning.ts +4 -0
  30. package/src/core/dialect/postgres/upsert.ts +43 -0
  31. package/src/core/dialect/sqlite/index.ts +65 -90
  32. package/src/core/dialect/sqlite/returning.ts +30 -0
  33. package/src/core/dialect/sqlite/upsert.ts +43 -0
  34. package/src/index.ts +22 -10
  35. package/src/core/dialect/base/sql-dialect.ts +0 -176
package/dist/index.js CHANGED
@@ -1533,159 +1533,6 @@ var SelectAstNormalizer = class {
1533
1533
  }
1534
1534
  };
1535
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
- }
1649
- compileJsonPath(_node) {
1650
- void _node;
1651
- throw new Error("JSON Path not supported by this dialect");
1652
- }
1653
- compileFunctionOperand(fnNode, ctx) {
1654
- const compiledArgs = fnNode.args.map((arg) => this.compileOperand(arg, ctx));
1655
- const renderer = this.functionStrategy.getRenderer(fnNode.name);
1656
- if (renderer) {
1657
- return renderer({
1658
- node: fnNode,
1659
- compiledArgs,
1660
- compileOperand: (operand) => this.compileOperand(operand, ctx)
1661
- });
1662
- }
1663
- return `${fnNode.name}(${compiledArgs.join(", ")})`;
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
- }
1687
- };
1688
-
1689
1536
  // src/core/dialect/base/pagination-strategy.ts
1690
1537
  var StandardLimitOffsetPagination = class {
1691
1538
  /**
@@ -1704,31 +1551,38 @@ var StandardLimitOffsetPagination = class {
1704
1551
 
1705
1552
  // src/core/dialect/base/returning-strategy.ts
1706
1553
  var NoReturningStrategy = class {
1707
- /**
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.
1712
- */
1713
- compileReturning(returning, _ctx) {
1554
+ compileReturning(returning, _ctx, _quoteIdentifier) {
1714
1555
  void _ctx;
1556
+ void _quoteIdentifier;
1715
1557
  if (!returning || returning.length === 0) return "";
1716
1558
  throw new Error("RETURNING is not supported by this dialect.");
1717
1559
  }
1718
- /**
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.
1723
- */
1724
- formatReturningColumns(returning, quoteIdentifier) {
1560
+ formatReturningColumns(returning, quoteIdentifier5) {
1725
1561
  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}`;
1562
+ const tablePart = column.table ? `${quoteIdentifier5(column.table)}.` : "";
1563
+ const aliasPart = column.alias ? ` AS ${quoteIdentifier5(column.alias)}` : "";
1564
+ return `${tablePart}${quoteIdentifier5(column.name)}${aliasPart}`;
1729
1565
  }).join(", ");
1730
1566
  }
1731
1567
  };
1568
+ var StandardReturningStrategy = class extends NoReturningStrategy {
1569
+ compileReturning(returning, _ctx, quoteIdentifier5) {
1570
+ void _ctx;
1571
+ if (!returning || returning.length === 0) return "";
1572
+ return ` RETURNING ${this.formatReturningColumns(returning, quoteIdentifier5)}`;
1573
+ }
1574
+ };
1575
+
1576
+ // src/core/dialect/base/upsert-strategy.ts
1577
+ var NoUpsertStrategy = class {
1578
+ compile(ast, _ctx, services) {
1579
+ void _ctx;
1580
+ if (!ast.onConflict) return "";
1581
+ throw new Error(
1582
+ `UPSERT/ON CONFLICT is not supported by dialect "${services.getDialectName()}".`
1583
+ );
1584
+ }
1585
+ };
1732
1586
 
1733
1587
  // src/core/dialect/base/function-table-formatter.ts
1734
1588
  var FunctionTableFormatter = class {
@@ -1846,13 +1700,13 @@ var CteCompiler = class {
1846
1700
  * @param stripTrailingSemicolon - Function to remove trailing semicolons from SQL.
1847
1701
  * @returns SQL WITH clause string (e.g., "WITH cte_name AS (...) ") or empty string if no CTEs.
1848
1702
  */
1849
- static compileCtes(ast, ctx, quoteIdentifier, compileSelectAst, normalizeSelectAst, stripTrailingSemicolon) {
1703
+ static compileCtes(ast, ctx, quoteIdentifier5, compileSelectAst, normalizeSelectAst, stripTrailingSemicolon) {
1850
1704
  if (!ast.ctes || ast.ctes.length === 0) return "";
1851
1705
  const hasRecursive = ast.ctes.some((cte) => cte.recursive);
1852
1706
  const prefix = hasRecursive ? "WITH RECURSIVE " : "WITH ";
1853
1707
  const cteDefs = ast.ctes.map((cte) => {
1854
- const name = quoteIdentifier(cte.name);
1855
- const cols = cte.columns && cte.columns.length ? `(${cte.columns.map((c) => quoteIdentifier(c)).join(", ")})` : "";
1708
+ const name = quoteIdentifier5(cte.name);
1709
+ const cols = cte.columns && cte.columns.length ? `(${cte.columns.map((c) => quoteIdentifier5(c)).join(", ")})` : "";
1856
1710
  const query = stripTrailingSemicolon(compileSelectAst(normalizeSelectAst(cte.query), ctx));
1857
1711
  return `${name}${cols} AS (${query})`;
1858
1712
  }).join(", ");
@@ -2075,113 +1929,174 @@ var StandardDeleteCompiler = class {
2075
1929
  }
2076
1930
  };
2077
1931
 
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)
1932
+ // src/core/dialect/base/sql-dialect-composer.ts
1933
+ var terminate = (sql) => {
1934
+ const trimmed = sql.trim();
1935
+ return trimmed.endsWith(";") ? trimmed : `${trimmed};`;
1936
+ };
1937
+ var composeSqlDialect = (config) => {
1938
+ const functionStrategy = config.functionStrategy ?? new StandardFunctionStrategy();
1939
+ const tableFunctionStrategy = config.tableFunctionStrategy ?? new StandardTableFunctionStrategy();
1940
+ const paginationStrategy = config.paginationStrategy ?? new StandardLimitOffsetPagination();
1941
+ const returningStrategy = config.returningStrategy ?? new NoReturningStrategy();
1942
+ const upsertStrategy = config.upsertStrategy ?? new NoUpsertStrategy();
1943
+ const selectAstNormalizer = new SelectAstNormalizer(
1944
+ (kind) => config.supportsSetOperation?.(kind) ?? true
1945
+ );
1946
+ let compilerSet;
1947
+ let expressionRegistry2;
1948
+ const createCompilerContext = () => {
1949
+ const params = [];
1950
+ let counter = 0;
1951
+ return {
1952
+ params,
1953
+ addParameter(value) {
1954
+ counter += 1;
1955
+ params.push(value);
1956
+ return config.formatPlaceholder?.(counter) ?? "?";
1957
+ }
2104
1958
  };
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);
2116
- }
2117
- compileUpdateAst(ast, ctx) {
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);
2133
- }
2134
- compileUpdateAssignments(assignments, table, ctx) {
2135
- return this.updateCompiler.compileAssignments(assignments, table, ctx);
2136
- }
2137
- compileSetTarget(column, table) {
2138
- return this.compileQualifiedColumn(column, table);
2139
- }
2140
- compileQualifiedColumn(column, table) {
2141
- const baseTableName = table.name;
2142
- const alias = table.alias;
2143
- const columnTable = column.table ?? alias ?? baseTableName;
2144
- const tableQualifier = alias && column.table === baseTableName ? alias : columnTable;
2145
- if (!tableQualifier) return this.quoteIdentifier(column.name);
2146
- return `${this.quoteIdentifier(tableQualifier)}.${this.quoteIdentifier(column.name)}`;
2147
- }
2148
- formatReturningColumns(returning) {
2149
- return this.returningStrategy.formatReturningColumns(
2150
- returning,
2151
- (id) => this.quoteIdentifier(id)
2152
- );
2153
- }
2154
- compileFrom(source, ctx) {
2155
- return this.sourceCompiler.compileFrom(source, ctx);
2156
- }
2157
- compileFunctionTable(fn9, ctx) {
2158
- return this.sourceCompiler.compileFunctionTable(fn9, ctx);
2159
- }
2160
- compileDerivedTable(table, ctx) {
2161
- return this.sourceCompiler.compileDerivedTable(table, ctx);
2162
- }
2163
- compileTableSource(table) {
2164
- return this.sourceCompiler.compileTableSource(table);
2165
- }
2166
- compileTableName(table) {
2167
- return this.sourceCompiler.compileTableName(table);
2168
- }
2169
- compileTableReference(table) {
2170
- return this.sourceCompiler.compileTableReference(table);
2171
- }
2172
- stripTrailingSemicolon(sql) {
2173
- return this.sourceCompiler.stripTrailingSemicolon(sql);
2174
- }
2175
- wrapSetOperand(sql) {
2176
- return this.sourceCompiler.wrapSetOperand(sql);
2177
- }
2178
- renderOrderByNulls(order) {
2179
- return order.nulls ? ` NULLS ${order.nulls}` : "";
2180
- }
2181
- renderOrderByCollation(order) {
2182
- return order.collation ? ` COLLATE ${order.collation}` : "";
2183
- }
1959
+ };
1960
+ const compileSelectAst = (ast, ctx) => compilerSet.select.compile(ast, ctx);
1961
+ const normalizeSelectAst = (ast) => selectAstNormalizer.normalize(ast);
1962
+ const compileSelectForExists = (ast, ctx) => {
1963
+ const normalized = normalizeSelectAst(ast);
1964
+ const full = compileSelectAst(normalized, ctx).trim().replace(/;$/, "");
1965
+ if (normalized.setOps && normalized.setOps.length > 0) {
1966
+ return `SELECT 1 FROM (${full}) AS _exists`;
1967
+ }
1968
+ const fromIndex = full.toUpperCase().indexOf(" FROM ");
1969
+ return fromIndex === -1 ? full : `SELECT 1${full.slice(fromIndex)}`;
1970
+ };
1971
+ const compileJsonPath = (node) => {
1972
+ if (!config.compileJsonPath) {
1973
+ throw new Error(`JSON Path not supported by dialect "${config.name}".`);
1974
+ }
1975
+ return config.compileJsonPath(node);
1976
+ };
1977
+ const compileFunctionOperand = (node, ctx) => {
1978
+ const compiledArgs = node.args.map((arg) => expressionRegistry2.compileOperand(arg, ctx));
1979
+ const renderer = functionStrategy.getRenderer(node.name);
1980
+ if (renderer) {
1981
+ return renderer({
1982
+ node,
1983
+ compiledArgs,
1984
+ compileOperand: (operand) => expressionRegistry2.compileOperand(operand, ctx)
1985
+ });
1986
+ }
1987
+ return `${node.name}(${compiledArgs.join(", ")})`;
1988
+ };
1989
+ expressionRegistry2 = new ExpressionCompilerRegistry({
1990
+ quoteIdentifier: config.quoteIdentifier,
1991
+ compileSelectAst,
1992
+ compileSelectForExists,
1993
+ compileJsonPath,
1994
+ compileFunctionOperand,
1995
+ describe: () => config.describe ?? config.name
1996
+ });
1997
+ const compileSetTarget = (column, table) => {
1998
+ if (config.compileSetTarget) return config.compileSetTarget(column, table);
1999
+ const columnTable = column.table ?? table.alias ?? table.name;
2000
+ const tableQualifier = table.alias && column.table === table.name ? table.alias : columnTable;
2001
+ return tableQualifier ? `${config.quoteIdentifier(tableQualifier)}.${config.quoteIdentifier(column.name)}` : config.quoteIdentifier(column.name);
2002
+ };
2003
+ let standardUpdate;
2004
+ const services = {
2005
+ getDialectName: () => config.name,
2006
+ getPaginationStrategy: () => paginationStrategy,
2007
+ getTableFunctionStrategy: () => tableFunctionStrategy,
2008
+ quoteIdentifier: config.quoteIdentifier,
2009
+ compileOperand: (node, ctx) => expressionRegistry2.compileOperand(node, ctx),
2010
+ compileExpression: (node, ctx) => expressionRegistry2.compileExpression(node, ctx),
2011
+ compileOrderingTerm: (term, ctx) => expressionRegistry2.compileOrderingTerm(term, ctx),
2012
+ normalizeSelectAst,
2013
+ compileSelectAst,
2014
+ compileReturning: (returning, ctx) => returningStrategy.compileReturning(returning, ctx, config.quoteIdentifier),
2015
+ compileUpsertClause: (ast, ctx) => upsertStrategy.compile(ast, ctx, {
2016
+ getDialectName: () => config.name,
2017
+ quoteIdentifier: config.quoteIdentifier,
2018
+ compileOperand: (node, compilerContext) => expressionRegistry2.compileOperand(node, compilerContext),
2019
+ compileExpression: (node, compilerContext) => expressionRegistry2.compileExpression(node, compilerContext),
2020
+ compileUpdateAssignments: (assignments, table, compilerContext) => standardUpdate.compileAssignments(assignments, table, compilerContext)
2021
+ }),
2022
+ compileSetTarget,
2023
+ renderOrderByNulls: (order) => config.renderOrderByNulls?.(order) ?? (order.nulls ? ` NULLS ${order.nulls}` : ""),
2024
+ renderOrderByCollation: (order) => config.renderOrderByCollation?.(order) ?? (order.collation ? ` COLLATE ${order.collation}` : "")
2025
+ };
2026
+ const sources = new StandardSqlSourceCompiler(services);
2027
+ const standardSelect = new StandardSelectCompiler(services, sources);
2028
+ const standardInsert = new StandardInsertCompiler(services, sources);
2029
+ standardUpdate = new StandardUpdateCompiler(services, sources);
2030
+ const standardDelete = new StandardDeleteCompiler(services, sources);
2031
+ const overrides = config.compilerFactory?.({ services, sources }) ?? {};
2032
+ compilerSet = {
2033
+ select: overrides.select ?? standardSelect,
2034
+ insert: overrides.insert ?? standardInsert,
2035
+ update: overrides.update ?? standardUpdate,
2036
+ delete: overrides.delete ?? standardDelete
2037
+ };
2038
+ const expressionApi = {
2039
+ registerExpressionCompiler(type, compiler) {
2040
+ expressionRegistry2.registerExpressionCompiler(type, compiler);
2041
+ },
2042
+ registerOperandCompiler(type, compiler) {
2043
+ expressionRegistry2.registerOperandCompiler(type, compiler);
2044
+ },
2045
+ compileExpression(node, ctx) {
2046
+ return expressionRegistry2.compileExpression(node, ctx);
2047
+ },
2048
+ compileOperand(node, ctx) {
2049
+ return expressionRegistry2.compileOperand(node, ctx);
2050
+ },
2051
+ compileOrderingTerm(term, ctx) {
2052
+ return expressionRegistry2.compileOrderingTerm(term, ctx);
2053
+ }
2054
+ };
2055
+ config.configureExpressions?.(expressionApi);
2056
+ const dialect = {
2057
+ quoteIdentifier: config.quoteIdentifier,
2058
+ supportsDmlReturningClause: () => config.supportsDmlReturning ?? false,
2059
+ compileSelect(ast) {
2060
+ const ctx = createCompilerContext();
2061
+ return {
2062
+ sql: terminate(compileSelectAst(normalizeSelectAst(ast), ctx)),
2063
+ params: [...ctx.params]
2064
+ };
2065
+ },
2066
+ compileInsert(ast) {
2067
+ const ctx = createCompilerContext();
2068
+ return {
2069
+ sql: terminate(compilerSet.insert.compile(ast, ctx)),
2070
+ params: [...ctx.params]
2071
+ };
2072
+ },
2073
+ compileUpdate(ast) {
2074
+ const ctx = createCompilerContext();
2075
+ return {
2076
+ sql: terminate(compilerSet.update.compile(ast, ctx)),
2077
+ params: [...ctx.params]
2078
+ };
2079
+ },
2080
+ compileDelete(ast) {
2081
+ const ctx = createCompilerContext();
2082
+ return {
2083
+ sql: terminate(compilerSet.delete.compile(ast, ctx)),
2084
+ params: [...ctx.params]
2085
+ };
2086
+ }
2087
+ };
2088
+ const runtime = {
2089
+ quoteIdentifier: config.quoteIdentifier,
2090
+ createCompilerContext,
2091
+ compileOperand: (node, ctx) => expressionRegistry2.compileOperand(node, ctx),
2092
+ compileExpression: (node, ctx) => expressionRegistry2.compileExpression(node, ctx),
2093
+ compileOrderingTerm: (term, ctx) => expressionRegistry2.compileOrderingTerm(term, ctx),
2094
+ normalizeSelectAst,
2095
+ compileSelectAst
2096
+ };
2097
+ return { dialect, runtime };
2184
2098
  };
2099
+ var createSqlDialect = (config) => composeSqlDialect(config).dialect;
2185
2100
 
2186
2101
  // src/core/dialect/postgres/functions.ts
2187
2102
  var PostgresFunctionStrategy = class extends StandardFunctionStrategy {
@@ -2344,106 +2259,41 @@ var PostgresTableFunctionStrategy = class extends StandardTableFunctionStrategy
2344
2259
  this.registerOverrides();
2345
2260
  }
2346
2261
  registerOverrides() {
2347
- this.add("ARRAY_UNNEST", ({ node, compiledArgs, quoteIdentifier }) => {
2262
+ this.add("ARRAY_UNNEST", ({ node, compiledArgs, quoteIdentifier: quoteIdentifier5 }) => {
2348
2263
  const lateral = node.lateral ?? true;
2349
2264
  const withOrd = node.withOrdinality ?? false;
2350
2265
  const base = `unnest(${compiledArgs.join(", ")})${withOrd ? " WITH ORDINALITY" : ""}`;
2351
2266
  if (node.columnAliases?.length && !node.alias) {
2352
2267
  throw new Error("tvf(ARRAY_UNNEST) with columnAliases requires an alias.");
2353
2268
  }
2354
- const alias = node.alias ? ` AS ${quoteIdentifier(node.alias)}` : "";
2355
- const cols = node.columnAliases?.length ? `(${node.columnAliases.map(quoteIdentifier).join(", ")})` : "";
2269
+ const alias = node.alias ? ` AS ${quoteIdentifier5(node.alias)}` : "";
2270
+ const cols = node.columnAliases?.length ? `(${node.columnAliases.map(quoteIdentifier5).join(", ")})` : "";
2356
2271
  return `${lateral ? "LATERAL " : ""}${base}${alias}${cols}`;
2357
2272
  });
2358
2273
  }
2359
2274
  };
2360
2275
 
2361
- // src/core/dialect/postgres/index.ts
2362
- var PostgresDialect = class extends SqlDialectBase {
2363
- dialect = "postgres";
2364
- /**
2365
- * Creates a new PostgresDialect instance
2366
- */
2367
- constructor() {
2368
- super(new PostgresFunctionStrategy(), new PostgresTableFunctionStrategy());
2369
- this.registerExpressionCompiler("BitwiseExpression", (node, ctx) => {
2370
- const left2 = this.compileOperand(node.left, ctx);
2371
- const right2 = this.compileOperand(node.right, ctx);
2372
- const op = node.operator === "^" ? "#" : node.operator;
2373
- return `${left2} ${op} ${right2}`;
2374
- });
2375
- this.registerOperandCompiler("BitwiseExpression", (node, ctx) => {
2376
- const left2 = this.compileOperand(node.left, ctx);
2377
- const right2 = this.compileOperand(node.right, ctx);
2378
- const op = node.operator === "^" ? "#" : node.operator;
2379
- return `(${left2} ${op} ${right2})`;
2380
- });
2381
- }
2382
- /**
2383
- * Quotes an identifier using PostgreSQL double-quote syntax
2384
- * @param id - Identifier to quote
2385
- * @returns Quoted identifier
2386
- */
2387
- quoteIdentifier(id) {
2388
- return `"${id}"`;
2389
- }
2390
- formatPlaceholder(index) {
2391
- return `$${index}`;
2392
- }
2393
- /**
2394
- * Compiles JSON path expression using PostgreSQL syntax
2395
- * @param node - JSON path node
2396
- * @returns PostgreSQL JSON path expression
2397
- */
2398
- compileJsonPath(node) {
2399
- const col2 = `${this.quoteIdentifier(node.column.table)}.${this.quoteIdentifier(node.column.name)}`;
2400
- return `${col2}->>'${node.path}'`;
2401
- }
2402
- compileReturning(returning, ctx) {
2403
- void ctx;
2404
- if (!returning || returning.length === 0) return "";
2405
- const columns = this.formatReturningColumns(returning);
2406
- return ` RETURNING ${columns}`;
2407
- }
2408
- compileUpsertClause(ast, ctx) {
2409
- if (!ast.onConflict) return "";
2410
- const clause = ast.onConflict;
2411
- const target = clause.target.constraint ? ` ON CONFLICT ON CONSTRAINT ${this.quoteIdentifier(clause.target.constraint)}` : (() => {
2412
- this.ensureConflictColumns(
2413
- clause,
2414
- "PostgreSQL ON CONFLICT requires conflict columns or a constraint name."
2415
- );
2416
- const cols = clause.target.columns.map((col2) => this.quoteIdentifier(col2.name)).join(", ");
2417
- return ` ON CONFLICT (${cols})`;
2418
- })();
2419
- if (clause.action.type === "DoNothing") {
2420
- return `${target} DO NOTHING`;
2421
- }
2422
- if (!clause.action.set.length) {
2423
- throw new Error("PostgreSQL ON CONFLICT DO UPDATE requires at least one assignment.");
2424
- }
2425
- const assignments = this.compileUpdateAssignments(clause.action.set, ast.into, ctx);
2426
- const where = clause.action.where ? ` WHERE ${this.compileExpression(clause.action.where, ctx)}` : "";
2427
- return `${target} DO UPDATE SET ${assignments}${where}`;
2428
- }
2429
- supportsDmlReturningClause() {
2430
- return true;
2276
+ // src/core/dialect/postgres/procedure-compiler.ts
2277
+ var PostgresProcedureCompiler = class {
2278
+ constructor(services) {
2279
+ this.services = services;
2431
2280
  }
2432
2281
  compileProcedureCall(ast) {
2433
- const ctx = this.createCompilerContext();
2434
- const qualifiedName = ast.ref.schema ? `${this.quoteIdentifier(ast.ref.schema)}.${this.quoteIdentifier(ast.ref.name)}` : this.quoteIdentifier(ast.ref.name);
2282
+ const ctx = this.services.createCompilerContext();
2283
+ const qualifiedName = ast.ref.schema ? `${this.services.quoteIdentifier(ast.ref.schema)}.${this.services.quoteIdentifier(ast.ref.name)}` : this.services.quoteIdentifier(ast.ref.name);
2435
2284
  const args = [];
2436
2285
  for (const param of ast.params) {
2437
2286
  if (param.direction === "out") continue;
2438
2287
  if (!param.value) {
2439
- throw new Error(`Procedure parameter "${param.name}" requires a value for direction "${param.direction}".`);
2288
+ throw new Error(
2289
+ `Procedure parameter "${param.name}" requires a value for direction "${param.direction}".`
2290
+ );
2440
2291
  }
2441
- args.push(this.compileOperand(param.value, ctx));
2292
+ args.push(this.services.compileOperand(param.value, ctx));
2442
2293
  }
2443
2294
  const outNames = ast.params.filter((param) => param.direction === "out" || param.direction === "inout").map((param) => param.name);
2444
- const rawSql = `CALL ${qualifiedName}(${args.join(", ")})`;
2445
2295
  return {
2446
- sql: `${rawSql};`,
2296
+ sql: `CALL ${qualifiedName}(${args.join(", ")});`,
2447
2297
  params: [...ctx.params],
2448
2298
  outParams: {
2449
2299
  source: outNames.length ? "firstResultSet" : "none",
@@ -2451,11 +2301,99 @@ var PostgresDialect = class extends SqlDialectBase {
2451
2301
  }
2452
2302
  };
2453
2303
  }
2454
- /**
2455
- * PostgreSQL requires unqualified column names in SET clause
2456
- */
2457
- compileSetTarget(column, _table) {
2458
- return this.quoteIdentifier(column.name);
2304
+ };
2305
+
2306
+ // src/core/dialect/postgres/returning.ts
2307
+ var PostgresReturningStrategy = class extends StandardReturningStrategy {
2308
+ };
2309
+
2310
+ // src/core/dialect/postgres/upsert.ts
2311
+ var PostgresUpsertStrategy = class {
2312
+ compile(ast, ctx, services) {
2313
+ if (!ast.onConflict) return "";
2314
+ const clause = ast.onConflict;
2315
+ const target = clause.target.constraint ? ` ON CONFLICT ON CONSTRAINT ${services.quoteIdentifier(clause.target.constraint)}` : (() => {
2316
+ if (!clause.target.columns.length) {
2317
+ throw new Error("PostgreSQL ON CONFLICT requires conflict columns or a constraint name.");
2318
+ }
2319
+ const columns = clause.target.columns.map((column) => services.quoteIdentifier(column.name)).join(", ");
2320
+ return ` ON CONFLICT (${columns})`;
2321
+ })();
2322
+ if (clause.action.type === "DoNothing") {
2323
+ return `${target} DO NOTHING`;
2324
+ }
2325
+ if (!clause.action.set.length) {
2326
+ throw new Error("PostgreSQL ON CONFLICT DO UPDATE requires at least one assignment.");
2327
+ }
2328
+ const assignments = services.compileUpdateAssignments(clause.action.set, ast.into, ctx);
2329
+ const where = clause.action.where ? ` WHERE ${services.compileExpression(clause.action.where, ctx)}` : "";
2330
+ return `${target} DO UPDATE SET ${assignments}${where}`;
2331
+ }
2332
+ };
2333
+
2334
+ // src/core/dialect/postgres/index.ts
2335
+ var quoteIdentifier = (id) => `"${id}"`;
2336
+ var createPostgresDialect = () => {
2337
+ const composition = composeSqlDialect({
2338
+ name: "postgres",
2339
+ quoteIdentifier,
2340
+ formatPlaceholder: (index) => `$${index}`,
2341
+ functionStrategy: new PostgresFunctionStrategy(),
2342
+ tableFunctionStrategy: new PostgresTableFunctionStrategy(),
2343
+ returningStrategy: new PostgresReturningStrategy(),
2344
+ upsertStrategy: new PostgresUpsertStrategy(),
2345
+ supportsDmlReturning: true,
2346
+ compileSetTarget: (column, _table) => {
2347
+ void _table;
2348
+ return quoteIdentifier(column.name);
2349
+ },
2350
+ compileJsonPath(node) {
2351
+ const column = `${quoteIdentifier(node.column.table)}.${quoteIdentifier(node.column.name)}`;
2352
+ return `${column}->>'${node.path}'`;
2353
+ },
2354
+ configureExpressions(api) {
2355
+ api.registerExpressionCompiler("BitwiseExpression", (node, ctx) => {
2356
+ const left2 = api.compileOperand(node.left, ctx);
2357
+ const right2 = api.compileOperand(node.right, ctx);
2358
+ const operator = node.operator === "^" ? "#" : node.operator;
2359
+ return `${left2} ${operator} ${right2}`;
2360
+ });
2361
+ api.registerOperandCompiler("BitwiseExpression", (node, ctx) => {
2362
+ const left2 = api.compileOperand(node.left, ctx);
2363
+ const right2 = api.compileOperand(node.right, ctx);
2364
+ const operator = node.operator === "^" ? "#" : node.operator;
2365
+ return `(${left2} ${operator} ${right2})`;
2366
+ });
2367
+ }
2368
+ });
2369
+ const procedures = new PostgresProcedureCompiler(composition.runtime);
2370
+ return {
2371
+ ...composition.dialect,
2372
+ compileProcedureCall: (ast) => procedures.compileProcedureCall(ast)
2373
+ };
2374
+ };
2375
+ var PostgresDialect = class {
2376
+ impl = createPostgresDialect();
2377
+ quoteIdentifier(id) {
2378
+ return this.impl.quoteIdentifier(id);
2379
+ }
2380
+ supportsDmlReturningClause() {
2381
+ return this.impl.supportsDmlReturningClause();
2382
+ }
2383
+ compileSelect(ast) {
2384
+ return this.impl.compileSelect(ast);
2385
+ }
2386
+ compileInsert(ast) {
2387
+ return this.impl.compileInsert(ast);
2388
+ }
2389
+ compileUpdate(ast) {
2390
+ return this.impl.compileUpdate(ast);
2391
+ }
2392
+ compileDelete(ast) {
2393
+ return this.impl.compileDelete(ast);
2394
+ }
2395
+ compileProcedureCall(ast) {
2396
+ return this.impl.compileProcedureCall(ast);
2459
2397
  }
2460
2398
  };
2461
2399
 
@@ -2557,72 +2495,15 @@ var MysqlFunctionStrategy = class extends StandardFunctionStrategy {
2557
2495
  }
2558
2496
  };
2559
2497
 
2560
- // src/core/dialect/mysql/index.ts
2498
+ // src/core/dialect/mysql/procedure-compiler.ts
2561
2499
  var sanitizeVariableSuffix = (value) => value.replace(/[^a-zA-Z0-9_]/g, "_");
2562
- var MySqlDialect = class extends SqlDialectBase {
2563
- dialect = "mysql";
2564
- /**
2565
- * Creates a new MySqlDialect instance
2566
- */
2567
- constructor() {
2568
- super(new MysqlFunctionStrategy());
2569
- this.registerExpressionCompiler(
2570
- "IsDistinctExpression",
2571
- (node, ctx) => {
2572
- const left2 = this.compileOperand(node.left, ctx);
2573
- const right2 = this.compileOperand(node.right, ctx);
2574
- const spaceship = `${left2} <=> ${right2}`;
2575
- if (node.operator === "IS NOT DISTINCT FROM") {
2576
- return spaceship;
2577
- }
2578
- return `NOT (${spaceship})`;
2579
- }
2580
- );
2581
- }
2582
- /**
2583
- * Quotes an identifier using MySQL backtick syntax
2584
- * @param id - Identifier to quote
2585
- * @returns Quoted identifier
2586
- */
2587
- quoteIdentifier(id) {
2588
- return `\`${id}\``;
2589
- }
2590
- /**
2591
- * Compiles JSON path expression using MySQL syntax
2592
- * @param node - JSON path node
2593
- * @returns MySQL JSON path expression
2594
- */
2595
- compileJsonPath(node) {
2596
- const col2 = `${this.quoteIdentifier(node.column.table)}.${this.quoteIdentifier(node.column.name)}`;
2597
- return `${col2}->'${node.path}'`;
2598
- }
2599
- compileUpsertClause(ast, ctx) {
2600
- if (!ast.onConflict) return "";
2601
- const clause = ast.onConflict;
2602
- if (clause.action.type === "DoNothing") {
2603
- const noOpColumn = clause.target.columns[0] ?? ast.columns[0];
2604
- if (!noOpColumn) {
2605
- throw new Error("MySQL ON DUPLICATE KEY UPDATE requires at least one target column.");
2606
- }
2607
- const col2 = this.quoteIdentifier(noOpColumn.name);
2608
- return ` ON DUPLICATE KEY UPDATE ${col2} = ${col2}`;
2609
- }
2610
- if (clause.action.where) {
2611
- throw new Error("MySQL ON DUPLICATE KEY UPDATE does not support a WHERE clause.");
2612
- }
2613
- if (!clause.action.set.length) {
2614
- throw new Error("MySQL ON DUPLICATE KEY UPDATE requires at least one assignment.");
2615
- }
2616
- const assignments = clause.action.set.map((assignment) => {
2617
- const target = this.quoteIdentifier(assignment.column.name);
2618
- const value = this.compileOperand(assignment.value, ctx);
2619
- return `${target} = ${value}`;
2620
- }).join(", ");
2621
- return ` ON DUPLICATE KEY UPDATE ${assignments}`;
2500
+ var MySqlProcedureCompiler = class {
2501
+ constructor(services) {
2502
+ this.services = services;
2622
2503
  }
2623
2504
  compileProcedureCall(ast) {
2624
- const ctx = this.createCompilerContext();
2625
- const qualifiedName = ast.ref.schema ? `${this.quoteIdentifier(ast.ref.schema)}.${this.quoteIdentifier(ast.ref.name)}` : this.quoteIdentifier(ast.ref.name);
2505
+ const ctx = this.services.createCompilerContext();
2506
+ const qualifiedName = ast.ref.schema ? `${this.services.quoteIdentifier(ast.ref.schema)}.${this.services.quoteIdentifier(ast.ref.name)}` : this.services.quoteIdentifier(ast.ref.name);
2626
2507
  const prelude = [];
2627
2508
  const callArgs = [];
2628
2509
  const outVars = [];
@@ -2633,25 +2514,23 @@ var MySqlDialect = class extends SqlDialectBase {
2633
2514
  if (!param.value) {
2634
2515
  throw new Error(`Procedure parameter "${param.name}" requires a value for direction "in".`);
2635
2516
  }
2636
- callArgs.push(this.compileOperand(param.value, ctx));
2517
+ callArgs.push(this.services.compileOperand(param.value, ctx));
2637
2518
  return;
2638
2519
  }
2639
2520
  if (param.direction === "inout") {
2640
2521
  if (!param.value) {
2641
2522
  throw new Error(`Procedure parameter "${param.name}" requires a value for direction "inout".`);
2642
2523
  }
2643
- prelude.push(`SET ${variable} = ${this.compileOperand(param.value, ctx)};`);
2524
+ prelude.push(`SET ${variable} = ${this.services.compileOperand(param.value, ctx)};`);
2644
2525
  }
2645
2526
  callArgs.push(variable);
2646
2527
  outVars.push({ variable, name: param.name });
2647
2528
  });
2648
2529
  const statements = [];
2649
- if (prelude.length) {
2650
- statements.push(...prelude);
2651
- }
2530
+ if (prelude.length) statements.push(...prelude);
2652
2531
  statements.push(`CALL ${qualifiedName}(${callArgs.join(", ")});`);
2653
2532
  if (outVars.length) {
2654
- const selectOut = outVars.map(({ variable, name }) => `${variable} AS ${this.quoteIdentifier(name)}`).join(", ");
2533
+ const selectOut = outVars.map(({ variable, name }) => `${variable} AS ${this.services.quoteIdentifier(name)}`).join(", ");
2655
2534
  statements.push(`SELECT ${selectOut};`);
2656
2535
  }
2657
2536
  return {
@@ -2665,6 +2544,89 @@ var MySqlDialect = class extends SqlDialectBase {
2665
2544
  }
2666
2545
  };
2667
2546
 
2547
+ // src/core/dialect/mysql/upsert.ts
2548
+ var MySqlUpsertStrategy = class {
2549
+ compile(ast, ctx, services) {
2550
+ if (!ast.onConflict) return "";
2551
+ const clause = ast.onConflict;
2552
+ if (clause.action.type === "DoNothing") {
2553
+ const noOpColumn = clause.target.columns[0] ?? ast.columns[0];
2554
+ if (!noOpColumn) {
2555
+ throw new Error("MySQL ON DUPLICATE KEY UPDATE requires at least one target column.");
2556
+ }
2557
+ const col2 = services.quoteIdentifier(noOpColumn.name);
2558
+ return ` ON DUPLICATE KEY UPDATE ${col2} = ${col2}`;
2559
+ }
2560
+ if (clause.action.where) {
2561
+ throw new Error("MySQL ON DUPLICATE KEY UPDATE does not support a WHERE clause.");
2562
+ }
2563
+ if (!clause.action.set.length) {
2564
+ throw new Error("MySQL ON DUPLICATE KEY UPDATE requires at least one assignment.");
2565
+ }
2566
+ const assignments = clause.action.set.map((assignment) => {
2567
+ const target = services.quoteIdentifier(assignment.column.name);
2568
+ const value = services.compileOperand(assignment.value, ctx);
2569
+ return `${target} = ${value}`;
2570
+ }).join(", ");
2571
+ return ` ON DUPLICATE KEY UPDATE ${assignments}`;
2572
+ }
2573
+ };
2574
+
2575
+ // src/core/dialect/mysql/index.ts
2576
+ var quoteIdentifier2 = (id) => `\`${id}\``;
2577
+ var createMySqlDialect = () => {
2578
+ const composition = composeSqlDialect({
2579
+ name: "mysql",
2580
+ quoteIdentifier: quoteIdentifier2,
2581
+ functionStrategy: new MysqlFunctionStrategy(),
2582
+ upsertStrategy: new MySqlUpsertStrategy(),
2583
+ compileJsonPath(node) {
2584
+ const column = `${quoteIdentifier2(node.column.table)}.${quoteIdentifier2(node.column.name)}`;
2585
+ return `${column}->'${node.path}'`;
2586
+ },
2587
+ configureExpressions(api) {
2588
+ api.registerExpressionCompiler(
2589
+ "IsDistinctExpression",
2590
+ (node, ctx) => {
2591
+ const left2 = api.compileOperand(node.left, ctx);
2592
+ const right2 = api.compileOperand(node.right, ctx);
2593
+ const spaceship = `${left2} <=> ${right2}`;
2594
+ return node.operator === "IS NOT DISTINCT FROM" ? spaceship : `NOT (${spaceship})`;
2595
+ }
2596
+ );
2597
+ }
2598
+ });
2599
+ const procedures = new MySqlProcedureCompiler(composition.runtime);
2600
+ return {
2601
+ ...composition.dialect,
2602
+ compileProcedureCall: (ast) => procedures.compileProcedureCall(ast)
2603
+ };
2604
+ };
2605
+ var MySqlDialect = class {
2606
+ impl = createMySqlDialect();
2607
+ quoteIdentifier(id) {
2608
+ return this.impl.quoteIdentifier(id);
2609
+ }
2610
+ supportsDmlReturningClause() {
2611
+ return this.impl.supportsDmlReturningClause();
2612
+ }
2613
+ compileSelect(ast) {
2614
+ return this.impl.compileSelect(ast);
2615
+ }
2616
+ compileInsert(ast) {
2617
+ return this.impl.compileInsert(ast);
2618
+ }
2619
+ compileUpdate(ast) {
2620
+ return this.impl.compileUpdate(ast);
2621
+ }
2622
+ compileDelete(ast) {
2623
+ return this.impl.compileDelete(ast);
2624
+ }
2625
+ compileProcedureCall(ast) {
2626
+ return this.impl.compileProcedureCall(ast);
2627
+ }
2628
+ };
2629
+
2668
2630
  // src/core/dialect/sqlite/functions.ts
2669
2631
  var SqliteFunctionStrategy = class extends StandardFunctionStrategy {
2670
2632
  constructor() {
@@ -2802,85 +2764,101 @@ var SqliteFunctionStrategy = class extends StandardFunctionStrategy {
2802
2764
  }
2803
2765
  };
2804
2766
 
2805
- // src/core/dialect/sqlite/index.ts
2806
- var SqliteDialect = class extends SqlDialectBase {
2807
- dialect = "sqlite";
2808
- /**
2809
- * Creates a new SqliteDialect instance
2810
- */
2811
- constructor() {
2812
- super(new SqliteFunctionStrategy());
2813
- this.registerExpressionCompiler("BitwiseExpression", (node, ctx) => {
2814
- const left2 = this.compileOperand(node.left, ctx);
2815
- const right2 = this.compileOperand(node.right, ctx);
2816
- if (node.operator === "^") {
2817
- return `(${left2} | ${right2}) & ~(${left2} & ${right2})`;
2818
- }
2819
- return `${left2} ${node.operator} ${right2}`;
2820
- });
2821
- this.registerOperandCompiler("BitwiseExpression", (node, ctx) => {
2822
- const left2 = this.compileOperand(node.left, ctx);
2823
- const right2 = this.compileOperand(node.right, ctx);
2824
- if (node.operator === "^") {
2825
- return `((${left2} | ${right2}) & ~(${left2} & ${right2}))`;
2826
- }
2827
- return `(${left2} ${node.operator} ${right2})`;
2828
- });
2829
- }
2830
- /**
2831
- * Quotes an identifier using SQLite double-quote syntax
2832
- * @param id - Identifier to quote
2833
- * @returns Quoted identifier
2834
- */
2835
- quoteIdentifier(id) {
2836
- return `"${id}"`;
2837
- }
2838
- /**
2839
- * Compiles JSON path expression using SQLite syntax
2840
- * @param node - JSON path node
2841
- * @returns SQLite JSON path expression
2842
- */
2843
- compileJsonPath(node) {
2844
- const col2 = `${this.quoteIdentifier(node.column.table)}.${this.quoteIdentifier(node.column.name)}`;
2845
- return `json_extract(${col2}, '${node.path}')`;
2846
- }
2847
- compileQualifiedColumn(column, _table) {
2848
- void _table;
2849
- return this.quoteIdentifier(column.name);
2850
- }
2851
- compileReturning(returning, ctx) {
2852
- void ctx;
2767
+ // src/core/dialect/sqlite/returning.ts
2768
+ var SqliteReturningStrategy = class {
2769
+ compileReturning(returning, _ctx, quoteIdentifier5) {
2770
+ void _ctx;
2853
2771
  if (!returning || returning.length === 0) return "";
2854
- const columns = this.formatReturningColumns(returning);
2855
- return ` RETURNING ${columns}`;
2772
+ return ` RETURNING ${this.formatReturningColumns(returning, quoteIdentifier5)}`;
2856
2773
  }
2857
- formatReturningColumns(returning) {
2774
+ formatReturningColumns(returning, quoteIdentifier5) {
2858
2775
  return returning.map((column) => {
2859
- const alias = column.alias ? ` AS ${this.quoteIdentifier(column.alias)}` : "";
2860
- return `${this.quoteIdentifier(column.name)}${alias}`;
2776
+ const alias = column.alias ? ` AS ${quoteIdentifier5(column.alias)}` : "";
2777
+ return `${quoteIdentifier5(column.name)}${alias}`;
2861
2778
  }).join(", ");
2862
2779
  }
2863
- compileUpsertClause(ast, ctx) {
2780
+ };
2781
+
2782
+ // src/core/dialect/sqlite/upsert.ts
2783
+ var SqliteUpsertStrategy = class {
2784
+ compile(ast, ctx, services) {
2864
2785
  if (!ast.onConflict) return "";
2865
2786
  const clause = ast.onConflict;
2866
2787
  if (clause.target.constraint) {
2867
2788
  throw new Error("SQLite ON CONFLICT does not support named constraints.");
2868
2789
  }
2869
- this.ensureConflictColumns(clause, "SQLite ON CONFLICT requires conflict columns.");
2870
- const cols = clause.target.columns.map((col2) => this.quoteIdentifier(col2.name)).join(", ");
2871
- const target = ` ON CONFLICT (${cols})`;
2790
+ if (!clause.target.columns.length) {
2791
+ throw new Error("SQLite ON CONFLICT requires conflict columns.");
2792
+ }
2793
+ const columns = clause.target.columns.map((column) => services.quoteIdentifier(column.name)).join(", ");
2794
+ const target = ` ON CONFLICT (${columns})`;
2872
2795
  if (clause.action.type === "DoNothing") {
2873
2796
  return `${target} DO NOTHING`;
2874
2797
  }
2875
2798
  if (!clause.action.set.length) {
2876
2799
  throw new Error("SQLite ON CONFLICT DO UPDATE requires at least one assignment.");
2877
2800
  }
2878
- const assignments = this.compileUpdateAssignments(clause.action.set, ast.into, ctx);
2879
- const where = clause.action.where ? ` WHERE ${this.compileExpression(clause.action.where, ctx)}` : "";
2801
+ const assignments = services.compileUpdateAssignments(clause.action.set, ast.into, ctx);
2802
+ const where = clause.action.where ? ` WHERE ${services.compileExpression(clause.action.where, ctx)}` : "";
2880
2803
  return `${target} DO UPDATE SET ${assignments}${where}`;
2881
2804
  }
2805
+ };
2806
+
2807
+ // src/core/dialect/sqlite/index.ts
2808
+ var quoteIdentifier3 = (id) => `"${id}"`;
2809
+ var createSqliteDialect = () => composeSqlDialect({
2810
+ name: "sqlite",
2811
+ quoteIdentifier: quoteIdentifier3,
2812
+ functionStrategy: new SqliteFunctionStrategy(),
2813
+ returningStrategy: new SqliteReturningStrategy(),
2814
+ upsertStrategy: new SqliteUpsertStrategy(),
2815
+ supportsDmlReturning: true,
2816
+ compileSetTarget: (column, _table) => {
2817
+ void _table;
2818
+ return quoteIdentifier3(column.name);
2819
+ },
2820
+ compileJsonPath(node) {
2821
+ const column = `${quoteIdentifier3(node.column.table)}.${quoteIdentifier3(node.column.name)}`;
2822
+ return `json_extract(${column}, '${node.path}')`;
2823
+ },
2824
+ configureExpressions(api) {
2825
+ api.registerExpressionCompiler("BitwiseExpression", (node, ctx) => {
2826
+ const left2 = api.compileOperand(node.left, ctx);
2827
+ const right2 = api.compileOperand(node.right, ctx);
2828
+ if (node.operator === "^") {
2829
+ return `(${left2} | ${right2}) & ~(${left2} & ${right2})`;
2830
+ }
2831
+ return `${left2} ${node.operator} ${right2}`;
2832
+ });
2833
+ api.registerOperandCompiler("BitwiseExpression", (node, ctx) => {
2834
+ const left2 = api.compileOperand(node.left, ctx);
2835
+ const right2 = api.compileOperand(node.right, ctx);
2836
+ if (node.operator === "^") {
2837
+ return `((${left2} | ${right2}) & ~(${left2} & ${right2}))`;
2838
+ }
2839
+ return `(${left2} ${node.operator} ${right2})`;
2840
+ });
2841
+ }
2842
+ }).dialect;
2843
+ var SqliteDialect = class {
2844
+ impl = createSqliteDialect();
2845
+ quoteIdentifier(id) {
2846
+ return this.impl.quoteIdentifier(id);
2847
+ }
2882
2848
  supportsDmlReturningClause() {
2883
- return true;
2849
+ return this.impl.supportsDmlReturningClause();
2850
+ }
2851
+ compileSelect(ast) {
2852
+ return this.impl.compileSelect(ast);
2853
+ }
2854
+ compileInsert(ast) {
2855
+ return this.impl.compileInsert(ast);
2856
+ }
2857
+ compileUpdate(ast) {
2858
+ return this.impl.compileUpdate(ast);
2859
+ }
2860
+ compileDelete(ast) {
2861
+ return this.impl.compileDelete(ast);
2884
2862
  }
2885
2863
  };
2886
2864
 
@@ -3008,202 +2986,107 @@ var MssqlFunctionStrategy = class extends StandardFunctionStrategy {
3008
2986
  }
3009
2987
  };
3010
2988
 
3011
- // src/core/dialect/mssql/index.ts
3012
- var sanitizeVariableSuffix2 = (value) => value.replace(/[^a-zA-Z0-9_]/g, "_");
3013
- var toProcedureParamReference = (value) => value.startsWith("@") ? value : `@${value}`;
3014
- var SqlServerDialect = class extends SqlDialectBase {
3015
- dialect = "mssql";
3016
- /**
3017
- * Creates a new SqlServerDialect instance
3018
- */
3019
- constructor() {
3020
- super(new MssqlFunctionStrategy());
3021
- }
3022
- /**
3023
- * Quotes an identifier using SQL Server bracket syntax
3024
- * @param id - Identifier to quote
3025
- * @returns Quoted identifier
3026
- */
3027
- quoteIdentifier(id) {
3028
- return `[${id}]`;
2989
+ // src/core/dialect/mssql/output.ts
2990
+ var MssqlOutputStrategy = class {
2991
+ compileReturning(returning, _ctx, quoteIdentifier5) {
2992
+ void _ctx;
2993
+ return this.compileOutput(returning, "inserted", quoteIdentifier5);
3029
2994
  }
3030
- /**
3031
- * Compiles JSON path expression using SQL Server syntax
3032
- * @param node - JSON path node
3033
- * @returns SQL Server JSON path expression
3034
- */
3035
- compileJsonPath(node) {
3036
- const col2 = `${this.quoteIdentifier(node.column.table)}.${this.quoteIdentifier(node.column.name)}`;
3037
- return `JSON_VALUE(${col2}, '${node.path}')`;
2995
+ compileOutput(returning, prefix, quoteIdentifier5) {
2996
+ if (!returning || returning.length === 0) return "";
2997
+ const columns = returning.map((column) => {
2998
+ const alias = column.alias ? ` AS ${quoteIdentifier5(column.alias)}` : "";
2999
+ return `${prefix}.${quoteIdentifier5(column.name)}${alias}`;
3000
+ }).join(", ");
3001
+ return ` OUTPUT ${columns}`;
3038
3002
  }
3039
- /**
3040
- * Formats parameter placeholders using SQL Server named parameter syntax
3041
- * @param index - Parameter index
3042
- * @returns Named parameter placeholder
3043
- */
3044
- formatPlaceholder(index) {
3045
- return `@p${index}`;
3003
+ formatReturningColumns(returning, quoteIdentifier5) {
3004
+ return returning.map((column) => {
3005
+ const alias = column.alias ? ` AS ${quoteIdentifier5(column.alias)}` : "";
3006
+ return `${quoteIdentifier5(column.name)}${alias}`;
3007
+ }).join(", ");
3046
3008
  }
3047
- /**
3048
- * Compiles SELECT query AST to SQL Server SQL
3049
- * @param ast - Query AST
3050
- * @param ctx - Compiler context
3051
- * @returns SQL Server SQL string
3052
- */
3053
- compileSelectAst(ast, ctx) {
3054
- const hasSetOps = !!(ast.setOps && ast.setOps.length);
3055
- const ctes = this.compileCtes(ast, ctx);
3056
- const baseAst = hasSetOps ? { ...ast, setOps: void 0, orderBy: void 0, limit: void 0, offset: void 0 } : ast;
3057
- const baseSelect = this.compileSelectCoreForMssql(baseAst, ctx);
3058
- if (!hasSetOps) {
3059
- return `${ctes}${baseSelect}`;
3060
- }
3061
- const compound = ast.setOps.map((op) => `${op.operator} ${this.wrapSetOperand(this.compileSelectAst(op.query, ctx))}`).join(" ");
3062
- const orderBy = this.compileOrderBy(ast, ctx);
3063
- const pagination = this.compilePagination(ast, orderBy);
3064
- const combined = `${this.wrapSetOperand(baseSelect)} ${compound}`;
3065
- const tail = pagination || orderBy;
3066
- return `${ctes}${combined}${tail}`;
3009
+ };
3010
+
3011
+ // src/core/dialect/mssql/delete-compiler.ts
3012
+ var MssqlDeleteCompiler = class {
3013
+ constructor(services, sources) {
3014
+ this.services = services;
3015
+ this.sources = sources;
3067
3016
  }
3068
- compileDeleteAst(ast, ctx) {
3017
+ output = new MssqlOutputStrategy();
3018
+ compile(ast, ctx) {
3069
3019
  if (ast.using) {
3070
3020
  throw new Error("DELETE ... USING is not supported in the MSSQL dialect; use join() instead.");
3071
3021
  }
3072
- if (ast.from.type !== "Table") {
3073
- throw new Error("DELETE only supports base tables in the MSSQL dialect.");
3074
- }
3075
3022
  const alias = ast.from.alias ?? ast.from.name;
3076
- const target = this.compileTableReference(ast.from);
3023
+ const target = this.sources.compileTableReference(ast.from);
3077
3024
  const joins = JoinCompiler.compileJoins(
3078
3025
  ast.joins,
3079
3026
  ctx,
3080
- this.compileFrom.bind(this),
3081
- this.compileExpression.bind(this)
3027
+ (source, compilerContext) => this.sources.compileFrom(source, compilerContext),
3028
+ (expression, compilerContext) => this.services.compileExpression(expression, compilerContext)
3082
3029
  );
3083
- const whereClause = this.compileWhere(ast.where, ctx);
3084
- const returning = this.compileOutputClause(ast.returning, "deleted");
3085
- return `DELETE ${this.quoteIdentifier(alias)}${returning} FROM ${target}${joins}${whereClause}`;
3086
- }
3087
- compileUpdateAst(ast, ctx) {
3088
- const target = this.compileTableReference(ast.table);
3089
- const assignments = this.compileUpdateAssignments(ast.set, ast.table, ctx);
3090
- const output = this.compileReturning(ast.returning, ctx);
3091
- const fromClause = ast.from ? ` FROM ${this.compileFrom(ast.from, ctx)}` : "";
3092
- const joins = ast.joins ? ast.joins.map((j) => {
3093
- const table = this.compileFrom(j.table, ctx);
3094
- const cond = this.compileExpression(j.condition, ctx);
3095
- return ` ${j.kind} JOIN ${table} ON ${cond}`;
3096
- }).join("") : "";
3097
- const whereClause = this.compileWhere(ast.where, ctx);
3098
- return `UPDATE ${target} SET ${assignments}${output}${fromClause}${joins}${whereClause}`;
3099
- }
3100
- compileSelectCoreForMssql(ast, ctx) {
3101
- const columns = ast.columns.map((c) => {
3102
- const expr = c.type === "Column" ? `${this.quoteIdentifier(c.table)}.${this.quoteIdentifier(c.name)}` : this.compileOperand(c, ctx);
3103
- if (c.alias) {
3104
- if (c.alias.includes("(")) return c.alias;
3105
- return `${expr} AS ${this.quoteIdentifier(c.alias)}`;
3106
- }
3107
- return expr;
3108
- }).join(", ");
3109
- const distinct = ast.distinct ? "DISTINCT " : "";
3110
- const from = this.compileFrom(ast.from, ctx);
3111
- const joins = ast.joins.map((j) => {
3112
- const table = this.compileFrom(j.table, ctx);
3113
- const cond = this.compileExpression(j.condition, ctx);
3114
- return `${j.kind} JOIN ${table} ON ${cond}`;
3115
- }).join(" ");
3116
- const whereClause = this.compileWhere(ast.where, ctx);
3117
- const groupBy = ast.groupBy && ast.groupBy.length > 0 ? " GROUP BY " + ast.groupBy.map((term) => this.compileOrderingTerm(term, ctx)).join(", ") : "";
3118
- const having = ast.having ? ` HAVING ${this.compileExpression(ast.having, ctx)}` : "";
3119
- const orderBy = this.compileOrderBy(ast, ctx);
3120
- const pagination = this.compilePagination(ast, orderBy);
3121
- if (pagination) {
3122
- return `SELECT ${distinct}${columns} FROM ${from}${joins ? " " + joins : ""}${whereClause}${groupBy}${having}${pagination}`;
3123
- }
3124
- return `SELECT ${distinct}${columns} FROM ${from}${joins ? " " + joins : ""}${whereClause}${groupBy}${having}${orderBy}`;
3125
- }
3126
- compileOrderBy(ast, ctx) {
3127
- return OrderByCompiler.compileOrderBy(
3128
- ast,
3129
- (term) => this.compileOrderingTerm(term, ctx),
3130
- this.renderOrderByNulls.bind(this),
3131
- this.renderOrderByCollation.bind(this)
3030
+ const where = ast.where ? ` WHERE ${this.services.compileExpression(ast.where, ctx)}` : "";
3031
+ const returning = this.output.compileOutput(
3032
+ ast.returning,
3033
+ "deleted",
3034
+ (id) => this.services.quoteIdentifier(id)
3132
3035
  );
3036
+ return `DELETE ${this.services.quoteIdentifier(alias)}${returning} FROM ${target}${joins}${where}`;
3133
3037
  }
3134
- compilePagination(ast, orderBy) {
3135
- const hasLimit = ast.limit !== void 0;
3136
- const hasOffset = ast.offset !== void 0;
3137
- if (!hasLimit && !hasOffset) return "";
3138
- const off = ast.offset ?? 0;
3139
- let orderClause = orderBy;
3140
- if (!orderClause) {
3141
- orderClause = ast.distinct && ast.distinct.length > 0 ? " ORDER BY 1" : " ORDER BY (SELECT NULL)";
3142
- }
3143
- let pagination = `${orderClause} OFFSET ${off} ROWS`;
3144
- if (hasLimit) {
3145
- pagination += ` FETCH NEXT ${ast.limit} ROWS ONLY`;
3146
- }
3147
- return pagination;
3148
- }
3149
- supportsDmlReturningClause() {
3150
- return true;
3151
- }
3152
- compileReturning(returning, _ctx) {
3153
- void _ctx;
3154
- return this.compileOutputClause(returning, "inserted");
3155
- }
3156
- compileOutputClause(returning, prefix) {
3157
- if (!returning || returning.length === 0) return "";
3158
- const columns = returning.map((column) => {
3159
- const colName = this.quoteIdentifier(column.name);
3160
- const alias = column.alias ? ` AS ${this.quoteIdentifier(column.alias)}` : "";
3161
- return `${prefix}.${colName}${alias}`;
3162
- }).join(", ");
3163
- return ` OUTPUT ${columns}`;
3038
+ };
3039
+
3040
+ // src/core/dialect/mssql/insert-compiler.ts
3041
+ var MssqlInsertCompiler = class {
3042
+ constructor(services, sources) {
3043
+ this.services = services;
3044
+ this.sources = sources;
3164
3045
  }
3165
- compileInsertAst(ast, ctx) {
3046
+ compile(ast, ctx) {
3166
3047
  if (!ast.columns.length) {
3167
3048
  throw new Error("INSERT queries must specify columns.");
3168
3049
  }
3169
- if (ast.onConflict) {
3170
- return this.compileMergeInsert(ast, ctx);
3171
- }
3172
- const table = this.compileTableName(ast.into);
3173
- const columnList = ast.columns.map((column) => this.quoteIdentifier(column.name)).join(", ");
3174
- const output = this.compileReturning(ast.returning, ctx);
3175
- const source = this.compileInsertValues(ast, ctx);
3176
- return `INSERT INTO ${table} (${columnList})${output} ${source}`;
3050
+ if (ast.onConflict) return this.compileMerge(ast, ctx);
3051
+ const table = this.sources.compileTableName(ast.into);
3052
+ const columns = ast.columns.map((column) => this.services.quoteIdentifier(column.name)).join(", ");
3053
+ const output = this.services.compileReturning(ast.returning, ctx);
3054
+ const source = this.compileInsertSource(ast, ctx);
3055
+ return `INSERT INTO ${table} (${columns})${output} ${source}`;
3177
3056
  }
3178
- compileMergeInsert(ast, ctx) {
3057
+ compileMerge(ast, ctx) {
3179
3058
  const clause = ast.onConflict;
3180
3059
  if (clause.target.constraint) {
3181
3060
  throw new Error("MSSQL MERGE does not support conflict target by constraint name.");
3182
3061
  }
3183
- this.ensureConflictColumns(clause, "MSSQL MERGE requires conflict columns for the ON clause.");
3184
- const table = this.compileTableName(ast.into);
3185
- const targetRef = this.quoteIdentifier(ast.into.alias ?? ast.into.name);
3186
- const sourceAlias = this.quoteIdentifier("src");
3187
- const sourceColumns = ast.columns.map((column) => this.quoteIdentifier(column.name)).join(", ");
3062
+ if (!clause.target.columns.length) {
3063
+ throw new Error("MSSQL MERGE requires conflict columns for the ON clause.");
3064
+ }
3065
+ const table = this.sources.compileTableName(ast.into);
3066
+ const targetRef = this.services.quoteIdentifier(ast.into.alias ?? ast.into.name);
3067
+ const sourceAlias = this.services.quoteIdentifier("src");
3068
+ const sourceColumns = ast.columns.map((column) => this.services.quoteIdentifier(column.name)).join(", ");
3188
3069
  const usingSource = this.compileMergeUsingSource(ast, ctx);
3189
- const onClause = clause.target.columns.map((column) => `${targetRef}.${this.quoteIdentifier(column.name)} = ${sourceAlias}.${this.quoteIdentifier(column.name)}`).join(" AND ");
3070
+ const onClause = clause.target.columns.map(
3071
+ (column) => `${targetRef}.${this.services.quoteIdentifier(column.name)} = ${sourceAlias}.${this.services.quoteIdentifier(column.name)}`
3072
+ ).join(" AND ");
3190
3073
  const branches = [];
3191
3074
  if (clause.action.type === "DoUpdate") {
3192
3075
  if (!clause.action.set.length) {
3193
3076
  throw new Error("MSSQL MERGE WHEN MATCHED UPDATE requires at least one assignment.");
3194
3077
  }
3195
3078
  const assignments = clause.action.set.map((assignment) => {
3196
- const target = `${targetRef}.${this.quoteIdentifier(assignment.column.name)}`;
3197
- const value = this.compileOperand(assignment.value, ctx);
3079
+ const target = `${targetRef}.${this.services.quoteIdentifier(assignment.column.name)}`;
3080
+ const value = this.services.compileOperand(assignment.value, ctx);
3198
3081
  return `${target} = ${value}`;
3199
3082
  }).join(", ");
3200
- const guard = clause.action.where ? ` AND ${this.compileExpression(clause.action.where, ctx)}` : "";
3083
+ const guard = clause.action.where ? ` AND ${this.services.compileExpression(clause.action.where, ctx)}` : "";
3201
3084
  branches.push(`WHEN MATCHED${guard} THEN UPDATE SET ${assignments}`);
3202
3085
  }
3203
- const insertColumns = ast.columns.map((column) => this.quoteIdentifier(column.name)).join(", ");
3204
- const insertValues = ast.columns.map((column) => `${sourceAlias}.${this.quoteIdentifier(column.name)}`).join(", ");
3086
+ const insertColumns = ast.columns.map((column) => this.services.quoteIdentifier(column.name)).join(", ");
3087
+ const insertValues = ast.columns.map((column) => `${sourceAlias}.${this.services.quoteIdentifier(column.name)}`).join(", ");
3205
3088
  branches.push(`WHEN NOT MATCHED THEN INSERT (${insertColumns}) VALUES (${insertValues})`);
3206
- const output = this.compileReturning(ast.returning, ctx);
3089
+ const output = this.services.compileReturning(ast.returning, ctx);
3207
3090
  return `MERGE INTO ${table} USING ${usingSource} AS ${sourceAlias} (${sourceColumns}) ON ${onClause} ${branches.join(" ")}${output}`;
3208
3091
  }
3209
3092
  compileMergeUsingSource(ast, ctx) {
@@ -3211,38 +3094,146 @@ var SqlServerDialect = class extends SqlDialectBase {
3211
3094
  if (!ast.source.rows.length) {
3212
3095
  throw new Error("INSERT ... VALUES requires at least one row.");
3213
3096
  }
3214
- const rows = ast.source.rows.map((row) => `(${row.map((value) => this.compileOperand(value, ctx)).join(", ")})`).join(", ");
3097
+ const rows = ast.source.rows.map((row) => `(${row.map((value) => this.services.compileOperand(value, ctx)).join(", ")})`).join(", ");
3215
3098
  return `(VALUES ${rows})`;
3216
3099
  }
3217
- const normalized = this.normalizeSelectAst(ast.source.query);
3218
- const selectSql = this.compileSelectAst(normalized, ctx).trim().replace(/;$/, "");
3100
+ const normalized = this.services.normalizeSelectAst(ast.source.query);
3101
+ const selectSql = this.sources.stripTrailingSemicolon(
3102
+ this.services.compileSelectAst(normalized, ctx)
3103
+ );
3219
3104
  return `(${selectSql})`;
3220
3105
  }
3221
- compileInsertValues(ast, ctx) {
3222
- const source = ast.source;
3223
- if (source.type === "InsertValues") {
3224
- if (!source.rows.length) {
3106
+ compileInsertSource(ast, ctx) {
3107
+ if (ast.source.type === "InsertValues") {
3108
+ if (!ast.source.rows.length) {
3225
3109
  throw new Error("INSERT ... VALUES requires at least one row.");
3226
3110
  }
3227
- const values = source.rows.map((row) => `(${row.map((value) => this.compileOperand(value, ctx)).join(", ")})`).join(", ");
3111
+ const values = ast.source.rows.map((row) => `(${row.map((value) => this.services.compileOperand(value, ctx)).join(", ")})`).join(", ");
3228
3112
  return `VALUES ${values}`;
3229
3113
  }
3230
- const normalized = this.normalizeSelectAst(source.query);
3231
- return this.compileSelectAst(normalized, ctx).trim();
3114
+ const normalized = this.services.normalizeSelectAst(ast.source.query);
3115
+ return this.services.compileSelectAst(normalized, ctx).trim();
3116
+ }
3117
+ };
3118
+
3119
+ // src/core/dialect/mssql/select-compiler.ts
3120
+ var MssqlSelectCompiler = class {
3121
+ constructor(services, sources) {
3122
+ this.services = services;
3123
+ this.sources = sources;
3124
+ }
3125
+ compile(ast, ctx) {
3126
+ const hasSetOps = !!(ast.setOps && ast.setOps.length);
3127
+ const ctes = this.compileCtes(ast, ctx);
3128
+ const baseAst = hasSetOps ? { ...ast, setOps: void 0, orderBy: void 0, limit: void 0, offset: void 0 } : ast;
3129
+ const baseSelect = this.compileCore(baseAst, ctx);
3130
+ if (!hasSetOps) return `${ctes}${baseSelect}`;
3131
+ const compound = ast.setOps.map((op) => `${op.operator} ${this.sources.wrapSetOperand(this.services.compileSelectAst(op.query, ctx))}`).join(" ");
3132
+ const orderBy = this.compileOrderBy(ast, ctx);
3133
+ const pagination = this.compilePagination(ast, orderBy);
3134
+ const combined = `${this.sources.wrapSetOperand(baseSelect)} ${compound}`;
3135
+ return `${ctes}${combined}${pagination || orderBy}`;
3136
+ }
3137
+ compileCore(ast, ctx) {
3138
+ const columns = ast.columns.map((column) => {
3139
+ const expr = column.type === "Column" ? `${this.services.quoteIdentifier(column.table)}.${this.services.quoteIdentifier(column.name)}` : this.services.compileOperand(column, ctx);
3140
+ if (!column.alias) return expr;
3141
+ if (column.alias.includes("(")) return column.alias;
3142
+ return `${expr} AS ${this.services.quoteIdentifier(column.alias)}`;
3143
+ }).join(", ");
3144
+ const distinct = ast.distinct ? "DISTINCT " : "";
3145
+ const from = this.sources.compileFrom(ast.from, ctx);
3146
+ const joins = ast.joins.map((join) => {
3147
+ const table = this.sources.compileFrom(join.table, ctx);
3148
+ const condition = this.services.compileExpression(join.condition, ctx);
3149
+ return `${join.kind} JOIN ${table} ON ${condition}`;
3150
+ }).join(" ");
3151
+ const where = ast.where ? ` WHERE ${this.services.compileExpression(ast.where, ctx)}` : "";
3152
+ const groupBy = ast.groupBy && ast.groupBy.length > 0 ? ` GROUP BY ${ast.groupBy.map((term) => this.services.compileOrderingTerm(term, ctx)).join(", ")}` : "";
3153
+ const having = ast.having ? ` HAVING ${this.services.compileExpression(ast.having, ctx)}` : "";
3154
+ const orderBy = this.compileOrderBy(ast, ctx);
3155
+ const pagination = this.compilePagination(ast, orderBy);
3156
+ if (pagination) {
3157
+ return `SELECT ${distinct}${columns} FROM ${from}${joins ? ` ${joins}` : ""}${where}${groupBy}${having}${pagination}`;
3158
+ }
3159
+ return `SELECT ${distinct}${columns} FROM ${from}${joins ? ` ${joins}` : ""}${where}${groupBy}${having}${orderBy}`;
3160
+ }
3161
+ compileOrderBy(ast, ctx) {
3162
+ return OrderByCompiler.compileOrderBy(
3163
+ ast,
3164
+ (term) => this.services.compileOrderingTerm(term, ctx),
3165
+ (order) => this.services.renderOrderByNulls(order),
3166
+ (order) => this.services.renderOrderByCollation(order)
3167
+ );
3168
+ }
3169
+ compilePagination(ast, orderBy) {
3170
+ const hasLimit = ast.limit !== void 0;
3171
+ const hasOffset = ast.offset !== void 0;
3172
+ if (!hasLimit && !hasOffset) return "";
3173
+ const offset = ast.offset ?? 0;
3174
+ let orderClause = orderBy;
3175
+ if (!orderClause) {
3176
+ orderClause = ast.distinct && ast.distinct.length > 0 ? " ORDER BY 1" : " ORDER BY (SELECT NULL)";
3177
+ }
3178
+ let pagination = `${orderClause} OFFSET ${offset} ROWS`;
3179
+ if (hasLimit) pagination += ` FETCH NEXT ${ast.limit} ROWS ONLY`;
3180
+ return pagination;
3232
3181
  }
3233
3182
  compileCtes(ast, ctx) {
3234
3183
  if (!ast.ctes || ast.ctes.length === 0) return "";
3235
- const defs = ast.ctes.map((cte) => {
3236
- const name = this.quoteIdentifier(cte.name);
3237
- const cols = cte.columns ? `(${cte.columns.map((c) => this.quoteIdentifier(c)).join(", ")})` : "";
3238
- const query = this.compileSelectAst(this.normalizeSelectAst(cte.query), ctx).trim().replace(/;$/, "");
3239
- return `${name}${cols} AS (${query})`;
3184
+ const definitions = ast.ctes.map((cte) => {
3185
+ const name = this.services.quoteIdentifier(cte.name);
3186
+ const columns = cte.columns ? `(${cte.columns.map((column) => this.services.quoteIdentifier(column)).join(", ")})` : "";
3187
+ const query = this.sources.stripTrailingSemicolon(
3188
+ this.services.compileSelectAst(this.services.normalizeSelectAst(cte.query), ctx)
3189
+ );
3190
+ return `${name}${columns} AS (${query})`;
3240
3191
  }).join(", ");
3241
- return `WITH ${defs} `;
3192
+ return `WITH ${definitions} `;
3193
+ }
3194
+ };
3195
+
3196
+ // src/core/dialect/mssql/update-compiler.ts
3197
+ var MssqlUpdateCompiler = class {
3198
+ constructor(services, sources) {
3199
+ this.services = services;
3200
+ this.sources = sources;
3201
+ this.standardUpdate = new StandardUpdateCompiler(services, sources);
3202
+ }
3203
+ standardUpdate;
3204
+ compile(ast, ctx) {
3205
+ const target = this.sources.compileTableReference(ast.table);
3206
+ const assignments = this.standardUpdate.compileAssignments(ast.set, ast.table, ctx);
3207
+ const output = this.services.compileReturning(ast.returning, ctx);
3208
+ const from = ast.from ? ` FROM ${this.sources.compileFrom(ast.from, ctx)}` : "";
3209
+ const joins = ast.joins ? ast.joins.map((join) => {
3210
+ const table = this.sources.compileFrom(join.table, ctx);
3211
+ const condition = this.services.compileExpression(join.condition, ctx);
3212
+ return ` ${join.kind} JOIN ${table} ON ${condition}`;
3213
+ }).join("") : "";
3214
+ const where = ast.where ? ` WHERE ${this.services.compileExpression(ast.where, ctx)}` : "";
3215
+ return `UPDATE ${target} SET ${assignments}${output}${from}${joins}${where}`;
3216
+ }
3217
+ };
3218
+
3219
+ // src/core/dialect/mssql/compiler-factory.ts
3220
+ var createMssqlCompilerSet = ({ services, sources }) => ({
3221
+ select: new MssqlSelectCompiler(services, sources),
3222
+ insert: new MssqlInsertCompiler(services, sources),
3223
+ update: new MssqlUpdateCompiler(services, sources),
3224
+ delete: new MssqlDeleteCompiler(services, sources)
3225
+ });
3226
+
3227
+ // src/core/dialect/mssql/procedure-compiler.ts
3228
+ var sanitizeVariableSuffix2 = (value) => value.replace(/[^a-zA-Z0-9_]/g, "_");
3229
+ var toProcedureParamReference = (value) => value.startsWith("@") ? value : `@${value}`;
3230
+ var MssqlProcedureCompiler = class {
3231
+ constructor(services) {
3232
+ this.services = services;
3242
3233
  }
3243
3234
  compileProcedureCall(ast) {
3244
- const ctx = this.createCompilerContext();
3245
- const qualifiedName = ast.ref.schema ? `${this.quoteIdentifier(ast.ref.schema)}.${this.quoteIdentifier(ast.ref.name)}` : this.quoteIdentifier(ast.ref.name);
3235
+ const ctx = this.services.createCompilerContext();
3236
+ const qualifiedName = ast.ref.schema ? `${this.services.quoteIdentifier(ast.ref.schema)}.${this.services.quoteIdentifier(ast.ref.name)}` : this.services.quoteIdentifier(ast.ref.name);
3246
3237
  const declarations = [];
3247
3238
  const assignments = [];
3248
3239
  const execArgs = [];
@@ -3253,7 +3244,7 @@ var SqlServerDialect = class extends SqlDialectBase {
3253
3244
  if (!param.value) {
3254
3245
  throw new Error(`Procedure parameter "${param.name}" requires a value for direction "in".`);
3255
3246
  }
3256
- execArgs.push(`${targetParam} = ${this.compileOperand(param.value, ctx)}`);
3247
+ execArgs.push(`${targetParam} = ${this.services.compileOperand(param.value, ctx)}`);
3257
3248
  return;
3258
3249
  }
3259
3250
  if (!param.dbType) {
@@ -3268,7 +3259,7 @@ var SqlServerDialect = class extends SqlDialectBase {
3268
3259
  if (!param.value) {
3269
3260
  throw new Error(`Procedure parameter "${param.name}" requires a value for direction "inout".`);
3270
3261
  }
3271
- assignments.push(`SET ${variable} = ${this.compileOperand(param.value, ctx)};`);
3262
+ assignments.push(`SET ${variable} = ${this.services.compileOperand(param.value, ctx)};`);
3272
3263
  }
3273
3264
  execArgs.push(`${targetParam} = ${variable} OUTPUT`);
3274
3265
  outVars.push({ variable, name: param.name });
@@ -3279,7 +3270,7 @@ var SqlServerDialect = class extends SqlDialectBase {
3279
3270
  const argsSql = execArgs.length ? ` ${execArgs.join(", ")}` : "";
3280
3271
  statements.push(`EXEC ${qualifiedName}${argsSql};`);
3281
3272
  if (outVars.length) {
3282
- const selectOut = outVars.map(({ variable, name }) => `${variable} AS ${this.quoteIdentifier(name)}`).join(", ");
3273
+ const selectOut = outVars.map(({ variable, name }) => `${variable} AS ${this.services.quoteIdentifier(name)}`).join(", ");
3283
3274
  statements.push(`SELECT ${selectOut};`);
3284
3275
  }
3285
3276
  return {
@@ -3293,6 +3284,53 @@ var SqlServerDialect = class extends SqlDialectBase {
3293
3284
  }
3294
3285
  };
3295
3286
 
3287
+ // src/core/dialect/mssql/index.ts
3288
+ var quoteIdentifier4 = (id) => `[${id}]`;
3289
+ var createSqlServerDialect = () => {
3290
+ const composition = composeSqlDialect({
3291
+ name: "mssql",
3292
+ quoteIdentifier: quoteIdentifier4,
3293
+ formatPlaceholder: (index) => `@p${index}`,
3294
+ functionStrategy: new MssqlFunctionStrategy(),
3295
+ returningStrategy: new MssqlOutputStrategy(),
3296
+ compilerFactory: createMssqlCompilerSet,
3297
+ supportsDmlReturning: true,
3298
+ compileJsonPath(node) {
3299
+ const column = `${quoteIdentifier4(node.column.table)}.${quoteIdentifier4(node.column.name)}`;
3300
+ return `JSON_VALUE(${column}, '${node.path}')`;
3301
+ }
3302
+ });
3303
+ const procedures = new MssqlProcedureCompiler(composition.runtime);
3304
+ return {
3305
+ ...composition.dialect,
3306
+ compileProcedureCall: (ast) => procedures.compileProcedureCall(ast)
3307
+ };
3308
+ };
3309
+ var SqlServerDialect = class {
3310
+ impl = createSqlServerDialect();
3311
+ quoteIdentifier(id) {
3312
+ return this.impl.quoteIdentifier(id);
3313
+ }
3314
+ supportsDmlReturningClause() {
3315
+ return this.impl.supportsDmlReturningClause();
3316
+ }
3317
+ compileSelect(ast) {
3318
+ return this.impl.compileSelect(ast);
3319
+ }
3320
+ compileInsert(ast) {
3321
+ return this.impl.compileInsert(ast);
3322
+ }
3323
+ compileUpdate(ast) {
3324
+ return this.impl.compileUpdate(ast);
3325
+ }
3326
+ compileDelete(ast) {
3327
+ return this.impl.compileDelete(ast);
3328
+ }
3329
+ compileProcedureCall(ast) {
3330
+ return this.impl.compileProcedureCall(ast);
3331
+ }
3332
+ };
3333
+
3296
3334
  // src/core/dialect/dialect-factory.ts
3297
3335
  var DialectFactory = class {
3298
3336
  static registry = /* @__PURE__ */ new Map();
@@ -3300,59 +3338,33 @@ var DialectFactory = class {
3300
3338
  static ensureDefaults() {
3301
3339
  if (this.defaultsInitialized) return;
3302
3340
  this.defaultsInitialized = true;
3303
- if (!this.registry.has("postgres")) {
3304
- this.registry.set("postgres", () => new PostgresDialect());
3305
- }
3306
- if (!this.registry.has("mysql")) {
3307
- this.registry.set("mysql", () => new MySqlDialect());
3308
- }
3309
- if (!this.registry.has("sqlite")) {
3310
- this.registry.set("sqlite", () => new SqliteDialect());
3311
- }
3312
- if (!this.registry.has("mssql")) {
3313
- this.registry.set("mssql", () => new SqlServerDialect());
3314
- }
3341
+ if (!this.registry.has("postgres")) this.registry.set("postgres", createPostgresDialect);
3342
+ if (!this.registry.has("mysql")) this.registry.set("mysql", createMySqlDialect);
3343
+ if (!this.registry.has("sqlite")) this.registry.set("sqlite", createSqliteDialect);
3344
+ if (!this.registry.has("mssql")) this.registry.set("mssql", createSqlServerDialect);
3315
3345
  }
3316
- /**
3317
- * Register (or override) a dialect factory for a key.
3318
- *
3319
- * Implementations are structural: extending DialectBase/SqlDialectBase is
3320
- * optional. A composed object satisfying Dialect is a valid registration.
3321
- */
3346
+ /** Register or replace a structural dialect factory. */
3322
3347
  static register(key, factory) {
3323
3348
  this.registry.set(key, factory);
3324
3349
  }
3325
- /**
3326
- * Resolve a key into a Dialect instance.
3327
- * Throws if the key is not registered.
3328
- */
3350
+ /** Resolve a key into a new Dialect instance. */
3329
3351
  static create(key) {
3330
3352
  this.ensureDefaults();
3331
3353
  const factory = this.registry.get(key);
3332
3354
  if (!factory) {
3333
3355
  throw new Error(
3334
- `Dialect "${String(
3335
- key
3336
- )}" is not registered. Use DialectFactory.register(...) to register it.`
3356
+ `Dialect "${String(key)}" is not registered. Use DialectFactory.register(...) to register it.`
3337
3357
  );
3338
3358
  }
3339
3359
  return factory();
3340
3360
  }
3341
- /**
3342
- * Clear all registrations (mainly for tests).
3343
- * Built-ins will be re-registered lazily on the next create().
3344
- */
3361
+ /** Clear registrations; built-ins are restored lazily on the next create(). */
3345
3362
  static clear() {
3346
3363
  this.registry.clear();
3347
3364
  this.defaultsInitialized = false;
3348
3365
  }
3349
3366
  };
3350
- var resolveDialectInput = (dialect) => {
3351
- if (typeof dialect === "string") {
3352
- return DialectFactory.create(dialect);
3353
- }
3354
- return dialect;
3355
- };
3367
+ var resolveDialectInput = (dialect) => typeof dialect === "string" ? DialectFactory.create(dialect) : dialect;
3356
3368
 
3357
3369
  // src/core/ast/builders.ts
3358
3370
  var isColumnNode = (col2) => "type" in col2 && col2.type === "Column";
@@ -21752,7 +21764,6 @@ export {
21752
21764
  DefaultMorphToReference,
21753
21765
  DefaultTypeStrategy,
21754
21766
  DeleteQueryBuilder,
21755
- DialectBase,
21756
21767
  DialectFactory,
21757
21768
  DomainEventBus,
21758
21769
  Email,
@@ -21770,13 +21781,26 @@ export {
21770
21781
  MorphMany,
21771
21782
  MorphOne,
21772
21783
  MorphTo,
21784
+ MssqlDeleteCompiler,
21785
+ MssqlInsertCompiler,
21786
+ MssqlOutputStrategy,
21787
+ MssqlProcedureCompiler,
21788
+ MssqlSelectCompiler,
21789
+ MssqlUpdateCompiler,
21773
21790
  MySqlDialect,
21791
+ MySqlProcedureCompiler,
21792
+ MySqlUpsertStrategy,
21774
21793
  NestedSetStrategy,
21794
+ NoReturningStrategy,
21795
+ NoUpsertStrategy,
21775
21796
  Orm,
21776
21797
  OrmSession,
21777
21798
  Pattern,
21778
21799
  Pool,
21779
21800
  PostgresDialect,
21801
+ PostgresProcedureCompiler,
21802
+ PostgresReturningStrategy,
21803
+ PostgresUpsertStrategy,
21780
21804
  PrimaryKey,
21781
21805
  ProcedureCallBuilder,
21782
21806
  PrototypeMaterializationStrategy,
@@ -21787,10 +21811,15 @@ export {
21787
21811
  SelectQueryBuilder,
21788
21812
  SqlServerDialect,
21789
21813
  SqliteDialect,
21814
+ SqliteReturningStrategy,
21815
+ SqliteUpsertStrategy,
21790
21816
  StandardDeleteCompiler,
21791
21817
  StandardInsertCompiler,
21818
+ StandardLimitOffsetPagination,
21819
+ StandardReturningStrategy,
21792
21820
  StandardSelectCompiler,
21793
21821
  StandardSqlSourceCompiler,
21822
+ StandardTableFunctionStrategy,
21794
21823
  StandardUpdateCompiler,
21795
21824
  StringTypeStrategy,
21796
21825
  TagIndex,
@@ -21861,6 +21890,7 @@ export {
21861
21890
  columnToOpenApiSchema,
21862
21891
  columnTypeToOpenApiFormat,
21863
21892
  columnTypeToOpenApiType,
21893
+ composeSqlDialect,
21864
21894
  computePaginationMetadata,
21865
21895
  computeSchemaHash,
21866
21896
  concat,
@@ -21878,12 +21908,18 @@ export {
21878
21908
  createEntityFromRow,
21879
21909
  createEntityProxy,
21880
21910
  createExecutorFromQueryRunner,
21911
+ createMssqlCompilerSet,
21881
21912
  createMssqlExecutor,
21913
+ createMySqlDialect,
21882
21914
  createMysqlExecutor,
21883
21915
  createPooledExecutorFactory,
21916
+ createPostgresDialect,
21884
21917
  createPostgresExecutor,
21885
21918
  createQueryLoggingExecutor,
21886
21919
  createRef,
21920
+ createSqlDialect,
21921
+ createSqlServerDialect,
21922
+ createSqliteDialect,
21887
21923
  createSqliteExecutor,
21888
21924
  createTediousExecutor,
21889
21925
  createTediousMssqlClient,