metal-orm 1.1.22 → 1.1.23
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +267 -400
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +95 -151
- package/dist/index.d.ts +95 -151
- package/dist/index.js +262 -400
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/core/dialect/abstract.ts +94 -417
- package/src/core/dialect/base/expression-compiler-registry.ts +254 -0
- package/src/core/dialect/base/function-table-formatter.ts +40 -78
- package/src/core/dialect/base/select-ast-normalizer.ts +61 -0
- package/src/core/dialect/base/sql-dialect.ts +36 -59
- package/src/core/dialect/capabilities/procedure-compiler.ts +30 -0
- package/src/core/dialect/dialect-factory.ts +3 -4
- package/src/core/dialect/mssql/index.ts +3 -2
- package/src/core/dialect/mysql/index.ts +3 -2
- package/src/core/dialect/postgres/index.ts +3 -2
- package/src/core/dialect/sqlite/index.ts +1 -7
- package/src/index.ts +4 -1
- package/src/orm/execute-procedure.ts +3 -2
- package/src/query-builder/procedure-call.ts +4 -18
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { ProcedureCallNode } from '../../ast/procedure.js';
|
|
2
|
+
import type { CompiledQuery } from '../abstract.js';
|
|
3
|
+
|
|
4
|
+
export interface CompiledProcedureCall extends CompiledQuery {
|
|
5
|
+
outParams: {
|
|
6
|
+
source: 'none' | 'firstResultSet' | 'lastResultSet';
|
|
7
|
+
names: string[];
|
|
8
|
+
};
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Optional dialect capability for stored-procedure compilation.
|
|
13
|
+
*
|
|
14
|
+
* Dialects that do not support procedures simply do not implement this
|
|
15
|
+
* interface; unsupported behavior is resolved at the capability boundary
|
|
16
|
+
* rather than through mandatory methods that only throw.
|
|
17
|
+
*/
|
|
18
|
+
export interface ProcedureCompiler {
|
|
19
|
+
compileProcedureCall(ast: ProcedureCallNode): CompiledProcedureCall;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export const isProcedureCompiler = (value: unknown): value is ProcedureCompiler =>
|
|
23
|
+
typeof (value as { compileProcedureCall?: unknown } | null)?.compileProcedureCall === 'function';
|
|
24
|
+
|
|
25
|
+
export const requireProcedureCompiler = (value: unknown): ProcedureCompiler => {
|
|
26
|
+
if (!isProcedureCompiler(value)) {
|
|
27
|
+
throw new Error('Stored procedures are not supported by this dialect.');
|
|
28
|
+
}
|
|
29
|
+
return value;
|
|
30
|
+
};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// Dialect factory for the SQL DSL.
|
|
2
2
|
// Centralizes how we go from a symbolic name ("sqlite") to a concrete Dialect instance.
|
|
3
3
|
|
|
4
|
-
import { Dialect } from './abstract.js';
|
|
4
|
+
import type { Dialect } from './abstract.js';
|
|
5
5
|
import { PostgresDialect } from './postgres/index.js';
|
|
6
6
|
import { MySqlDialect } from './mysql/index.js';
|
|
7
7
|
import { SqliteDialect } from './sqlite/index.js';
|
|
@@ -42,9 +42,8 @@ export class DialectFactory {
|
|
|
42
42
|
/**
|
|
43
43
|
* Register (or override) a dialect factory for a key.
|
|
44
44
|
*
|
|
45
|
-
*
|
|
46
|
-
*
|
|
47
|
-
* DialectFactory.register('my-tenant-dialect', () => new CustomDialect());
|
|
45
|
+
* Implementations are structural: extending DialectBase/SqlDialectBase is
|
|
46
|
+
* optional. A composed object satisfying Dialect is a valid registration.
|
|
48
47
|
*/
|
|
49
48
|
public static register(key: DialectKey, factory: DialectFactoryFn): void {
|
|
50
49
|
this.registry.set(key, factory);
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { CompilerContext
|
|
1
|
+
import { CompilerContext } from '../abstract.js';
|
|
2
|
+
import type { CompiledProcedureCall, ProcedureCompiler } from '../capabilities/procedure-compiler.js';
|
|
2
3
|
import {
|
|
3
4
|
SelectQueryNode,
|
|
4
5
|
InsertQueryNode,
|
|
@@ -21,7 +22,7 @@ const toProcedureParamReference = (value: string): string =>
|
|
|
21
22
|
/**
|
|
22
23
|
* Microsoft SQL Server dialect implementation
|
|
23
24
|
*/
|
|
24
|
-
export class SqlServerDialect extends SqlDialectBase {
|
|
25
|
+
export class SqlServerDialect extends SqlDialectBase implements ProcedureCompiler {
|
|
25
26
|
protected readonly dialect = 'mssql';
|
|
26
27
|
/**
|
|
27
28
|
* Creates a new SqlServerDialect instance
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { CompilerContext
|
|
1
|
+
import { CompilerContext } from '../abstract.js';
|
|
2
|
+
import type { CompiledProcedureCall, ProcedureCompiler } from '../capabilities/procedure-compiler.js';
|
|
2
3
|
import { JsonPathNode, IsDistinctExpressionNode } from '../../ast/expression.js';
|
|
3
4
|
import { InsertQueryNode } from '../../ast/query.js';
|
|
4
5
|
import { SqlDialectBase } from '../base/sql-dialect.js';
|
|
@@ -11,7 +12,7 @@ const sanitizeVariableSuffix = (value: string): string =>
|
|
|
11
12
|
/**
|
|
12
13
|
* MySQL dialect implementation
|
|
13
14
|
*/
|
|
14
|
-
export class MySqlDialect extends SqlDialectBase {
|
|
15
|
+
export class MySqlDialect extends SqlDialectBase implements ProcedureCompiler {
|
|
15
16
|
protected readonly dialect = 'mysql';
|
|
16
17
|
/**
|
|
17
18
|
* Creates a new MySqlDialect instance
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { CompilerContext
|
|
1
|
+
import { CompilerContext } from '../abstract.js';
|
|
2
|
+
import type { CompiledProcedureCall, ProcedureCompiler } from '../capabilities/procedure-compiler.js';
|
|
2
3
|
import { JsonPathNode, ColumnNode, BitwiseExpressionNode } from '../../ast/expression.js';
|
|
3
4
|
import { InsertQueryNode, TableNode } from '../../ast/query.js';
|
|
4
5
|
import { SqlDialectBase } from '../base/sql-dialect.js';
|
|
@@ -9,7 +10,7 @@ import { ProcedureCallNode } from '../../ast/procedure.js';
|
|
|
9
10
|
/**
|
|
10
11
|
* PostgreSQL dialect implementation
|
|
11
12
|
*/
|
|
12
|
-
export class PostgresDialect extends SqlDialectBase {
|
|
13
|
+
export class PostgresDialect extends SqlDialectBase implements ProcedureCompiler {
|
|
13
14
|
protected readonly dialect = 'postgres';
|
|
14
15
|
/**
|
|
15
16
|
* Creates a new PostgresDialect instance
|
|
@@ -1,9 +1,8 @@
|
|
|
1
|
-
import { CompilerContext
|
|
1
|
+
import { CompilerContext } from '../abstract.js';
|
|
2
2
|
import { JsonPathNode, ColumnNode, BitwiseExpressionNode } from '../../ast/expression.js';
|
|
3
3
|
import { InsertQueryNode, TableNode } from '../../ast/query.js';
|
|
4
4
|
import { SqlDialectBase } from '../base/sql-dialect.js';
|
|
5
5
|
import { SqliteFunctionStrategy } from './functions.js';
|
|
6
|
-
import { ProcedureCallNode } from '../../ast/procedure.js';
|
|
7
6
|
|
|
8
7
|
/**
|
|
9
8
|
* SQLite dialect implementation
|
|
@@ -104,9 +103,4 @@ export class SqliteDialect extends SqlDialectBase {
|
|
|
104
103
|
supportsDmlReturningClause(): boolean {
|
|
105
104
|
return true;
|
|
106
105
|
}
|
|
107
|
-
|
|
108
|
-
compileProcedureCall(_ast: ProcedureCallNode): CompiledProcedureCall {
|
|
109
|
-
void _ast;
|
|
110
|
-
throw new Error('Stored procedures are not supported by the SQLite dialect.');
|
|
111
|
-
}
|
|
112
106
|
}
|
package/src/index.ts
CHANGED
|
@@ -17,6 +17,9 @@ export * from './core/ast/expression.js';
|
|
|
17
17
|
export * from './core/ast/procedure.js';
|
|
18
18
|
export * from './core/ast/window-functions.js';
|
|
19
19
|
export * from './core/hydration/types.js';
|
|
20
|
+
export * from './core/dialect/abstract.js';
|
|
21
|
+
export * from './core/dialect/dialect-factory.js';
|
|
22
|
+
export * from './core/dialect/capabilities/procedure-compiler.js';
|
|
20
23
|
export * from './core/dialect/mysql/index.js';
|
|
21
24
|
export * from './core/dialect/mssql/index.js';
|
|
22
25
|
export * from './core/dialect/sqlite/index.js';
|
|
@@ -85,4 +88,4 @@ export * from './tree/index.js';
|
|
|
85
88
|
export * from './cache/index.js';
|
|
86
89
|
|
|
87
90
|
// Bulk operations module
|
|
88
|
-
export * from './bulk/index.js';
|
|
91
|
+
export * from './bulk/index.js';
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import type { ProcedureCallNode } from '../core/ast/procedure.js';
|
|
2
2
|
import type { QueryResult } from '../core/execution/db-executor.js';
|
|
3
3
|
import { payloadResultSets } from '../core/execution/db-executor.js';
|
|
4
|
-
import type { CompiledProcedureCall } from '../core/dialect/
|
|
4
|
+
import type { CompiledProcedureCall } from '../core/dialect/capabilities/procedure-compiler.js';
|
|
5
|
+
import { requireProcedureCompiler } from '../core/dialect/capabilities/procedure-compiler.js';
|
|
5
6
|
import type { OrmSession } from './orm-session.js';
|
|
6
7
|
|
|
7
8
|
export interface ProcedureExecutionResult {
|
|
@@ -63,7 +64,7 @@ export const executeProcedureAst = async (
|
|
|
63
64
|
ast: ProcedureCallNode
|
|
64
65
|
): Promise<ProcedureExecutionResult> => {
|
|
65
66
|
const execCtx = session.getExecutionContext();
|
|
66
|
-
const compiled = execCtx.dialect.compileProcedureCall(ast);
|
|
67
|
+
const compiled = requireProcedureCompiler(execCtx.dialect).compileProcedureCall(ast);
|
|
67
68
|
const payload = await execCtx.interceptors.run(
|
|
68
69
|
{ sql: compiled.sql, params: compiled.params },
|
|
69
70
|
execCtx.executor
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import type { ProcedureCallNode, ProcedureParamNode } from '../core/ast/procedure.js';
|
|
2
|
-
import type {
|
|
2
|
+
import type { Dialect } from '../core/dialect/abstract.js';
|
|
3
|
+
import type { CompiledProcedureCall } from '../core/dialect/capabilities/procedure-compiler.js';
|
|
4
|
+
import { requireProcedureCompiler } from '../core/dialect/capabilities/procedure-compiler.js';
|
|
3
5
|
import { DialectKey, resolveDialectInput } from '../core/dialect/dialect-factory.js';
|
|
4
6
|
import { valueToOperand, ValueOperandInput } from '../core/ast/expression-builders.js';
|
|
5
7
|
import type { OrmSession } from '../orm/orm-session.js';
|
|
@@ -82,8 +84,7 @@ export class ProcedureCallBuilder {
|
|
|
82
84
|
|
|
83
85
|
compile(dialect: ProcedureDialectInput): CompiledProcedureCall {
|
|
84
86
|
const resolved = resolveDialectInput(dialect);
|
|
85
|
-
this.
|
|
86
|
-
return resolved.compileProcedureCall(this.getAST());
|
|
87
|
+
return requireProcedureCompiler(resolved).compileProcedureCall(this.getAST());
|
|
87
88
|
}
|
|
88
89
|
|
|
89
90
|
toSql(dialect: ProcedureDialectInput): string {
|
|
@@ -99,23 +100,8 @@ export class ProcedureCallBuilder {
|
|
|
99
100
|
}
|
|
100
101
|
|
|
101
102
|
async execute(session: OrmSession): Promise<ProcedureExecutionResult> {
|
|
102
|
-
this.validateMssqlOutDbType(session.getExecutionContext().dialect);
|
|
103
103
|
return executeProcedureAst(session, this.getAST());
|
|
104
104
|
}
|
|
105
|
-
|
|
106
|
-
private validateMssqlOutDbType(dialect: Dialect): void {
|
|
107
|
-
const isMssqlDialect = dialect.constructor.name === 'SqlServerDialect';
|
|
108
|
-
if (!isMssqlDialect) return;
|
|
109
|
-
|
|
110
|
-
for (const param of this.ast.params) {
|
|
111
|
-
const needsDbType = param.direction === 'out' || param.direction === 'inout';
|
|
112
|
-
if (needsDbType && !param.dbType) {
|
|
113
|
-
throw new Error(
|
|
114
|
-
`MSSQL requires "dbType" for procedure parameter "${param.name}" with direction "${param.direction}".`
|
|
115
|
-
);
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
105
|
}
|
|
120
106
|
|
|
121
107
|
export const callProcedure = (name: string, options?: CallProcedureOptions): ProcedureCallBuilder =>
|