@mikro-orm/oracledb 7.0.7 → 7.0.8-dev.0

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.
@@ -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
- RawQueryFragment,
10
- type Transaction,
11
- } from '@mikro-orm/sql';
1
+ import { AbstractSqlConnection, type AnyEntity, type EntityData, type LoggingOptions, NativeQueryBuilder, OracleDialect, type QueryResult, 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
- 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;
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
  }
@@ -1,178 +1,177 @@
1
- import { AbstractSqlConnection, NativeQueryBuilder, OracleDialect, RawQueryFragment, Utils } from '@mikro-orm/sql';
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
- 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;
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
+ }
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
- throw e;
30
- }
31
- /* v8 ignore stop */
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;
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);
32
70
  }
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
- };
71
+ async execute(query, params = [], method = 'all', ctx, loggerContext) {
72
+ await this.ensureConnection();
73
+ if (query instanceof NativeQueryBuilder) {
74
+ query = query.toRaw();
41
75
  }
42
- if (metaData.dbType === oracledb.DB_TYPE_BLOB) {
43
- return {
44
- type: oracledb.BUFFER,
45
- };
76
+ if (query instanceof RawQueryFragment) {
77
+ params = query.params;
78
+ query = query.sql;
46
79
  }
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();
74
- }
75
- if (query instanceof RawQueryFragment) {
76
- params = query.params;
77
- query = query.sql;
78
- }
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];
88
- }
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);
80
+ query = this.stripTrailingSemicolon(query);
81
+ let last;
82
+ let rawQuery;
83
+ const lastParam = params[params.length - 1];
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];
99
89
  }
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
- }
90
+ query = this.config.get('onQuery')(query, params);
91
+ const formatted = this.platform.formatQuery(query, params);
92
+ const sql = this.getSql(rawQuery ?? query, formatted, loggerContext);
93
+ return this.executeQuery(sql, async () => {
94
+ const compiled = CompiledQuery.raw(formatted, last);
95
+ if (ctx) {
96
+ const res = await ctx.executeQuery(compiled);
97
+ return this.transformRawResult(res, method);
98
+ }
99
+ const res = await this.getClient().executeQuery({
100
+ ...compiled,
101
+ autoCommit: true,
102
+ });
103
+ return this.transformRawResult(res, method);
104
+ }, { query, params, ...loggerContext });
126
105
  }
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];
106
+ /** @inheritDoc */
107
+ async executeDump(dump) {
108
+ await this.ensureConnection();
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
+ }
137
125
  }
138
- if (method === 'all') {
139
- return res.rows;
126
+ stripTrailingSemicolon(sql) {
127
+ if (sql.endsWith(';') && !/end(\s+\w+)?;$/i.test(sql)) {
128
+ return sql.slice(0, -1);
129
+ }
130
+ return sql;
140
131
  }
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];
132
+ transformRawResult(res, method) {
133
+ if (method === 'get') {
134
+ return res.rows[0];
135
+ }
136
+ if (method === 'all') {
137
+ return res.rows;
138
+ }
139
+ if (res.numAffectedRows > 0n && res.outBinds) {
140
+ const keys = Object.keys(res.outBinds);
141
+ const rows = [];
142
+ res.rows = rows;
143
+ for (let i = 0; i < res.numAffectedRows; i++) {
144
+ const o = {};
145
+ for (const key of keys) {
146
+ o[key.replace(/^out_/, '')] = res.outBinds[key][i];
147
+ }
148
+ rows.push(o);
149
+ }
150
+ }
151
+ else if (res.outBinds) {
152
+ const keys = Object.keys(res.outBinds);
153
+ const rows = [];
154
+ for (const key of keys) {
155
+ const [k, i] = key.split('__');
156
+ rows[+i] ??= {};
157
+ rows[+i][k.replace(/^out_/, '')] = res.outBinds[key];
158
+ }
159
+ res.rows = rows;
149
160
  }
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;
161
+ const rowCount = res.rows.length;
162
+ /* v8 ignore start: internal result-shape branches depend on Oracle driver internals */
163
+ const hasEmptyCount = rowCount === 1 && '' in res.rows[0];
164
+ const emptyRow = hasEmptyCount && Number(res.rows[0]['']);
165
+ const affectedRows = hasEmptyCount
166
+ ? emptyRow
167
+ : res.numAffectedRows == null
168
+ ? rowCount
169
+ : Number(res.numAffectedRows ?? rowCount);
170
+ /* v8 ignore stop */
171
+ return {
172
+ affectedRows,
173
+ row: res.rows[0],
174
+ rows: res.rows,
175
+ };
161
176
  }
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
- }
178
177
  }
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
- 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>;
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
- 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);
9
+ constructor(config) {
10
+ super(config, new OraclePlatform(), OracleConnection, ['kysely', 'oracledb']);
20
11
  }
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]];
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
- for (let i = 0; i < collections.length; i++) {
45
- await this.processManyToMany(meta, pk[i], collections[i], false, options);
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
- 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);
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
- // 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;
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
- * @see https://docs.oracle.com/cd/B28359_01/server.111/b28278/toc.htm
6
- */
7
- convertException(exception: Error & Dictionary): DriverException;
4
+ /**
5
+ * @see https://docs.oracle.com/cd/B28359_01/server.111/b28278/toc.htm
6
+ */
7
+ convertException(exception: Error & Dictionary): DriverException;
8
8
  }