@mikro-orm/oracledb 7.0.8-dev.7 → 7.0.8
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 +163 -162
- 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
|
+
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,177 +1,178 @@
|
|
|
1
|
-
import { AbstractSqlConnection, NativeQueryBuilder, OracleDialect, RawQueryFragment, Utils
|
|
1
|
+
import { AbstractSqlConnection, NativeQueryBuilder, OracleDialect, RawQueryFragment, 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 poolOptions = {
|
|
11
|
+
...options,
|
|
12
|
+
/* v8 ignore next: password-as-function branch requires mocking pool creation */
|
|
13
|
+
password: typeof password === 'function' ? await password() : password,
|
|
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
|
-
return new OracleDialect({
|
|
52
|
-
pool,
|
|
53
|
-
executeOptions: executeOptions,
|
|
54
|
-
});
|
|
55
|
-
}
|
|
56
|
-
mapOptions(overrides) {
|
|
57
|
-
const ret = { ...this.getConnectionOptions() };
|
|
58
|
-
const dbName = this.config.get('dbName');
|
|
59
|
-
const pool = this.config.get('pool');
|
|
60
|
-
ret.poolMin = pool?.min;
|
|
61
|
-
ret.poolMax = pool?.max;
|
|
62
|
-
ret.poolTimeout = pool?.idleTimeoutMillis;
|
|
63
|
-
const user = this.config.get('user', dbName);
|
|
64
|
-
ret.user = user.startsWith('"') || user === 'system' ? user : this.platform.quoteIdentifier(user);
|
|
65
|
-
ret.connectionString = this.options.clientUrl ?? this.platform.getDefaultClientUrl();
|
|
66
|
-
Reflect.deleteProperty(ret, 'database');
|
|
67
|
-
Reflect.deleteProperty(ret, 'port');
|
|
68
|
-
Reflect.deleteProperty(ret, 'host');
|
|
69
|
-
return Utils.mergeConfig(ret, overrides);
|
|
29
|
+
throw e;
|
|
30
|
+
}
|
|
31
|
+
/* v8 ignore stop */
|
|
70
32
|
}
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
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
|
+
};
|
|
79
41
|
}
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
if (Utils.isObject(lastParam) && '__outBindings' in lastParam && lastParam.__outBindings) {
|
|
85
|
-
rawQuery = lastParam.__rawQuery;
|
|
86
|
-
const { __outBindings, ...rest } = lastParam;
|
|
87
|
-
last = rest;
|
|
88
|
-
params = [...params.slice(0, -1), last];
|
|
42
|
+
if (metaData.dbType === oracledb.DB_TYPE_BLOB) {
|
|
43
|
+
return {
|
|
44
|
+
type: oracledb.BUFFER,
|
|
45
|
+
};
|
|
89
46
|
}
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
47
|
+
return undefined;
|
|
48
|
+
},
|
|
49
|
+
};
|
|
50
|
+
return new OracleDialect({
|
|
51
|
+
pool,
|
|
52
|
+
executeOptions: executeOptions,
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
mapOptions(overrides) {
|
|
56
|
+
const ret = { ...this.getConnectionOptions() };
|
|
57
|
+
const dbName = this.config.get('dbName');
|
|
58
|
+
const pool = this.config.get('pool');
|
|
59
|
+
ret.poolMin = pool?.min;
|
|
60
|
+
ret.poolMax = pool?.max;
|
|
61
|
+
ret.poolTimeout = pool?.idleTimeoutMillis;
|
|
62
|
+
const user = this.config.get('user', dbName);
|
|
63
|
+
ret.user = user.startsWith('"') || user === 'system' ? user : this.platform.quoteIdentifier(user);
|
|
64
|
+
ret.connectionString = this.options.clientUrl ?? this.platform.getDefaultClientUrl();
|
|
65
|
+
Reflect.deleteProperty(ret, 'database');
|
|
66
|
+
Reflect.deleteProperty(ret, 'port');
|
|
67
|
+
Reflect.deleteProperty(ret, 'host');
|
|
68
|
+
return Utils.mergeConfig(ret, overrides);
|
|
69
|
+
}
|
|
70
|
+
async execute(query, params = [], method = 'all', ctx, loggerContext) {
|
|
71
|
+
await this.ensureConnection();
|
|
72
|
+
if (query instanceof NativeQueryBuilder) {
|
|
73
|
+
query = query.toRaw();
|
|
105
74
|
}
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
const lines = dump.split('\n').filter(i => i.trim());
|
|
110
|
-
for (let line of lines) {
|
|
111
|
-
if (line.startsWith('--')) {
|
|
112
|
-
continue;
|
|
113
|
-
}
|
|
114
|
-
line = this.stripTrailingSemicolon(line);
|
|
115
|
-
const raw = CompiledQuery.raw(line);
|
|
116
|
-
const now = Date.now();
|
|
117
|
-
try {
|
|
118
|
-
await this.getClient().executeQuery(raw);
|
|
119
|
-
}
|
|
120
|
-
catch (e) {
|
|
121
|
-
this.logQuery(line, { took: Date.now() - now, level: 'error', query: line });
|
|
122
|
-
throw e;
|
|
123
|
-
}
|
|
124
|
-
}
|
|
75
|
+
if (query instanceof RawQueryFragment) {
|
|
76
|
+
params = query.params;
|
|
77
|
+
query = query.sql;
|
|
125
78
|
}
|
|
126
|
-
stripTrailingSemicolon(
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
79
|
+
query = this.stripTrailingSemicolon(query);
|
|
80
|
+
let last;
|
|
81
|
+
let rawQuery;
|
|
82
|
+
const lastParam = params[params.length - 1];
|
|
83
|
+
if (Utils.isObject(lastParam) && '__outBindings' in lastParam && lastParam.__outBindings) {
|
|
84
|
+
rawQuery = lastParam.__rawQuery;
|
|
85
|
+
const { __outBindings, ...rest } = lastParam;
|
|
86
|
+
last = rest;
|
|
87
|
+
params = [...params.slice(0, -1), last];
|
|
131
88
|
}
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
89
|
+
query = this.config.get('onQuery')(query, params);
|
|
90
|
+
const formatted = this.platform.formatQuery(query, params);
|
|
91
|
+
const sql = this.getSql(rawQuery ?? query, formatted, loggerContext);
|
|
92
|
+
return this.executeQuery(
|
|
93
|
+
sql,
|
|
94
|
+
async () => {
|
|
95
|
+
const compiled = CompiledQuery.raw(formatted, last);
|
|
96
|
+
if (ctx) {
|
|
97
|
+
const res = await ctx.executeQuery(compiled);
|
|
98
|
+
return this.transformRawResult(res, method);
|
|
138
99
|
}
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
100
|
+
const res = await this.getClient().executeQuery({
|
|
101
|
+
...compiled,
|
|
102
|
+
autoCommit: true,
|
|
103
|
+
});
|
|
104
|
+
return this.transformRawResult(res, method);
|
|
105
|
+
},
|
|
106
|
+
{ query, params, ...loggerContext },
|
|
107
|
+
);
|
|
108
|
+
}
|
|
109
|
+
/** @inheritDoc */
|
|
110
|
+
async executeDump(dump) {
|
|
111
|
+
await this.ensureConnection();
|
|
112
|
+
const lines = dump.split('\n').filter(i => i.trim());
|
|
113
|
+
for (let line of lines) {
|
|
114
|
+
if (line.startsWith('--')) {
|
|
115
|
+
continue;
|
|
116
|
+
}
|
|
117
|
+
line = this.stripTrailingSemicolon(line);
|
|
118
|
+
const raw = CompiledQuery.raw(line);
|
|
119
|
+
const now = Date.now();
|
|
120
|
+
try {
|
|
121
|
+
await this.getClient().executeQuery(raw);
|
|
122
|
+
} catch (e) {
|
|
123
|
+
this.logQuery(line, { took: Date.now() - now, level: 'error', query: line });
|
|
124
|
+
throw e;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
stripTrailingSemicolon(sql) {
|
|
129
|
+
if (sql.endsWith(';') && !/end(\s+\w+)?;$/i.test(sql)) {
|
|
130
|
+
return sql.slice(0, -1);
|
|
131
|
+
}
|
|
132
|
+
return sql;
|
|
133
|
+
}
|
|
134
|
+
transformRawResult(res, method) {
|
|
135
|
+
if (method === 'get') {
|
|
136
|
+
return res.rows[0];
|
|
137
|
+
}
|
|
138
|
+
if (method === 'all') {
|
|
139
|
+
return res.rows;
|
|
140
|
+
}
|
|
141
|
+
if (res.numAffectedRows > 0n && res.outBinds) {
|
|
142
|
+
const keys = Object.keys(res.outBinds);
|
|
143
|
+
const rows = [];
|
|
144
|
+
res.rows = rows;
|
|
145
|
+
for (let i = 0; i < res.numAffectedRows; i++) {
|
|
146
|
+
const o = {};
|
|
147
|
+
for (const key of keys) {
|
|
148
|
+
o[key.replace(/^out_/, '')] = res.outBinds[key][i];
|
|
160
149
|
}
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
affectedRows,
|
|
173
|
-
row: res.rows[0],
|
|
174
|
-
rows: res.rows,
|
|
175
|
-
};
|
|
150
|
+
rows.push(o);
|
|
151
|
+
}
|
|
152
|
+
} else if (res.outBinds) {
|
|
153
|
+
const keys = Object.keys(res.outBinds);
|
|
154
|
+
const rows = [];
|
|
155
|
+
for (const key of keys) {
|
|
156
|
+
const [k, i] = key.split('__');
|
|
157
|
+
rows[+i] ??= {};
|
|
158
|
+
rows[+i][k.replace(/^out_/, '')] = res.outBinds[key];
|
|
159
|
+
}
|
|
160
|
+
res.rows = rows;
|
|
176
161
|
}
|
|
162
|
+
const rowCount = res.rows.length;
|
|
163
|
+
/* v8 ignore start: internal result-shape branches depend on Oracle driver internals */
|
|
164
|
+
const hasEmptyCount = rowCount === 1 && '' in res.rows[0];
|
|
165
|
+
const emptyRow = hasEmptyCount && Number(res.rows[0]['']);
|
|
166
|
+
const affectedRows = hasEmptyCount
|
|
167
|
+
? emptyRow
|
|
168
|
+
: res.numAffectedRows == null
|
|
169
|
+
? rowCount
|
|
170
|
+
: Number(res.numAffectedRows ?? rowCount);
|
|
171
|
+
/* v8 ignore stop */
|
|
172
|
+
return {
|
|
173
|
+
affectedRows,
|
|
174
|
+
row: res.rows[0],
|
|
175
|
+
rows: res.rows,
|
|
176
|
+
};
|
|
177
|
+
}
|
|
177
178
|
}
|
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
|
}
|