metal-orm 1.1.22 → 1.1.24
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +564 -575
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +196 -164
- package/dist/index.d.ts +196 -164
- package/dist/index.js +554 -575
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/core/dialect/abstract.ts +94 -417
- package/src/core/dialect/base/expression-compiler-registry.ts +254 -0
- package/src/core/dialect/base/function-table-formatter.ts +40 -78
- package/src/core/dialect/base/select-ast-normalizer.ts +61 -0
- package/src/core/dialect/base/sql-dialect.ts +84 -245
- package/src/core/dialect/base/standard-delete-compiler.ts +37 -0
- package/src/core/dialect/base/standard-insert-compiler.ts +49 -0
- package/src/core/dialect/base/standard-select-compiler.ts +82 -0
- package/src/core/dialect/base/standard-sql-services.ts +44 -0
- package/src/core/dialect/base/standard-sql-source-compiler.ts +88 -0
- package/src/core/dialect/base/standard-update-compiler.ts +53 -0
- package/src/core/dialect/capabilities/procedure-compiler.ts +30 -0
- package/src/core/dialect/dialect-factory.ts +3 -4
- package/src/core/dialect/mssql/index.ts +3 -2
- package/src/core/dialect/mysql/index.ts +3 -2
- package/src/core/dialect/postgres/index.ts +3 -2
- package/src/core/dialect/sqlite/index.ts +1 -7
- package/src/index.ts +10 -1
- package/src/orm/execute-procedure.ts +3 -2
- package/src/query-builder/procedure-call.ts +4 -18
package/dist/index.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,
|
|
@@ -107,6 +109,11 @@ __export(index_exports, {
|
|
|
107
109
|
SelectQueryBuilder: () => SelectQueryBuilder,
|
|
108
110
|
SqlServerDialect: () => SqlServerDialect,
|
|
109
111
|
SqliteDialect: () => SqliteDialect,
|
|
112
|
+
StandardDeleteCompiler: () => StandardDeleteCompiler,
|
|
113
|
+
StandardInsertCompiler: () => StandardInsertCompiler,
|
|
114
|
+
StandardSelectCompiler: () => StandardSelectCompiler,
|
|
115
|
+
StandardSqlSourceCompiler: () => StandardSqlSourceCompiler,
|
|
116
|
+
StandardUpdateCompiler: () => StandardUpdateCompiler,
|
|
110
117
|
StringTypeStrategy: () => StringTypeStrategy,
|
|
111
118
|
TagIndex: () => TagIndex,
|
|
112
119
|
Title: () => Title,
|
|
@@ -301,6 +308,7 @@ __export(index_exports, {
|
|
|
301
308
|
isNull: () => isNull,
|
|
302
309
|
isNullableColumn: () => isNullableColumn,
|
|
303
310
|
isOperandNode: () => isOperandNode,
|
|
311
|
+
isProcedureCompiler: () => isProcedureCompiler,
|
|
304
312
|
isSingleTargetRelation: () => isSingleTargetRelation,
|
|
305
313
|
isTableDef: () => isTableDef2,
|
|
306
314
|
isTreeConfig: () => isTreeConfig,
|
|
@@ -398,6 +406,8 @@ __export(index_exports, {
|
|
|
398
406
|
repeat: () => repeat,
|
|
399
407
|
replace: () => replace,
|
|
400
408
|
replaceWithRefs: () => replaceWithRefs,
|
|
409
|
+
requireProcedureCompiler: () => requireProcedureCompiler,
|
|
410
|
+
resolveDialectInput: () => resolveDialectInput,
|
|
401
411
|
resolveTreeConfig: () => resolveTreeConfig,
|
|
402
412
|
resolveValidator: () => resolveValidator,
|
|
403
413
|
responseToRef: () => responseToRef,
|
|
@@ -1755,268 +1765,40 @@ var StandardTableFunctionStrategy = class {
|
|
|
1755
1765
|
}
|
|
1756
1766
|
};
|
|
1757
1767
|
|
|
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();
|
|
1768
|
+
// src/core/dialect/base/expression-compiler-registry.ts
|
|
1769
|
+
var ExpressionCompilerRegistry = class {
|
|
1770
|
+
constructor(host) {
|
|
1771
|
+
this.host = host;
|
|
1937
1772
|
this.registerDefaultOperandCompilers();
|
|
1938
1773
|
this.registerDefaultExpressionCompilers();
|
|
1939
1774
|
}
|
|
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
|
-
*/
|
|
1775
|
+
expressionCompilers = /* @__PURE__ */ new Map();
|
|
1776
|
+
operandCompilers = /* @__PURE__ */ new Map();
|
|
1974
1777
|
registerExpressionCompiler(type, compiler) {
|
|
1975
1778
|
this.expressionCompilers.set(type, compiler);
|
|
1976
1779
|
}
|
|
1977
|
-
/**
|
|
1978
|
-
* Registers an operand compiler for a specific node type
|
|
1979
|
-
* @param type - Operand node type
|
|
1980
|
-
* @param compiler - Compiler function
|
|
1981
|
-
*/
|
|
1982
1780
|
registerOperandCompiler(type, compiler) {
|
|
1983
1781
|
this.operandCompilers.set(type, compiler);
|
|
1984
1782
|
}
|
|
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
1783
|
compileExpression(node, ctx) {
|
|
1992
1784
|
const compiler = this.expressionCompilers.get(node.type);
|
|
1993
1785
|
if (!compiler) {
|
|
1994
|
-
throw new Error(`Unsupported expression node type "${node.type}" for ${this.
|
|
1786
|
+
throw new Error(`Unsupported expression node type "${node.type}" for ${this.host.describe()}`);
|
|
1995
1787
|
}
|
|
1996
1788
|
return compiler(node, ctx);
|
|
1997
1789
|
}
|
|
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
1790
|
compileOperand(node, ctx) {
|
|
2005
1791
|
const compiler = this.operandCompilers.get(node.type);
|
|
2006
1792
|
if (!compiler) {
|
|
2007
|
-
throw new Error(`Unsupported operand node type "${node.type}" for ${this.
|
|
1793
|
+
throw new Error(`Unsupported operand node type "${node.type}" for ${this.host.describe()}`);
|
|
2008
1794
|
}
|
|
2009
1795
|
return compiler(node, ctx);
|
|
2010
1796
|
}
|
|
2011
|
-
/**
|
|
2012
|
-
* Compiles an ordering term (operand, expression, or alias reference).
|
|
2013
|
-
*/
|
|
2014
1797
|
compileOrderingTerm(term, ctx) {
|
|
2015
1798
|
if (isOperandNode(term)) {
|
|
2016
1799
|
return this.compileOperand(term, ctx);
|
|
2017
1800
|
}
|
|
2018
|
-
|
|
2019
|
-
return `(${expr})`;
|
|
1801
|
+
return `(${this.compileExpression(term, ctx)})`;
|
|
2020
1802
|
}
|
|
2021
1803
|
registerDefaultExpressionCompilers() {
|
|
2022
1804
|
this.registerExpressionCompiler("BinaryExpression", (binary, ctx) => {
|
|
@@ -2051,11 +1833,11 @@ var Dialect = class _Dialect {
|
|
|
2051
1833
|
const values = inExpr.right.map((v) => this.compileOperand(v, ctx)).join(", ");
|
|
2052
1834
|
return `${left2} ${inExpr.operator} (${values})`;
|
|
2053
1835
|
}
|
|
2054
|
-
const subquerySql = this.compileSelectAst(inExpr.right.query, ctx).trim().replace(/;$/, "");
|
|
1836
|
+
const subquerySql = this.host.compileSelectAst(inExpr.right.query, ctx).trim().replace(/;$/, "");
|
|
2055
1837
|
return `${left2} ${inExpr.operator} (${subquerySql})`;
|
|
2056
1838
|
});
|
|
2057
1839
|
this.registerExpressionCompiler("ExistsExpression", (existsExpr, ctx) => {
|
|
2058
|
-
const subquerySql = this.compileSelectForExists(existsExpr.subquery, ctx);
|
|
1840
|
+
const subquerySql = this.host.compileSelectForExists(existsExpr.subquery, ctx);
|
|
2059
1841
|
return `${existsExpr.operator} (${subquerySql})`;
|
|
2060
1842
|
});
|
|
2061
1843
|
this.registerExpressionCompiler("BetweenExpression", (betweenExpr, ctx) => {
|
|
@@ -2081,25 +1863,28 @@ var Dialect = class _Dialect {
|
|
|
2081
1863
|
});
|
|
2082
1864
|
}
|
|
2083
1865
|
registerDefaultOperandCompilers() {
|
|
2084
|
-
this.registerOperandCompiler(
|
|
2085
|
-
|
|
2086
|
-
|
|
2087
|
-
|
|
2088
|
-
|
|
2089
|
-
|
|
2090
|
-
|
|
2091
|
-
|
|
2092
|
-
|
|
1866
|
+
this.registerOperandCompiler(
|
|
1867
|
+
"Literal",
|
|
1868
|
+
(literal, ctx) => ctx.addParameter(literal.value)
|
|
1869
|
+
);
|
|
1870
|
+
this.registerOperandCompiler(
|
|
1871
|
+
"AliasRef",
|
|
1872
|
+
(alias) => this.host.quoteIdentifier(alias.name)
|
|
1873
|
+
);
|
|
1874
|
+
this.registerOperandCompiler(
|
|
1875
|
+
"Column",
|
|
1876
|
+
(column) => `${this.host.quoteIdentifier(column.table)}.${this.host.quoteIdentifier(column.name)}`
|
|
1877
|
+
);
|
|
2093
1878
|
this.registerOperandCompiler(
|
|
2094
1879
|
"Function",
|
|
2095
|
-
(fnNode, ctx) => this.compileFunctionOperand(fnNode, ctx)
|
|
1880
|
+
(fnNode, ctx) => this.host.compileFunctionOperand(fnNode, ctx)
|
|
1881
|
+
);
|
|
1882
|
+
this.registerOperandCompiler(
|
|
1883
|
+
"JsonPath",
|
|
1884
|
+
(path) => this.host.compileJsonPath(path)
|
|
2096
1885
|
);
|
|
2097
|
-
this.registerOperandCompiler("JsonPath", (path, _ctx) => {
|
|
2098
|
-
void _ctx;
|
|
2099
|
-
return this.compileJsonPath(path);
|
|
2100
|
-
});
|
|
2101
1886
|
this.registerOperandCompiler("ScalarSubquery", (node, ctx) => {
|
|
2102
|
-
const sql = this.compileSelectAst(node.query, ctx).trim().replace(/;$/, "");
|
|
1887
|
+
const sql = this.host.compileSelectAst(node.query, ctx).trim().replace(/;$/, "");
|
|
2103
1888
|
return `(${sql})`;
|
|
2104
1889
|
});
|
|
2105
1890
|
this.registerOperandCompiler("CaseExpression", (node, ctx) => {
|
|
@@ -2126,7 +1911,7 @@ var Dialect = class _Dialect {
|
|
|
2126
1911
|
const parts = [];
|
|
2127
1912
|
if (node.partitionBy && node.partitionBy.length > 0) {
|
|
2128
1913
|
const partitionClause = "PARTITION BY " + node.partitionBy.map(
|
|
2129
|
-
(col2) => `${this.quoteIdentifier(col2.table)}.${this.quoteIdentifier(col2.name)}`
|
|
1914
|
+
(col2) => `${this.host.quoteIdentifier(col2.table)}.${this.host.quoteIdentifier(col2.name)}`
|
|
2130
1915
|
).join(", ");
|
|
2131
1916
|
parts.push(partitionClause);
|
|
2132
1917
|
}
|
|
@@ -2158,14 +1943,164 @@ var Dialect = class _Dialect {
|
|
|
2158
1943
|
return `${expr} COLLATE ${node.collation}`;
|
|
2159
1944
|
});
|
|
2160
1945
|
}
|
|
2161
|
-
|
|
1946
|
+
};
|
|
1947
|
+
|
|
1948
|
+
// src/core/dialect/base/select-ast-normalizer.ts
|
|
1949
|
+
var SelectAstNormalizer = class {
|
|
1950
|
+
constructor(supportsSetOperation) {
|
|
1951
|
+
this.supportsSetOperation = supportsSetOperation;
|
|
1952
|
+
}
|
|
1953
|
+
normalize(ast) {
|
|
1954
|
+
this.validateSetOperations(ast, true);
|
|
1955
|
+
const { normalized, hoistedCtes } = this.hoistCtes(ast);
|
|
1956
|
+
const combinedCtes = [...normalized.ctes ?? [], ...hoistedCtes];
|
|
1957
|
+
return combinedCtes.length ? { ...normalized, ctes: combinedCtes } : normalized;
|
|
1958
|
+
}
|
|
1959
|
+
validateSetOperations(ast, isOutermost) {
|
|
1960
|
+
const hasSetOps = !!(ast.setOps && ast.setOps.length);
|
|
1961
|
+
if (!isOutermost && (ast.orderBy || ast.limit !== void 0 || ast.offset !== void 0)) {
|
|
1962
|
+
throw new Error("ORDER BY / LIMIT / OFFSET are only allowed on the outermost compound query.");
|
|
1963
|
+
}
|
|
1964
|
+
if (!hasSetOps) return;
|
|
1965
|
+
for (const op of ast.setOps) {
|
|
1966
|
+
if (!this.supportsSetOperation(op.operator)) {
|
|
1967
|
+
throw new Error(`Set operation ${op.operator} is not supported by this dialect.`);
|
|
1968
|
+
}
|
|
1969
|
+
this.validateSetOperations(op.query, false);
|
|
1970
|
+
}
|
|
1971
|
+
}
|
|
1972
|
+
hoistCtes(ast) {
|
|
1973
|
+
let hoisted = [];
|
|
1974
|
+
const normalizedSetOps = ast.setOps?.map((op) => {
|
|
1975
|
+
const { normalized: child, hoistedCtes: childHoisted } = this.hoistCtes(op.query);
|
|
1976
|
+
const childCtes = child.ctes ?? [];
|
|
1977
|
+
if (childCtes.length) hoisted = hoisted.concat(childCtes);
|
|
1978
|
+
hoisted = hoisted.concat(childHoisted);
|
|
1979
|
+
const queryWithoutCtes = childCtes.length ? { ...child, ctes: void 0 } : child;
|
|
1980
|
+
return { ...op, query: queryWithoutCtes };
|
|
1981
|
+
});
|
|
1982
|
+
const normalized = normalizedSetOps ? { ...ast, setOps: normalizedSetOps } : ast;
|
|
1983
|
+
return { normalized, hoistedCtes: hoisted };
|
|
1984
|
+
}
|
|
1985
|
+
};
|
|
1986
|
+
|
|
1987
|
+
// src/core/dialect/abstract.ts
|
|
1988
|
+
var DialectBase = class _DialectBase {
|
|
1989
|
+
expressionCompilerRegistry;
|
|
1990
|
+
selectAstNormalizer;
|
|
1991
|
+
functionStrategy;
|
|
1992
|
+
tableFunctionStrategy;
|
|
1993
|
+
constructor(functionStrategy, tableFunctionStrategy) {
|
|
1994
|
+
this.functionStrategy = functionStrategy ?? new StandardFunctionStrategy();
|
|
1995
|
+
this.tableFunctionStrategy = tableFunctionStrategy ?? new StandardTableFunctionStrategy();
|
|
1996
|
+
this.selectAstNormalizer = new SelectAstNormalizer((kind) => this.supportsSetOperation(kind));
|
|
1997
|
+
this.expressionCompilerRegistry = new ExpressionCompilerRegistry({
|
|
1998
|
+
quoteIdentifier: (id) => this.quoteIdentifier(id),
|
|
1999
|
+
compileSelectAst: (ast, ctx) => this.compileSelectAst(ast, ctx),
|
|
2000
|
+
compileSelectForExists: (ast, ctx) => this.compileSelectForExists(ast, ctx),
|
|
2001
|
+
compileJsonPath: (node) => this.compileJsonPath(node),
|
|
2002
|
+
compileFunctionOperand: (node, ctx) => this.compileFunctionOperand(node, ctx),
|
|
2003
|
+
describe: () => this.constructor.name
|
|
2004
|
+
});
|
|
2005
|
+
}
|
|
2006
|
+
compileSelect(ast) {
|
|
2007
|
+
const ctx = this.createCompilerContext();
|
|
2008
|
+
const normalized = this.normalizeSelectAst(ast);
|
|
2009
|
+
const rawSql = this.compileSelectAst(normalized, ctx).trim();
|
|
2010
|
+
return {
|
|
2011
|
+
sql: rawSql.endsWith(";") ? rawSql : `${rawSql};`,
|
|
2012
|
+
params: [...ctx.params]
|
|
2013
|
+
};
|
|
2014
|
+
}
|
|
2015
|
+
compileInsert(ast) {
|
|
2016
|
+
const ctx = this.createCompilerContext();
|
|
2017
|
+
const rawSql = this.compileInsertAst(ast, ctx).trim();
|
|
2018
|
+
return {
|
|
2019
|
+
sql: rawSql.endsWith(";") ? rawSql : `${rawSql};`,
|
|
2020
|
+
params: [...ctx.params]
|
|
2021
|
+
};
|
|
2022
|
+
}
|
|
2023
|
+
compileUpdate(ast) {
|
|
2024
|
+
const ctx = this.createCompilerContext();
|
|
2025
|
+
const rawSql = this.compileUpdateAst(ast, ctx).trim();
|
|
2026
|
+
return {
|
|
2027
|
+
sql: rawSql.endsWith(";") ? rawSql : `${rawSql};`,
|
|
2028
|
+
params: [...ctx.params]
|
|
2029
|
+
};
|
|
2030
|
+
}
|
|
2031
|
+
compileDelete(ast) {
|
|
2032
|
+
const ctx = this.createCompilerContext();
|
|
2033
|
+
const rawSql = this.compileDeleteAst(ast, ctx).trim();
|
|
2034
|
+
return {
|
|
2035
|
+
sql: rawSql.endsWith(";") ? rawSql : `${rawSql};`,
|
|
2036
|
+
params: [...ctx.params]
|
|
2037
|
+
};
|
|
2038
|
+
}
|
|
2039
|
+
supportsDmlReturningClause() {
|
|
2040
|
+
return false;
|
|
2041
|
+
}
|
|
2042
|
+
compileWhere(where, ctx) {
|
|
2043
|
+
if (!where) return "";
|
|
2044
|
+
return ` WHERE ${this.compileExpression(where, ctx)}`;
|
|
2045
|
+
}
|
|
2046
|
+
compileReturning(returning, _ctx) {
|
|
2047
|
+
void _ctx;
|
|
2048
|
+
if (!returning || returning.length === 0) return "";
|
|
2049
|
+
throw new Error("RETURNING is not supported by this dialect.");
|
|
2050
|
+
}
|
|
2051
|
+
compileSelectForExists(ast, ctx) {
|
|
2052
|
+
const normalized = this.normalizeSelectAst(ast);
|
|
2053
|
+
const full = this.compileSelectAst(normalized, ctx).trim().replace(/;$/, "");
|
|
2054
|
+
if (normalized.setOps && normalized.setOps.length > 0) {
|
|
2055
|
+
return `SELECT 1 FROM (${full}) AS _exists`;
|
|
2056
|
+
}
|
|
2057
|
+
const upper2 = full.toUpperCase();
|
|
2058
|
+
const fromIndex = upper2.indexOf(" FROM ");
|
|
2059
|
+
if (fromIndex === -1) return full;
|
|
2060
|
+
return `SELECT 1${full.slice(fromIndex)}`;
|
|
2061
|
+
}
|
|
2062
|
+
createCompilerContext() {
|
|
2063
|
+
const params = [];
|
|
2064
|
+
let counter = 0;
|
|
2065
|
+
return {
|
|
2066
|
+
params,
|
|
2067
|
+
addParameter: (value) => {
|
|
2068
|
+
counter += 1;
|
|
2069
|
+
params.push(value);
|
|
2070
|
+
return this.formatPlaceholder(counter);
|
|
2071
|
+
}
|
|
2072
|
+
};
|
|
2073
|
+
}
|
|
2074
|
+
formatPlaceholder(_index) {
|
|
2075
|
+
void _index;
|
|
2076
|
+
return "?";
|
|
2077
|
+
}
|
|
2078
|
+
supportsSetOperation(_kind) {
|
|
2079
|
+
void _kind;
|
|
2080
|
+
return true;
|
|
2081
|
+
}
|
|
2082
|
+
normalizeSelectAst(ast) {
|
|
2083
|
+
return this.selectAstNormalizer.normalize(ast);
|
|
2084
|
+
}
|
|
2085
|
+
registerExpressionCompiler(type, compiler) {
|
|
2086
|
+
this.expressionCompilerRegistry.registerExpressionCompiler(type, compiler);
|
|
2087
|
+
}
|
|
2088
|
+
registerOperandCompiler(type, compiler) {
|
|
2089
|
+
this.expressionCompilerRegistry.registerOperandCompiler(type, compiler);
|
|
2090
|
+
}
|
|
2091
|
+
compileExpression(node, ctx) {
|
|
2092
|
+
return this.expressionCompilerRegistry.compileExpression(node, ctx);
|
|
2093
|
+
}
|
|
2094
|
+
compileOperand(node, ctx) {
|
|
2095
|
+
return this.expressionCompilerRegistry.compileOperand(node, ctx);
|
|
2096
|
+
}
|
|
2097
|
+
compileOrderingTerm(term, ctx) {
|
|
2098
|
+
return this.expressionCompilerRegistry.compileOrderingTerm(term, ctx);
|
|
2099
|
+
}
|
|
2162
2100
|
compileJsonPath(_node) {
|
|
2163
2101
|
void _node;
|
|
2164
2102
|
throw new Error("JSON Path not supported by this dialect");
|
|
2165
2103
|
}
|
|
2166
|
-
/**
|
|
2167
|
-
* Compiles a function operand, using the dialect's function strategy.
|
|
2168
|
-
*/
|
|
2169
2104
|
compileFunctionOperand(fnNode, ctx) {
|
|
2170
2105
|
const compiledArgs = fnNode.args.map((arg) => this.compileOperand(arg, ctx));
|
|
2171
2106
|
const renderer = this.functionStrategy.getRenderer(fnNode.name);
|
|
@@ -2178,115 +2113,175 @@ var Dialect = class _Dialect {
|
|
|
2178
2113
|
}
|
|
2179
2114
|
return `${fnNode.name}(${compiledArgs.join(", ")})`;
|
|
2180
2115
|
}
|
|
2116
|
+
/** Creates a minimal dialect implementation for isolated compiler tests. */
|
|
2117
|
+
static create(functionStrategy, tableFunctionStrategy) {
|
|
2118
|
+
class TestDialect extends _DialectBase {
|
|
2119
|
+
dialect = "sqlite";
|
|
2120
|
+
quoteIdentifier(id) {
|
|
2121
|
+
return `"${id}"`;
|
|
2122
|
+
}
|
|
2123
|
+
compileSelectAst() {
|
|
2124
|
+
throw new Error("Not implemented");
|
|
2125
|
+
}
|
|
2126
|
+
compileInsertAst() {
|
|
2127
|
+
throw new Error("Not implemented");
|
|
2128
|
+
}
|
|
2129
|
+
compileUpdateAst() {
|
|
2130
|
+
throw new Error("Not implemented");
|
|
2131
|
+
}
|
|
2132
|
+
compileDeleteAst() {
|
|
2133
|
+
throw new Error("Not implemented");
|
|
2134
|
+
}
|
|
2135
|
+
}
|
|
2136
|
+
return new TestDialect(functionStrategy, tableFunctionStrategy);
|
|
2137
|
+
}
|
|
2181
2138
|
};
|
|
2182
2139
|
|
|
2183
|
-
// src/core/dialect/base/
|
|
2184
|
-
var
|
|
2140
|
+
// src/core/dialect/base/pagination-strategy.ts
|
|
2141
|
+
var StandardLimitOffsetPagination = class {
|
|
2185
2142
|
/**
|
|
2186
|
-
*
|
|
2187
|
-
* @param
|
|
2188
|
-
* @param
|
|
2189
|
-
* @
|
|
2190
|
-
* @returns SQL function table expression (e.g., "LATERAL schema.func(args) WITH ORDINALITY AS alias(col1, col2)").
|
|
2143
|
+
* Compiles LIMIT/OFFSET pagination clause.
|
|
2144
|
+
* @param limit - The maximum number of rows to return.
|
|
2145
|
+
* @param offset - The number of rows to skip.
|
|
2146
|
+
* @returns SQL pagination clause with LIMIT and/or OFFSET.
|
|
2191
2147
|
*/
|
|
2192
|
-
|
|
2193
|
-
const
|
|
2194
|
-
|
|
2195
|
-
|
|
2196
|
-
|
|
2197
|
-
const alias = this.formatAlias(fn9, dialect);
|
|
2198
|
-
const colAliases = this.formatColumnAliases(fn9, dialect);
|
|
2199
|
-
return `${lateral}${base}${alias}${colAliases}`;
|
|
2148
|
+
compilePagination(limit, offset) {
|
|
2149
|
+
const parts = [];
|
|
2150
|
+
if (limit !== void 0) parts.push(`LIMIT ${limit}`);
|
|
2151
|
+
if (offset !== void 0) parts.push(`OFFSET ${offset}`);
|
|
2152
|
+
return parts.length ? ` ${parts.join(" ")}` : "";
|
|
2200
2153
|
}
|
|
2154
|
+
};
|
|
2155
|
+
|
|
2156
|
+
// src/core/dialect/base/returning-strategy.ts
|
|
2157
|
+
var NoReturningStrategy = class {
|
|
2201
2158
|
/**
|
|
2202
|
-
*
|
|
2203
|
-
* @param
|
|
2204
|
-
* @param
|
|
2205
|
-
* @
|
|
2206
|
-
* @internal
|
|
2159
|
+
* Throws an error as RETURNING is not supported.
|
|
2160
|
+
* @param returning - Columns to return (causes error if non-empty).
|
|
2161
|
+
* @param _ctx - Compiler context (unused).
|
|
2162
|
+
* @throws Error indicating RETURNING is not supported.
|
|
2207
2163
|
*/
|
|
2208
|
-
|
|
2209
|
-
|
|
2210
|
-
|
|
2211
|
-
|
|
2164
|
+
compileReturning(returning, _ctx) {
|
|
2165
|
+
void _ctx;
|
|
2166
|
+
if (!returning || returning.length === 0) return "";
|
|
2167
|
+
throw new Error("RETURNING is not supported by this dialect.");
|
|
2212
2168
|
}
|
|
2213
2169
|
/**
|
|
2214
|
-
* Formats
|
|
2215
|
-
* @param
|
|
2216
|
-
* @param
|
|
2217
|
-
* @
|
|
2218
|
-
* @returns Comma-separated function arguments.
|
|
2219
|
-
* @internal
|
|
2170
|
+
* Formats column names for RETURNING clause.
|
|
2171
|
+
* @param returning - Columns to format.
|
|
2172
|
+
* @param quoteIdentifier - Function to quote identifiers according to dialect rules.
|
|
2173
|
+
* @returns Simple comma-separated column names.
|
|
2220
2174
|
*/
|
|
2221
|
-
|
|
2222
|
-
return
|
|
2223
|
-
|
|
2224
|
-
|
|
2225
|
-
}
|
|
2226
|
-
return String(a);
|
|
2175
|
+
formatReturningColumns(returning, quoteIdentifier) {
|
|
2176
|
+
return returning.map((column) => {
|
|
2177
|
+
const tablePart = column.table ? `${quoteIdentifier(column.table)}.` : "";
|
|
2178
|
+
const aliasPart = column.alias ? ` AS ${quoteIdentifier(column.alias)}` : "";
|
|
2179
|
+
return `${tablePart}${quoteIdentifier(column.name)}${aliasPart}`;
|
|
2227
2180
|
}).join(", ");
|
|
2228
2181
|
}
|
|
2229
|
-
|
|
2230
|
-
|
|
2231
|
-
|
|
2232
|
-
|
|
2233
|
-
|
|
2234
|
-
|
|
2235
|
-
|
|
2236
|
-
|
|
2237
|
-
|
|
2182
|
+
};
|
|
2183
|
+
|
|
2184
|
+
// src/core/dialect/base/function-table-formatter.ts
|
|
2185
|
+
var FunctionTableFormatter = class {
|
|
2186
|
+
static format(fn9, ctx, formatter) {
|
|
2187
|
+
const schemaPart = this.formatSchema(fn9, formatter);
|
|
2188
|
+
const args = this.formatArgs(fn9, ctx, formatter);
|
|
2189
|
+
const base = this.formatBase(fn9, schemaPart, args);
|
|
2190
|
+
const lateral = this.formatLateral(fn9);
|
|
2191
|
+
const alias = this.formatAlias(fn9, formatter);
|
|
2192
|
+
const colAliases = this.formatColumnAliases(fn9, formatter);
|
|
2193
|
+
return `${lateral}${base}${alias}${colAliases}`;
|
|
2194
|
+
}
|
|
2195
|
+
static formatSchema(fn9, formatter) {
|
|
2196
|
+
if (!fn9.schema) return "";
|
|
2197
|
+
return `${formatter.quoteIdentifier(fn9.schema)}.`;
|
|
2198
|
+
}
|
|
2199
|
+
static formatArgs(fn9, ctx, formatter) {
|
|
2200
|
+
return (fn9.args || []).map((arg) => ctx ? formatter.compileOperand(arg, ctx) : String(arg)).join(", ");
|
|
2201
|
+
}
|
|
2238
2202
|
static formatBase(fn9, schemaPart, args) {
|
|
2239
2203
|
const ordinality = fn9.withOrdinality ? " WITH ORDINALITY" : "";
|
|
2240
2204
|
return `${schemaPart}${fn9.name}(${args})${ordinality}`;
|
|
2241
2205
|
}
|
|
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
2206
|
static formatLateral(fn9) {
|
|
2249
2207
|
return fn9.lateral ? "LATERAL " : "";
|
|
2250
2208
|
}
|
|
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) {
|
|
2209
|
+
static formatAlias(fn9, formatter) {
|
|
2259
2210
|
if (!fn9.alias) return "";
|
|
2260
|
-
|
|
2261
|
-
|
|
2262
|
-
|
|
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) {
|
|
2211
|
+
return ` AS ${formatter.quoteIdentifier(fn9.alias)}`;
|
|
2212
|
+
}
|
|
2213
|
+
static formatColumnAliases(fn9, formatter) {
|
|
2271
2214
|
if (!fn9.columnAliases || !fn9.columnAliases.length) return "";
|
|
2272
|
-
const aliases = fn9.columnAliases.map((col2) =>
|
|
2215
|
+
const aliases = fn9.columnAliases.map((col2) => formatter.quoteIdentifier(col2)).join(", ");
|
|
2273
2216
|
return `(${aliases})`;
|
|
2274
2217
|
}
|
|
2275
2218
|
};
|
|
2276
2219
|
|
|
2277
|
-
// src/core/dialect/base/
|
|
2278
|
-
var
|
|
2279
|
-
|
|
2280
|
-
|
|
2281
|
-
|
|
2282
|
-
|
|
2283
|
-
|
|
2284
|
-
|
|
2285
|
-
|
|
2286
|
-
|
|
2287
|
-
|
|
2288
|
-
|
|
2289
|
-
|
|
2220
|
+
// src/core/dialect/base/standard-sql-source-compiler.ts
|
|
2221
|
+
var StandardSqlSourceCompiler = class {
|
|
2222
|
+
constructor(services) {
|
|
2223
|
+
this.services = services;
|
|
2224
|
+
}
|
|
2225
|
+
compileFrom(source, ctx) {
|
|
2226
|
+
if (source.type === "FunctionTable") return this.compileFunctionTable(source, ctx);
|
|
2227
|
+
if (source.type === "DerivedTable") return this.compileDerivedTable(source, ctx);
|
|
2228
|
+
return this.compileTableSource(source);
|
|
2229
|
+
}
|
|
2230
|
+
compileFunctionTable(fn9, ctx) {
|
|
2231
|
+
const key = fn9.key ?? fn9.name;
|
|
2232
|
+
if (ctx) {
|
|
2233
|
+
const renderer = this.services.getTableFunctionStrategy().getRenderer(key);
|
|
2234
|
+
if (renderer) {
|
|
2235
|
+
const compiledArgs = (fn9.args ?? []).map((arg) => this.services.compileOperand(arg, ctx));
|
|
2236
|
+
return renderer({
|
|
2237
|
+
node: fn9,
|
|
2238
|
+
compiledArgs,
|
|
2239
|
+
compileOperand: (operand) => this.services.compileOperand(operand, ctx),
|
|
2240
|
+
quoteIdentifier: (id) => this.services.quoteIdentifier(id)
|
|
2241
|
+
});
|
|
2242
|
+
}
|
|
2243
|
+
if (fn9.key) {
|
|
2244
|
+
throw new Error(
|
|
2245
|
+
`Table function "${key}" is not supported by dialect "${this.services.getDialectName()}".`
|
|
2246
|
+
);
|
|
2247
|
+
}
|
|
2248
|
+
}
|
|
2249
|
+
return FunctionTableFormatter.format(fn9, ctx, {
|
|
2250
|
+
quoteIdentifier: (id) => this.services.quoteIdentifier(id),
|
|
2251
|
+
compileOperand: (node, compilerContext) => this.services.compileOperand(node, compilerContext)
|
|
2252
|
+
});
|
|
2253
|
+
}
|
|
2254
|
+
compileDerivedTable(table, ctx) {
|
|
2255
|
+
if (!table.alias) throw new Error("Derived tables must have an alias.");
|
|
2256
|
+
if (!ctx) throw new Error("Derived table compilation requires a compiler context.");
|
|
2257
|
+
const normalized = this.services.normalizeSelectAst(table.query);
|
|
2258
|
+
const subquery = this.services.compileSelectAst(normalized, ctx).trim().replace(/;$/, "");
|
|
2259
|
+
const columns = table.columnAliases?.length ? ` (${table.columnAliases.map((column) => this.services.quoteIdentifier(column)).join(", ")})` : "";
|
|
2260
|
+
return `(${subquery}) AS ${this.services.quoteIdentifier(table.alias)}${columns}`;
|
|
2261
|
+
}
|
|
2262
|
+
compileTableSource(table) {
|
|
2263
|
+
if (table.type === "FunctionTable") return this.compileFunctionTable(table);
|
|
2264
|
+
if (table.type === "DerivedTable") {
|
|
2265
|
+
throw new Error("Derived table compilation requires a compiler context.");
|
|
2266
|
+
}
|
|
2267
|
+
const base = this.compileTableName(table);
|
|
2268
|
+
return table.alias ? `${base} AS ${this.services.quoteIdentifier(table.alias)}` : base;
|
|
2269
|
+
}
|
|
2270
|
+
compileTableName(table) {
|
|
2271
|
+
if (table.schema) {
|
|
2272
|
+
return `${this.services.quoteIdentifier(table.schema)}.${this.services.quoteIdentifier(table.name)}`;
|
|
2273
|
+
}
|
|
2274
|
+
return this.services.quoteIdentifier(table.name);
|
|
2275
|
+
}
|
|
2276
|
+
compileTableReference(table) {
|
|
2277
|
+
const base = this.compileTableName(table);
|
|
2278
|
+
return table.alias ? `${base} AS ${this.services.quoteIdentifier(table.alias)}` : base;
|
|
2279
|
+
}
|
|
2280
|
+
stripTrailingSemicolon(sql) {
|
|
2281
|
+
return sql.trim().replace(/;$/, "");
|
|
2282
|
+
}
|
|
2283
|
+
wrapSetOperand(sql) {
|
|
2284
|
+
return `(${this.stripTrailingSemicolon(sql)})`;
|
|
2290
2285
|
}
|
|
2291
2286
|
};
|
|
2292
2287
|
|
|
@@ -2316,34 +2311,6 @@ var CteCompiler = class {
|
|
|
2316
2311
|
}
|
|
2317
2312
|
};
|
|
2318
2313
|
|
|
2319
|
-
// src/core/dialect/base/returning-strategy.ts
|
|
2320
|
-
var NoReturningStrategy = class {
|
|
2321
|
-
/**
|
|
2322
|
-
* Throws an error as RETURNING is not supported.
|
|
2323
|
-
* @param returning - Columns to return (causes error if non-empty).
|
|
2324
|
-
* @param _ctx - Compiler context (unused).
|
|
2325
|
-
* @throws Error indicating RETURNING is not supported.
|
|
2326
|
-
*/
|
|
2327
|
-
compileReturning(returning, _ctx) {
|
|
2328
|
-
void _ctx;
|
|
2329
|
-
if (!returning || returning.length === 0) return "";
|
|
2330
|
-
throw new Error("RETURNING is not supported by this dialect.");
|
|
2331
|
-
}
|
|
2332
|
-
/**
|
|
2333
|
-
* Formats column names for RETURNING clause.
|
|
2334
|
-
* @param returning - Columns to format.
|
|
2335
|
-
* @param quoteIdentifier - Function to quote identifiers according to dialect rules.
|
|
2336
|
-
* @returns Simple comma-separated column names.
|
|
2337
|
-
*/
|
|
2338
|
-
formatReturningColumns(returning, quoteIdentifier) {
|
|
2339
|
-
return returning.map((column) => {
|
|
2340
|
-
const tablePart = column.table ? `${quoteIdentifier(column.table)}.` : "";
|
|
2341
|
-
const aliasPart = column.alias ? ` AS ${quoteIdentifier(column.alias)}` : "";
|
|
2342
|
-
return `${tablePart}${quoteIdentifier(column.name)}${aliasPart}`;
|
|
2343
|
-
}).join(", ");
|
|
2344
|
-
}
|
|
2345
|
-
};
|
|
2346
|
-
|
|
2347
2314
|
// src/core/dialect/base/join-compiler.ts
|
|
2348
2315
|
var JoinCompiler = class {
|
|
2349
2316
|
static compileJoins(joins, ctx, compileFrom, compileExpression) {
|
|
@@ -2394,113 +2361,229 @@ var OrderByCompiler = class {
|
|
|
2394
2361
|
}
|
|
2395
2362
|
};
|
|
2396
2363
|
|
|
2397
|
-
// src/core/dialect/base/
|
|
2398
|
-
var
|
|
2399
|
-
|
|
2400
|
-
|
|
2401
|
-
|
|
2364
|
+
// src/core/dialect/base/standard-select-compiler.ts
|
|
2365
|
+
var StandardSelectCompiler = class {
|
|
2366
|
+
constructor(services, sources) {
|
|
2367
|
+
this.services = services;
|
|
2368
|
+
this.sources = sources;
|
|
2369
|
+
}
|
|
2370
|
+
compile(ast, ctx) {
|
|
2402
2371
|
const hasSetOps = !!(ast.setOps && ast.setOps.length);
|
|
2403
2372
|
const ctes = CteCompiler.compileCtes(
|
|
2404
2373
|
ast,
|
|
2405
2374
|
ctx,
|
|
2406
|
-
this.quoteIdentifier
|
|
2407
|
-
this.compileSelectAst
|
|
2408
|
-
|
|
2409
|
-
this.stripTrailingSemicolon
|
|
2375
|
+
(id) => this.services.quoteIdentifier(id),
|
|
2376
|
+
(query, compilerContext) => this.services.compileSelectAst(query, compilerContext),
|
|
2377
|
+
(query) => this.services.normalizeSelectAst(query),
|
|
2378
|
+
(sql) => this.sources.stripTrailingSemicolon(sql)
|
|
2410
2379
|
);
|
|
2411
2380
|
const baseAst = hasSetOps ? { ...ast, setOps: void 0, orderBy: void 0, limit: void 0, offset: void 0 } : ast;
|
|
2412
|
-
const baseSelect = this.
|
|
2413
|
-
if (!hasSetOps) {
|
|
2414
|
-
|
|
2415
|
-
|
|
2416
|
-
|
|
2381
|
+
const baseSelect = this.compileCore(baseAst, ctx);
|
|
2382
|
+
if (!hasSetOps) return `${ctes}${baseSelect}`;
|
|
2383
|
+
const compound = ast.setOps.map((op) => `${op.operator} ${this.sources.wrapSetOperand(this.services.compileSelectAst(op.query, ctx))}`).join(" ");
|
|
2384
|
+
const orderBy = this.compileOrderBy(ast, ctx);
|
|
2385
|
+
const pagination = this.services.getPaginationStrategy().compilePagination(ast.limit, ast.offset);
|
|
2386
|
+
const combined = `${this.sources.wrapSetOperand(baseSelect)} ${compound}`;
|
|
2387
|
+
return `${ctes}${combined}${orderBy}${pagination}`;
|
|
2417
2388
|
}
|
|
2418
|
-
|
|
2419
|
-
const
|
|
2420
|
-
const
|
|
2389
|
+
compileCore(ast, ctx) {
|
|
2390
|
+
const columns = this.compileColumns(ast, ctx);
|
|
2391
|
+
const from = this.sources.compileFrom(ast.from, ctx);
|
|
2392
|
+
const joins = JoinCompiler.compileJoins(
|
|
2393
|
+
ast.joins,
|
|
2394
|
+
ctx,
|
|
2395
|
+
(source, compilerContext) => this.sources.compileFrom(source, compilerContext),
|
|
2396
|
+
(expression, compilerContext) => this.services.compileExpression(expression, compilerContext)
|
|
2397
|
+
);
|
|
2398
|
+
const where = ast.where ? ` WHERE ${this.services.compileExpression(ast.where, ctx)}` : "";
|
|
2399
|
+
const groupBy = GroupByCompiler.compileGroupBy(
|
|
2421
2400
|
ast,
|
|
2422
|
-
(term) => this.compileOrderingTerm(term, ctx)
|
|
2423
|
-
this.renderOrderByNulls.bind(this),
|
|
2424
|
-
this.renderOrderByCollation.bind(this)
|
|
2401
|
+
(term) => this.services.compileOrderingTerm(term, ctx)
|
|
2425
2402
|
);
|
|
2426
|
-
const
|
|
2427
|
-
const
|
|
2428
|
-
|
|
2403
|
+
const having = ast.having ? ` HAVING ${this.services.compileExpression(ast.having, ctx)}` : "";
|
|
2404
|
+
const orderBy = this.compileOrderBy(ast, ctx);
|
|
2405
|
+
const pagination = this.services.getPaginationStrategy().compilePagination(ast.limit, ast.offset);
|
|
2406
|
+
return `SELECT ${ast.distinct ? "DISTINCT " : ""}${columns} FROM ${from}${joins}${where}${groupBy}${having}${orderBy}${pagination}`;
|
|
2407
|
+
}
|
|
2408
|
+
compileColumns(ast, ctx) {
|
|
2409
|
+
if (!ast.columns || ast.columns.length === 0) return "*";
|
|
2410
|
+
return ast.columns.map((column) => {
|
|
2411
|
+
const expr = this.services.compileOperand(column, ctx);
|
|
2412
|
+
if (!column.alias) return expr;
|
|
2413
|
+
if (column.alias.includes("(")) return column.alias;
|
|
2414
|
+
return `${expr} AS ${this.services.quoteIdentifier(column.alias)}`;
|
|
2415
|
+
}).join(", ");
|
|
2429
2416
|
}
|
|
2430
|
-
|
|
2417
|
+
compileOrderBy(ast, ctx) {
|
|
2418
|
+
return OrderByCompiler.compileOrderBy(
|
|
2419
|
+
ast,
|
|
2420
|
+
(term) => this.services.compileOrderingTerm(term, ctx),
|
|
2421
|
+
(order) => this.services.renderOrderByNulls(order),
|
|
2422
|
+
(order) => this.services.renderOrderByCollation(order)
|
|
2423
|
+
);
|
|
2424
|
+
}
|
|
2425
|
+
};
|
|
2426
|
+
|
|
2427
|
+
// src/core/dialect/base/standard-insert-compiler.ts
|
|
2428
|
+
var StandardInsertCompiler = class {
|
|
2429
|
+
constructor(services, sources) {
|
|
2430
|
+
this.services = services;
|
|
2431
|
+
this.sources = sources;
|
|
2432
|
+
}
|
|
2433
|
+
compile(ast, ctx) {
|
|
2431
2434
|
if (!ast.columns.length) {
|
|
2432
2435
|
throw new Error("INSERT queries must specify columns.");
|
|
2433
2436
|
}
|
|
2434
|
-
const table = this.compileTableName(ast.into);
|
|
2435
|
-
const columnList = this.
|
|
2436
|
-
const source = this.
|
|
2437
|
-
const upsert = this.compileUpsertClause(ast, ctx);
|
|
2438
|
-
const returning = this.compileReturning(ast.returning, ctx);
|
|
2437
|
+
const table = this.sources.compileTableName(ast.into);
|
|
2438
|
+
const columnList = this.compileColumnList(ast.columns);
|
|
2439
|
+
const source = this.compileSource(ast.source, ctx);
|
|
2440
|
+
const upsert = this.services.compileUpsertClause(ast, ctx);
|
|
2441
|
+
const returning = this.services.compileReturning(ast.returning, ctx);
|
|
2439
2442
|
return `INSERT INTO ${table} (${columnList}) ${source}${upsert}${returning}`;
|
|
2440
2443
|
}
|
|
2441
|
-
|
|
2442
|
-
void _ctx;
|
|
2443
|
-
if (!ast.onConflict) return "";
|
|
2444
|
-
throw new Error(`UPSERT/ON CONFLICT is not supported by dialect "${this.dialect}".`);
|
|
2445
|
-
}
|
|
2446
|
-
compileReturning(returning, ctx) {
|
|
2447
|
-
return this.returningStrategy.compileReturning(returning, ctx);
|
|
2448
|
-
}
|
|
2449
|
-
compileInsertSource(source, ctx) {
|
|
2444
|
+
compileSource(source, ctx) {
|
|
2450
2445
|
if (source.type === "InsertValues") {
|
|
2451
2446
|
if (!source.rows.length) {
|
|
2452
2447
|
throw new Error("INSERT ... VALUES requires at least one row.");
|
|
2453
2448
|
}
|
|
2454
|
-
const values = source.rows.map((row) => `(${row.map((value) => this.compileOperand(value, ctx)).join(", ")})`).join(", ");
|
|
2449
|
+
const values = source.rows.map((row) => `(${row.map((value) => this.services.compileOperand(value, ctx)).join(", ")})`).join(", ");
|
|
2455
2450
|
return `VALUES ${values}`;
|
|
2456
2451
|
}
|
|
2457
|
-
const normalized = this.normalizeSelectAst(source.query);
|
|
2458
|
-
return this.compileSelectAst(normalized, ctx).trim();
|
|
2452
|
+
const normalized = this.services.normalizeSelectAst(source.query);
|
|
2453
|
+
return this.services.compileSelectAst(normalized, ctx).trim();
|
|
2459
2454
|
}
|
|
2460
|
-
|
|
2461
|
-
return columns.map((column) => this.quoteIdentifier(column.name)).join(", ");
|
|
2455
|
+
compileColumnList(columns) {
|
|
2456
|
+
return columns.map((column) => this.services.quoteIdentifier(column.name)).join(", ");
|
|
2462
2457
|
}
|
|
2463
2458
|
ensureConflictColumns(clause, message) {
|
|
2464
|
-
if (!clause.target.columns.length)
|
|
2465
|
-
throw new Error(message);
|
|
2466
|
-
}
|
|
2459
|
+
if (!clause.target.columns.length) throw new Error(message);
|
|
2467
2460
|
}
|
|
2468
|
-
|
|
2469
|
-
|
|
2470
|
-
|
|
2461
|
+
};
|
|
2462
|
+
|
|
2463
|
+
// src/core/dialect/base/standard-update-compiler.ts
|
|
2464
|
+
var StandardUpdateCompiler = class {
|
|
2465
|
+
constructor(services, sources) {
|
|
2466
|
+
this.services = services;
|
|
2467
|
+
this.sources = sources;
|
|
2468
|
+
}
|
|
2469
|
+
compile(ast, ctx) {
|
|
2470
|
+
const target = this.sources.compileTableReference(ast.table);
|
|
2471
|
+
const assignments = this.compileAssignments(ast.set, ast.table, ctx);
|
|
2472
|
+
const from = this.compileFromClause(ast, ctx);
|
|
2473
|
+
const where = ast.where ? ` WHERE ${this.services.compileExpression(ast.where, ctx)}` : "";
|
|
2474
|
+
const returning = this.services.compileReturning(ast.returning, ctx);
|
|
2475
|
+
return `UPDATE ${target} SET ${assignments}${from}${where}${returning}`;
|
|
2476
|
+
}
|
|
2477
|
+
compileAssignments(assignments, table, ctx) {
|
|
2478
|
+
return assignments.map((assignment) => {
|
|
2479
|
+
const target = this.services.compileSetTarget(assignment.column, table);
|
|
2480
|
+
const value = this.services.compileOperand(assignment.value, ctx);
|
|
2481
|
+
return `${target} = ${value}`;
|
|
2482
|
+
}).join(", ");
|
|
2483
|
+
}
|
|
2484
|
+
compileFromClause(ast, ctx) {
|
|
2485
|
+
if (!ast.from && (!ast.joins || ast.joins.length === 0)) return "";
|
|
2486
|
+
if (!ast.from) {
|
|
2487
|
+
throw new Error("UPDATE with JOINs requires an explicit FROM clause.");
|
|
2488
|
+
}
|
|
2489
|
+
const from = this.sources.compileFrom(ast.from, ctx);
|
|
2471
2490
|
const joins = JoinCompiler.compileJoins(
|
|
2472
2491
|
ast.joins,
|
|
2473
2492
|
ctx,
|
|
2474
|
-
this.compileFrom
|
|
2475
|
-
this.compileExpression
|
|
2493
|
+
(source, compilerContext) => this.sources.compileFrom(source, compilerContext),
|
|
2494
|
+
(expression, compilerContext) => this.services.compileExpression(expression, compilerContext)
|
|
2476
2495
|
);
|
|
2477
|
-
|
|
2478
|
-
|
|
2479
|
-
|
|
2480
|
-
|
|
2481
|
-
|
|
2482
|
-
|
|
2483
|
-
|
|
2484
|
-
|
|
2496
|
+
return ` FROM ${from}${joins}`;
|
|
2497
|
+
}
|
|
2498
|
+
};
|
|
2499
|
+
|
|
2500
|
+
// src/core/dialect/base/standard-delete-compiler.ts
|
|
2501
|
+
var StandardDeleteCompiler = class {
|
|
2502
|
+
constructor(services, sources) {
|
|
2503
|
+
this.services = services;
|
|
2504
|
+
this.sources = sources;
|
|
2505
|
+
}
|
|
2506
|
+
compile(ast, ctx) {
|
|
2507
|
+
const target = this.sources.compileTableReference(ast.from);
|
|
2508
|
+
const using = this.compileUsingClause(ast, ctx);
|
|
2509
|
+
const where = ast.where ? ` WHERE ${this.services.compileExpression(ast.where, ctx)}` : "";
|
|
2510
|
+
const returning = this.services.compileReturning(ast.returning, ctx);
|
|
2511
|
+
return `DELETE FROM ${target}${using}${where}${returning}`;
|
|
2512
|
+
}
|
|
2513
|
+
compileUsingClause(ast, ctx) {
|
|
2514
|
+
if (!ast.using && (!ast.joins || ast.joins.length === 0)) return "";
|
|
2515
|
+
if (!ast.using) {
|
|
2516
|
+
throw new Error("DELETE with JOINs requires a USING clause.");
|
|
2517
|
+
}
|
|
2518
|
+
const usingTable = this.sources.compileFrom(ast.using, ctx);
|
|
2519
|
+
const joins = JoinCompiler.compileJoins(
|
|
2520
|
+
ast.joins,
|
|
2521
|
+
ctx,
|
|
2522
|
+
(source, compilerContext) => this.sources.compileFrom(source, compilerContext),
|
|
2523
|
+
(expression, compilerContext) => this.services.compileExpression(expression, compilerContext)
|
|
2485
2524
|
);
|
|
2486
|
-
|
|
2487
|
-
|
|
2525
|
+
return ` USING ${usingTable}${joins}`;
|
|
2526
|
+
}
|
|
2527
|
+
};
|
|
2528
|
+
|
|
2529
|
+
// src/core/dialect/base/sql-dialect.ts
|
|
2530
|
+
var SqlDialectBase = class extends DialectBase {
|
|
2531
|
+
paginationStrategy = new StandardLimitOffsetPagination();
|
|
2532
|
+
returningStrategy = new NoReturningStrategy();
|
|
2533
|
+
sourceCompiler;
|
|
2534
|
+
selectCompiler;
|
|
2535
|
+
insertCompiler;
|
|
2536
|
+
updateCompiler;
|
|
2537
|
+
deleteCompiler;
|
|
2538
|
+
constructor(functionStrategy, tableFunctionStrategy) {
|
|
2539
|
+
super(functionStrategy, tableFunctionStrategy);
|
|
2540
|
+
const services = {
|
|
2541
|
+
getDialectName: () => this.dialect,
|
|
2542
|
+
getPaginationStrategy: () => this.paginationStrategy,
|
|
2543
|
+
getTableFunctionStrategy: () => this.tableFunctionStrategy,
|
|
2544
|
+
quoteIdentifier: (id) => this.quoteIdentifier(id),
|
|
2545
|
+
compileOperand: (node, ctx) => this.compileOperand(node, ctx),
|
|
2546
|
+
compileExpression: (node, ctx) => this.compileExpression(node, ctx),
|
|
2547
|
+
compileOrderingTerm: (term, ctx) => this.compileOrderingTerm(term, ctx),
|
|
2548
|
+
normalizeSelectAst: (ast) => this.normalizeSelectAst(ast),
|
|
2549
|
+
compileSelectAst: (ast, ctx) => this.compileSelectAst(ast, ctx),
|
|
2550
|
+
compileReturning: (returning, ctx) => this.compileReturning(returning, ctx),
|
|
2551
|
+
compileUpsertClause: (ast, ctx) => this.compileUpsertClause(ast, ctx),
|
|
2552
|
+
compileSetTarget: (column, table) => this.compileSetTarget(column, table),
|
|
2553
|
+
renderOrderByNulls: (order) => this.renderOrderByNulls(order),
|
|
2554
|
+
renderOrderByCollation: (order) => this.renderOrderByCollation(order)
|
|
2555
|
+
};
|
|
2556
|
+
this.sourceCompiler = new StandardSqlSourceCompiler(services);
|
|
2557
|
+
this.selectCompiler = new StandardSelectCompiler(services, this.sourceCompiler);
|
|
2558
|
+
this.insertCompiler = new StandardInsertCompiler(services, this.sourceCompiler);
|
|
2559
|
+
this.updateCompiler = new StandardUpdateCompiler(services, this.sourceCompiler);
|
|
2560
|
+
this.deleteCompiler = new StandardDeleteCompiler(services, this.sourceCompiler);
|
|
2561
|
+
}
|
|
2562
|
+
compileSelectAst(ast, ctx) {
|
|
2563
|
+
return this.selectCompiler.compile(ast, ctx);
|
|
2564
|
+
}
|
|
2565
|
+
compileInsertAst(ast, ctx) {
|
|
2566
|
+
return this.insertCompiler.compile(ast, ctx);
|
|
2488
2567
|
}
|
|
2489
2568
|
compileUpdateAst(ast, ctx) {
|
|
2490
|
-
|
|
2491
|
-
|
|
2492
|
-
|
|
2493
|
-
|
|
2494
|
-
|
|
2495
|
-
|
|
2569
|
+
return this.updateCompiler.compile(ast, ctx);
|
|
2570
|
+
}
|
|
2571
|
+
compileDeleteAst(ast, ctx) {
|
|
2572
|
+
return this.deleteCompiler.compile(ast, ctx);
|
|
2573
|
+
}
|
|
2574
|
+
compileUpsertClause(ast, _ctx) {
|
|
2575
|
+
void _ctx;
|
|
2576
|
+
if (!ast.onConflict) return "";
|
|
2577
|
+
throw new Error(`UPSERT/ON CONFLICT is not supported by dialect "${this.dialect}".`);
|
|
2578
|
+
}
|
|
2579
|
+
compileReturning(returning, ctx) {
|
|
2580
|
+
return this.returningStrategy.compileReturning(returning, ctx);
|
|
2581
|
+
}
|
|
2582
|
+
ensureConflictColumns(clause, message) {
|
|
2583
|
+
this.insertCompiler.ensureConflictColumns(clause, message);
|
|
2496
2584
|
}
|
|
2497
2585
|
compileUpdateAssignments(assignments, table, ctx) {
|
|
2498
|
-
return
|
|
2499
|
-
const col2 = assignment.column;
|
|
2500
|
-
const target = this.compileSetTarget(col2, table);
|
|
2501
|
-
const value = this.compileOperand(assignment.value, ctx);
|
|
2502
|
-
return `${target} = ${value}`;
|
|
2503
|
-
}).join(", ");
|
|
2586
|
+
return this.updateCompiler.compileAssignments(assignments, table, ctx);
|
|
2504
2587
|
}
|
|
2505
2588
|
compileSetTarget(column, table) {
|
|
2506
2589
|
return this.compileQualifiedColumn(column, table);
|
|
@@ -2510,132 +2593,38 @@ var SqlDialectBase = class extends Dialect {
|
|
|
2510
2593
|
const alias = table.alias;
|
|
2511
2594
|
const columnTable = column.table ?? alias ?? baseTableName;
|
|
2512
2595
|
const tableQualifier = alias && column.table === baseTableName ? alias : columnTable;
|
|
2513
|
-
if (!tableQualifier)
|
|
2514
|
-
return this.quoteIdentifier(column.name);
|
|
2515
|
-
}
|
|
2596
|
+
if (!tableQualifier) return this.quoteIdentifier(column.name);
|
|
2516
2597
|
return `${this.quoteIdentifier(tableQualifier)}.${this.quoteIdentifier(column.name)}`;
|
|
2517
2598
|
}
|
|
2518
|
-
compileDeleteAst(ast, ctx) {
|
|
2519
|
-
const target = this.compileTableReference(ast.from);
|
|
2520
|
-
const usingClause = this.compileDeleteUsingClause(ast, ctx);
|
|
2521
|
-
const whereClause = this.compileWhere(ast.where, ctx);
|
|
2522
|
-
const returning = this.compileReturning(ast.returning, ctx);
|
|
2523
|
-
return `DELETE FROM ${target}${usingClause}${whereClause}${returning}`;
|
|
2524
|
-
}
|
|
2525
2599
|
formatReturningColumns(returning) {
|
|
2526
|
-
return this.returningStrategy.formatReturningColumns(
|
|
2527
|
-
|
|
2528
|
-
|
|
2529
|
-
|
|
2530
|
-
}
|
|
2531
|
-
compileSelectColumns(ast, ctx) {
|
|
2532
|
-
if (!ast.columns || ast.columns.length === 0) {
|
|
2533
|
-
return "*";
|
|
2534
|
-
}
|
|
2535
|
-
return ast.columns.map((c) => {
|
|
2536
|
-
const expr = this.compileOperand(c, ctx);
|
|
2537
|
-
if (c.alias) {
|
|
2538
|
-
if (c.alias.includes("(")) return c.alias;
|
|
2539
|
-
return `${expr} AS ${this.quoteIdentifier(c.alias)}`;
|
|
2540
|
-
}
|
|
2541
|
-
return expr;
|
|
2542
|
-
}).join(", ");
|
|
2600
|
+
return this.returningStrategy.formatReturningColumns(
|
|
2601
|
+
returning,
|
|
2602
|
+
(id) => this.quoteIdentifier(id)
|
|
2603
|
+
);
|
|
2543
2604
|
}
|
|
2544
|
-
compileFrom(
|
|
2545
|
-
|
|
2546
|
-
if (tableSource.type === "FunctionTable") {
|
|
2547
|
-
return this.compileFunctionTable(tableSource, ctx);
|
|
2548
|
-
}
|
|
2549
|
-
if (tableSource.type === "DerivedTable") {
|
|
2550
|
-
return this.compileDerivedTable(tableSource, ctx);
|
|
2551
|
-
}
|
|
2552
|
-
return this.compileTableSource(tableSource);
|
|
2605
|
+
compileFrom(source, ctx) {
|
|
2606
|
+
return this.sourceCompiler.compileFrom(source, ctx);
|
|
2553
2607
|
}
|
|
2554
2608
|
compileFunctionTable(fn9, ctx) {
|
|
2555
|
-
|
|
2556
|
-
if (ctx) {
|
|
2557
|
-
const renderer = this.tableFunctionStrategy.getRenderer(key);
|
|
2558
|
-
if (renderer) {
|
|
2559
|
-
const compiledArgs = (fn9.args ?? []).map((arg) => this.compileOperand(arg, ctx));
|
|
2560
|
-
return renderer({
|
|
2561
|
-
node: fn9,
|
|
2562
|
-
compiledArgs,
|
|
2563
|
-
compileOperand: (operand) => this.compileOperand(operand, ctx),
|
|
2564
|
-
quoteIdentifier: this.quoteIdentifier.bind(this)
|
|
2565
|
-
});
|
|
2566
|
-
}
|
|
2567
|
-
if (fn9.key) {
|
|
2568
|
-
throw new Error(`Table function "${key}" is not supported by dialect "${this.dialect}".`);
|
|
2569
|
-
}
|
|
2570
|
-
}
|
|
2571
|
-
return FunctionTableFormatter.format(fn9, ctx, this);
|
|
2609
|
+
return this.sourceCompiler.compileFunctionTable(fn9, ctx);
|
|
2572
2610
|
}
|
|
2573
2611
|
compileDerivedTable(table, ctx) {
|
|
2574
|
-
|
|
2575
|
-
throw new Error("Derived tables must have an alias.");
|
|
2576
|
-
}
|
|
2577
|
-
const subquery = this.compileSelectAst(this.normalizeSelectAst(table.query), ctx).trim().replace(/;$/, "");
|
|
2578
|
-
const columns = table.columnAliases?.length ? ` (${table.columnAliases.map((c) => this.quoteIdentifier(c)).join(", ")})` : "";
|
|
2579
|
-
return `(${subquery}) AS ${this.quoteIdentifier(table.alias)}${columns}`;
|
|
2612
|
+
return this.sourceCompiler.compileDerivedTable(table, ctx);
|
|
2580
2613
|
}
|
|
2581
2614
|
compileTableSource(table) {
|
|
2582
|
-
|
|
2583
|
-
return this.compileFunctionTable(table);
|
|
2584
|
-
}
|
|
2585
|
-
if (table.type === "DerivedTable") {
|
|
2586
|
-
return this.compileDerivedTable(table);
|
|
2587
|
-
}
|
|
2588
|
-
const base = this.compileTableName(table);
|
|
2589
|
-
return table.alias ? `${base} AS ${this.quoteIdentifier(table.alias)}` : base;
|
|
2615
|
+
return this.sourceCompiler.compileTableSource(table);
|
|
2590
2616
|
}
|
|
2591
2617
|
compileTableName(table) {
|
|
2592
|
-
|
|
2593
|
-
return `${this.quoteIdentifier(table.schema)}.${this.quoteIdentifier(table.name)}`;
|
|
2594
|
-
}
|
|
2595
|
-
return this.quoteIdentifier(table.name);
|
|
2618
|
+
return this.sourceCompiler.compileTableName(table);
|
|
2596
2619
|
}
|
|
2597
2620
|
compileTableReference(table) {
|
|
2598
|
-
|
|
2599
|
-
return table.alias ? `${base} AS ${this.quoteIdentifier(table.alias)}` : base;
|
|
2600
|
-
}
|
|
2601
|
-
compileUpdateFromClause(ast, ctx) {
|
|
2602
|
-
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
|
-
}
|
|
2606
|
-
const from = this.compileFrom(ast.from, ctx);
|
|
2607
|
-
const joins = JoinCompiler.compileJoins(
|
|
2608
|
-
ast.joins,
|
|
2609
|
-
ctx,
|
|
2610
|
-
this.compileFrom.bind(this),
|
|
2611
|
-
this.compileExpression.bind(this)
|
|
2612
|
-
);
|
|
2613
|
-
return ` FROM ${from}${joins}`;
|
|
2614
|
-
}
|
|
2615
|
-
compileDeleteUsingClause(ast, ctx) {
|
|
2616
|
-
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
|
-
}
|
|
2620
|
-
const usingTable = this.compileFrom(ast.using, ctx);
|
|
2621
|
-
const joins = JoinCompiler.compileJoins(
|
|
2622
|
-
ast.joins,
|
|
2623
|
-
ctx,
|
|
2624
|
-
this.compileFrom.bind(this),
|
|
2625
|
-
this.compileExpression.bind(this)
|
|
2626
|
-
);
|
|
2627
|
-
return ` USING ${usingTable}${joins}`;
|
|
2628
|
-
}
|
|
2629
|
-
compileHaving(ast, ctx) {
|
|
2630
|
-
if (!ast.having) return "";
|
|
2631
|
-
return ` HAVING ${this.compileExpression(ast.having, ctx)}`;
|
|
2621
|
+
return this.sourceCompiler.compileTableReference(table);
|
|
2632
2622
|
}
|
|
2633
2623
|
stripTrailingSemicolon(sql) {
|
|
2634
|
-
return
|
|
2624
|
+
return this.sourceCompiler.stripTrailingSemicolon(sql);
|
|
2635
2625
|
}
|
|
2636
2626
|
wrapSetOperand(sql) {
|
|
2637
|
-
|
|
2638
|
-
return `(${trimmed})`;
|
|
2627
|
+
return this.sourceCompiler.wrapSetOperand(sql);
|
|
2639
2628
|
}
|
|
2640
2629
|
renderOrderByNulls(order) {
|
|
2641
2630
|
return order.nulls ? ` NULLS ${order.nulls}` : "";
|
|
@@ -3344,10 +3333,6 @@ var SqliteDialect = class extends SqlDialectBase {
|
|
|
3344
3333
|
supportsDmlReturningClause() {
|
|
3345
3334
|
return true;
|
|
3346
3335
|
}
|
|
3347
|
-
compileProcedureCall(_ast) {
|
|
3348
|
-
void _ast;
|
|
3349
|
-
throw new Error("Stored procedures are not supported by the SQLite dialect.");
|
|
3350
|
-
}
|
|
3351
3336
|
};
|
|
3352
3337
|
|
|
3353
3338
|
// src/core/dialect/mssql/functions.ts
|
|
@@ -3782,9 +3767,8 @@ var DialectFactory = class {
|
|
|
3782
3767
|
/**
|
|
3783
3768
|
* Register (or override) a dialect factory for a key.
|
|
3784
3769
|
*
|
|
3785
|
-
*
|
|
3786
|
-
*
|
|
3787
|
-
* DialectFactory.register('my-tenant-dialect', () => new CustomDialect());
|
|
3770
|
+
* Implementations are structural: extending DialectBase/SqlDialectBase is
|
|
3771
|
+
* optional. A composed object satisfying Dialect is a valid registration.
|
|
3788
3772
|
*/
|
|
3789
3773
|
static register(key, factory) {
|
|
3790
3774
|
this.registry.set(key, factory);
|
|
@@ -11357,6 +11341,15 @@ var DeleteQueryBuilder = class _DeleteQueryBuilder {
|
|
|
11357
11341
|
};
|
|
11358
11342
|
var isTableSourceNode2 = (source) => typeof source.type === "string";
|
|
11359
11343
|
|
|
11344
|
+
// src/core/dialect/capabilities/procedure-compiler.ts
|
|
11345
|
+
var isProcedureCompiler = (value) => typeof value?.compileProcedureCall === "function";
|
|
11346
|
+
var requireProcedureCompiler = (value) => {
|
|
11347
|
+
if (!isProcedureCompiler(value)) {
|
|
11348
|
+
throw new Error("Stored procedures are not supported by this dialect.");
|
|
11349
|
+
}
|
|
11350
|
+
return value;
|
|
11351
|
+
};
|
|
11352
|
+
|
|
11360
11353
|
// src/orm/execute-procedure.ts
|
|
11361
11354
|
var resolveColumnIndex = (columns, expectedName) => {
|
|
11362
11355
|
const exact = columns.findIndex((column) => column === expectedName);
|
|
@@ -11395,7 +11388,7 @@ var extractOutValues = (compiled, resultSets) => {
|
|
|
11395
11388
|
};
|
|
11396
11389
|
var executeProcedureAst = async (session, ast) => {
|
|
11397
11390
|
const execCtx = session.getExecutionContext();
|
|
11398
|
-
const compiled = execCtx.dialect.compileProcedureCall(ast);
|
|
11391
|
+
const compiled = requireProcedureCompiler(execCtx.dialect).compileProcedureCall(ast);
|
|
11399
11392
|
const payload = await execCtx.interceptors.run(
|
|
11400
11393
|
{ sql: compiled.sql, params: compiled.params },
|
|
11401
11394
|
execCtx.executor
|
|
@@ -11468,8 +11461,7 @@ var ProcedureCallBuilder = class _ProcedureCallBuilder {
|
|
|
11468
11461
|
}
|
|
11469
11462
|
compile(dialect) {
|
|
11470
11463
|
const resolved = resolveDialectInput(dialect);
|
|
11471
|
-
this.
|
|
11472
|
-
return resolved.compileProcedureCall(this.getAST());
|
|
11464
|
+
return requireProcedureCompiler(resolved).compileProcedureCall(this.getAST());
|
|
11473
11465
|
}
|
|
11474
11466
|
toSql(dialect) {
|
|
11475
11467
|
return this.compile(dialect).sql;
|
|
@@ -11482,21 +11474,8 @@ var ProcedureCallBuilder = class _ProcedureCallBuilder {
|
|
|
11482
11474
|
};
|
|
11483
11475
|
}
|
|
11484
11476
|
async execute(session) {
|
|
11485
|
-
this.validateMssqlOutDbType(session.getExecutionContext().dialect);
|
|
11486
11477
|
return executeProcedureAst(session, this.getAST());
|
|
11487
11478
|
}
|
|
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
11479
|
};
|
|
11501
11480
|
var callProcedure = (name, options) => new ProcedureCallBuilder(name, options);
|
|
11502
11481
|
|
|
@@ -22225,6 +22204,8 @@ async function bulkUpsert(session, table, rows, options = {}) {
|
|
|
22225
22204
|
DefaultMorphToReference,
|
|
22226
22205
|
DefaultTypeStrategy,
|
|
22227
22206
|
DeleteQueryBuilder,
|
|
22207
|
+
DialectBase,
|
|
22208
|
+
DialectFactory,
|
|
22228
22209
|
DomainEventBus,
|
|
22229
22210
|
Email,
|
|
22230
22211
|
Entity,
|
|
@@ -22258,6 +22239,11 @@ async function bulkUpsert(session, table, rows, options = {}) {
|
|
|
22258
22239
|
SelectQueryBuilder,
|
|
22259
22240
|
SqlServerDialect,
|
|
22260
22241
|
SqliteDialect,
|
|
22242
|
+
StandardDeleteCompiler,
|
|
22243
|
+
StandardInsertCompiler,
|
|
22244
|
+
StandardSelectCompiler,
|
|
22245
|
+
StandardSqlSourceCompiler,
|
|
22246
|
+
StandardUpdateCompiler,
|
|
22261
22247
|
StringTypeStrategy,
|
|
22262
22248
|
TagIndex,
|
|
22263
22249
|
Title,
|
|
@@ -22452,6 +22438,7 @@ async function bulkUpsert(session, table, rows, options = {}) {
|
|
|
22452
22438
|
isNull,
|
|
22453
22439
|
isNullableColumn,
|
|
22454
22440
|
isOperandNode,
|
|
22441
|
+
isProcedureCompiler,
|
|
22455
22442
|
isSingleTargetRelation,
|
|
22456
22443
|
isTableDef,
|
|
22457
22444
|
isTreeConfig,
|
|
@@ -22549,6 +22536,8 @@ async function bulkUpsert(session, table, rows, options = {}) {
|
|
|
22549
22536
|
repeat,
|
|
22550
22537
|
replace,
|
|
22551
22538
|
replaceWithRefs,
|
|
22539
|
+
requireProcedureCompiler,
|
|
22540
|
+
resolveDialectInput,
|
|
22552
22541
|
resolveTreeConfig,
|
|
22553
22542
|
resolveValidator,
|
|
22554
22543
|
responseToRef,
|