metal-orm 1.1.24 → 1.1.26
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +770 -710
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +294 -318
- package/dist/index.d.ts +294 -318
- package/dist/index.js +745 -709
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/core/dialect/abstract.ts +7 -229
- 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-composer.ts +294 -0
- package/src/core/dialect/base/standard-sql-services.ts +2 -6
- package/src/core/dialect/base/upsert-strategy.ts +44 -0
- package/src/core/dialect/capabilities/procedure-compiler.ts +10 -8
- package/src/core/dialect/dialect-factory.ts +17 -49
- 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 +52 -370
- 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 +66 -126
- 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 +75 -114
- 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 +65 -90
- package/src/core/dialect/sqlite/returning.ts +30 -0
- package/src/core/dialect/sqlite/upsert.ts +43 -0
- package/src/index.ts +22 -10
- package/src/core/dialect/base/sql-dialect.ts +0 -176
|
@@ -11,19 +11,15 @@ import type {
|
|
|
11
11
|
ExpressionNode,
|
|
12
12
|
OperandNode
|
|
13
13
|
} from '../../ast/expression.js';
|
|
14
|
-
import type { DialectName } from '../../sql/sql.js';
|
|
15
14
|
import type { PaginationStrategy } from './pagination-strategy.js';
|
|
16
15
|
import type { TableFunctionStrategy } from '../../functions/table-types.js';
|
|
17
16
|
|
|
18
17
|
/**
|
|
19
18
|
* 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.
|
|
19
|
+
* It deliberately depends on no dialect superclass or built-in dialect union.
|
|
24
20
|
*/
|
|
25
21
|
export interface StandardSqlCompilerServices {
|
|
26
|
-
getDialectName():
|
|
22
|
+
getDialectName(): string;
|
|
27
23
|
getPaginationStrategy(): PaginationStrategy;
|
|
28
24
|
getTableFunctionStrategy(): TableFunctionStrategy;
|
|
29
25
|
|
|
@@ -0,0 +1,44 @@
|
|
|
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
|
+
|
|
9
|
+
/** Narrow services needed by backend-specific UPSERT implementations. */
|
|
10
|
+
export interface UpsertCompilationServices {
|
|
11
|
+
getDialectName(): string;
|
|
12
|
+
quoteIdentifier(id: string): string;
|
|
13
|
+
compileOperand(node: OperandNode, ctx: CompilerContext): string;
|
|
14
|
+
compileExpression(node: ExpressionNode, ctx: CompilerContext): string;
|
|
15
|
+
compileUpdateAssignments(
|
|
16
|
+
assignments: UpdateAssignmentNode[],
|
|
17
|
+
table: TableNode,
|
|
18
|
+
ctx: CompilerContext
|
|
19
|
+
): string;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/** Backend-specific INSERT conflict/upsert rendering strategy. */
|
|
23
|
+
export interface UpsertStrategy {
|
|
24
|
+
compile(
|
|
25
|
+
ast: InsertQueryNode,
|
|
26
|
+
ctx: CompilerContext,
|
|
27
|
+
services: UpsertCompilationServices
|
|
28
|
+
): string;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/** Default strategy for dialects without UPSERT support. */
|
|
32
|
+
export class NoUpsertStrategy implements UpsertStrategy {
|
|
33
|
+
compile(
|
|
34
|
+
ast: InsertQueryNode,
|
|
35
|
+
_ctx: CompilerContext,
|
|
36
|
+
services: UpsertCompilationServices
|
|
37
|
+
): string {
|
|
38
|
+
void _ctx;
|
|
39
|
+
if (!ast.onConflict) return '';
|
|
40
|
+
throw new Error(
|
|
41
|
+
`UPSERT/ON CONFLICT is not supported by dialect "${services.getDialectName()}".`
|
|
42
|
+
);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
@@ -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
|
}
|
|
@@ -1,20 +1,20 @@
|
|
|
1
1
|
// Dialect factory for the SQL DSL.
|
|
2
|
-
// Centralizes how we go from a symbolic name ("sqlite") to a
|
|
2
|
+
// Centralizes how we go from a symbolic name ("sqlite") to a structural Dialect.
|
|
3
3
|
|
|
4
4
|
import type { Dialect } from './abstract.js';
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
5
|
+
import { createPostgresDialect } from './postgres/index.js';
|
|
6
|
+
import { createMySqlDialect } from './mysql/index.js';
|
|
7
|
+
import { createSqliteDialect } from './sqlite/index.js';
|
|
8
|
+
import { createSqlServerDialect } from './mssql/index.js';
|
|
9
9
|
|
|
10
10
|
export type DialectKey =
|
|
11
11
|
| 'postgres'
|
|
12
12
|
| 'mysql'
|
|
13
13
|
| 'sqlite'
|
|
14
14
|
| 'mssql'
|
|
15
|
-
| (string & {});
|
|
15
|
+
| (string & {});
|
|
16
16
|
|
|
17
|
-
type DialectFactoryFn = () => Dialect;
|
|
17
|
+
export type DialectFactoryFn = () => Dialect;
|
|
18
18
|
|
|
19
19
|
export class DialectFactory {
|
|
20
20
|
private static registry = new Map<DialectKey, DialectFactoryFn>();
|
|
@@ -24,67 +24,35 @@ export class DialectFactory {
|
|
|
24
24
|
if (this.defaultsInitialized) return;
|
|
25
25
|
this.defaultsInitialized = true;
|
|
26
26
|
|
|
27
|
-
|
|
28
|
-
if (!this.registry.has('
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
if (!this.registry.has('mysql')) {
|
|
32
|
-
this.registry.set('mysql', () => new MySqlDialect());
|
|
33
|
-
}
|
|
34
|
-
if (!this.registry.has('sqlite')) {
|
|
35
|
-
this.registry.set('sqlite', () => new SqliteDialect());
|
|
36
|
-
}
|
|
37
|
-
if (!this.registry.has('mssql')) {
|
|
38
|
-
this.registry.set('mssql', () => new SqlServerDialect());
|
|
39
|
-
}
|
|
27
|
+
if (!this.registry.has('postgres')) this.registry.set('postgres', createPostgresDialect);
|
|
28
|
+
if (!this.registry.has('mysql')) this.registry.set('mysql', createMySqlDialect);
|
|
29
|
+
if (!this.registry.has('sqlite')) this.registry.set('sqlite', createSqliteDialect);
|
|
30
|
+
if (!this.registry.has('mssql')) this.registry.set('mssql', createSqlServerDialect);
|
|
40
31
|
}
|
|
41
32
|
|
|
42
|
-
/**
|
|
43
|
-
* Register (or override) a dialect factory for a key.
|
|
44
|
-
*
|
|
45
|
-
* Implementations are structural: extending DialectBase/SqlDialectBase is
|
|
46
|
-
* optional. A composed object satisfying Dialect is a valid registration.
|
|
47
|
-
*/
|
|
33
|
+
/** Register or replace a structural dialect factory. */
|
|
48
34
|
public static register(key: DialectKey, factory: DialectFactoryFn): void {
|
|
49
35
|
this.registry.set(key, factory);
|
|
50
36
|
}
|
|
51
37
|
|
|
52
|
-
/**
|
|
53
|
-
* Resolve a key into a Dialect instance.
|
|
54
|
-
* Throws if the key is not registered.
|
|
55
|
-
*/
|
|
38
|
+
/** Resolve a key into a new Dialect instance. */
|
|
56
39
|
public static create(key: DialectKey): Dialect {
|
|
57
40
|
this.ensureDefaults();
|
|
58
41
|
const factory = this.registry.get(key);
|
|
59
42
|
if (!factory) {
|
|
60
43
|
throw new Error(
|
|
61
|
-
`Dialect "${String(
|
|
62
|
-
key
|
|
63
|
-
)}" is not registered. Use DialectFactory.register(...) to register it.`
|
|
44
|
+
`Dialect "${String(key)}" is not registered. Use DialectFactory.register(...) to register it.`
|
|
64
45
|
);
|
|
65
46
|
}
|
|
66
47
|
return factory();
|
|
67
48
|
}
|
|
68
49
|
|
|
69
|
-
/**
|
|
70
|
-
* Clear all registrations (mainly for tests).
|
|
71
|
-
* Built-ins will be re-registered lazily on the next create().
|
|
72
|
-
*/
|
|
50
|
+
/** Clear registrations; built-ins are restored lazily on the next create(). */
|
|
73
51
|
public static clear(): void {
|
|
74
52
|
this.registry.clear();
|
|
75
53
|
this.defaultsInitialized = false;
|
|
76
54
|
}
|
|
77
55
|
}
|
|
78
56
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
* This is what query builders will use.
|
|
82
|
-
*/
|
|
83
|
-
export const resolveDialectInput = (
|
|
84
|
-
dialect: Dialect | DialectKey
|
|
85
|
-
): Dialect => {
|
|
86
|
-
if (typeof dialect === 'string') {
|
|
87
|
-
return DialectFactory.create(dialect);
|
|
88
|
-
}
|
|
89
|
-
return dialect;
|
|
90
|
-
};
|
|
57
|
+
export const resolveDialectInput = (dialect: Dialect | DialectKey): Dialect =>
|
|
58
|
+
typeof dialect === 'string' ? DialectFactory.create(dialect) : dialect;
|
|
@@ -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
|
+
}
|