metal-orm 1.1.22 → 1.1.23
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +267 -400
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +95 -151
- package/dist/index.d.ts +95 -151
- package/dist/index.js +262 -400
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/core/dialect/abstract.ts +94 -417
- package/src/core/dialect/base/expression-compiler-registry.ts +254 -0
- package/src/core/dialect/base/function-table-formatter.ts +40 -78
- package/src/core/dialect/base/select-ast-normalizer.ts +61 -0
- package/src/core/dialect/base/sql-dialect.ts +36 -59
- package/src/core/dialect/capabilities/procedure-compiler.ts +30 -0
- package/src/core/dialect/dialect-factory.ts +3 -4
- package/src/core/dialect/mssql/index.ts +3 -2
- package/src/core/dialect/mysql/index.ts +3 -2
- package/src/core/dialect/postgres/index.ts +3 -2
- package/src/core/dialect/sqlite/index.ts +1 -7
- package/src/index.ts +4 -1
- package/src/orm/execute-procedure.ts +3 -2
- package/src/query-builder/procedure-call.ts +4 -18
package/dist/index.cjs
CHANGED
|
@@ -74,6 +74,8 @@ __export(index_exports, {
|
|
|
74
74
|
DefaultMorphToReference: () => DefaultMorphToReference,
|
|
75
75
|
DefaultTypeStrategy: () => DefaultTypeStrategy,
|
|
76
76
|
DeleteQueryBuilder: () => DeleteQueryBuilder,
|
|
77
|
+
DialectBase: () => DialectBase,
|
|
78
|
+
DialectFactory: () => DialectFactory,
|
|
77
79
|
DomainEventBus: () => DomainEventBus,
|
|
78
80
|
Email: () => Email,
|
|
79
81
|
Entity: () => Entity,
|
|
@@ -301,6 +303,7 @@ __export(index_exports, {
|
|
|
301
303
|
isNull: () => isNull,
|
|
302
304
|
isNullableColumn: () => isNullableColumn,
|
|
303
305
|
isOperandNode: () => isOperandNode,
|
|
306
|
+
isProcedureCompiler: () => isProcedureCompiler,
|
|
304
307
|
isSingleTargetRelation: () => isSingleTargetRelation,
|
|
305
308
|
isTableDef: () => isTableDef2,
|
|
306
309
|
isTreeConfig: () => isTreeConfig,
|
|
@@ -398,6 +401,8 @@ __export(index_exports, {
|
|
|
398
401
|
repeat: () => repeat,
|
|
399
402
|
replace: () => replace,
|
|
400
403
|
replaceWithRefs: () => replaceWithRefs,
|
|
404
|
+
requireProcedureCompiler: () => requireProcedureCompiler,
|
|
405
|
+
resolveDialectInput: () => resolveDialectInput,
|
|
401
406
|
resolveTreeConfig: () => resolveTreeConfig,
|
|
402
407
|
resolveValidator: () => resolveValidator,
|
|
403
408
|
responseToRef: () => responseToRef,
|
|
@@ -1755,268 +1760,40 @@ var StandardTableFunctionStrategy = class {
|
|
|
1755
1760
|
}
|
|
1756
1761
|
};
|
|
1757
1762
|
|
|
1758
|
-
// src/core/dialect/
|
|
1759
|
-
var
|
|
1760
|
-
|
|
1761
|
-
|
|
1762
|
-
* @param ast - Query AST to compile
|
|
1763
|
-
* @returns Compiled query with SQL and parameters
|
|
1764
|
-
*/
|
|
1765
|
-
compileSelect(ast) {
|
|
1766
|
-
const ctx = this.createCompilerContext();
|
|
1767
|
-
const normalized = this.normalizeSelectAst(ast);
|
|
1768
|
-
const rawSql = this.compileSelectAst(normalized, ctx).trim();
|
|
1769
|
-
const sql = rawSql.endsWith(";") ? rawSql : `${rawSql};`;
|
|
1770
|
-
return {
|
|
1771
|
-
sql,
|
|
1772
|
-
params: [...ctx.params]
|
|
1773
|
-
};
|
|
1774
|
-
}
|
|
1775
|
-
compileInsert(ast) {
|
|
1776
|
-
const ctx = this.createCompilerContext();
|
|
1777
|
-
const rawSql = this.compileInsertAst(ast, ctx).trim();
|
|
1778
|
-
const sql = rawSql.endsWith(";") ? rawSql : `${rawSql};`;
|
|
1779
|
-
return {
|
|
1780
|
-
sql,
|
|
1781
|
-
params: [...ctx.params]
|
|
1782
|
-
};
|
|
1783
|
-
}
|
|
1784
|
-
compileUpdate(ast) {
|
|
1785
|
-
const ctx = this.createCompilerContext();
|
|
1786
|
-
const rawSql = this.compileUpdateAst(ast, ctx).trim();
|
|
1787
|
-
const sql = rawSql.endsWith(";") ? rawSql : `${rawSql};`;
|
|
1788
|
-
return {
|
|
1789
|
-
sql,
|
|
1790
|
-
params: [...ctx.params]
|
|
1791
|
-
};
|
|
1792
|
-
}
|
|
1793
|
-
compileDelete(ast) {
|
|
1794
|
-
const ctx = this.createCompilerContext();
|
|
1795
|
-
const rawSql = this.compileDeleteAst(ast, ctx).trim();
|
|
1796
|
-
const sql = rawSql.endsWith(";") ? rawSql : `${rawSql};`;
|
|
1797
|
-
return {
|
|
1798
|
-
sql,
|
|
1799
|
-
params: [...ctx.params]
|
|
1800
|
-
};
|
|
1801
|
-
}
|
|
1802
|
-
supportsDmlReturningClause() {
|
|
1803
|
-
return false;
|
|
1804
|
-
}
|
|
1805
|
-
/**
|
|
1806
|
-
* Compiles a WHERE clause
|
|
1807
|
-
* @param where - WHERE expression
|
|
1808
|
-
* @param ctx - Compiler context
|
|
1809
|
-
* @returns SQL WHERE clause or empty string
|
|
1810
|
-
*/
|
|
1811
|
-
compileWhere(where, ctx) {
|
|
1812
|
-
if (!where) return "";
|
|
1813
|
-
return ` WHERE ${this.compileExpression(where, ctx)}`;
|
|
1814
|
-
}
|
|
1815
|
-
compileReturning(returning, _ctx) {
|
|
1816
|
-
void _ctx;
|
|
1817
|
-
if (!returning || returning.length === 0) return "";
|
|
1818
|
-
throw new Error("RETURNING is not supported by this dialect.");
|
|
1819
|
-
}
|
|
1820
|
-
/**
|
|
1821
|
-
* Generates subquery for EXISTS expressions
|
|
1822
|
-
* Rule: Always forces SELECT 1, ignoring column list
|
|
1823
|
-
* Maintains FROM, JOINs, WHERE, GROUP BY, ORDER BY, LIMIT/OFFSET
|
|
1824
|
-
* Does not add ';' at the end
|
|
1825
|
-
* @param ast - Query AST
|
|
1826
|
-
* @param ctx - Compiler context
|
|
1827
|
-
* @returns SQL for EXISTS subquery
|
|
1828
|
-
*/
|
|
1829
|
-
compileSelectForExists(ast, ctx) {
|
|
1830
|
-
const normalized = this.normalizeSelectAst(ast);
|
|
1831
|
-
const full = this.compileSelectAst(normalized, ctx).trim().replace(/;$/, "");
|
|
1832
|
-
if (normalized.setOps && normalized.setOps.length > 0) {
|
|
1833
|
-
return `SELECT 1 FROM (${full}) AS _exists`;
|
|
1834
|
-
}
|
|
1835
|
-
const upper2 = full.toUpperCase();
|
|
1836
|
-
const fromIndex = upper2.indexOf(" FROM ");
|
|
1837
|
-
if (fromIndex === -1) {
|
|
1838
|
-
return full;
|
|
1839
|
-
}
|
|
1840
|
-
const tail = full.slice(fromIndex);
|
|
1841
|
-
return `SELECT 1${tail}`;
|
|
1842
|
-
}
|
|
1843
|
-
/**
|
|
1844
|
-
* Creates a new compiler context
|
|
1845
|
-
* @returns Compiler context with parameter management
|
|
1846
|
-
*/
|
|
1847
|
-
createCompilerContext() {
|
|
1848
|
-
const params = [];
|
|
1849
|
-
let counter = 0;
|
|
1850
|
-
return {
|
|
1851
|
-
params,
|
|
1852
|
-
addParameter: (value) => {
|
|
1853
|
-
counter += 1;
|
|
1854
|
-
params.push(value);
|
|
1855
|
-
return this.formatPlaceholder(counter);
|
|
1856
|
-
}
|
|
1857
|
-
};
|
|
1858
|
-
}
|
|
1859
|
-
/**
|
|
1860
|
-
* Formats a parameter placeholder
|
|
1861
|
-
* @param index - Parameter index
|
|
1862
|
-
* @returns Formatted placeholder string
|
|
1863
|
-
*/
|
|
1864
|
-
formatPlaceholder(_index) {
|
|
1865
|
-
void _index;
|
|
1866
|
-
return "?";
|
|
1867
|
-
}
|
|
1868
|
-
/**
|
|
1869
|
-
* Whether the current dialect supports a given set operation.
|
|
1870
|
-
* Override in concrete dialects to restrict support.
|
|
1871
|
-
*/
|
|
1872
|
-
supportsSetOperation(_kind) {
|
|
1873
|
-
void _kind;
|
|
1874
|
-
return true;
|
|
1875
|
-
}
|
|
1876
|
-
/**
|
|
1877
|
-
* Validates set-operation semantics:
|
|
1878
|
-
* - Ensures the dialect supports requested operators.
|
|
1879
|
-
* - Enforces that only the outermost compound query may have ORDER/LIMIT/OFFSET.
|
|
1880
|
-
* @param ast - Query to validate
|
|
1881
|
-
* @param isOutermost - Whether this node is the outermost compound query
|
|
1882
|
-
*/
|
|
1883
|
-
validateSetOperations(ast, isOutermost = true) {
|
|
1884
|
-
const hasSetOps = !!(ast.setOps && ast.setOps.length);
|
|
1885
|
-
if (!isOutermost && (ast.orderBy || ast.limit !== void 0 || ast.offset !== void 0)) {
|
|
1886
|
-
throw new Error("ORDER BY / LIMIT / OFFSET are only allowed on the outermost compound query.");
|
|
1887
|
-
}
|
|
1888
|
-
if (hasSetOps) {
|
|
1889
|
-
for (const op of ast.setOps) {
|
|
1890
|
-
if (!this.supportsSetOperation(op.operator)) {
|
|
1891
|
-
throw new Error(`Set operation ${op.operator} is not supported by this dialect.`);
|
|
1892
|
-
}
|
|
1893
|
-
this.validateSetOperations(op.query, false);
|
|
1894
|
-
}
|
|
1895
|
-
}
|
|
1896
|
-
}
|
|
1897
|
-
/**
|
|
1898
|
-
* Hoists CTEs from set-operation operands to the outermost query so WITH appears once.
|
|
1899
|
-
* @param ast - Query AST
|
|
1900
|
-
* @returns Normalized AST without inner CTEs and a list of hoisted CTEs
|
|
1901
|
-
*/
|
|
1902
|
-
hoistCtes(ast) {
|
|
1903
|
-
let hoisted = [];
|
|
1904
|
-
const normalizedSetOps = ast.setOps?.map((op) => {
|
|
1905
|
-
const { normalized: child, hoistedCtes: childHoisted } = this.hoistCtes(op.query);
|
|
1906
|
-
const childCtes = child.ctes ?? [];
|
|
1907
|
-
if (childCtes.length) {
|
|
1908
|
-
hoisted = hoisted.concat(childCtes);
|
|
1909
|
-
}
|
|
1910
|
-
hoisted = hoisted.concat(childHoisted);
|
|
1911
|
-
const queryWithoutCtes = childCtes.length ? { ...child, ctes: void 0 } : child;
|
|
1912
|
-
return { ...op, query: queryWithoutCtes };
|
|
1913
|
-
});
|
|
1914
|
-
const normalized = normalizedSetOps ? { ...ast, setOps: normalizedSetOps } : ast;
|
|
1915
|
-
return { normalized, hoistedCtes: hoisted };
|
|
1916
|
-
}
|
|
1917
|
-
/**
|
|
1918
|
-
* Normalizes a SELECT AST before compilation (validation + CTE hoisting).
|
|
1919
|
-
* @param ast - Query AST
|
|
1920
|
-
* @returns Normalized query AST
|
|
1921
|
-
*/
|
|
1922
|
-
normalizeSelectAst(ast) {
|
|
1923
|
-
this.validateSetOperations(ast, true);
|
|
1924
|
-
const { normalized, hoistedCtes } = this.hoistCtes(ast);
|
|
1925
|
-
const combinedCtes = [...normalized.ctes ?? [], ...hoistedCtes];
|
|
1926
|
-
return combinedCtes.length ? { ...normalized, ctes: combinedCtes } : normalized;
|
|
1927
|
-
}
|
|
1928
|
-
expressionCompilers;
|
|
1929
|
-
operandCompilers;
|
|
1930
|
-
functionStrategy;
|
|
1931
|
-
tableFunctionStrategy;
|
|
1932
|
-
constructor(functionStrategy, tableFunctionStrategy) {
|
|
1933
|
-
this.expressionCompilers = /* @__PURE__ */ new Map();
|
|
1934
|
-
this.operandCompilers = /* @__PURE__ */ new Map();
|
|
1935
|
-
this.functionStrategy = functionStrategy || new StandardFunctionStrategy();
|
|
1936
|
-
this.tableFunctionStrategy = tableFunctionStrategy || new StandardTableFunctionStrategy();
|
|
1763
|
+
// src/core/dialect/base/expression-compiler-registry.ts
|
|
1764
|
+
var ExpressionCompilerRegistry = class {
|
|
1765
|
+
constructor(host) {
|
|
1766
|
+
this.host = host;
|
|
1937
1767
|
this.registerDefaultOperandCompilers();
|
|
1938
1768
|
this.registerDefaultExpressionCompilers();
|
|
1939
1769
|
}
|
|
1940
|
-
|
|
1941
|
-
|
|
1942
|
-
* @param functionStrategy - Optional function strategy
|
|
1943
|
-
* @returns New Dialect instance
|
|
1944
|
-
*/
|
|
1945
|
-
static create(functionStrategy, tableFunctionStrategy) {
|
|
1946
|
-
class TestDialect extends _Dialect {
|
|
1947
|
-
dialect = "sqlite";
|
|
1948
|
-
quoteIdentifier(id) {
|
|
1949
|
-
return `"${id}"`;
|
|
1950
|
-
}
|
|
1951
|
-
compileSelectAst() {
|
|
1952
|
-
throw new Error("Not implemented");
|
|
1953
|
-
}
|
|
1954
|
-
compileInsertAst() {
|
|
1955
|
-
throw new Error("Not implemented");
|
|
1956
|
-
}
|
|
1957
|
-
compileUpdateAst() {
|
|
1958
|
-
throw new Error("Not implemented");
|
|
1959
|
-
}
|
|
1960
|
-
compileDeleteAst() {
|
|
1961
|
-
throw new Error("Not implemented");
|
|
1962
|
-
}
|
|
1963
|
-
compileProcedureCall() {
|
|
1964
|
-
throw new Error("Not implemented");
|
|
1965
|
-
}
|
|
1966
|
-
}
|
|
1967
|
-
return new TestDialect(functionStrategy, tableFunctionStrategy);
|
|
1968
|
-
}
|
|
1969
|
-
/**
|
|
1970
|
-
* Registers an expression compiler for a specific node type
|
|
1971
|
-
* @param type - Expression node type
|
|
1972
|
-
* @param compiler - Compiler function
|
|
1973
|
-
*/
|
|
1770
|
+
expressionCompilers = /* @__PURE__ */ new Map();
|
|
1771
|
+
operandCompilers = /* @__PURE__ */ new Map();
|
|
1974
1772
|
registerExpressionCompiler(type, compiler) {
|
|
1975
1773
|
this.expressionCompilers.set(type, compiler);
|
|
1976
1774
|
}
|
|
1977
|
-
/**
|
|
1978
|
-
* Registers an operand compiler for a specific node type
|
|
1979
|
-
* @param type - Operand node type
|
|
1980
|
-
* @param compiler - Compiler function
|
|
1981
|
-
*/
|
|
1982
1775
|
registerOperandCompiler(type, compiler) {
|
|
1983
1776
|
this.operandCompilers.set(type, compiler);
|
|
1984
1777
|
}
|
|
1985
|
-
/**
|
|
1986
|
-
* Compiles an expression node
|
|
1987
|
-
* @param node - Expression node to compile
|
|
1988
|
-
* @param ctx - Compiler context
|
|
1989
|
-
* @returns Compiled SQL expression
|
|
1990
|
-
*/
|
|
1991
1778
|
compileExpression(node, ctx) {
|
|
1992
1779
|
const compiler = this.expressionCompilers.get(node.type);
|
|
1993
1780
|
if (!compiler) {
|
|
1994
|
-
throw new Error(`Unsupported expression node type "${node.type}" for ${this.
|
|
1781
|
+
throw new Error(`Unsupported expression node type "${node.type}" for ${this.host.describe()}`);
|
|
1995
1782
|
}
|
|
1996
1783
|
return compiler(node, ctx);
|
|
1997
1784
|
}
|
|
1998
|
-
/**
|
|
1999
|
-
* Compiles an operand node
|
|
2000
|
-
* @param node - Operand node to compile
|
|
2001
|
-
* @param ctx - Compiler context
|
|
2002
|
-
* @returns Compiled SQL operand
|
|
2003
|
-
*/
|
|
2004
1785
|
compileOperand(node, ctx) {
|
|
2005
1786
|
const compiler = this.operandCompilers.get(node.type);
|
|
2006
1787
|
if (!compiler) {
|
|
2007
|
-
throw new Error(`Unsupported operand node type "${node.type}" for ${this.
|
|
1788
|
+
throw new Error(`Unsupported operand node type "${node.type}" for ${this.host.describe()}`);
|
|
2008
1789
|
}
|
|
2009
1790
|
return compiler(node, ctx);
|
|
2010
1791
|
}
|
|
2011
|
-
/**
|
|
2012
|
-
* Compiles an ordering term (operand, expression, or alias reference).
|
|
2013
|
-
*/
|
|
2014
1792
|
compileOrderingTerm(term, ctx) {
|
|
2015
1793
|
if (isOperandNode(term)) {
|
|
2016
1794
|
return this.compileOperand(term, ctx);
|
|
2017
1795
|
}
|
|
2018
|
-
|
|
2019
|
-
return `(${expr})`;
|
|
1796
|
+
return `(${this.compileExpression(term, ctx)})`;
|
|
2020
1797
|
}
|
|
2021
1798
|
registerDefaultExpressionCompilers() {
|
|
2022
1799
|
this.registerExpressionCompiler("BinaryExpression", (binary, ctx) => {
|
|
@@ -2051,11 +1828,11 @@ var Dialect = class _Dialect {
|
|
|
2051
1828
|
const values = inExpr.right.map((v) => this.compileOperand(v, ctx)).join(", ");
|
|
2052
1829
|
return `${left2} ${inExpr.operator} (${values})`;
|
|
2053
1830
|
}
|
|
2054
|
-
const subquerySql = this.compileSelectAst(inExpr.right.query, ctx).trim().replace(/;$/, "");
|
|
1831
|
+
const subquerySql = this.host.compileSelectAst(inExpr.right.query, ctx).trim().replace(/;$/, "");
|
|
2055
1832
|
return `${left2} ${inExpr.operator} (${subquerySql})`;
|
|
2056
1833
|
});
|
|
2057
1834
|
this.registerExpressionCompiler("ExistsExpression", (existsExpr, ctx) => {
|
|
2058
|
-
const subquerySql = this.compileSelectForExists(existsExpr.subquery, ctx);
|
|
1835
|
+
const subquerySql = this.host.compileSelectForExists(existsExpr.subquery, ctx);
|
|
2059
1836
|
return `${existsExpr.operator} (${subquerySql})`;
|
|
2060
1837
|
});
|
|
2061
1838
|
this.registerExpressionCompiler("BetweenExpression", (betweenExpr, ctx) => {
|
|
@@ -2081,25 +1858,28 @@ var Dialect = class _Dialect {
|
|
|
2081
1858
|
});
|
|
2082
1859
|
}
|
|
2083
1860
|
registerDefaultOperandCompilers() {
|
|
2084
|
-
this.registerOperandCompiler(
|
|
2085
|
-
|
|
2086
|
-
|
|
2087
|
-
|
|
2088
|
-
|
|
2089
|
-
|
|
2090
|
-
|
|
2091
|
-
|
|
2092
|
-
|
|
1861
|
+
this.registerOperandCompiler(
|
|
1862
|
+
"Literal",
|
|
1863
|
+
(literal, ctx) => ctx.addParameter(literal.value)
|
|
1864
|
+
);
|
|
1865
|
+
this.registerOperandCompiler(
|
|
1866
|
+
"AliasRef",
|
|
1867
|
+
(alias) => this.host.quoteIdentifier(alias.name)
|
|
1868
|
+
);
|
|
1869
|
+
this.registerOperandCompiler(
|
|
1870
|
+
"Column",
|
|
1871
|
+
(column) => `${this.host.quoteIdentifier(column.table)}.${this.host.quoteIdentifier(column.name)}`
|
|
1872
|
+
);
|
|
2093
1873
|
this.registerOperandCompiler(
|
|
2094
1874
|
"Function",
|
|
2095
|
-
(fnNode, ctx) => this.compileFunctionOperand(fnNode, ctx)
|
|
1875
|
+
(fnNode, ctx) => this.host.compileFunctionOperand(fnNode, ctx)
|
|
1876
|
+
);
|
|
1877
|
+
this.registerOperandCompiler(
|
|
1878
|
+
"JsonPath",
|
|
1879
|
+
(path) => this.host.compileJsonPath(path)
|
|
2096
1880
|
);
|
|
2097
|
-
this.registerOperandCompiler("JsonPath", (path, _ctx) => {
|
|
2098
|
-
void _ctx;
|
|
2099
|
-
return this.compileJsonPath(path);
|
|
2100
|
-
});
|
|
2101
1881
|
this.registerOperandCompiler("ScalarSubquery", (node, ctx) => {
|
|
2102
|
-
const sql = this.compileSelectAst(node.query, ctx).trim().replace(/;$/, "");
|
|
1882
|
+
const sql = this.host.compileSelectAst(node.query, ctx).trim().replace(/;$/, "");
|
|
2103
1883
|
return `(${sql})`;
|
|
2104
1884
|
});
|
|
2105
1885
|
this.registerOperandCompiler("CaseExpression", (node, ctx) => {
|
|
@@ -2126,7 +1906,7 @@ var Dialect = class _Dialect {
|
|
|
2126
1906
|
const parts = [];
|
|
2127
1907
|
if (node.partitionBy && node.partitionBy.length > 0) {
|
|
2128
1908
|
const partitionClause = "PARTITION BY " + node.partitionBy.map(
|
|
2129
|
-
(col2) => `${this.quoteIdentifier(col2.table)}.${this.quoteIdentifier(col2.name)}`
|
|
1909
|
+
(col2) => `${this.host.quoteIdentifier(col2.table)}.${this.host.quoteIdentifier(col2.name)}`
|
|
2130
1910
|
).join(", ");
|
|
2131
1911
|
parts.push(partitionClause);
|
|
2132
1912
|
}
|
|
@@ -2158,14 +1938,164 @@ var Dialect = class _Dialect {
|
|
|
2158
1938
|
return `${expr} COLLATE ${node.collation}`;
|
|
2159
1939
|
});
|
|
2160
1940
|
}
|
|
2161
|
-
|
|
1941
|
+
};
|
|
1942
|
+
|
|
1943
|
+
// src/core/dialect/base/select-ast-normalizer.ts
|
|
1944
|
+
var SelectAstNormalizer = class {
|
|
1945
|
+
constructor(supportsSetOperation) {
|
|
1946
|
+
this.supportsSetOperation = supportsSetOperation;
|
|
1947
|
+
}
|
|
1948
|
+
normalize(ast) {
|
|
1949
|
+
this.validateSetOperations(ast, true);
|
|
1950
|
+
const { normalized, hoistedCtes } = this.hoistCtes(ast);
|
|
1951
|
+
const combinedCtes = [...normalized.ctes ?? [], ...hoistedCtes];
|
|
1952
|
+
return combinedCtes.length ? { ...normalized, ctes: combinedCtes } : normalized;
|
|
1953
|
+
}
|
|
1954
|
+
validateSetOperations(ast, isOutermost) {
|
|
1955
|
+
const hasSetOps = !!(ast.setOps && ast.setOps.length);
|
|
1956
|
+
if (!isOutermost && (ast.orderBy || ast.limit !== void 0 || ast.offset !== void 0)) {
|
|
1957
|
+
throw new Error("ORDER BY / LIMIT / OFFSET are only allowed on the outermost compound query.");
|
|
1958
|
+
}
|
|
1959
|
+
if (!hasSetOps) return;
|
|
1960
|
+
for (const op of ast.setOps) {
|
|
1961
|
+
if (!this.supportsSetOperation(op.operator)) {
|
|
1962
|
+
throw new Error(`Set operation ${op.operator} is not supported by this dialect.`);
|
|
1963
|
+
}
|
|
1964
|
+
this.validateSetOperations(op.query, false);
|
|
1965
|
+
}
|
|
1966
|
+
}
|
|
1967
|
+
hoistCtes(ast) {
|
|
1968
|
+
let hoisted = [];
|
|
1969
|
+
const normalizedSetOps = ast.setOps?.map((op) => {
|
|
1970
|
+
const { normalized: child, hoistedCtes: childHoisted } = this.hoistCtes(op.query);
|
|
1971
|
+
const childCtes = child.ctes ?? [];
|
|
1972
|
+
if (childCtes.length) hoisted = hoisted.concat(childCtes);
|
|
1973
|
+
hoisted = hoisted.concat(childHoisted);
|
|
1974
|
+
const queryWithoutCtes = childCtes.length ? { ...child, ctes: void 0 } : child;
|
|
1975
|
+
return { ...op, query: queryWithoutCtes };
|
|
1976
|
+
});
|
|
1977
|
+
const normalized = normalizedSetOps ? { ...ast, setOps: normalizedSetOps } : ast;
|
|
1978
|
+
return { normalized, hoistedCtes: hoisted };
|
|
1979
|
+
}
|
|
1980
|
+
};
|
|
1981
|
+
|
|
1982
|
+
// src/core/dialect/abstract.ts
|
|
1983
|
+
var DialectBase = class _DialectBase {
|
|
1984
|
+
expressionCompilerRegistry;
|
|
1985
|
+
selectAstNormalizer;
|
|
1986
|
+
functionStrategy;
|
|
1987
|
+
tableFunctionStrategy;
|
|
1988
|
+
constructor(functionStrategy, tableFunctionStrategy) {
|
|
1989
|
+
this.functionStrategy = functionStrategy ?? new StandardFunctionStrategy();
|
|
1990
|
+
this.tableFunctionStrategy = tableFunctionStrategy ?? new StandardTableFunctionStrategy();
|
|
1991
|
+
this.selectAstNormalizer = new SelectAstNormalizer((kind) => this.supportsSetOperation(kind));
|
|
1992
|
+
this.expressionCompilerRegistry = new ExpressionCompilerRegistry({
|
|
1993
|
+
quoteIdentifier: (id) => this.quoteIdentifier(id),
|
|
1994
|
+
compileSelectAst: (ast, ctx) => this.compileSelectAst(ast, ctx),
|
|
1995
|
+
compileSelectForExists: (ast, ctx) => this.compileSelectForExists(ast, ctx),
|
|
1996
|
+
compileJsonPath: (node) => this.compileJsonPath(node),
|
|
1997
|
+
compileFunctionOperand: (node, ctx) => this.compileFunctionOperand(node, ctx),
|
|
1998
|
+
describe: () => this.constructor.name
|
|
1999
|
+
});
|
|
2000
|
+
}
|
|
2001
|
+
compileSelect(ast) {
|
|
2002
|
+
const ctx = this.createCompilerContext();
|
|
2003
|
+
const normalized = this.normalizeSelectAst(ast);
|
|
2004
|
+
const rawSql = this.compileSelectAst(normalized, ctx).trim();
|
|
2005
|
+
return {
|
|
2006
|
+
sql: rawSql.endsWith(";") ? rawSql : `${rawSql};`,
|
|
2007
|
+
params: [...ctx.params]
|
|
2008
|
+
};
|
|
2009
|
+
}
|
|
2010
|
+
compileInsert(ast) {
|
|
2011
|
+
const ctx = this.createCompilerContext();
|
|
2012
|
+
const rawSql = this.compileInsertAst(ast, ctx).trim();
|
|
2013
|
+
return {
|
|
2014
|
+
sql: rawSql.endsWith(";") ? rawSql : `${rawSql};`,
|
|
2015
|
+
params: [...ctx.params]
|
|
2016
|
+
};
|
|
2017
|
+
}
|
|
2018
|
+
compileUpdate(ast) {
|
|
2019
|
+
const ctx = this.createCompilerContext();
|
|
2020
|
+
const rawSql = this.compileUpdateAst(ast, ctx).trim();
|
|
2021
|
+
return {
|
|
2022
|
+
sql: rawSql.endsWith(";") ? rawSql : `${rawSql};`,
|
|
2023
|
+
params: [...ctx.params]
|
|
2024
|
+
};
|
|
2025
|
+
}
|
|
2026
|
+
compileDelete(ast) {
|
|
2027
|
+
const ctx = this.createCompilerContext();
|
|
2028
|
+
const rawSql = this.compileDeleteAst(ast, ctx).trim();
|
|
2029
|
+
return {
|
|
2030
|
+
sql: rawSql.endsWith(";") ? rawSql : `${rawSql};`,
|
|
2031
|
+
params: [...ctx.params]
|
|
2032
|
+
};
|
|
2033
|
+
}
|
|
2034
|
+
supportsDmlReturningClause() {
|
|
2035
|
+
return false;
|
|
2036
|
+
}
|
|
2037
|
+
compileWhere(where, ctx) {
|
|
2038
|
+
if (!where) return "";
|
|
2039
|
+
return ` WHERE ${this.compileExpression(where, ctx)}`;
|
|
2040
|
+
}
|
|
2041
|
+
compileReturning(returning, _ctx) {
|
|
2042
|
+
void _ctx;
|
|
2043
|
+
if (!returning || returning.length === 0) return "";
|
|
2044
|
+
throw new Error("RETURNING is not supported by this dialect.");
|
|
2045
|
+
}
|
|
2046
|
+
compileSelectForExists(ast, ctx) {
|
|
2047
|
+
const normalized = this.normalizeSelectAst(ast);
|
|
2048
|
+
const full = this.compileSelectAst(normalized, ctx).trim().replace(/;$/, "");
|
|
2049
|
+
if (normalized.setOps && normalized.setOps.length > 0) {
|
|
2050
|
+
return `SELECT 1 FROM (${full}) AS _exists`;
|
|
2051
|
+
}
|
|
2052
|
+
const upper2 = full.toUpperCase();
|
|
2053
|
+
const fromIndex = upper2.indexOf(" FROM ");
|
|
2054
|
+
if (fromIndex === -1) return full;
|
|
2055
|
+
return `SELECT 1${full.slice(fromIndex)}`;
|
|
2056
|
+
}
|
|
2057
|
+
createCompilerContext() {
|
|
2058
|
+
const params = [];
|
|
2059
|
+
let counter = 0;
|
|
2060
|
+
return {
|
|
2061
|
+
params,
|
|
2062
|
+
addParameter: (value) => {
|
|
2063
|
+
counter += 1;
|
|
2064
|
+
params.push(value);
|
|
2065
|
+
return this.formatPlaceholder(counter);
|
|
2066
|
+
}
|
|
2067
|
+
};
|
|
2068
|
+
}
|
|
2069
|
+
formatPlaceholder(_index) {
|
|
2070
|
+
void _index;
|
|
2071
|
+
return "?";
|
|
2072
|
+
}
|
|
2073
|
+
supportsSetOperation(_kind) {
|
|
2074
|
+
void _kind;
|
|
2075
|
+
return true;
|
|
2076
|
+
}
|
|
2077
|
+
normalizeSelectAst(ast) {
|
|
2078
|
+
return this.selectAstNormalizer.normalize(ast);
|
|
2079
|
+
}
|
|
2080
|
+
registerExpressionCompiler(type, compiler) {
|
|
2081
|
+
this.expressionCompilerRegistry.registerExpressionCompiler(type, compiler);
|
|
2082
|
+
}
|
|
2083
|
+
registerOperandCompiler(type, compiler) {
|
|
2084
|
+
this.expressionCompilerRegistry.registerOperandCompiler(type, compiler);
|
|
2085
|
+
}
|
|
2086
|
+
compileExpression(node, ctx) {
|
|
2087
|
+
return this.expressionCompilerRegistry.compileExpression(node, ctx);
|
|
2088
|
+
}
|
|
2089
|
+
compileOperand(node, ctx) {
|
|
2090
|
+
return this.expressionCompilerRegistry.compileOperand(node, ctx);
|
|
2091
|
+
}
|
|
2092
|
+
compileOrderingTerm(term, ctx) {
|
|
2093
|
+
return this.expressionCompilerRegistry.compileOrderingTerm(term, ctx);
|
|
2094
|
+
}
|
|
2162
2095
|
compileJsonPath(_node) {
|
|
2163
2096
|
void _node;
|
|
2164
2097
|
throw new Error("JSON Path not supported by this dialect");
|
|
2165
2098
|
}
|
|
2166
|
-
/**
|
|
2167
|
-
* Compiles a function operand, using the dialect's function strategy.
|
|
2168
|
-
*/
|
|
2169
2099
|
compileFunctionOperand(fnNode, ctx) {
|
|
2170
2100
|
const compiledArgs = fnNode.args.map((arg) => this.compileOperand(arg, ctx));
|
|
2171
2101
|
const renderer = this.functionStrategy.getRenderer(fnNode.name);
|
|
@@ -2178,98 +2108,62 @@ var Dialect = class _Dialect {
|
|
|
2178
2108
|
}
|
|
2179
2109
|
return `${fnNode.name}(${compiledArgs.join(", ")})`;
|
|
2180
2110
|
}
|
|
2111
|
+
/** Creates a minimal dialect implementation for isolated compiler tests. */
|
|
2112
|
+
static create(functionStrategy, tableFunctionStrategy) {
|
|
2113
|
+
class TestDialect extends _DialectBase {
|
|
2114
|
+
dialect = "sqlite";
|
|
2115
|
+
quoteIdentifier(id) {
|
|
2116
|
+
return `"${id}"`;
|
|
2117
|
+
}
|
|
2118
|
+
compileSelectAst() {
|
|
2119
|
+
throw new Error("Not implemented");
|
|
2120
|
+
}
|
|
2121
|
+
compileInsertAst() {
|
|
2122
|
+
throw new Error("Not implemented");
|
|
2123
|
+
}
|
|
2124
|
+
compileUpdateAst() {
|
|
2125
|
+
throw new Error("Not implemented");
|
|
2126
|
+
}
|
|
2127
|
+
compileDeleteAst() {
|
|
2128
|
+
throw new Error("Not implemented");
|
|
2129
|
+
}
|
|
2130
|
+
}
|
|
2131
|
+
return new TestDialect(functionStrategy, tableFunctionStrategy);
|
|
2132
|
+
}
|
|
2181
2133
|
};
|
|
2182
2134
|
|
|
2183
2135
|
// src/core/dialect/base/function-table-formatter.ts
|
|
2184
2136
|
var FunctionTableFormatter = class {
|
|
2185
|
-
|
|
2186
|
-
|
|
2187
|
-
|
|
2188
|
-
* @param ctx - Optional compiler context for operand compilation.
|
|
2189
|
-
* @param dialect - The dialect instance for compiling operands.
|
|
2190
|
-
* @returns SQL function table expression (e.g., "LATERAL schema.func(args) WITH ORDINALITY AS alias(col1, col2)").
|
|
2191
|
-
*/
|
|
2192
|
-
static format(fn9, ctx, dialect) {
|
|
2193
|
-
const schemaPart = this.formatSchema(fn9, dialect);
|
|
2194
|
-
const args = this.formatArgs(fn9, ctx, dialect);
|
|
2137
|
+
static format(fn9, ctx, formatter) {
|
|
2138
|
+
const schemaPart = this.formatSchema(fn9, formatter);
|
|
2139
|
+
const args = this.formatArgs(fn9, ctx, formatter);
|
|
2195
2140
|
const base = this.formatBase(fn9, schemaPart, args);
|
|
2196
2141
|
const lateral = this.formatLateral(fn9);
|
|
2197
|
-
const alias = this.formatAlias(fn9,
|
|
2198
|
-
const colAliases = this.formatColumnAliases(fn9,
|
|
2142
|
+
const alias = this.formatAlias(fn9, formatter);
|
|
2143
|
+
const colAliases = this.formatColumnAliases(fn9, formatter);
|
|
2199
2144
|
return `${lateral}${base}${alias}${colAliases}`;
|
|
2200
2145
|
}
|
|
2201
|
-
|
|
2202
|
-
* Formats the schema prefix for the function name.
|
|
2203
|
-
* @param fn - The function table node.
|
|
2204
|
-
* @param dialect - The dialect instance for quoting identifiers.
|
|
2205
|
-
* @returns Schema prefix (e.g., "schema.") or empty string.
|
|
2206
|
-
* @internal
|
|
2207
|
-
*/
|
|
2208
|
-
static formatSchema(fn9, dialect) {
|
|
2146
|
+
static formatSchema(fn9, formatter) {
|
|
2209
2147
|
if (!fn9.schema) return "";
|
|
2210
|
-
|
|
2211
|
-
return `${quoted}.`;
|
|
2148
|
+
return `${formatter.quoteIdentifier(fn9.schema)}.`;
|
|
2212
2149
|
}
|
|
2213
|
-
|
|
2214
|
-
|
|
2215
|
-
* @param fn - The function table node containing arguments.
|
|
2216
|
-
* @param ctx - Optional compiler context for operand compilation.
|
|
2217
|
-
* @param dialect - The dialect instance for compiling operands.
|
|
2218
|
-
* @returns Comma-separated function arguments.
|
|
2219
|
-
* @internal
|
|
2220
|
-
*/
|
|
2221
|
-
static formatArgs(fn9, ctx, dialect) {
|
|
2222
|
-
return (fn9.args || []).map((a) => {
|
|
2223
|
-
if (ctx && dialect) {
|
|
2224
|
-
return dialect.compileOperand(a, ctx);
|
|
2225
|
-
}
|
|
2226
|
-
return String(a);
|
|
2227
|
-
}).join(", ");
|
|
2150
|
+
static formatArgs(fn9, ctx, formatter) {
|
|
2151
|
+
return (fn9.args || []).map((arg) => ctx ? formatter.compileOperand(arg, ctx) : String(arg)).join(", ");
|
|
2228
2152
|
}
|
|
2229
|
-
/**
|
|
2230
|
-
* Formats the base function call with WITH ORDINALITY if present.
|
|
2231
|
-
* @param fn - The function table node.
|
|
2232
|
-
* @param schemaPart - Formatted schema prefix.
|
|
2233
|
-
* @param args - Formatted function arguments.
|
|
2234
|
-
* @param dialect - The dialect instance for quoting identifiers.
|
|
2235
|
-
* @returns Base function call expression (e.g., "schema.func(args) WITH ORDINALITY").
|
|
2236
|
-
* @internal
|
|
2237
|
-
*/
|
|
2238
2153
|
static formatBase(fn9, schemaPart, args) {
|
|
2239
2154
|
const ordinality = fn9.withOrdinality ? " WITH ORDINALITY" : "";
|
|
2240
2155
|
return `${schemaPart}${fn9.name}(${args})${ordinality}`;
|
|
2241
2156
|
}
|
|
2242
|
-
/**
|
|
2243
|
-
* Formats the LATERAL keyword if present.
|
|
2244
|
-
* @param fn - The function table node.
|
|
2245
|
-
* @returns "LATERAL " or empty string.
|
|
2246
|
-
* @internal
|
|
2247
|
-
*/
|
|
2248
2157
|
static formatLateral(fn9) {
|
|
2249
2158
|
return fn9.lateral ? "LATERAL " : "";
|
|
2250
2159
|
}
|
|
2251
|
-
|
|
2252
|
-
* Formats the table alias for the function table.
|
|
2253
|
-
* @param fn - The function table node.
|
|
2254
|
-
* @param dialect - The dialect instance for quoting identifiers.
|
|
2255
|
-
* @returns " AS alias" or empty string.
|
|
2256
|
-
* @internal
|
|
2257
|
-
*/
|
|
2258
|
-
static formatAlias(fn9, dialect) {
|
|
2160
|
+
static formatAlias(fn9, formatter) {
|
|
2259
2161
|
if (!fn9.alias) return "";
|
|
2260
|
-
|
|
2261
|
-
return ` AS ${quoted}`;
|
|
2162
|
+
return ` AS ${formatter.quoteIdentifier(fn9.alias)}`;
|
|
2262
2163
|
}
|
|
2263
|
-
|
|
2264
|
-
* Formats column aliases for the function table result columns.
|
|
2265
|
-
* @param fn - The function table node containing column aliases.
|
|
2266
|
-
* @param dialect - The dialect instance for quoting identifiers.
|
|
2267
|
-
* @returns "(col1, col2, ...)" or empty string.
|
|
2268
|
-
* @internal
|
|
2269
|
-
*/
|
|
2270
|
-
static formatColumnAliases(fn9, dialect) {
|
|
2164
|
+
static formatColumnAliases(fn9, formatter) {
|
|
2271
2165
|
if (!fn9.columnAliases || !fn9.columnAliases.length) return "";
|
|
2272
|
-
const aliases = fn9.columnAliases.map((col2) =>
|
|
2166
|
+
const aliases = fn9.columnAliases.map((col2) => formatter.quoteIdentifier(col2)).join(", ");
|
|
2273
2167
|
return `(${aliases})`;
|
|
2274
2168
|
}
|
|
2275
2169
|
};
|
|
@@ -2395,7 +2289,7 @@ var OrderByCompiler = class {
|
|
|
2395
2289
|
};
|
|
2396
2290
|
|
|
2397
2291
|
// src/core/dialect/base/sql-dialect.ts
|
|
2398
|
-
var SqlDialectBase = class extends
|
|
2292
|
+
var SqlDialectBase = class extends DialectBase {
|
|
2399
2293
|
paginationStrategy = new StandardLimitOffsetPagination();
|
|
2400
2294
|
returningStrategy = new NoReturningStrategy();
|
|
2401
2295
|
compileSelectAst(ast, ctx) {
|
|
@@ -2405,14 +2299,12 @@ var SqlDialectBase = class extends Dialect {
|
|
|
2405
2299
|
ctx,
|
|
2406
2300
|
this.quoteIdentifier.bind(this),
|
|
2407
2301
|
this.compileSelectAst.bind(this),
|
|
2408
|
-
this.normalizeSelectAst
|
|
2302
|
+
this.normalizeSelectAst.bind(this),
|
|
2409
2303
|
this.stripTrailingSemicolon.bind(this)
|
|
2410
2304
|
);
|
|
2411
2305
|
const baseAst = hasSetOps ? { ...ast, setOps: void 0, orderBy: void 0, limit: void 0, offset: void 0 } : ast;
|
|
2412
2306
|
const baseSelect = this.compileSelectCore(baseAst, ctx);
|
|
2413
|
-
if (!hasSetOps) {
|
|
2414
|
-
return `${ctes}${baseSelect}`;
|
|
2415
|
-
}
|
|
2307
|
+
if (!hasSetOps) return `${ctes}${baseSelect}`;
|
|
2416
2308
|
return this.compileSelectWithSetOps(ast, baseSelect, ctes, ctx);
|
|
2417
2309
|
}
|
|
2418
2310
|
compileSelectWithSetOps(ast, baseSelect, ctes, ctx) {
|
|
@@ -2461,9 +2353,7 @@ var SqlDialectBase = class extends Dialect {
|
|
|
2461
2353
|
return columns.map((column) => this.quoteIdentifier(column.name)).join(", ");
|
|
2462
2354
|
}
|
|
2463
2355
|
ensureConflictColumns(clause, message) {
|
|
2464
|
-
if (!clause.target.columns.length)
|
|
2465
|
-
throw new Error(message);
|
|
2466
|
-
}
|
|
2356
|
+
if (!clause.target.columns.length) throw new Error(message);
|
|
2467
2357
|
}
|
|
2468
2358
|
compileSelectCore(ast, ctx) {
|
|
2469
2359
|
const columns = this.compileSelectColumns(ast, ctx);
|
|
@@ -2496,8 +2386,7 @@ var SqlDialectBase = class extends Dialect {
|
|
|
2496
2386
|
}
|
|
2497
2387
|
compileUpdateAssignments(assignments, table, ctx) {
|
|
2498
2388
|
return assignments.map((assignment) => {
|
|
2499
|
-
const
|
|
2500
|
-
const target = this.compileSetTarget(col2, table);
|
|
2389
|
+
const target = this.compileSetTarget(assignment.column, table);
|
|
2501
2390
|
const value = this.compileOperand(assignment.value, ctx);
|
|
2502
2391
|
return `${target} = ${value}`;
|
|
2503
2392
|
}).join(", ");
|
|
@@ -2510,9 +2399,7 @@ var SqlDialectBase = class extends Dialect {
|
|
|
2510
2399
|
const alias = table.alias;
|
|
2511
2400
|
const columnTable = column.table ?? alias ?? baseTableName;
|
|
2512
2401
|
const tableQualifier = alias && column.table === baseTableName ? alias : columnTable;
|
|
2513
|
-
if (!tableQualifier)
|
|
2514
|
-
return this.quoteIdentifier(column.name);
|
|
2515
|
-
}
|
|
2402
|
+
if (!tableQualifier) return this.quoteIdentifier(column.name);
|
|
2516
2403
|
return `${this.quoteIdentifier(tableQualifier)}.${this.quoteIdentifier(column.name)}`;
|
|
2517
2404
|
}
|
|
2518
2405
|
compileDeleteAst(ast, ctx) {
|
|
@@ -2529,27 +2416,20 @@ var SqlDialectBase = class extends Dialect {
|
|
|
2529
2416
|
return ast.distinct ? "DISTINCT " : "";
|
|
2530
2417
|
}
|
|
2531
2418
|
compileSelectColumns(ast, ctx) {
|
|
2532
|
-
if (!ast.columns || ast.columns.length === 0)
|
|
2533
|
-
|
|
2534
|
-
|
|
2535
|
-
|
|
2536
|
-
|
|
2537
|
-
|
|
2538
|
-
if (c.alias.includes("(")) return c.alias;
|
|
2539
|
-
return `${expr} AS ${this.quoteIdentifier(c.alias)}`;
|
|
2419
|
+
if (!ast.columns || ast.columns.length === 0) return "*";
|
|
2420
|
+
return ast.columns.map((column) => {
|
|
2421
|
+
const expr = this.compileOperand(column, ctx);
|
|
2422
|
+
if (column.alias) {
|
|
2423
|
+
if (column.alias.includes("(")) return column.alias;
|
|
2424
|
+
return `${expr} AS ${this.quoteIdentifier(column.alias)}`;
|
|
2540
2425
|
}
|
|
2541
2426
|
return expr;
|
|
2542
2427
|
}).join(", ");
|
|
2543
2428
|
}
|
|
2544
2429
|
compileFrom(ast, ctx) {
|
|
2545
|
-
|
|
2546
|
-
if (
|
|
2547
|
-
|
|
2548
|
-
}
|
|
2549
|
-
if (tableSource.type === "DerivedTable") {
|
|
2550
|
-
return this.compileDerivedTable(tableSource, ctx);
|
|
2551
|
-
}
|
|
2552
|
-
return this.compileTableSource(tableSource);
|
|
2430
|
+
if (ast.type === "FunctionTable") return this.compileFunctionTable(ast, ctx);
|
|
2431
|
+
if (ast.type === "DerivedTable") return this.compileDerivedTable(ast, ctx);
|
|
2432
|
+
return this.compileTableSource(ast);
|
|
2553
2433
|
}
|
|
2554
2434
|
compileFunctionTable(fn9, ctx) {
|
|
2555
2435
|
const key = fn9.key ?? fn9.name;
|
|
@@ -2568,23 +2448,20 @@ var SqlDialectBase = class extends Dialect {
|
|
|
2568
2448
|
throw new Error(`Table function "${key}" is not supported by dialect "${this.dialect}".`);
|
|
2569
2449
|
}
|
|
2570
2450
|
}
|
|
2571
|
-
return FunctionTableFormatter.format(fn9, ctx,
|
|
2451
|
+
return FunctionTableFormatter.format(fn9, ctx, {
|
|
2452
|
+
quoteIdentifier: (id) => this.quoteIdentifier(id),
|
|
2453
|
+
compileOperand: (node, compilerContext) => this.compileOperand(node, compilerContext)
|
|
2454
|
+
});
|
|
2572
2455
|
}
|
|
2573
2456
|
compileDerivedTable(table, ctx) {
|
|
2574
|
-
if (!table.alias)
|
|
2575
|
-
throw new Error("Derived tables must have an alias.");
|
|
2576
|
-
}
|
|
2457
|
+
if (!table.alias) throw new Error("Derived tables must have an alias.");
|
|
2577
2458
|
const subquery = this.compileSelectAst(this.normalizeSelectAst(table.query), ctx).trim().replace(/;$/, "");
|
|
2578
2459
|
const columns = table.columnAliases?.length ? ` (${table.columnAliases.map((c) => this.quoteIdentifier(c)).join(", ")})` : "";
|
|
2579
2460
|
return `(${subquery}) AS ${this.quoteIdentifier(table.alias)}${columns}`;
|
|
2580
2461
|
}
|
|
2581
2462
|
compileTableSource(table) {
|
|
2582
|
-
if (table.type === "FunctionTable")
|
|
2583
|
-
|
|
2584
|
-
}
|
|
2585
|
-
if (table.type === "DerivedTable") {
|
|
2586
|
-
return this.compileDerivedTable(table);
|
|
2587
|
-
}
|
|
2463
|
+
if (table.type === "FunctionTable") return this.compileFunctionTable(table);
|
|
2464
|
+
if (table.type === "DerivedTable") return this.compileDerivedTable(table);
|
|
2588
2465
|
const base = this.compileTableName(table);
|
|
2589
2466
|
return table.alias ? `${base} AS ${this.quoteIdentifier(table.alias)}` : base;
|
|
2590
2467
|
}
|
|
@@ -2600,9 +2477,7 @@ var SqlDialectBase = class extends Dialect {
|
|
|
2600
2477
|
}
|
|
2601
2478
|
compileUpdateFromClause(ast, ctx) {
|
|
2602
2479
|
if (!ast.from && (!ast.joins || ast.joins.length === 0)) return "";
|
|
2603
|
-
if (!ast.from)
|
|
2604
|
-
throw new Error("UPDATE with JOINs requires an explicit FROM clause.");
|
|
2605
|
-
}
|
|
2480
|
+
if (!ast.from) throw new Error("UPDATE with JOINs requires an explicit FROM clause.");
|
|
2606
2481
|
const from = this.compileFrom(ast.from, ctx);
|
|
2607
2482
|
const joins = JoinCompiler.compileJoins(
|
|
2608
2483
|
ast.joins,
|
|
@@ -2614,9 +2489,7 @@ var SqlDialectBase = class extends Dialect {
|
|
|
2614
2489
|
}
|
|
2615
2490
|
compileDeleteUsingClause(ast, ctx) {
|
|
2616
2491
|
if (!ast.using && (!ast.joins || ast.joins.length === 0)) return "";
|
|
2617
|
-
if (!ast.using)
|
|
2618
|
-
throw new Error("DELETE with JOINs requires a USING clause.");
|
|
2619
|
-
}
|
|
2492
|
+
if (!ast.using) throw new Error("DELETE with JOINs requires a USING clause.");
|
|
2620
2493
|
const usingTable = this.compileFrom(ast.using, ctx);
|
|
2621
2494
|
const joins = JoinCompiler.compileJoins(
|
|
2622
2495
|
ast.joins,
|
|
@@ -2634,8 +2507,7 @@ var SqlDialectBase = class extends Dialect {
|
|
|
2634
2507
|
return sql.trim().replace(/;$/, "");
|
|
2635
2508
|
}
|
|
2636
2509
|
wrapSetOperand(sql) {
|
|
2637
|
-
|
|
2638
|
-
return `(${trimmed})`;
|
|
2510
|
+
return `(${this.stripTrailingSemicolon(sql)})`;
|
|
2639
2511
|
}
|
|
2640
2512
|
renderOrderByNulls(order) {
|
|
2641
2513
|
return order.nulls ? ` NULLS ${order.nulls}` : "";
|
|
@@ -3344,10 +3216,6 @@ var SqliteDialect = class extends SqlDialectBase {
|
|
|
3344
3216
|
supportsDmlReturningClause() {
|
|
3345
3217
|
return true;
|
|
3346
3218
|
}
|
|
3347
|
-
compileProcedureCall(_ast) {
|
|
3348
|
-
void _ast;
|
|
3349
|
-
throw new Error("Stored procedures are not supported by the SQLite dialect.");
|
|
3350
|
-
}
|
|
3351
3219
|
};
|
|
3352
3220
|
|
|
3353
3221
|
// src/core/dialect/mssql/functions.ts
|
|
@@ -3782,9 +3650,8 @@ var DialectFactory = class {
|
|
|
3782
3650
|
/**
|
|
3783
3651
|
* Register (or override) a dialect factory for a key.
|
|
3784
3652
|
*
|
|
3785
|
-
*
|
|
3786
|
-
*
|
|
3787
|
-
* DialectFactory.register('my-tenant-dialect', () => new CustomDialect());
|
|
3653
|
+
* Implementations are structural: extending DialectBase/SqlDialectBase is
|
|
3654
|
+
* optional. A composed object satisfying Dialect is a valid registration.
|
|
3788
3655
|
*/
|
|
3789
3656
|
static register(key, factory) {
|
|
3790
3657
|
this.registry.set(key, factory);
|
|
@@ -11357,6 +11224,15 @@ var DeleteQueryBuilder = class _DeleteQueryBuilder {
|
|
|
11357
11224
|
};
|
|
11358
11225
|
var isTableSourceNode2 = (source) => typeof source.type === "string";
|
|
11359
11226
|
|
|
11227
|
+
// src/core/dialect/capabilities/procedure-compiler.ts
|
|
11228
|
+
var isProcedureCompiler = (value) => typeof value?.compileProcedureCall === "function";
|
|
11229
|
+
var requireProcedureCompiler = (value) => {
|
|
11230
|
+
if (!isProcedureCompiler(value)) {
|
|
11231
|
+
throw new Error("Stored procedures are not supported by this dialect.");
|
|
11232
|
+
}
|
|
11233
|
+
return value;
|
|
11234
|
+
};
|
|
11235
|
+
|
|
11360
11236
|
// src/orm/execute-procedure.ts
|
|
11361
11237
|
var resolveColumnIndex = (columns, expectedName) => {
|
|
11362
11238
|
const exact = columns.findIndex((column) => column === expectedName);
|
|
@@ -11395,7 +11271,7 @@ var extractOutValues = (compiled, resultSets) => {
|
|
|
11395
11271
|
};
|
|
11396
11272
|
var executeProcedureAst = async (session, ast) => {
|
|
11397
11273
|
const execCtx = session.getExecutionContext();
|
|
11398
|
-
const compiled = execCtx.dialect.compileProcedureCall(ast);
|
|
11274
|
+
const compiled = requireProcedureCompiler(execCtx.dialect).compileProcedureCall(ast);
|
|
11399
11275
|
const payload = await execCtx.interceptors.run(
|
|
11400
11276
|
{ sql: compiled.sql, params: compiled.params },
|
|
11401
11277
|
execCtx.executor
|
|
@@ -11468,8 +11344,7 @@ var ProcedureCallBuilder = class _ProcedureCallBuilder {
|
|
|
11468
11344
|
}
|
|
11469
11345
|
compile(dialect) {
|
|
11470
11346
|
const resolved = resolveDialectInput(dialect);
|
|
11471
|
-
this.
|
|
11472
|
-
return resolved.compileProcedureCall(this.getAST());
|
|
11347
|
+
return requireProcedureCompiler(resolved).compileProcedureCall(this.getAST());
|
|
11473
11348
|
}
|
|
11474
11349
|
toSql(dialect) {
|
|
11475
11350
|
return this.compile(dialect).sql;
|
|
@@ -11482,21 +11357,8 @@ var ProcedureCallBuilder = class _ProcedureCallBuilder {
|
|
|
11482
11357
|
};
|
|
11483
11358
|
}
|
|
11484
11359
|
async execute(session) {
|
|
11485
|
-
this.validateMssqlOutDbType(session.getExecutionContext().dialect);
|
|
11486
11360
|
return executeProcedureAst(session, this.getAST());
|
|
11487
11361
|
}
|
|
11488
|
-
validateMssqlOutDbType(dialect) {
|
|
11489
|
-
const isMssqlDialect = dialect.constructor.name === "SqlServerDialect";
|
|
11490
|
-
if (!isMssqlDialect) return;
|
|
11491
|
-
for (const param of this.ast.params) {
|
|
11492
|
-
const needsDbType = param.direction === "out" || param.direction === "inout";
|
|
11493
|
-
if (needsDbType && !param.dbType) {
|
|
11494
|
-
throw new Error(
|
|
11495
|
-
`MSSQL requires "dbType" for procedure parameter "${param.name}" with direction "${param.direction}".`
|
|
11496
|
-
);
|
|
11497
|
-
}
|
|
11498
|
-
}
|
|
11499
|
-
}
|
|
11500
11362
|
};
|
|
11501
11363
|
var callProcedure = (name, options) => new ProcedureCallBuilder(name, options);
|
|
11502
11364
|
|
|
@@ -22225,6 +22087,8 @@ async function bulkUpsert(session, table, rows, options = {}) {
|
|
|
22225
22087
|
DefaultMorphToReference,
|
|
22226
22088
|
DefaultTypeStrategy,
|
|
22227
22089
|
DeleteQueryBuilder,
|
|
22090
|
+
DialectBase,
|
|
22091
|
+
DialectFactory,
|
|
22228
22092
|
DomainEventBus,
|
|
22229
22093
|
Email,
|
|
22230
22094
|
Entity,
|
|
@@ -22452,6 +22316,7 @@ async function bulkUpsert(session, table, rows, options = {}) {
|
|
|
22452
22316
|
isNull,
|
|
22453
22317
|
isNullableColumn,
|
|
22454
22318
|
isOperandNode,
|
|
22319
|
+
isProcedureCompiler,
|
|
22455
22320
|
isSingleTargetRelation,
|
|
22456
22321
|
isTableDef,
|
|
22457
22322
|
isTreeConfig,
|
|
@@ -22549,6 +22414,8 @@ async function bulkUpsert(session, table, rows, options = {}) {
|
|
|
22549
22414
|
repeat,
|
|
22550
22415
|
replace,
|
|
22551
22416
|
replaceWithRefs,
|
|
22417
|
+
requireProcedureCompiler,
|
|
22418
|
+
resolveDialectInput,
|
|
22552
22419
|
resolveTreeConfig,
|
|
22553
22420
|
resolveValidator,
|
|
22554
22421
|
responseToRef,
|