metal-orm 1.1.23 → 1.1.25
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 +832 -583
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +281 -144
- package/dist/index.d.ts +281 -144
- package/dist/index.js +807 -583
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/core/dialect/base/returning-strategy.ts +40 -39
- package/src/core/dialect/base/sql-compiler-set.ts +33 -0
- package/src/core/dialect/base/sql-dialect.ts +125 -222
- 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/base/upsert-strategy.ts +45 -0
- package/src/core/dialect/capabilities/procedure-compiler.ts +10 -8
- package/src/core/dialect/mssql/compiler-factory.ts +12 -0
- package/src/core/dialect/mssql/delete-compiler.ts +40 -0
- package/src/core/dialect/mssql/index.ts +24 -371
- package/src/core/dialect/mssql/insert-compiler.ts +112 -0
- package/src/core/dialect/mssql/output.ts +46 -0
- package/src/core/dialect/mssql/procedure-compiler.ts +81 -0
- package/src/core/dialect/mssql/select-compiler.ts +116 -0
- package/src/core/dialect/mssql/update-compiler.ts +37 -0
- package/src/core/dialect/mysql/index.ts +24 -117
- package/src/core/dialect/mysql/procedure-compiler.ts +67 -0
- package/src/core/dialect/mysql/upsert.ts +42 -0
- package/src/core/dialect/postgres/index.ts +34 -101
- package/src/core/dialect/postgres/procedure-compiler.ts +41 -0
- package/src/core/dialect/postgres/returning.ts +4 -0
- package/src/core/dialect/postgres/upsert.ts +43 -0
- package/src/core/dialect/sqlite/index.ts +15 -70
- package/src/core/dialect/sqlite/returning.ts +30 -0
- package/src/core/dialect/sqlite/upsert.ts +43 -0
- package/src/index.ts +28 -10
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import type { CompilerContext } from '../abstract.js';
|
|
2
|
+
import type { SelectQueryNode } from '../../ast/query.js';
|
|
3
|
+
import { CteCompiler } from './cte-compiler.js';
|
|
4
|
+
import { JoinCompiler } from './join-compiler.js';
|
|
5
|
+
import { GroupByCompiler } from './groupby-compiler.js';
|
|
6
|
+
import { OrderByCompiler } from './orderby-compiler.js';
|
|
7
|
+
import { StandardSqlSourceCompiler } from './standard-sql-source-compiler.js';
|
|
8
|
+
import type { StandardSqlCompilerServices } from './standard-sql-services.js';
|
|
9
|
+
|
|
10
|
+
/** Standard SELECT orchestration, independent from any dialect class hierarchy. */
|
|
11
|
+
export class StandardSelectCompiler {
|
|
12
|
+
public constructor(
|
|
13
|
+
private readonly services: StandardSqlCompilerServices,
|
|
14
|
+
private readonly sources: StandardSqlSourceCompiler
|
|
15
|
+
) {}
|
|
16
|
+
|
|
17
|
+
compile(ast: SelectQueryNode, ctx: CompilerContext): string {
|
|
18
|
+
const hasSetOps = !!(ast.setOps && ast.setOps.length);
|
|
19
|
+
const ctes = CteCompiler.compileCtes(
|
|
20
|
+
ast,
|
|
21
|
+
ctx,
|
|
22
|
+
id => this.services.quoteIdentifier(id),
|
|
23
|
+
(query, compilerContext) => this.services.compileSelectAst(query, compilerContext),
|
|
24
|
+
query => this.services.normalizeSelectAst(query),
|
|
25
|
+
sql => this.sources.stripTrailingSemicolon(sql)
|
|
26
|
+
);
|
|
27
|
+
|
|
28
|
+
const baseAst: SelectQueryNode = hasSetOps
|
|
29
|
+
? { ...ast, setOps: undefined, orderBy: undefined, limit: undefined, offset: undefined }
|
|
30
|
+
: ast;
|
|
31
|
+
const baseSelect = this.compileCore(baseAst, ctx);
|
|
32
|
+
|
|
33
|
+
if (!hasSetOps) return `${ctes}${baseSelect}`;
|
|
34
|
+
|
|
35
|
+
const compound = ast.setOps!
|
|
36
|
+
.map(op => `${op.operator} ${this.sources.wrapSetOperand(this.services.compileSelectAst(op.query, ctx))}`)
|
|
37
|
+
.join(' ');
|
|
38
|
+
const orderBy = this.compileOrderBy(ast, ctx);
|
|
39
|
+
const pagination = this.services.getPaginationStrategy().compilePagination(ast.limit, ast.offset);
|
|
40
|
+
const combined = `${this.sources.wrapSetOperand(baseSelect)} ${compound}`;
|
|
41
|
+
return `${ctes}${combined}${orderBy}${pagination}`;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
private compileCore(ast: SelectQueryNode, ctx: CompilerContext): string {
|
|
45
|
+
const columns = this.compileColumns(ast, ctx);
|
|
46
|
+
const from = this.sources.compileFrom(ast.from, ctx);
|
|
47
|
+
const joins = JoinCompiler.compileJoins(
|
|
48
|
+
ast.joins,
|
|
49
|
+
ctx,
|
|
50
|
+
(source, compilerContext) => this.sources.compileFrom(source, compilerContext),
|
|
51
|
+
(expression, compilerContext) => this.services.compileExpression(expression, compilerContext)
|
|
52
|
+
);
|
|
53
|
+
const where = ast.where ? ` WHERE ${this.services.compileExpression(ast.where, ctx)}` : '';
|
|
54
|
+
const groupBy = GroupByCompiler.compileGroupBy(
|
|
55
|
+
ast,
|
|
56
|
+
term => this.services.compileOrderingTerm(term, ctx)
|
|
57
|
+
);
|
|
58
|
+
const having = ast.having ? ` HAVING ${this.services.compileExpression(ast.having, ctx)}` : '';
|
|
59
|
+
const orderBy = this.compileOrderBy(ast, ctx);
|
|
60
|
+
const pagination = this.services.getPaginationStrategy().compilePagination(ast.limit, ast.offset);
|
|
61
|
+
return `SELECT ${ast.distinct ? 'DISTINCT ' : ''}${columns} FROM ${from}${joins}${where}${groupBy}${having}${orderBy}${pagination}`;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
private compileColumns(ast: SelectQueryNode, ctx: CompilerContext): string {
|
|
65
|
+
if (!ast.columns || ast.columns.length === 0) return '*';
|
|
66
|
+
return ast.columns.map(column => {
|
|
67
|
+
const expr = this.services.compileOperand(column, ctx);
|
|
68
|
+
if (!column.alias) return expr;
|
|
69
|
+
if (column.alias.includes('(')) return column.alias;
|
|
70
|
+
return `${expr} AS ${this.services.quoteIdentifier(column.alias)}`;
|
|
71
|
+
}).join(', ');
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
private compileOrderBy(ast: SelectQueryNode, ctx: CompilerContext): string {
|
|
75
|
+
return OrderByCompiler.compileOrderBy(
|
|
76
|
+
ast,
|
|
77
|
+
term => this.services.compileOrderingTerm(term, ctx),
|
|
78
|
+
order => this.services.renderOrderByNulls(order),
|
|
79
|
+
order => this.services.renderOrderByCollation(order)
|
|
80
|
+
);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import type { CompilerContext } from '../abstract.js';
|
|
2
|
+
import type {
|
|
3
|
+
SelectQueryNode,
|
|
4
|
+
InsertQueryNode,
|
|
5
|
+
OrderByNode,
|
|
6
|
+
OrderingTerm,
|
|
7
|
+
TableNode
|
|
8
|
+
} from '../../ast/query.js';
|
|
9
|
+
import type {
|
|
10
|
+
ColumnNode,
|
|
11
|
+
ExpressionNode,
|
|
12
|
+
OperandNode
|
|
13
|
+
} from '../../ast/expression.js';
|
|
14
|
+
import type { DialectName } from '../../sql/sql.js';
|
|
15
|
+
import type { PaginationStrategy } from './pagination-strategy.js';
|
|
16
|
+
import type { TableFunctionStrategy } from '../../functions/table-types.js';
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Narrow callback surface consumed by the standard SQL compilers.
|
|
20
|
+
*
|
|
21
|
+
* The compilers deliberately know nothing about SqlDialectBase or any concrete
|
|
22
|
+
* backend class. A dialect can assemble these services through inheritance,
|
|
23
|
+
* composition, or a plain object.
|
|
24
|
+
*/
|
|
25
|
+
export interface StandardSqlCompilerServices {
|
|
26
|
+
getDialectName(): DialectName;
|
|
27
|
+
getPaginationStrategy(): PaginationStrategy;
|
|
28
|
+
getTableFunctionStrategy(): TableFunctionStrategy;
|
|
29
|
+
|
|
30
|
+
quoteIdentifier(id: string): string;
|
|
31
|
+
compileOperand(node: OperandNode, ctx: CompilerContext): string;
|
|
32
|
+
compileExpression(node: ExpressionNode, ctx: CompilerContext): string;
|
|
33
|
+
compileOrderingTerm(term: OrderingTerm, ctx: CompilerContext): string;
|
|
34
|
+
|
|
35
|
+
normalizeSelectAst(ast: SelectQueryNode): SelectQueryNode;
|
|
36
|
+
compileSelectAst(ast: SelectQueryNode, ctx: CompilerContext): string;
|
|
37
|
+
|
|
38
|
+
compileReturning(returning: ColumnNode[] | undefined, ctx: CompilerContext): string;
|
|
39
|
+
compileUpsertClause(ast: InsertQueryNode, ctx: CompilerContext): string;
|
|
40
|
+
compileSetTarget(column: ColumnNode, table: TableNode): string;
|
|
41
|
+
|
|
42
|
+
renderOrderByNulls(order: OrderByNode): string | undefined;
|
|
43
|
+
renderOrderByCollation(order: OrderByNode): string | undefined;
|
|
44
|
+
}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import type { CompilerContext } from '../abstract.js';
|
|
2
|
+
import type {
|
|
3
|
+
DerivedTableNode,
|
|
4
|
+
FunctionTableNode,
|
|
5
|
+
TableSourceNode
|
|
6
|
+
} from '../../ast/query.js';
|
|
7
|
+
import { FunctionTableFormatter } from './function-table-formatter.js';
|
|
8
|
+
import type { StandardSqlCompilerServices } from './standard-sql-services.js';
|
|
9
|
+
|
|
10
|
+
/** Shared FROM/table-source rendering used by the standard query compilers. */
|
|
11
|
+
export class StandardSqlSourceCompiler {
|
|
12
|
+
public constructor(private readonly services: StandardSqlCompilerServices) {}
|
|
13
|
+
|
|
14
|
+
compileFrom(source: TableSourceNode, ctx?: CompilerContext): string {
|
|
15
|
+
if (source.type === 'FunctionTable') return this.compileFunctionTable(source, ctx);
|
|
16
|
+
if (source.type === 'DerivedTable') return this.compileDerivedTable(source, ctx);
|
|
17
|
+
return this.compileTableSource(source);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
compileFunctionTable(fn: FunctionTableNode, ctx?: CompilerContext): string {
|
|
21
|
+
const key = fn.key ?? fn.name;
|
|
22
|
+
|
|
23
|
+
if (ctx) {
|
|
24
|
+
const renderer = this.services.getTableFunctionStrategy().getRenderer(key);
|
|
25
|
+
if (renderer) {
|
|
26
|
+
const compiledArgs = (fn.args ?? []).map(arg => this.services.compileOperand(arg, ctx));
|
|
27
|
+
return renderer({
|
|
28
|
+
node: fn,
|
|
29
|
+
compiledArgs,
|
|
30
|
+
compileOperand: operand => this.services.compileOperand(operand, ctx),
|
|
31
|
+
quoteIdentifier: id => this.services.quoteIdentifier(id)
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
if (fn.key) {
|
|
36
|
+
throw new Error(
|
|
37
|
+
`Table function "${key}" is not supported by dialect "${this.services.getDialectName()}".`
|
|
38
|
+
);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
return FunctionTableFormatter.format(fn, ctx, {
|
|
43
|
+
quoteIdentifier: id => this.services.quoteIdentifier(id),
|
|
44
|
+
compileOperand: (node, compilerContext) => this.services.compileOperand(node, compilerContext)
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
compileDerivedTable(table: DerivedTableNode, ctx?: CompilerContext): string {
|
|
49
|
+
if (!table.alias) throw new Error('Derived tables must have an alias.');
|
|
50
|
+
if (!ctx) throw new Error('Derived table compilation requires a compiler context.');
|
|
51
|
+
|
|
52
|
+
const normalized = this.services.normalizeSelectAst(table.query);
|
|
53
|
+
const subquery = this.services.compileSelectAst(normalized, ctx).trim().replace(/;$/, '');
|
|
54
|
+
const columns = table.columnAliases?.length
|
|
55
|
+
? ` (${table.columnAliases.map(column => this.services.quoteIdentifier(column)).join(', ')})`
|
|
56
|
+
: '';
|
|
57
|
+
return `(${subquery}) AS ${this.services.quoteIdentifier(table.alias)}${columns}`;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
compileTableSource(table: TableSourceNode): string {
|
|
61
|
+
if (table.type === 'FunctionTable') return this.compileFunctionTable(table);
|
|
62
|
+
if (table.type === 'DerivedTable') {
|
|
63
|
+
throw new Error('Derived table compilation requires a compiler context.');
|
|
64
|
+
}
|
|
65
|
+
const base = this.compileTableName(table);
|
|
66
|
+
return table.alias ? `${base} AS ${this.services.quoteIdentifier(table.alias)}` : base;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
compileTableName(table: { name: string; schema?: string }): string {
|
|
70
|
+
if (table.schema) {
|
|
71
|
+
return `${this.services.quoteIdentifier(table.schema)}.${this.services.quoteIdentifier(table.name)}`;
|
|
72
|
+
}
|
|
73
|
+
return this.services.quoteIdentifier(table.name);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
compileTableReference(table: { name: string; schema?: string; alias?: string }): string {
|
|
77
|
+
const base = this.compileTableName(table);
|
|
78
|
+
return table.alias ? `${base} AS ${this.services.quoteIdentifier(table.alias)}` : base;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
stripTrailingSemicolon(sql: string): string {
|
|
82
|
+
return sql.trim().replace(/;$/, '');
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
wrapSetOperand(sql: string): string {
|
|
86
|
+
return `(${this.stripTrailingSemicolon(sql)})`;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import type { CompilerContext } from '../abstract.js';
|
|
2
|
+
import type { UpdateQueryNode, TableNode } from '../../ast/query.js';
|
|
3
|
+
import type { ColumnNode, OperandNode } from '../../ast/expression.js';
|
|
4
|
+
import { JoinCompiler } from './join-compiler.js';
|
|
5
|
+
import { StandardSqlSourceCompiler } from './standard-sql-source-compiler.js';
|
|
6
|
+
import type { StandardSqlCompilerServices } from './standard-sql-services.js';
|
|
7
|
+
|
|
8
|
+
/** Standard UPDATE orchestration, independent from concrete dialect classes. */
|
|
9
|
+
export class StandardUpdateCompiler {
|
|
10
|
+
public constructor(
|
|
11
|
+
private readonly services: StandardSqlCompilerServices,
|
|
12
|
+
private readonly sources: StandardSqlSourceCompiler
|
|
13
|
+
) {}
|
|
14
|
+
|
|
15
|
+
compile(ast: UpdateQueryNode, ctx: CompilerContext): string {
|
|
16
|
+
const target = this.sources.compileTableReference(ast.table);
|
|
17
|
+
const assignments = this.compileAssignments(ast.set, ast.table, ctx);
|
|
18
|
+
const from = this.compileFromClause(ast, ctx);
|
|
19
|
+
const where = ast.where ? ` WHERE ${this.services.compileExpression(ast.where, ctx)}` : '';
|
|
20
|
+
const returning = this.services.compileReturning(ast.returning, ctx);
|
|
21
|
+
return `UPDATE ${target} SET ${assignments}${from}${where}${returning}`;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
compileAssignments(
|
|
25
|
+
assignments: { column: ColumnNode; value: OperandNode }[],
|
|
26
|
+
table: TableNode,
|
|
27
|
+
ctx: CompilerContext
|
|
28
|
+
): string {
|
|
29
|
+
return assignments
|
|
30
|
+
.map(assignment => {
|
|
31
|
+
const target = this.services.compileSetTarget(assignment.column, table);
|
|
32
|
+
const value = this.services.compileOperand(assignment.value, ctx);
|
|
33
|
+
return `${target} = ${value}`;
|
|
34
|
+
})
|
|
35
|
+
.join(', ');
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
private compileFromClause(ast: UpdateQueryNode, ctx: CompilerContext): string {
|
|
39
|
+
if (!ast.from && (!ast.joins || ast.joins.length === 0)) return '';
|
|
40
|
+
if (!ast.from) {
|
|
41
|
+
throw new Error('UPDATE with JOINs requires an explicit FROM clause.');
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const from = this.sources.compileFrom(ast.from, ctx);
|
|
45
|
+
const joins = JoinCompiler.compileJoins(
|
|
46
|
+
ast.joins,
|
|
47
|
+
ctx,
|
|
48
|
+
(source, compilerContext) => this.sources.compileFrom(source, compilerContext),
|
|
49
|
+
(expression, compilerContext) => this.services.compileExpression(expression, compilerContext)
|
|
50
|
+
);
|
|
51
|
+
return ` FROM ${from}${joins}`;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import type { CompilerContext } from '../abstract.js';
|
|
2
|
+
import type {
|
|
3
|
+
InsertQueryNode,
|
|
4
|
+
TableNode,
|
|
5
|
+
UpdateAssignmentNode
|
|
6
|
+
} from '../../ast/query.js';
|
|
7
|
+
import type { ExpressionNode, OperandNode } from '../../ast/expression.js';
|
|
8
|
+
import type { DialectName } from '../../sql/sql.js';
|
|
9
|
+
|
|
10
|
+
/** Narrow services needed by backend-specific UPSERT implementations. */
|
|
11
|
+
export interface UpsertCompilationServices {
|
|
12
|
+
getDialectName(): DialectName;
|
|
13
|
+
quoteIdentifier(id: string): string;
|
|
14
|
+
compileOperand(node: OperandNode, ctx: CompilerContext): string;
|
|
15
|
+
compileExpression(node: ExpressionNode, ctx: CompilerContext): string;
|
|
16
|
+
compileUpdateAssignments(
|
|
17
|
+
assignments: UpdateAssignmentNode[],
|
|
18
|
+
table: TableNode,
|
|
19
|
+
ctx: CompilerContext
|
|
20
|
+
): string;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/** Backend-specific INSERT conflict/upsert rendering strategy. */
|
|
24
|
+
export interface UpsertStrategy {
|
|
25
|
+
compile(
|
|
26
|
+
ast: InsertQueryNode,
|
|
27
|
+
ctx: CompilerContext,
|
|
28
|
+
services: UpsertCompilationServices
|
|
29
|
+
): string;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/** Default strategy for dialects without UPSERT support. */
|
|
33
|
+
export class NoUpsertStrategy implements UpsertStrategy {
|
|
34
|
+
compile(
|
|
35
|
+
ast: InsertQueryNode,
|
|
36
|
+
_ctx: CompilerContext,
|
|
37
|
+
services: UpsertCompilationServices
|
|
38
|
+
): string {
|
|
39
|
+
void _ctx;
|
|
40
|
+
if (!ast.onConflict) return '';
|
|
41
|
+
throw new Error(
|
|
42
|
+
`UPSERT/ON CONFLICT is not supported by dialect "${services.getDialectName()}".`
|
|
43
|
+
);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { ProcedureCallNode } from '../../ast/procedure.js';
|
|
2
|
-
import type {
|
|
2
|
+
import type { OperandNode } from '../../ast/expression.js';
|
|
3
|
+
import type { CompiledQuery, CompilerContext } from '../abstract.js';
|
|
3
4
|
|
|
4
5
|
export interface CompiledProcedureCall extends CompiledQuery {
|
|
5
6
|
outParams: {
|
|
@@ -8,13 +9,14 @@ export interface CompiledProcedureCall extends CompiledQuery {
|
|
|
8
9
|
};
|
|
9
10
|
}
|
|
10
11
|
|
|
11
|
-
/**
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
12
|
+
/** Narrow SQL services consumed by reusable procedure compiler components. */
|
|
13
|
+
export interface ProcedureCompilerServices {
|
|
14
|
+
quoteIdentifier(id: string): string;
|
|
15
|
+
createCompilerContext(): CompilerContext;
|
|
16
|
+
compileOperand(node: OperandNode, ctx: CompilerContext): string;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/** Optional dialect capability for stored-procedure compilation. */
|
|
18
20
|
export interface ProcedureCompiler {
|
|
19
21
|
compileProcedureCall(ast: ProcedureCallNode): CompiledProcedureCall;
|
|
20
22
|
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { SqlCompilerFactory } from '../base/sql-compiler-set.js';
|
|
2
|
+
import { MssqlDeleteCompiler } from './delete-compiler.js';
|
|
3
|
+
import { MssqlInsertCompiler } from './insert-compiler.js';
|
|
4
|
+
import { MssqlSelectCompiler } from './select-compiler.js';
|
|
5
|
+
import { MssqlUpdateCompiler } from './update-compiler.js';
|
|
6
|
+
|
|
7
|
+
export const createMssqlCompilerSet: SqlCompilerFactory = ({ services, sources }) => ({
|
|
8
|
+
select: new MssqlSelectCompiler(services, sources),
|
|
9
|
+
insert: new MssqlInsertCompiler(services, sources),
|
|
10
|
+
update: new MssqlUpdateCompiler(services, sources),
|
|
11
|
+
delete: new MssqlDeleteCompiler(services, sources)
|
|
12
|
+
});
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import type { DeleteQueryNode } from '../../ast/query.js';
|
|
2
|
+
import type { CompilerContext } from '../abstract.js';
|
|
3
|
+
import { JoinCompiler } from '../base/join-compiler.js';
|
|
4
|
+
import type { SqlAstCompiler } from '../base/sql-compiler-set.js';
|
|
5
|
+
import type { StandardSqlCompilerServices } from '../base/standard-sql-services.js';
|
|
6
|
+
import type { StandardSqlSourceCompiler } from '../base/standard-sql-source-compiler.js';
|
|
7
|
+
import { MssqlOutputStrategy } from './output.js';
|
|
8
|
+
|
|
9
|
+
export class MssqlDeleteCompiler implements SqlAstCompiler<DeleteQueryNode> {
|
|
10
|
+
private readonly output = new MssqlOutputStrategy();
|
|
11
|
+
|
|
12
|
+
constructor(
|
|
13
|
+
private readonly services: StandardSqlCompilerServices,
|
|
14
|
+
private readonly sources: StandardSqlSourceCompiler
|
|
15
|
+
) {}
|
|
16
|
+
|
|
17
|
+
compile(ast: DeleteQueryNode, ctx: CompilerContext): string {
|
|
18
|
+
if (ast.using) {
|
|
19
|
+
throw new Error('DELETE ... USING is not supported in the MSSQL dialect; use join() instead.');
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const alias = ast.from.alias ?? ast.from.name;
|
|
23
|
+
const target = this.sources.compileTableReference(ast.from);
|
|
24
|
+
const joins = JoinCompiler.compileJoins(
|
|
25
|
+
ast.joins,
|
|
26
|
+
ctx,
|
|
27
|
+
(source, compilerContext) => this.sources.compileFrom(source, compilerContext),
|
|
28
|
+
(expression, compilerContext) => this.services.compileExpression(expression, compilerContext)
|
|
29
|
+
);
|
|
30
|
+
const where = ast.where
|
|
31
|
+
? ` WHERE ${this.services.compileExpression(ast.where, ctx)}`
|
|
32
|
+
: '';
|
|
33
|
+
const returning = this.output.compileOutput(
|
|
34
|
+
ast.returning,
|
|
35
|
+
'deleted',
|
|
36
|
+
id => this.services.quoteIdentifier(id)
|
|
37
|
+
);
|
|
38
|
+
return `DELETE ${this.services.quoteIdentifier(alias)}${returning} FROM ${target}${joins}${where}`;
|
|
39
|
+
}
|
|
40
|
+
}
|