metal-orm 1.1.11 → 1.1.18
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/README.md +758 -769
- package/dist/index.cjs.map +1 -1
- package/dist/index.js.map +1 -1
- package/package.json +100 -96
- package/scripts/generate-entities/schema.mjs +122 -122
- package/scripts/generate-entities/tree-detection.mjs +92 -92
- package/scripts/inflection/pt-br.mjs +468 -468
- package/scripts/run-eslint.mjs +33 -34
- package/scripts/show-sql-seed.sql +102 -0
- package/scripts/show-sql.mjs +321 -325
- package/src/codegen/naming-strategy.ts +54 -54
- package/src/codegen/typescript.ts +482 -482
- package/src/core/ast/adapters.ts +1 -1
- package/src/core/ast/builders.ts +123 -123
- package/src/core/ast/expression-builders.ts +745 -745
- package/src/core/ast/expression-nodes.ts +304 -304
- package/src/core/ast/expression-visitor.ts +212 -212
- package/src/core/ast/expression.ts +20 -20
- package/src/core/ast/helpers.ts +14 -14
- package/src/core/ast/join.ts +18 -18
- package/src/core/ast/query.ts +200 -200
- package/src/core/ddl/dialects/base-schema-dialect.ts +1 -1
- package/src/core/ddl/dialects/mssql-schema-dialect.ts +1 -1
- package/src/core/ddl/dialects/mysql-schema-dialect.ts +1 -1
- package/src/core/ddl/dialects/postgres-schema-dialect.ts +1 -1
- package/src/core/ddl/dialects/render-reference.test.ts +70 -70
- package/src/core/ddl/dialects/sqlite-schema-dialect.ts +1 -1
- package/src/core/ddl/introspect/catalogs/index.ts +5 -5
- package/src/core/ddl/introspect/catalogs/postgres.ts +146 -146
- package/src/core/ddl/introspect/context.ts +15 -15
- package/src/core/ddl/introspect/functions/postgres.ts +35 -35
- package/src/core/ddl/introspect/registry.ts +40 -40
- package/src/core/ddl/introspect/run-select.ts +35 -35
- package/src/core/ddl/introspect/utils.ts +56 -56
- package/src/core/ddl/naming-strategy.ts +16 -16
- package/src/core/ddl/schema-dialect.ts +56 -56
- package/src/core/ddl/schema-diff.ts +234 -234
- package/src/core/ddl/schema-generator.ts +1 -1
- package/src/core/ddl/schema-introspect.ts +25 -25
- package/src/core/ddl/sql-writing.ts +171 -171
- package/src/core/dialect/abstract.ts +541 -541
- package/src/core/dialect/base/cte-compiler.ts +33 -33
- package/src/core/dialect/base/function-table-formatter.ts +103 -103
- package/src/core/dialect/base/groupby-compiler.ts +21 -21
- package/src/core/dialect/base/join-compiler.ts +25 -25
- package/src/core/dialect/base/orderby-compiler.ts +35 -35
- package/src/core/dialect/base/pagination-strategy.ts +32 -32
- package/src/core/dialect/base/returning-strategy.ts +57 -57
- package/src/core/dialect/base/sql-dialect.ts +294 -294
- package/src/core/dialect/dialect-factory.ts +91 -91
- package/src/core/dialect/mssql/functions.ts +120 -120
- package/src/core/dialect/mssql/index.ts +317 -317
- package/src/core/dialect/mysql/functions.ts +103 -103
- package/src/core/dialect/mysql/index.ts +105 -105
- package/src/core/dialect/postgres/functions.ts +108 -108
- package/src/core/dialect/postgres/index.ts +91 -91
- package/src/core/dialect/sqlite/functions.ts +129 -129
- package/src/core/dialect/sqlite/index.ts +67 -67
- package/src/core/driver/database-driver.ts +19 -19
- package/src/core/driver/mssql-driver.ts +23 -23
- package/src/core/driver/mysql-driver.ts +23 -23
- package/src/core/driver/postgres-driver.ts +23 -23
- package/src/core/driver/sqlite-driver.ts +23 -23
- package/src/core/execution/db-executor.ts +92 -92
- package/src/core/execution/executors/better-sqlite3-executor.ts +90 -90
- package/src/core/execution/executors/mssql-executor.ts +184 -184
- package/src/core/execution/executors/mysql-executor.ts +88 -88
- package/src/core/execution/executors/postgres-executor.ts +26 -26
- package/src/core/execution/executors/sqlite-executor.ts +42 -42
- package/src/core/execution/pooling/pool-types.ts +30 -30
- package/src/core/execution/pooling/pool.ts +275 -275
- package/src/core/functions/array.ts +35 -35
- package/src/core/functions/control-flow.ts +79 -79
- package/src/core/functions/datetime.ts +237 -237
- package/src/core/functions/json.ts +70 -70
- package/src/core/functions/numeric.ts +297 -297
- package/src/core/functions/text.ts +334 -334
- package/src/core/functions/types.ts +33 -33
- package/src/core/hydration/types.ts +51 -51
- package/src/core/sql/sql-operator-config.ts +39 -39
- package/src/core/sql/sql.ts +152 -152
- package/src/decorators/column-decorator.ts +87 -87
- package/src/decorators/decorator-metadata.ts +143 -143
- package/src/decorators/entity.ts +93 -93
- package/src/decorators/index.ts +39 -39
- package/src/decorators/relations.ts +231 -231
- package/src/decorators/transformers/built-in/string-transformers.ts +231 -231
- package/src/decorators/transformers/transformer-decorators.ts +134 -134
- package/src/decorators/transformers/transformer-executor.ts +171 -171
- package/src/decorators/transformers/transformer-metadata.ts +73 -73
- package/src/decorators/validators/built-in/br-cep-validator.ts +55 -55
- package/src/decorators/validators/built-in/br-cnpj-validator.ts +105 -105
- package/src/decorators/validators/built-in/br-cpf-validator.ts +103 -103
- package/src/decorators/validators/country-validator-registry.ts +64 -64
- package/src/decorators/validators/country-validators-decorators.ts +203 -203
- package/src/decorators/validators/country-validators.ts +105 -105
- package/src/decorators/validators/validator-metadata.ts +59 -59
- package/src/dto/dto-types.ts +226 -226
- package/src/dto/filter-types.ts +141 -141
- package/src/dto/index.ts +95 -95
- package/src/dto/openapi/generators/base.ts +29 -29
- package/src/dto/openapi/generators/column.ts +37 -37
- package/src/dto/openapi/generators/dto.ts +91 -91
- package/src/dto/openapi/generators/filter.ts +75 -75
- package/src/dto/openapi/generators/nested-dto.ts +618 -618
- package/src/dto/openapi/generators/pagination.ts +111 -111
- package/src/dto/openapi/generators/relation-filter.ts +228 -228
- package/src/dto/openapi/index.ts +12 -12
- package/src/dto/openapi/types.ts +101 -101
- package/src/dto/openapi/utilities.ts +95 -95
- package/src/dto/pagination-utils.ts +150 -150
- package/src/dto/transform.ts +197 -197
- package/src/index.ts +86 -86
- package/src/orm/als.ts +58 -58
- package/src/orm/domain-event-bus.ts +119 -119
- package/src/orm/entity-context.ts +86 -86
- package/src/orm/entity-materializer.ts +159 -159
- package/src/orm/entity-meta.ts +97 -97
- package/src/orm/entity-registry.ts +39 -39
- package/src/orm/entity-relation-cache.ts +39 -39
- package/src/orm/execute.ts +194 -194
- package/src/orm/execution-context.ts +18 -18
- package/src/orm/hydration-context.ts +26 -26
- package/src/orm/hydration.ts +112 -112
- package/src/orm/identity-map.ts +61 -61
- package/src/orm/interceptor-pipeline.ts +16 -16
- package/src/orm/lazy-batch/belongs-to-many.ts +119 -119
- package/src/orm/lazy-batch/belongs-to.ts +108 -108
- package/src/orm/lazy-batch/has-many.ts +69 -69
- package/src/orm/lazy-batch/has-one.ts +68 -68
- package/src/orm/lazy-batch/shared.ts +125 -125
- package/src/orm/orm-session.ts +620 -620
- package/src/orm/orm.ts +34 -34
- package/src/orm/pooled-executor-factory.ts +121 -121
- package/src/orm/query-logger.ts +40 -40
- package/src/orm/relation-change-processor.ts +420 -420
- package/src/orm/relations/belongs-to.ts +143 -143
- package/src/orm/relations/has-many.ts +204 -204
- package/src/orm/relations/has-one.ts +174 -174
- package/src/orm/relations/many-to-many.ts +288 -288
- package/src/orm/relations/morph-many.ts +156 -156
- package/src/orm/relations/morph-one.ts +151 -151
- package/src/orm/relations/morph-to.ts +162 -162
- package/src/orm/runtime-types.ts +92 -92
- package/src/orm/save-graph.ts +561 -561
- package/src/orm/transaction-runner.ts +24 -24
- package/src/orm/unit-of-work.ts +426 -426
- package/src/query/index.ts +69 -69
- package/src/query/target.ts +46 -46
- package/src/query-builder/column-selector.ts +81 -81
- package/src/query-builder/delete.ts +141 -141
- package/src/query-builder/insert-query-state.ts +149 -149
- package/src/query-builder/insert.ts +117 -117
- package/src/query-builder/query-ast-service.ts +287 -287
- package/src/query-builder/query-resolution.ts +78 -78
- package/src/query-builder/raw-column-parser.ts +38 -38
- package/src/query-builder/relation-filter-utils.ts +153 -153
- package/src/query-builder/relation-join-planner.ts +10 -10
- package/src/query-builder/relation-manager.ts +87 -87
- package/src/query-builder/relation-projection-helper.ts +102 -102
- package/src/query-builder/relation-types.ts +9 -9
- package/src/query-builder/relation-utils.ts +15 -15
- package/src/query-builder/select/cte-facet.ts +40 -40
- package/src/query-builder/select/from-facet.ts +80 -80
- package/src/query-builder/select/join-facet.ts +62 -62
- package/src/query-builder/select/predicate-facet.ts +104 -104
- package/src/query-builder/select/projection-facet.ts +70 -70
- package/src/query-builder/select/relation-facet.ts +81 -81
- package/src/query-builder/select/setop-facet.ts +36 -36
- package/src/query-builder/select-helpers.ts +1 -1
- package/src/query-builder/select-query-builder-deps.ts +130 -130
- package/src/query-builder/select-query-state.ts +207 -207
- package/src/query-builder/update.ts +151 -151
- package/src/schema/column-types.ts +322 -322
- package/src/schema/table-guards.ts +37 -37
- package/src/schema/table.ts +281 -281
- package/src/tree/index.ts +13 -13
- package/src/tree/nested-set-strategy.ts +545 -545
- package/src/tree/tree-decorator.ts +397 -397
- package/src/tree/tree-manager.ts +754 -754
- package/src/tree/tree-query.ts +427 -427
- package/src/tree/tree-types.ts +299 -299
|
@@ -1,20 +1,20 @@
|
|
|
1
|
-
// src/core/execution/executors/mssql-executor.ts
|
|
2
|
-
import {
|
|
3
|
-
DbExecutor,
|
|
4
|
-
toExecutionPayload,
|
|
5
|
-
rowsToQueryResult
|
|
6
|
-
} from '../db-executor.js';
|
|
7
|
-
|
|
1
|
+
// src/core/execution/executors/mssql-executor.ts
|
|
2
|
+
import {
|
|
3
|
+
DbExecutor,
|
|
4
|
+
toExecutionPayload,
|
|
5
|
+
rowsToQueryResult
|
|
6
|
+
} from '../db-executor.js';
|
|
7
|
+
|
|
8
8
|
export interface MssqlClientLike {
|
|
9
|
-
query(
|
|
10
|
-
sql: string,
|
|
11
|
-
params?: unknown[]
|
|
12
|
-
): Promise<{
|
|
13
|
-
recordset?: Array<Record<string, unknown>>;
|
|
14
|
-
recordsets?: Array<Array<Record<string, unknown>>>;
|
|
15
|
-
}>;
|
|
16
|
-
beginTransaction?(): Promise<void>;
|
|
17
|
-
commit?(): Promise<void>;
|
|
9
|
+
query(
|
|
10
|
+
sql: string,
|
|
11
|
+
params?: unknown[]
|
|
12
|
+
): Promise<{
|
|
13
|
+
recordset?: Array<Record<string, unknown>>;
|
|
14
|
+
recordsets?: Array<Array<Record<string, unknown>>>;
|
|
15
|
+
}>;
|
|
16
|
+
beginTransaction?(): Promise<void>;
|
|
17
|
+
commit?(): Promise<void>;
|
|
18
18
|
rollback?(): Promise<void>;
|
|
19
19
|
}
|
|
20
20
|
|
|
@@ -27,43 +27,43 @@ const sanitizeSavepointName = (name: string): string => {
|
|
|
27
27
|
}
|
|
28
28
|
return trimmed;
|
|
29
29
|
};
|
|
30
|
-
|
|
31
|
-
/**
|
|
32
|
-
* Creates a database executor for Microsoft SQL Server.
|
|
33
|
-
* @param client A SQL Server client instance.
|
|
34
|
-
* @returns A DbExecutor implementation for MSSQL.
|
|
35
|
-
*/
|
|
36
|
-
export function createMssqlExecutor(
|
|
37
|
-
client: MssqlClientLike
|
|
38
|
-
): DbExecutor {
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Creates a database executor for Microsoft SQL Server.
|
|
33
|
+
* @param client A SQL Server client instance.
|
|
34
|
+
* @returns A DbExecutor implementation for MSSQL.
|
|
35
|
+
*/
|
|
36
|
+
export function createMssqlExecutor(
|
|
37
|
+
client: MssqlClientLike
|
|
38
|
+
): DbExecutor {
|
|
39
39
|
const supportsTransactions =
|
|
40
40
|
typeof client.beginTransaction === 'function' &&
|
|
41
41
|
typeof client.commit === 'function' &&
|
|
42
42
|
typeof client.rollback === 'function';
|
|
43
43
|
const supportsSavepoints = supportsTransactions;
|
|
44
|
-
|
|
45
|
-
return {
|
|
44
|
+
|
|
45
|
+
return {
|
|
46
46
|
capabilities: {
|
|
47
47
|
transactions: supportsTransactions,
|
|
48
48
|
...(supportsSavepoints ? { savepoints: true } : {}),
|
|
49
49
|
},
|
|
50
|
-
async executeSql(sql, params) {
|
|
51
|
-
const { recordset, recordsets } = await client.query(sql, params);
|
|
52
|
-
const sets = Array.isArray(recordsets) ? recordsets : [recordset ?? []];
|
|
53
|
-
return toExecutionPayload(sets.map(set => rowsToQueryResult(set ?? [])));
|
|
54
|
-
},
|
|
55
|
-
async beginTransaction() {
|
|
56
|
-
if (!supportsTransactions) {
|
|
57
|
-
throw new Error('Transactions are not supported by this executor');
|
|
58
|
-
}
|
|
59
|
-
await client.beginTransaction!();
|
|
60
|
-
},
|
|
61
|
-
async commitTransaction() {
|
|
62
|
-
if (!supportsTransactions) {
|
|
63
|
-
throw new Error('Transactions are not supported by this executor');
|
|
64
|
-
}
|
|
65
|
-
await client.commit!();
|
|
66
|
-
},
|
|
50
|
+
async executeSql(sql, params) {
|
|
51
|
+
const { recordset, recordsets } = await client.query(sql, params);
|
|
52
|
+
const sets = Array.isArray(recordsets) ? recordsets : [recordset ?? []];
|
|
53
|
+
return toExecutionPayload(sets.map(set => rowsToQueryResult(set ?? [])));
|
|
54
|
+
},
|
|
55
|
+
async beginTransaction() {
|
|
56
|
+
if (!supportsTransactions) {
|
|
57
|
+
throw new Error('Transactions are not supported by this executor');
|
|
58
|
+
}
|
|
59
|
+
await client.beginTransaction!();
|
|
60
|
+
},
|
|
61
|
+
async commitTransaction() {
|
|
62
|
+
if (!supportsTransactions) {
|
|
63
|
+
throw new Error('Transactions are not supported by this executor');
|
|
64
|
+
}
|
|
65
|
+
await client.commit!();
|
|
66
|
+
},
|
|
67
67
|
async rollbackTransaction() {
|
|
68
68
|
if (!supportsTransactions) {
|
|
69
69
|
throw new Error('Transactions are not supported by this executor');
|
|
@@ -93,143 +93,143 @@ export function createMssqlExecutor(
|
|
|
93
93
|
async dispose() {
|
|
94
94
|
// Connection lifecycle is owned by the caller/driver. Pool lease executors should implement dispose.
|
|
95
95
|
},
|
|
96
|
-
};
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
// ---------------------------------------------------------------------------
|
|
100
|
-
// Tedious integration helper (driver adapter)
|
|
101
|
-
// ---------------------------------------------------------------------------
|
|
102
|
-
|
|
103
|
-
export interface TediousColumn {
|
|
104
|
-
metadata: { colName: string };
|
|
105
|
-
value: unknown;
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
export interface TediousRequest {
|
|
109
|
-
addParameter(name: string, type: unknown, value: unknown): void;
|
|
110
|
-
on(event: 'row', listener: (columns: TediousColumn[]) => void): void;
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
export interface TediousRequestCtor {
|
|
114
|
-
new(sql: string, callback: (err?: Error | null) => void): TediousRequest;
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
export interface TediousTypes {
|
|
118
|
-
NVarChar: unknown;
|
|
119
|
-
Int: unknown;
|
|
120
|
-
Float: unknown;
|
|
121
|
-
BigInt: unknown;
|
|
122
|
-
Bit: unknown;
|
|
123
|
-
DateTime: unknown;
|
|
124
|
-
VarBinary: unknown;
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
export interface TediousModule {
|
|
128
|
-
Request: TediousRequestCtor;
|
|
129
|
-
TYPES: TediousTypes;
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
export interface TediousConnectionLike {
|
|
133
|
-
execSql(request: TediousRequest): void;
|
|
134
|
-
beginTransaction?(cb: (err?: Error | null) => void): void;
|
|
135
|
-
commitTransaction?(cb: (err?: Error | null) => void): void;
|
|
136
|
-
rollbackTransaction?(cb: (err?: Error | null) => void): void;
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
export interface CreateTediousClientOptions {
|
|
140
|
-
inferType?(value: unknown, TYPES: TediousTypes): unknown;
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
const defaultInferType = (value: unknown, TYPES: TediousTypes): unknown => {
|
|
144
|
-
if (value === null || value === undefined) return TYPES.NVarChar;
|
|
145
|
-
if (typeof value === 'number') {
|
|
146
|
-
return Number.isInteger(value) ? TYPES.Int : TYPES.Float;
|
|
147
|
-
}
|
|
148
|
-
if (typeof value === 'bigint') return TYPES.BigInt;
|
|
149
|
-
if (typeof value === 'boolean') return TYPES.Bit;
|
|
150
|
-
if (value instanceof Date) return TYPES.DateTime;
|
|
151
|
-
if (typeof Buffer !== 'undefined' && Buffer.isBuffer(value)) {
|
|
152
|
-
return TYPES.VarBinary;
|
|
153
|
-
}
|
|
154
|
-
return TYPES.NVarChar;
|
|
155
|
-
};
|
|
156
|
-
|
|
157
|
-
export function createTediousMssqlClient(
|
|
158
|
-
connection: TediousConnectionLike,
|
|
159
|
-
{ Request, TYPES }: TediousModule,
|
|
160
|
-
options?: CreateTediousClientOptions
|
|
161
|
-
): MssqlClientLike {
|
|
162
|
-
const inferType = options?.inferType ?? defaultInferType;
|
|
163
|
-
|
|
164
|
-
return {
|
|
165
|
-
async query(sql: string, params: unknown[] = []) {
|
|
166
|
-
const rows = await new Promise<Array<Record<string, unknown>>>(
|
|
167
|
-
(resolve, reject) => {
|
|
168
|
-
const collected: Record<string, unknown>[] = [];
|
|
169
|
-
|
|
170
|
-
const request = new Request(sql, err => {
|
|
171
|
-
if (err) return reject(err);
|
|
172
|
-
resolve(collected);
|
|
173
|
-
});
|
|
174
|
-
|
|
175
|
-
params.forEach((value, idx) => {
|
|
176
|
-
const sqlType = inferType(value, TYPES);
|
|
177
|
-
request.addParameter(
|
|
178
|
-
`p${idx + 1}`,
|
|
179
|
-
sqlType,
|
|
180
|
-
value as unknown
|
|
181
|
-
);
|
|
182
|
-
});
|
|
183
|
-
|
|
184
|
-
request.on('row', cols => {
|
|
185
|
-
const row: Record<string, unknown> = {};
|
|
186
|
-
for (const col of cols) {
|
|
187
|
-
row[col.metadata.colName] = col.value;
|
|
188
|
-
}
|
|
189
|
-
collected.push(row);
|
|
190
|
-
});
|
|
191
|
-
|
|
192
|
-
connection.execSql(request);
|
|
193
|
-
}
|
|
194
|
-
);
|
|
195
|
-
|
|
196
|
-
return { recordset: rows, recordsets: [rows] };
|
|
197
|
-
},
|
|
198
|
-
|
|
199
|
-
beginTransaction: connection.beginTransaction
|
|
200
|
-
? () =>
|
|
201
|
-
new Promise<void>((resolve, reject) => {
|
|
202
|
-
connection.beginTransaction!(err =>
|
|
203
|
-
err ? reject(err) : resolve()
|
|
204
|
-
);
|
|
205
|
-
})
|
|
206
|
-
: undefined,
|
|
207
|
-
|
|
208
|
-
commit: connection.commitTransaction
|
|
209
|
-
? () =>
|
|
210
|
-
new Promise<void>((resolve, reject) => {
|
|
211
|
-
connection.commitTransaction!(err =>
|
|
212
|
-
err ? reject(err) : resolve()
|
|
213
|
-
);
|
|
214
|
-
})
|
|
215
|
-
: undefined,
|
|
216
|
-
|
|
217
|
-
rollback: connection.rollbackTransaction
|
|
218
|
-
? () =>
|
|
219
|
-
new Promise<void>((resolve, reject) => {
|
|
220
|
-
connection.rollbackTransaction!(err =>
|
|
221
|
-
err ? reject(err) : resolve()
|
|
222
|
-
);
|
|
223
|
-
})
|
|
224
|
-
: undefined,
|
|
225
|
-
};
|
|
226
|
-
}
|
|
227
|
-
|
|
228
|
-
export function createTediousExecutor(
|
|
229
|
-
connection: TediousConnectionLike,
|
|
230
|
-
module: TediousModule,
|
|
231
|
-
options?: CreateTediousClientOptions
|
|
232
|
-
): DbExecutor {
|
|
233
|
-
const client = createTediousMssqlClient(connection, module, options);
|
|
234
|
-
return createMssqlExecutor(client);
|
|
235
|
-
}
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// ---------------------------------------------------------------------------
|
|
100
|
+
// Tedious integration helper (driver adapter)
|
|
101
|
+
// ---------------------------------------------------------------------------
|
|
102
|
+
|
|
103
|
+
export interface TediousColumn {
|
|
104
|
+
metadata: { colName: string };
|
|
105
|
+
value: unknown;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
export interface TediousRequest {
|
|
109
|
+
addParameter(name: string, type: unknown, value: unknown): void;
|
|
110
|
+
on(event: 'row', listener: (columns: TediousColumn[]) => void): void;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
export interface TediousRequestCtor {
|
|
114
|
+
new(sql: string, callback: (err?: Error | null) => void): TediousRequest;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
export interface TediousTypes {
|
|
118
|
+
NVarChar: unknown;
|
|
119
|
+
Int: unknown;
|
|
120
|
+
Float: unknown;
|
|
121
|
+
BigInt: unknown;
|
|
122
|
+
Bit: unknown;
|
|
123
|
+
DateTime: unknown;
|
|
124
|
+
VarBinary: unknown;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
export interface TediousModule {
|
|
128
|
+
Request: TediousRequestCtor;
|
|
129
|
+
TYPES: TediousTypes;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
export interface TediousConnectionLike {
|
|
133
|
+
execSql(request: TediousRequest): void;
|
|
134
|
+
beginTransaction?(cb: (err?: Error | null) => void): void;
|
|
135
|
+
commitTransaction?(cb: (err?: Error | null) => void): void;
|
|
136
|
+
rollbackTransaction?(cb: (err?: Error | null) => void): void;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
export interface CreateTediousClientOptions {
|
|
140
|
+
inferType?(value: unknown, TYPES: TediousTypes): unknown;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
const defaultInferType = (value: unknown, TYPES: TediousTypes): unknown => {
|
|
144
|
+
if (value === null || value === undefined) return TYPES.NVarChar;
|
|
145
|
+
if (typeof value === 'number') {
|
|
146
|
+
return Number.isInteger(value) ? TYPES.Int : TYPES.Float;
|
|
147
|
+
}
|
|
148
|
+
if (typeof value === 'bigint') return TYPES.BigInt;
|
|
149
|
+
if (typeof value === 'boolean') return TYPES.Bit;
|
|
150
|
+
if (value instanceof Date) return TYPES.DateTime;
|
|
151
|
+
if (typeof Buffer !== 'undefined' && Buffer.isBuffer(value)) {
|
|
152
|
+
return TYPES.VarBinary;
|
|
153
|
+
}
|
|
154
|
+
return TYPES.NVarChar;
|
|
155
|
+
};
|
|
156
|
+
|
|
157
|
+
export function createTediousMssqlClient(
|
|
158
|
+
connection: TediousConnectionLike,
|
|
159
|
+
{ Request, TYPES }: TediousModule,
|
|
160
|
+
options?: CreateTediousClientOptions
|
|
161
|
+
): MssqlClientLike {
|
|
162
|
+
const inferType = options?.inferType ?? defaultInferType;
|
|
163
|
+
|
|
164
|
+
return {
|
|
165
|
+
async query(sql: string, params: unknown[] = []) {
|
|
166
|
+
const rows = await new Promise<Array<Record<string, unknown>>>(
|
|
167
|
+
(resolve, reject) => {
|
|
168
|
+
const collected: Record<string, unknown>[] = [];
|
|
169
|
+
|
|
170
|
+
const request = new Request(sql, err => {
|
|
171
|
+
if (err) return reject(err);
|
|
172
|
+
resolve(collected);
|
|
173
|
+
});
|
|
174
|
+
|
|
175
|
+
params.forEach((value, idx) => {
|
|
176
|
+
const sqlType = inferType(value, TYPES);
|
|
177
|
+
request.addParameter(
|
|
178
|
+
`p${idx + 1}`,
|
|
179
|
+
sqlType,
|
|
180
|
+
value as unknown
|
|
181
|
+
);
|
|
182
|
+
});
|
|
183
|
+
|
|
184
|
+
request.on('row', cols => {
|
|
185
|
+
const row: Record<string, unknown> = {};
|
|
186
|
+
for (const col of cols) {
|
|
187
|
+
row[col.metadata.colName] = col.value;
|
|
188
|
+
}
|
|
189
|
+
collected.push(row);
|
|
190
|
+
});
|
|
191
|
+
|
|
192
|
+
connection.execSql(request);
|
|
193
|
+
}
|
|
194
|
+
);
|
|
195
|
+
|
|
196
|
+
return { recordset: rows, recordsets: [rows] };
|
|
197
|
+
},
|
|
198
|
+
|
|
199
|
+
beginTransaction: connection.beginTransaction
|
|
200
|
+
? () =>
|
|
201
|
+
new Promise<void>((resolve, reject) => {
|
|
202
|
+
connection.beginTransaction!(err =>
|
|
203
|
+
err ? reject(err) : resolve()
|
|
204
|
+
);
|
|
205
|
+
})
|
|
206
|
+
: undefined,
|
|
207
|
+
|
|
208
|
+
commit: connection.commitTransaction
|
|
209
|
+
? () =>
|
|
210
|
+
new Promise<void>((resolve, reject) => {
|
|
211
|
+
connection.commitTransaction!(err =>
|
|
212
|
+
err ? reject(err) : resolve()
|
|
213
|
+
);
|
|
214
|
+
})
|
|
215
|
+
: undefined,
|
|
216
|
+
|
|
217
|
+
rollback: connection.rollbackTransaction
|
|
218
|
+
? () =>
|
|
219
|
+
new Promise<void>((resolve, reject) => {
|
|
220
|
+
connection.rollbackTransaction!(err =>
|
|
221
|
+
err ? reject(err) : resolve()
|
|
222
|
+
);
|
|
223
|
+
})
|
|
224
|
+
: undefined,
|
|
225
|
+
};
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
export function createTediousExecutor(
|
|
229
|
+
connection: TediousConnectionLike,
|
|
230
|
+
module: TediousModule,
|
|
231
|
+
options?: CreateTediousClientOptions
|
|
232
|
+
): DbExecutor {
|
|
233
|
+
const client = createTediousMssqlClient(connection, module, options);
|
|
234
|
+
return createMssqlExecutor(client);
|
|
235
|
+
}
|
|
@@ -1,43 +1,43 @@
|
|
|
1
|
-
// src/core/execution/executors/mysql-executor.ts
|
|
2
|
-
import {
|
|
3
|
-
DbExecutor,
|
|
4
|
-
QueryResult,
|
|
5
|
-
toExecutionPayload,
|
|
6
|
-
rowsToQueryResult
|
|
7
|
-
} from '../db-executor.js';
|
|
8
|
-
|
|
9
|
-
export interface MysqlClientLike {
|
|
10
|
-
query(
|
|
11
|
-
sql: string,
|
|
12
|
-
params?: unknown[]
|
|
13
|
-
): Promise<[unknown, unknown?]>; // rows, metadata
|
|
14
|
-
beginTransaction?(): Promise<void>;
|
|
15
|
-
commit?(): Promise<void>;
|
|
16
|
-
rollback?(): Promise<void>;
|
|
17
|
-
}
|
|
18
|
-
|
|
1
|
+
// src/core/execution/executors/mysql-executor.ts
|
|
2
|
+
import {
|
|
3
|
+
DbExecutor,
|
|
4
|
+
QueryResult,
|
|
5
|
+
toExecutionPayload,
|
|
6
|
+
rowsToQueryResult
|
|
7
|
+
} from '../db-executor.js';
|
|
8
|
+
|
|
9
|
+
export interface MysqlClientLike {
|
|
10
|
+
query(
|
|
11
|
+
sql: string,
|
|
12
|
+
params?: unknown[]
|
|
13
|
+
): Promise<[unknown, unknown?]>; // rows, metadata
|
|
14
|
+
beginTransaction?(): Promise<void>;
|
|
15
|
+
commit?(): Promise<void>;
|
|
16
|
+
rollback?(): Promise<void>;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
19
|
type RowObject = Record<string, unknown>;
|
|
20
20
|
const SAVEPOINT_NAME_PATTERN = /^[A-Za-z_][A-Za-z0-9_]*$/;
|
|
21
21
|
|
|
22
22
|
const isRowObject = (value: unknown): value is RowObject =>
|
|
23
23
|
typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
24
|
-
|
|
25
|
-
const isRowObjectArray = (value: unknown): value is RowObject[] =>
|
|
26
|
-
Array.isArray(value) && value.every(isRowObject);
|
|
27
|
-
|
|
28
|
-
const isMysqlResultHeader = (value: unknown): value is Record<string, unknown> =>
|
|
29
|
-
isRowObject(value) &&
|
|
30
|
-
('affectedRows' in value ||
|
|
31
|
-
'insertId' in value ||
|
|
32
|
-
'warningStatus' in value ||
|
|
33
|
-
'serverStatus' in value);
|
|
34
|
-
|
|
24
|
+
|
|
25
|
+
const isRowObjectArray = (value: unknown): value is RowObject[] =>
|
|
26
|
+
Array.isArray(value) && value.every(isRowObject);
|
|
27
|
+
|
|
28
|
+
const isMysqlResultHeader = (value: unknown): value is Record<string, unknown> =>
|
|
29
|
+
isRowObject(value) &&
|
|
30
|
+
('affectedRows' in value ||
|
|
31
|
+
'insertId' in value ||
|
|
32
|
+
'warningStatus' in value ||
|
|
33
|
+
'serverStatus' in value);
|
|
34
|
+
|
|
35
35
|
const headerToQueryResult = (header: Record<string, unknown>): QueryResult => ({
|
|
36
|
-
columns: [],
|
|
37
|
-
values: [],
|
|
38
|
-
meta: {
|
|
39
|
-
insertId: header.insertId as number | string | undefined,
|
|
40
|
-
rowsAffected: header.affectedRows as number | undefined,
|
|
36
|
+
columns: [],
|
|
37
|
+
values: [],
|
|
38
|
+
meta: {
|
|
39
|
+
insertId: header.insertId as number | string | undefined,
|
|
40
|
+
rowsAffected: header.affectedRows as number | undefined,
|
|
41
41
|
}
|
|
42
42
|
});
|
|
43
43
|
|
|
@@ -48,67 +48,67 @@ const sanitizeSavepointName = (name: string): string => {
|
|
|
48
48
|
}
|
|
49
49
|
return trimmed;
|
|
50
50
|
};
|
|
51
|
-
|
|
52
|
-
const normalizeMysqlResults = (rows: unknown): QueryResult[] => {
|
|
53
|
-
if (!Array.isArray(rows)) {
|
|
54
|
-
return isMysqlResultHeader(rows)
|
|
55
|
-
? [headerToQueryResult(rows)]
|
|
56
|
-
: [rowsToQueryResult([])];
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
if (isRowObjectArray(rows)) {
|
|
60
|
-
return [rowsToQueryResult(rows)];
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
const normalized: QueryResult[] = [];
|
|
64
|
-
for (const chunk of rows) {
|
|
65
|
-
if (isRowObjectArray(chunk)) {
|
|
66
|
-
normalized.push(rowsToQueryResult(chunk));
|
|
67
|
-
continue;
|
|
68
|
-
}
|
|
69
|
-
if (isMysqlResultHeader(chunk)) {
|
|
70
|
-
normalized.push(headerToQueryResult(chunk));
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
return normalized.length ? normalized : [rowsToQueryResult([])];
|
|
75
|
-
};
|
|
76
|
-
|
|
77
|
-
/**
|
|
78
|
-
* Creates a database executor for MySQL.
|
|
79
|
-
* @param client A MySQL client instance.
|
|
80
|
-
* @returns A DbExecutor implementation for MySQL.
|
|
81
|
-
*/
|
|
82
|
-
export function createMysqlExecutor(
|
|
83
|
-
client: MysqlClientLike
|
|
84
|
-
): DbExecutor {
|
|
51
|
+
|
|
52
|
+
const normalizeMysqlResults = (rows: unknown): QueryResult[] => {
|
|
53
|
+
if (!Array.isArray(rows)) {
|
|
54
|
+
return isMysqlResultHeader(rows)
|
|
55
|
+
? [headerToQueryResult(rows)]
|
|
56
|
+
: [rowsToQueryResult([])];
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
if (isRowObjectArray(rows)) {
|
|
60
|
+
return [rowsToQueryResult(rows)];
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
const normalized: QueryResult[] = [];
|
|
64
|
+
for (const chunk of rows) {
|
|
65
|
+
if (isRowObjectArray(chunk)) {
|
|
66
|
+
normalized.push(rowsToQueryResult(chunk));
|
|
67
|
+
continue;
|
|
68
|
+
}
|
|
69
|
+
if (isMysqlResultHeader(chunk)) {
|
|
70
|
+
normalized.push(headerToQueryResult(chunk));
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
return normalized.length ? normalized : [rowsToQueryResult([])];
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Creates a database executor for MySQL.
|
|
79
|
+
* @param client A MySQL client instance.
|
|
80
|
+
* @returns A DbExecutor implementation for MySQL.
|
|
81
|
+
*/
|
|
82
|
+
export function createMysqlExecutor(
|
|
83
|
+
client: MysqlClientLike
|
|
84
|
+
): DbExecutor {
|
|
85
85
|
const supportsTransactions =
|
|
86
86
|
typeof client.beginTransaction === 'function' &&
|
|
87
87
|
typeof client.commit === 'function' &&
|
|
88
88
|
typeof client.rollback === 'function';
|
|
89
89
|
const supportsSavepoints = supportsTransactions;
|
|
90
|
-
|
|
91
|
-
return {
|
|
90
|
+
|
|
91
|
+
return {
|
|
92
92
|
capabilities: {
|
|
93
93
|
transactions: supportsTransactions,
|
|
94
94
|
...(supportsSavepoints ? { savepoints: true } : {}),
|
|
95
95
|
},
|
|
96
|
-
async executeSql(sql, params) {
|
|
97
|
-
const [rows] = await client.query(sql, params);
|
|
98
|
-
return toExecutionPayload(normalizeMysqlResults(rows));
|
|
99
|
-
},
|
|
100
|
-
async beginTransaction() {
|
|
101
|
-
if (!supportsTransactions) {
|
|
102
|
-
throw new Error('Transactions are not supported by this executor');
|
|
103
|
-
}
|
|
104
|
-
await client.beginTransaction!();
|
|
105
|
-
},
|
|
106
|
-
async commitTransaction() {
|
|
107
|
-
if (!supportsTransactions) {
|
|
108
|
-
throw new Error('Transactions are not supported by this executor');
|
|
109
|
-
}
|
|
110
|
-
await client.commit!();
|
|
111
|
-
},
|
|
96
|
+
async executeSql(sql, params) {
|
|
97
|
+
const [rows] = await client.query(sql, params);
|
|
98
|
+
return toExecutionPayload(normalizeMysqlResults(rows));
|
|
99
|
+
},
|
|
100
|
+
async beginTransaction() {
|
|
101
|
+
if (!supportsTransactions) {
|
|
102
|
+
throw new Error('Transactions are not supported by this executor');
|
|
103
|
+
}
|
|
104
|
+
await client.beginTransaction!();
|
|
105
|
+
},
|
|
106
|
+
async commitTransaction() {
|
|
107
|
+
if (!supportsTransactions) {
|
|
108
|
+
throw new Error('Transactions are not supported by this executor');
|
|
109
|
+
}
|
|
110
|
+
await client.commit!();
|
|
111
|
+
},
|
|
112
112
|
async rollbackTransaction() {
|
|
113
113
|
if (!supportsTransactions) {
|
|
114
114
|
throw new Error('Transactions are not supported by this executor');
|
|
@@ -139,5 +139,5 @@ export function createMysqlExecutor(
|
|
|
139
139
|
async dispose() {
|
|
140
140
|
// Connection lifecycle is owned by the caller/driver. Pool lease executors should implement dispose.
|
|
141
141
|
},
|
|
142
|
-
};
|
|
143
|
-
}
|
|
142
|
+
};
|
|
143
|
+
}
|
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
// src/core/execution/executors/postgres-executor.ts
|
|
1
|
+
// src/core/execution/executors/postgres-executor.ts
|
|
2
2
|
import {
|
|
3
3
|
DbExecutor,
|
|
4
4
|
createExecutorFromQueryRunner
|
|
5
5
|
} from '../db-executor.js';
|
|
6
|
-
|
|
6
|
+
|
|
7
7
|
export interface PostgresClientLike {
|
|
8
|
-
query(
|
|
9
|
-
text: string,
|
|
10
|
-
params?: unknown[]
|
|
11
|
-
): Promise<{ rows: Array<Record<string, unknown>> }>;
|
|
8
|
+
query(
|
|
9
|
+
text: string,
|
|
10
|
+
params?: unknown[]
|
|
11
|
+
): Promise<{ rows: Array<Record<string, unknown>> }>;
|
|
12
12
|
}
|
|
13
13
|
|
|
14
14
|
const SAVEPOINT_NAME_PATTERN = /^[A-Za-z_][A-Za-z0-9_]*$/;
|
|
@@ -20,26 +20,26 @@ const sanitizeSavepointName = (name: string): string => {
|
|
|
20
20
|
}
|
|
21
21
|
return trimmed;
|
|
22
22
|
};
|
|
23
|
-
|
|
24
|
-
/**
|
|
25
|
-
* Creates a database executor for PostgreSQL.
|
|
26
|
-
* @param client A PostgreSQL client or pool instance.
|
|
27
|
-
* @returns A DbExecutor implementation for Postgres.
|
|
28
|
-
*/
|
|
29
|
-
export function createPostgresExecutor(
|
|
30
|
-
client: PostgresClientLike
|
|
31
|
-
): DbExecutor {
|
|
32
|
-
return createExecutorFromQueryRunner({
|
|
33
|
-
async query(sql, params) {
|
|
34
|
-
const { rows } = await client.query(sql, params);
|
|
35
|
-
return rows;
|
|
36
|
-
},
|
|
37
|
-
async beginTransaction() {
|
|
38
|
-
await client.query('BEGIN');
|
|
39
|
-
},
|
|
40
|
-
async commitTransaction() {
|
|
41
|
-
await client.query('COMMIT');
|
|
42
|
-
},
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Creates a database executor for PostgreSQL.
|
|
26
|
+
* @param client A PostgreSQL client or pool instance.
|
|
27
|
+
* @returns A DbExecutor implementation for Postgres.
|
|
28
|
+
*/
|
|
29
|
+
export function createPostgresExecutor(
|
|
30
|
+
client: PostgresClientLike
|
|
31
|
+
): DbExecutor {
|
|
32
|
+
return createExecutorFromQueryRunner({
|
|
33
|
+
async query(sql, params) {
|
|
34
|
+
const { rows } = await client.query(sql, params);
|
|
35
|
+
return rows;
|
|
36
|
+
},
|
|
37
|
+
async beginTransaction() {
|
|
38
|
+
await client.query('BEGIN');
|
|
39
|
+
},
|
|
40
|
+
async commitTransaction() {
|
|
41
|
+
await client.query('COMMIT');
|
|
42
|
+
},
|
|
43
43
|
async rollbackTransaction() {
|
|
44
44
|
await client.query('ROLLBACK');
|
|
45
45
|
},
|