@mikro-orm/oracledb 7.0.13-dev.9 → 7.0.13
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 +24 -8
- package/OracleConnection.js +174 -172
- package/OracleDriver.d.ts +37 -7
- package/OracleDriver.js +68 -67
- package/OracleExceptionConverter.d.ts +4 -4
- package/OracleExceptionConverter.js +156 -140
- package/OracleMikroORM.d.ts +50 -12
- package/OracleMikroORM.js +14 -14
- package/OraclePlatform.d.ts +113 -120
- package/OraclePlatform.js +299 -284
- package/OracleQueryBuilder.d.ts +25 -7
- package/OracleQueryBuilder.js +82 -75
- package/OracleSchemaGenerator.d.ts +45 -37
- package/OracleSchemaGenerator.js +390 -372
- package/OracleSchemaHelper.d.ts +89 -43
- package/OracleSchemaHelper.js +523 -514
- package/README.md +1 -1
- package/package.json +4 -4
package/OracleConnection.d.ts
CHANGED
|
@@ -1,12 +1,28 @@
|
|
|
1
|
-
import {
|
|
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';
|
|
2
12
|
import { type PoolAttributes } from 'oracledb';
|
|
3
13
|
/** Oracle database connection using the `oracledb` driver. */
|
|
4
14
|
export declare class OracleConnection extends AbstractSqlConnection {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
15
|
+
createKyselyDialect(overrides: PoolAttributes): Promise<OracleDialect>;
|
|
16
|
+
mapOptions(overrides: PoolAttributes): PoolAttributes;
|
|
17
|
+
execute<T extends QueryResult | EntityData<AnyEntity> | EntityData<AnyEntity>[] = EntityData<AnyEntity>[]>(
|
|
18
|
+
query: string | NativeQueryBuilder | RawQueryFragment,
|
|
19
|
+
params?: readonly unknown[],
|
|
20
|
+
method?: 'all' | 'get' | 'run',
|
|
21
|
+
ctx?: Transaction,
|
|
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;
|
|
12
28
|
}
|
package/OracleConnection.js
CHANGED
|
@@ -1,187 +1,189 @@
|
|
|
1
|
-
import { AbstractSqlConnection, isRaw, NativeQueryBuilder, OracleDialect, Utils
|
|
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
|
-
|
|
28
|
-
continue;
|
|
29
|
-
}
|
|
30
|
-
throw e;
|
|
31
|
-
}
|
|
32
|
-
/* v8 ignore stop */
|
|
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
|
+
} catch (e) {
|
|
25
|
+
if (attempt < maxRetries && (e.errorNum === 1017 || e.errorNum === 12514 || e.errorNum === 12541)) {
|
|
26
|
+
await new Promise(resolve => setTimeout(resolve, 250 * attempt));
|
|
27
|
+
continue;
|
|
33
28
|
}
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
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;
|
|
49
|
-
},
|
|
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
|
-
});
|
|
29
|
+
throw e;
|
|
30
|
+
}
|
|
31
|
+
/* v8 ignore stop */
|
|
65
32
|
}
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
const
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
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;
|
|
33
|
+
const executeOptions = {
|
|
34
|
+
fetchTypeHandler: metaData => {
|
|
35
|
+
const bigInt = metaData.dbType === oracledb.DB_TYPE_NUMBER && (metaData.precision ?? 0) > 10;
|
|
36
|
+
metaData.name = metaData.name.toLowerCase();
|
|
37
|
+
if (bigInt || metaData.dbType === oracledb.DB_TYPE_CLOB) {
|
|
38
|
+
return {
|
|
39
|
+
type: oracledb.DB_TYPE_VARCHAR,
|
|
40
|
+
};
|
|
89
41
|
}
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
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];
|
|
42
|
+
if (metaData.dbType === oracledb.DB_TYPE_BLOB) {
|
|
43
|
+
return {
|
|
44
|
+
type: oracledb.BUFFER,
|
|
45
|
+
};
|
|
99
46
|
}
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
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() });
|
|
57
|
+
},
|
|
58
|
+
close: drainTime => pool.close(drainTime),
|
|
59
|
+
}
|
|
60
|
+
: pool;
|
|
61
|
+
return new OracleDialect({
|
|
62
|
+
pool: wrappedPool,
|
|
63
|
+
executeOptions: executeOptions,
|
|
64
|
+
});
|
|
65
|
+
}
|
|
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);
|
|
80
|
+
}
|
|
81
|
+
async execute(query, params = [], method = 'all', ctx, loggerContext) {
|
|
82
|
+
await this.ensureConnection();
|
|
83
|
+
if (query instanceof NativeQueryBuilder) {
|
|
84
|
+
query = query.toRaw();
|
|
115
85
|
}
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
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
|
-
}
|
|
86
|
+
if (isRaw(query)) {
|
|
87
|
+
params = query.params;
|
|
88
|
+
query = query.sql;
|
|
135
89
|
}
|
|
136
|
-
stripTrailingSemicolon(
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
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];
|
|
141
99
|
}
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
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(
|
|
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);
|
|
145
110
|
}
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
111
|
+
const res = await this.getClient().executeQuery({
|
|
112
|
+
...compiled,
|
|
113
|
+
autoCommit: true,
|
|
114
|
+
});
|
|
115
|
+
return this.transformRawResult(res, method);
|
|
116
|
+
},
|
|
117
|
+
{ query, params, ...loggerContext },
|
|
118
|
+
);
|
|
119
|
+
}
|
|
120
|
+
/** @inheritDoc */
|
|
121
|
+
async executeDump(dump) {
|
|
122
|
+
await this.ensureConnection();
|
|
123
|
+
const lines = dump.split('\n').filter(i => i.trim());
|
|
124
|
+
for (let line of lines) {
|
|
125
|
+
if (line.startsWith('--')) {
|
|
126
|
+
continue;
|
|
127
|
+
}
|
|
128
|
+
line = this.stripTrailingSemicolon(line);
|
|
129
|
+
const raw = CompiledQuery.raw(line);
|
|
130
|
+
const now = Date.now();
|
|
131
|
+
try {
|
|
132
|
+
await this.getClient().executeQuery(raw);
|
|
133
|
+
} catch (e) {
|
|
134
|
+
this.logQuery(line, { took: Date.now() - now, level: 'error', query: line });
|
|
135
|
+
throw e;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
stripTrailingSemicolon(sql) {
|
|
140
|
+
if (sql.endsWith(';') && !/end(\s+\w+)?;$/i.test(sql)) {
|
|
141
|
+
return sql.slice(0, -1);
|
|
142
|
+
}
|
|
143
|
+
return sql;
|
|
144
|
+
}
|
|
145
|
+
transformRawResult(res, method) {
|
|
146
|
+
if (method === 'get') {
|
|
147
|
+
return res.rows[0];
|
|
148
|
+
}
|
|
149
|
+
if (method === 'all') {
|
|
150
|
+
return res.rows;
|
|
151
|
+
}
|
|
152
|
+
if (res.numAffectedRows > 0n && res.outBinds) {
|
|
153
|
+
const keys = Object.keys(res.outBinds);
|
|
154
|
+
const rows = [];
|
|
155
|
+
res.rows = rows;
|
|
156
|
+
for (let i = 0; i < res.numAffectedRows; i++) {
|
|
157
|
+
const o = {};
|
|
158
|
+
for (const key of keys) {
|
|
159
|
+
o[key.replace(/^out_/, '')] = res.outBinds[key][i];
|
|
170
160
|
}
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
affectedRows,
|
|
183
|
-
row: res.rows[0],
|
|
184
|
-
rows: res.rows,
|
|
185
|
-
};
|
|
161
|
+
rows.push(o);
|
|
162
|
+
}
|
|
163
|
+
} else if (res.outBinds) {
|
|
164
|
+
const keys = Object.keys(res.outBinds);
|
|
165
|
+
const rows = [];
|
|
166
|
+
for (const key of keys) {
|
|
167
|
+
const [k, i] = key.split('__');
|
|
168
|
+
rows[+i] ??= {};
|
|
169
|
+
rows[+i][k.replace(/^out_/, '')] = res.outBinds[key];
|
|
170
|
+
}
|
|
171
|
+
res.rows = rows;
|
|
186
172
|
}
|
|
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
|
+
}
|
|
187
189
|
}
|
package/OracleDriver.d.ts
CHANGED
|
@@ -1,4 +1,17 @@
|
|
|
1
|
-
import {
|
|
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';
|
|
2
15
|
import { AbstractSqlDriver, type SqlEntityManager } from '@mikro-orm/sql';
|
|
3
16
|
import { OracleConnection } from './OracleConnection.js';
|
|
4
17
|
import { OracleMikroORM } from './OracleMikroORM.js';
|
|
@@ -6,10 +19,27 @@ import { OracleQueryBuilder } from './OracleQueryBuilder.js';
|
|
|
6
19
|
import { OraclePlatform } from './OraclePlatform.js';
|
|
7
20
|
/** Database driver for Oracle. */
|
|
8
21
|
export declare class OracleDriver extends AbstractSqlDriver<OracleConnection, OraclePlatform> {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
22
|
+
constructor(config: Configuration);
|
|
23
|
+
createQueryBuilder<T extends AnyEntity<T>>(
|
|
24
|
+
entityName: EntityName<T>,
|
|
25
|
+
ctx?: Transaction,
|
|
26
|
+
preferredConnectionType?: ConnectionType,
|
|
27
|
+
convertCustomTypes?: boolean,
|
|
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>;
|
|
15
45
|
}
|
package/OracleDriver.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { isRaw, QueryFlag, Utils
|
|
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,76 +6,77 @@ 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
|
-
|
|
9
|
+
constructor(config) {
|
|
10
|
+
super(config, new OraclePlatform(), OracleConnection, ['kysely', 'oracledb']);
|
|
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);
|
|
11
20
|
}
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
21
|
+
return qb;
|
|
22
|
+
}
|
|
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(
|
|
30
|
+
this.getSchemaName(meta, options),
|
|
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]];
|
|
22
43
|
}
|
|
23
|
-
|
|
24
|
-
|
|
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;
|
|
44
|
+
for (let i = 0; i < collections.length; i++) {
|
|
45
|
+
await this.processManyToMany(meta, pk[i], collections[i], false, options);
|
|
47
46
|
}
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
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;
|
|
47
|
+
return res;
|
|
48
|
+
}
|
|
49
|
+
async nativeUpdateMany(entityName, where, data, options = {}) {
|
|
50
|
+
const meta = this.metadata.get(entityName);
|
|
51
|
+
const returning = new Set();
|
|
52
|
+
const into = [];
|
|
53
|
+
const outBindingsMap = {};
|
|
54
|
+
for (const row of data) {
|
|
55
|
+
for (const k of Utils.keys(row)) {
|
|
56
|
+
if (isRaw(row[k])) {
|
|
57
|
+
returning.add(k);
|
|
66
58
|
}
|
|
67
|
-
|
|
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
|
-
});
|
|
59
|
+
}
|
|
76
60
|
}
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
61
|
+
// reload generated columns and version fields
|
|
62
|
+
meta.props.filter(prop => prop.generated || prop.version || prop.primary).forEach(prop => returning.add(prop.name));
|
|
63
|
+
for (const propName of returning) {
|
|
64
|
+
const prop = meta.properties[propName];
|
|
65
|
+
into.push(`:out_${prop.fieldNames[0]}`);
|
|
66
|
+
outBindingsMap[`out_${prop.fieldNames[0]}`] = prop.runtimeType;
|
|
80
67
|
}
|
|
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
|
+
}
|
|
81
82
|
}
|
|
@@ -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
|
}
|