@mikro-orm/oracledb 7.0.13 → 7.0.14-dev.1
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/OracleConnection.d.ts +8 -24
- package/OracleConnection.js +172 -174
- package/OracleDriver.d.ts +7 -37
- package/OracleDriver.js +67 -68
- package/OracleExceptionConverter.d.ts +4 -4
- package/OracleExceptionConverter.js +140 -156
- package/OracleMikroORM.d.ts +12 -50
- package/OracleMikroORM.js +14 -14
- package/OraclePlatform.d.ts +120 -113
- package/OraclePlatform.js +284 -299
- package/OracleQueryBuilder.d.ts +7 -25
- package/OracleQueryBuilder.js +75 -82
- package/OracleSchemaGenerator.d.ts +37 -45
- package/OracleSchemaGenerator.js +372 -390
- package/OracleSchemaHelper.d.ts +43 -89
- package/OracleSchemaHelper.js +514 -523
- package/README.md +1 -1
- package/package.json +3 -3
package/OracleConnection.d.ts
CHANGED
|
@@ -1,28 +1,12 @@
|
|
|
1
|
-
import {
|
|
2
|
-
AbstractSqlConnection,
|
|
3
|
-
type AnyEntity,
|
|
4
|
-
type EntityData,
|
|
5
|
-
type LoggingOptions,
|
|
6
|
-
NativeQueryBuilder,
|
|
7
|
-
OracleDialect,
|
|
8
|
-
type QueryResult,
|
|
9
|
-
type RawQueryFragment,
|
|
10
|
-
type Transaction,
|
|
11
|
-
} from '@mikro-orm/sql';
|
|
1
|
+
import { AbstractSqlConnection, type AnyEntity, type EntityData, type LoggingOptions, NativeQueryBuilder, OracleDialect, type QueryResult, type RawQueryFragment, type Transaction } from '@mikro-orm/sql';
|
|
12
2
|
import { type PoolAttributes } from 'oracledb';
|
|
13
3
|
/** Oracle database connection using the `oracledb` driver. */
|
|
14
4
|
export declare class OracleConnection extends AbstractSqlConnection {
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
loggerContext?: LoggingOptions,
|
|
23
|
-
): Promise<T>;
|
|
24
|
-
/** @inheritDoc */
|
|
25
|
-
executeDump(dump: string): Promise<void>;
|
|
26
|
-
private stripTrailingSemicolon;
|
|
27
|
-
protected transformRawResult<T>(res: any, method: 'all' | 'get' | 'run'): T;
|
|
5
|
+
createKyselyDialect(overrides: PoolAttributes): Promise<OracleDialect>;
|
|
6
|
+
mapOptions(overrides: PoolAttributes): PoolAttributes;
|
|
7
|
+
execute<T extends QueryResult | EntityData<AnyEntity> | EntityData<AnyEntity>[] = EntityData<AnyEntity>[]>(query: string | NativeQueryBuilder | RawQueryFragment, params?: readonly unknown[], method?: 'all' | 'get' | 'run', ctx?: Transaction, loggerContext?: LoggingOptions): Promise<T>;
|
|
8
|
+
/** @inheritDoc */
|
|
9
|
+
executeDump(dump: string): Promise<void>;
|
|
10
|
+
private stripTrailingSemicolon;
|
|
11
|
+
protected transformRawResult<T>(res: any, method: 'all' | 'get' | 'run'): T;
|
|
28
12
|
}
|
package/OracleConnection.js
CHANGED
|
@@ -1,189 +1,187 @@
|
|
|
1
|
-
import { AbstractSqlConnection, isRaw, NativeQueryBuilder, OracleDialect, Utils } from '@mikro-orm/sql';
|
|
1
|
+
import { AbstractSqlConnection, isRaw, NativeQueryBuilder, OracleDialect, Utils, } from '@mikro-orm/sql';
|
|
2
2
|
import { CompiledQuery } from 'kysely';
|
|
3
3
|
import oracledb from 'oracledb';
|
|
4
4
|
/** Oracle database connection using the `oracledb` driver. */
|
|
5
5
|
export class OracleConnection extends AbstractSqlConnection {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
6
|
+
async createKyselyDialect(overrides) {
|
|
7
|
+
const options = this.mapOptions(overrides);
|
|
8
|
+
const password = options.password;
|
|
9
|
+
const onCreateConnection = this.options.onCreateConnection ?? this.config.get('onCreateConnection');
|
|
10
|
+
const initialPassword = typeof password === 'function' ? await password() : password;
|
|
11
|
+
const poolOptions = {
|
|
12
|
+
...options,
|
|
13
|
+
password: initialPassword,
|
|
14
|
+
sessionCallback: onCreateConnection,
|
|
15
|
+
};
|
|
16
|
+
// Retry pool creation for transient Oracle errors (e.g. ORA-01017 under load)
|
|
17
|
+
let pool;
|
|
18
|
+
const maxRetries = 3;
|
|
19
|
+
for (let attempt = 1;; attempt++) {
|
|
20
|
+
try {
|
|
21
|
+
pool = await oracledb.createPool(poolOptions);
|
|
22
|
+
break;
|
|
23
|
+
/* v8 ignore start: transient Oracle pool-creation errors are not reproducible in tests */
|
|
24
|
+
}
|
|
25
|
+
catch (e) {
|
|
26
|
+
if (attempt < maxRetries && (e.errorNum === 1017 || e.errorNum === 12514 || e.errorNum === 12541)) {
|
|
27
|
+
await new Promise(resolve => setTimeout(resolve, 250 * attempt));
|
|
28
|
+
continue;
|
|
29
|
+
}
|
|
30
|
+
throw e;
|
|
31
|
+
}
|
|
32
|
+
/* v8 ignore stop */
|
|
28
33
|
}
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
type: oracledb.BUFFER,
|
|
45
|
-
};
|
|
46
|
-
}
|
|
47
|
-
return undefined;
|
|
48
|
-
},
|
|
49
|
-
};
|
|
50
|
-
// When password is a callback, wrap the pool to resolve it per-connection.
|
|
51
|
-
// oracledb supports per-connection password override via getConnection({ password }).
|
|
52
|
-
const wrappedPool =
|
|
53
|
-
typeof password === 'function'
|
|
54
|
-
? {
|
|
55
|
-
async getConnection() {
|
|
56
|
-
return pool.getConnection({ password: await password() });
|
|
34
|
+
const executeOptions = {
|
|
35
|
+
fetchTypeHandler: metaData => {
|
|
36
|
+
const bigInt = metaData.dbType === oracledb.DB_TYPE_NUMBER && (metaData.precision ?? 0) > 10;
|
|
37
|
+
metaData.name = metaData.name.toLowerCase();
|
|
38
|
+
if (bigInt || metaData.dbType === oracledb.DB_TYPE_CLOB) {
|
|
39
|
+
return {
|
|
40
|
+
type: oracledb.DB_TYPE_VARCHAR,
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
if (metaData.dbType === oracledb.DB_TYPE_BLOB) {
|
|
44
|
+
return {
|
|
45
|
+
type: oracledb.BUFFER,
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
return undefined;
|
|
57
49
|
},
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
const user = this.config.get('user', dbName);
|
|
74
|
-
ret.user = user.startsWith('"') || user === 'system' ? user : this.platform.quoteIdentifier(user);
|
|
75
|
-
ret.connectionString = this.options.clientUrl ?? this.platform.getDefaultClientUrl();
|
|
76
|
-
Reflect.deleteProperty(ret, 'database');
|
|
77
|
-
Reflect.deleteProperty(ret, 'port');
|
|
78
|
-
Reflect.deleteProperty(ret, 'host');
|
|
79
|
-
return Utils.mergeConfig(ret, overrides);
|
|
80
|
-
}
|
|
81
|
-
async execute(query, params = [], method = 'all', ctx, loggerContext) {
|
|
82
|
-
await this.ensureConnection();
|
|
83
|
-
if (query instanceof NativeQueryBuilder) {
|
|
84
|
-
query = query.toRaw();
|
|
85
|
-
}
|
|
86
|
-
if (isRaw(query)) {
|
|
87
|
-
params = query.params;
|
|
88
|
-
query = query.sql;
|
|
50
|
+
};
|
|
51
|
+
// When password is a callback, wrap the pool to resolve it per-connection.
|
|
52
|
+
// oracledb supports per-connection password override via getConnection({ password }).
|
|
53
|
+
const wrappedPool = typeof password === 'function'
|
|
54
|
+
? {
|
|
55
|
+
async getConnection() {
|
|
56
|
+
return pool.getConnection({ password: await password() });
|
|
57
|
+
},
|
|
58
|
+
close: (drainTime) => pool.close(drainTime),
|
|
59
|
+
}
|
|
60
|
+
: pool;
|
|
61
|
+
return new OracleDialect({
|
|
62
|
+
pool: wrappedPool,
|
|
63
|
+
executeOptions: executeOptions,
|
|
64
|
+
});
|
|
89
65
|
}
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
66
|
+
mapOptions(overrides) {
|
|
67
|
+
const ret = { ...this.getConnectionOptions() };
|
|
68
|
+
const dbName = this.config.get('dbName');
|
|
69
|
+
const pool = this.config.get('pool');
|
|
70
|
+
ret.poolMin = pool?.min;
|
|
71
|
+
ret.poolMax = pool?.max;
|
|
72
|
+
ret.poolTimeout = pool?.idleTimeoutMillis;
|
|
73
|
+
const user = this.config.get('user', dbName);
|
|
74
|
+
ret.user = user.startsWith('"') || user === 'system' ? user : this.platform.quoteIdentifier(user);
|
|
75
|
+
ret.connectionString = this.options.clientUrl ?? this.platform.getDefaultClientUrl();
|
|
76
|
+
Reflect.deleteProperty(ret, 'database');
|
|
77
|
+
Reflect.deleteProperty(ret, 'port');
|
|
78
|
+
Reflect.deleteProperty(ret, 'host');
|
|
79
|
+
return Utils.mergeConfig(ret, overrides);
|
|
99
80
|
}
|
|
100
|
-
query =
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
sql,
|
|
105
|
-
async () => {
|
|
106
|
-
const compiled = CompiledQuery.raw(formatted, last);
|
|
107
|
-
if (ctx) {
|
|
108
|
-
const res = await ctx.executeQuery(compiled);
|
|
109
|
-
return this.transformRawResult(res, method);
|
|
81
|
+
async execute(query, params = [], method = 'all', ctx, loggerContext) {
|
|
82
|
+
await this.ensureConnection();
|
|
83
|
+
if (query instanceof NativeQueryBuilder) {
|
|
84
|
+
query = query.toRaw();
|
|
110
85
|
}
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
if (sql.endsWith(';') && !/end(\s+\w+)?;$/i.test(sql)) {
|
|
141
|
-
return sql.slice(0, -1);
|
|
86
|
+
if (isRaw(query)) {
|
|
87
|
+
params = query.params;
|
|
88
|
+
query = query.sql;
|
|
89
|
+
}
|
|
90
|
+
query = this.stripTrailingSemicolon(query);
|
|
91
|
+
let last;
|
|
92
|
+
let rawQuery;
|
|
93
|
+
const lastParam = params[params.length - 1];
|
|
94
|
+
if (Utils.isObject(lastParam) && '__outBindings' in lastParam && lastParam.__outBindings) {
|
|
95
|
+
rawQuery = lastParam.__rawQuery;
|
|
96
|
+
const { __outBindings, ...rest } = lastParam;
|
|
97
|
+
last = rest;
|
|
98
|
+
params = [...params.slice(0, -1), last];
|
|
99
|
+
}
|
|
100
|
+
query = this.config.get('onQuery')(query, params);
|
|
101
|
+
const formatted = this.platform.formatQuery(query, params);
|
|
102
|
+
const sql = this.getSql(rawQuery ?? query, formatted, loggerContext);
|
|
103
|
+
return this.executeQuery(sql, async () => {
|
|
104
|
+
const compiled = CompiledQuery.raw(formatted, last);
|
|
105
|
+
if (ctx) {
|
|
106
|
+
const res = await ctx.executeQuery(compiled);
|
|
107
|
+
return this.transformRawResult(res, method);
|
|
108
|
+
}
|
|
109
|
+
const res = await this.getClient().executeQuery({
|
|
110
|
+
...compiled,
|
|
111
|
+
autoCommit: true,
|
|
112
|
+
});
|
|
113
|
+
return this.transformRawResult(res, method);
|
|
114
|
+
}, { query, params, ...loggerContext });
|
|
142
115
|
}
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
116
|
+
/** @inheritDoc */
|
|
117
|
+
async executeDump(dump) {
|
|
118
|
+
await this.ensureConnection();
|
|
119
|
+
const lines = dump.split('\n').filter(i => i.trim());
|
|
120
|
+
for (let line of lines) {
|
|
121
|
+
if (line.startsWith('--')) {
|
|
122
|
+
continue;
|
|
123
|
+
}
|
|
124
|
+
line = this.stripTrailingSemicolon(line);
|
|
125
|
+
const raw = CompiledQuery.raw(line);
|
|
126
|
+
const now = Date.now();
|
|
127
|
+
try {
|
|
128
|
+
await this.getClient().executeQuery(raw);
|
|
129
|
+
}
|
|
130
|
+
catch (e) {
|
|
131
|
+
this.logQuery(line, { took: Date.now() - now, level: 'error', query: line });
|
|
132
|
+
throw e;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
148
135
|
}
|
|
149
|
-
|
|
150
|
-
|
|
136
|
+
stripTrailingSemicolon(sql) {
|
|
137
|
+
if (sql.endsWith(';') && !/end(\s+\w+)?;$/i.test(sql)) {
|
|
138
|
+
return sql.slice(0, -1);
|
|
139
|
+
}
|
|
140
|
+
return sql;
|
|
151
141
|
}
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
142
|
+
transformRawResult(res, method) {
|
|
143
|
+
if (method === 'get') {
|
|
144
|
+
return res.rows[0];
|
|
145
|
+
}
|
|
146
|
+
if (method === 'all') {
|
|
147
|
+
return res.rows;
|
|
148
|
+
}
|
|
149
|
+
if (res.numAffectedRows > 0n && res.outBinds) {
|
|
150
|
+
const keys = Object.keys(res.outBinds);
|
|
151
|
+
const rows = [];
|
|
152
|
+
res.rows = rows;
|
|
153
|
+
for (let i = 0; i < res.numAffectedRows; i++) {
|
|
154
|
+
const o = {};
|
|
155
|
+
for (const key of keys) {
|
|
156
|
+
o[key.replace(/^out_/, '')] = res.outBinds[key][i];
|
|
157
|
+
}
|
|
158
|
+
rows.push(o);
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
else if (res.outBinds) {
|
|
162
|
+
const keys = Object.keys(res.outBinds);
|
|
163
|
+
const rows = [];
|
|
164
|
+
for (const key of keys) {
|
|
165
|
+
const [k, i] = key.split('__');
|
|
166
|
+
rows[+i] ??= {};
|
|
167
|
+
rows[+i][k.replace(/^out_/, '')] = res.outBinds[key];
|
|
168
|
+
}
|
|
169
|
+
res.rows = rows;
|
|
160
170
|
}
|
|
161
|
-
rows.
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
171
|
+
const rowCount = res.rows.length;
|
|
172
|
+
/* v8 ignore start: internal result-shape branches depend on Oracle driver internals */
|
|
173
|
+
const hasEmptyCount = rowCount === 1 && '' in res.rows[0];
|
|
174
|
+
const emptyRow = hasEmptyCount && Number(res.rows[0]['']);
|
|
175
|
+
const affectedRows = hasEmptyCount
|
|
176
|
+
? emptyRow
|
|
177
|
+
: res.numAffectedRows == null
|
|
178
|
+
? rowCount
|
|
179
|
+
: Number(res.numAffectedRows ?? rowCount);
|
|
180
|
+
/* v8 ignore stop */
|
|
181
|
+
return {
|
|
182
|
+
affectedRows,
|
|
183
|
+
row: res.rows[0],
|
|
184
|
+
rows: res.rows,
|
|
185
|
+
};
|
|
172
186
|
}
|
|
173
|
-
const rowCount = res.rows.length;
|
|
174
|
-
/* v8 ignore start: internal result-shape branches depend on Oracle driver internals */
|
|
175
|
-
const hasEmptyCount = rowCount === 1 && '' in res.rows[0];
|
|
176
|
-
const emptyRow = hasEmptyCount && Number(res.rows[0]['']);
|
|
177
|
-
const affectedRows = hasEmptyCount
|
|
178
|
-
? emptyRow
|
|
179
|
-
: res.numAffectedRows == null
|
|
180
|
-
? rowCount
|
|
181
|
-
: Number(res.numAffectedRows ?? rowCount);
|
|
182
|
-
/* v8 ignore stop */
|
|
183
|
-
return {
|
|
184
|
-
affectedRows,
|
|
185
|
-
row: res.rows[0],
|
|
186
|
-
rows: res.rows,
|
|
187
|
-
};
|
|
188
|
-
}
|
|
189
187
|
}
|
package/OracleDriver.d.ts
CHANGED
|
@@ -1,17 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
type AnyEntity,
|
|
3
|
-
type Configuration,
|
|
4
|
-
type ConnectionType,
|
|
5
|
-
type Constructor,
|
|
6
|
-
type EntityDictionary,
|
|
7
|
-
type EntityName,
|
|
8
|
-
type FilterQuery,
|
|
9
|
-
type LoggingOptions,
|
|
10
|
-
type NativeInsertUpdateManyOptions,
|
|
11
|
-
type QueryResult,
|
|
12
|
-
type Transaction,
|
|
13
|
-
type UpsertManyOptions,
|
|
14
|
-
} from '@mikro-orm/core';
|
|
1
|
+
import { type AnyEntity, type Configuration, type ConnectionType, type Constructor, type EntityDictionary, type EntityName, type FilterQuery, type LoggingOptions, type NativeInsertUpdateManyOptions, type QueryResult, type Transaction, type UpsertManyOptions } from '@mikro-orm/core';
|
|
15
2
|
import { AbstractSqlDriver, type SqlEntityManager } from '@mikro-orm/sql';
|
|
16
3
|
import { OracleConnection } from './OracleConnection.js';
|
|
17
4
|
import { OracleMikroORM } from './OracleMikroORM.js';
|
|
@@ -19,27 +6,10 @@ import { OracleQueryBuilder } from './OracleQueryBuilder.js';
|
|
|
19
6
|
import { OraclePlatform } from './OraclePlatform.js';
|
|
20
7
|
/** Database driver for Oracle. */
|
|
21
8
|
export declare class OracleDriver extends AbstractSqlDriver<OracleConnection, OraclePlatform> {
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
entityName: EntityName<T>,
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
loggerContext?: LoggingOptions,
|
|
29
|
-
alias?: string,
|
|
30
|
-
em?: SqlEntityManager,
|
|
31
|
-
): OracleQueryBuilder<T, any, any, any>;
|
|
32
|
-
nativeInsertMany<T extends object>(
|
|
33
|
-
entityName: EntityName<T>,
|
|
34
|
-
data: EntityDictionary<T>[],
|
|
35
|
-
options?: NativeInsertUpdateManyOptions<T>,
|
|
36
|
-
): Promise<QueryResult<T>>;
|
|
37
|
-
nativeUpdateMany<T extends object>(
|
|
38
|
-
entityName: EntityName<T>,
|
|
39
|
-
where: FilterQuery<T>[],
|
|
40
|
-
data: EntityDictionary<T>[],
|
|
41
|
-
options?: NativeInsertUpdateManyOptions<T> & UpsertManyOptions<T>,
|
|
42
|
-
): Promise<QueryResult<T>>;
|
|
43
|
-
/** @inheritDoc */
|
|
44
|
-
getORMClass(): Constructor<OracleMikroORM>;
|
|
9
|
+
constructor(config: Configuration);
|
|
10
|
+
createQueryBuilder<T extends AnyEntity<T>>(entityName: EntityName<T>, ctx?: Transaction, preferredConnectionType?: ConnectionType, convertCustomTypes?: boolean, loggerContext?: LoggingOptions, alias?: string, em?: SqlEntityManager): OracleQueryBuilder<T, any, any, any>;
|
|
11
|
+
nativeInsertMany<T extends object>(entityName: EntityName<T>, data: EntityDictionary<T>[], options?: NativeInsertUpdateManyOptions<T>): Promise<QueryResult<T>>;
|
|
12
|
+
nativeUpdateMany<T extends object>(entityName: EntityName<T>, where: FilterQuery<T>[], data: EntityDictionary<T>[], options?: NativeInsertUpdateManyOptions<T> & UpsertManyOptions<T>): Promise<QueryResult<T>>;
|
|
13
|
+
/** @inheritDoc */
|
|
14
|
+
getORMClass(): Constructor<OracleMikroORM>;
|
|
45
15
|
}
|
package/OracleDriver.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { isRaw, QueryFlag, Utils } from '@mikro-orm/core';
|
|
1
|
+
import { isRaw, QueryFlag, Utils, } from '@mikro-orm/core';
|
|
2
2
|
import { AbstractSqlDriver } from '@mikro-orm/sql';
|
|
3
3
|
import { OracleConnection } from './OracleConnection.js';
|
|
4
4
|
import { OracleMikroORM } from './OracleMikroORM.js';
|
|
@@ -6,77 +6,76 @@ import { OracleQueryBuilder } from './OracleQueryBuilder.js';
|
|
|
6
6
|
import { OraclePlatform } from './OraclePlatform.js';
|
|
7
7
|
/** Database driver for Oracle. */
|
|
8
8
|
export class OracleDriver extends AbstractSqlDriver {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
}
|
|
12
|
-
createQueryBuilder(entityName, ctx, preferredConnectionType, convertCustomTypes, loggerContext, alias, em) {
|
|
13
|
-
// do not compute the connectionType if EM is provided as it will be computed from it in the QB later on
|
|
14
|
-
const connectionType = em
|
|
15
|
-
? preferredConnectionType
|
|
16
|
-
: this.resolveConnectionType({ ctx, connectionType: preferredConnectionType });
|
|
17
|
-
const qb = new OracleQueryBuilder(entityName, this.metadata, this, ctx, alias, connectionType, em, loggerContext);
|
|
18
|
-
if (!convertCustomTypes) {
|
|
19
|
-
qb.unsetFlag(QueryFlag.CONVERT_CUSTOM_TYPES);
|
|
9
|
+
constructor(config) {
|
|
10
|
+
super(config, new OraclePlatform(), OracleConnection, ['kysely', 'oracledb']);
|
|
20
11
|
}
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
);
|
|
32
|
-
qb.insert(data);
|
|
33
|
-
const res = await this.rethrow(qb.execute('run'));
|
|
34
|
-
let pk;
|
|
35
|
-
if (pks.length > 1) {
|
|
36
|
-
// owner has composite pk
|
|
37
|
-
pk = data.map(d => Utils.getPrimaryKeyCond(d, pks));
|
|
38
|
-
} else {
|
|
39
|
-
res.row ??= {};
|
|
40
|
-
res.rows ??= [];
|
|
41
|
-
pk = data.map((d, i) => d[pks[0]] ?? res.rows[i]?.[pks[0]]).map(d => [d]);
|
|
42
|
-
res.insertId = res.insertId || res.row[pks[0]];
|
|
12
|
+
createQueryBuilder(entityName, ctx, preferredConnectionType, convertCustomTypes, loggerContext, alias, em) {
|
|
13
|
+
// do not compute the connectionType if EM is provided as it will be computed from it in the QB later on
|
|
14
|
+
const connectionType = em
|
|
15
|
+
? preferredConnectionType
|
|
16
|
+
: this.resolveConnectionType({ ctx, connectionType: preferredConnectionType });
|
|
17
|
+
const qb = new OracleQueryBuilder(entityName, this.metadata, this, ctx, alias, connectionType, em, loggerContext);
|
|
18
|
+
if (!convertCustomTypes) {
|
|
19
|
+
qb.unsetFlag(QueryFlag.CONVERT_CUSTOM_TYPES);
|
|
20
|
+
}
|
|
21
|
+
return qb;
|
|
43
22
|
}
|
|
44
|
-
|
|
45
|
-
|
|
23
|
+
async nativeInsertMany(entityName, data, options = {}) {
|
|
24
|
+
options.processCollections ??= true;
|
|
25
|
+
options.convertCustomTypes ??= true;
|
|
26
|
+
const meta = this.metadata.get(entityName);
|
|
27
|
+
const pks = this.getPrimaryKeyFields(meta);
|
|
28
|
+
const collections = options.processCollections ? data.map(d => this.extractManyToMany(meta, d)) : [];
|
|
29
|
+
const qb = this.createQueryBuilder(entityName, options.ctx, 'write', options.convertCustomTypes).withSchema(this.getSchemaName(meta, options));
|
|
30
|
+
qb.insert(data);
|
|
31
|
+
const res = await this.rethrow(qb.execute('run'));
|
|
32
|
+
let pk;
|
|
33
|
+
if (pks.length > 1) {
|
|
34
|
+
// owner has composite pk
|
|
35
|
+
pk = data.map(d => Utils.getPrimaryKeyCond(d, pks));
|
|
36
|
+
}
|
|
37
|
+
else {
|
|
38
|
+
res.row ??= {};
|
|
39
|
+
res.rows ??= [];
|
|
40
|
+
pk = data.map((d, i) => d[pks[0]] ?? res.rows[i]?.[pks[0]]).map(d => [d]);
|
|
41
|
+
res.insertId = res.insertId || res.row[pks[0]];
|
|
42
|
+
}
|
|
43
|
+
for (let i = 0; i < collections.length; i++) {
|
|
44
|
+
await this.processManyToMany(meta, pk[i], collections[i], false, options);
|
|
45
|
+
}
|
|
46
|
+
return res;
|
|
46
47
|
}
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
48
|
+
async nativeUpdateMany(entityName, where, data, options = {}) {
|
|
49
|
+
const meta = this.metadata.get(entityName);
|
|
50
|
+
const returning = new Set();
|
|
51
|
+
const into = [];
|
|
52
|
+
const outBindingsMap = {};
|
|
53
|
+
for (const row of data) {
|
|
54
|
+
for (const k of Utils.keys(row)) {
|
|
55
|
+
if (isRaw(row[k])) {
|
|
56
|
+
returning.add(k);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
// reload generated columns and version fields
|
|
61
|
+
meta.props.filter(prop => prop.generated || prop.version || prop.primary).forEach(prop => returning.add(prop.name));
|
|
62
|
+
for (const propName of returning) {
|
|
63
|
+
const prop = meta.properties[propName];
|
|
64
|
+
into.push(`:out_${prop.fieldNames[0]}`);
|
|
65
|
+
outBindingsMap[`out_${prop.fieldNames[0]}`] = prop.runtimeType;
|
|
58
66
|
}
|
|
59
|
-
|
|
67
|
+
const outBindings = this.platform.createOutBindings(outBindingsMap);
|
|
68
|
+
return super.nativeUpdateMany(entityName, where, data, options, (sql, params) => {
|
|
69
|
+
/* v8 ignore next 2: defensive guard — PKs are always added to `returning` above */
|
|
70
|
+
if (into.length === 0) {
|
|
71
|
+
return sql;
|
|
72
|
+
}
|
|
73
|
+
params.push(outBindings);
|
|
74
|
+
return `${sql} into ${into.join(', ')}`;
|
|
75
|
+
});
|
|
60
76
|
}
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
const prop = meta.properties[propName];
|
|
65
|
-
into.push(`:out_${prop.fieldNames[0]}`);
|
|
66
|
-
outBindingsMap[`out_${prop.fieldNames[0]}`] = prop.runtimeType;
|
|
77
|
+
/** @inheritDoc */
|
|
78
|
+
getORMClass() {
|
|
79
|
+
return OracleMikroORM;
|
|
67
80
|
}
|
|
68
|
-
const outBindings = this.platform.createOutBindings(outBindingsMap);
|
|
69
|
-
return super.nativeUpdateMany(entityName, where, data, options, (sql, params) => {
|
|
70
|
-
/* v8 ignore next 2: defensive guard — PKs are always added to `returning` above */
|
|
71
|
-
if (into.length === 0) {
|
|
72
|
-
return sql;
|
|
73
|
-
}
|
|
74
|
-
params.push(outBindings);
|
|
75
|
-
return `${sql} into ${into.join(', ')}`;
|
|
76
|
-
});
|
|
77
|
-
}
|
|
78
|
-
/** @inheritDoc */
|
|
79
|
-
getORMClass() {
|
|
80
|
-
return OracleMikroORM;
|
|
81
|
-
}
|
|
82
81
|
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { ExceptionConverter, type Dictionary, type DriverException } from '@mikro-orm/core';
|
|
2
2
|
/** Converts Oracle native errors into typed MikroORM driver exceptions. */
|
|
3
3
|
export declare class OracleExceptionConverter extends ExceptionConverter {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
4
|
+
/**
|
|
5
|
+
* @see https://docs.oracle.com/cd/B28359_01/server.111/b28278/toc.htm
|
|
6
|
+
*/
|
|
7
|
+
convertException(exception: Error & Dictionary): DriverException;
|
|
8
8
|
}
|