@mikro-orm/oracledb 7.0.14-dev.8 → 7.0.14

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,12 +1,28 @@
1
- import { AbstractSqlConnection, type AnyEntity, type EntityData, type LoggingOptions, NativeQueryBuilder, OracleDialect, type QueryResult, type RawQueryFragment, type Transaction } from '@mikro-orm/sql';
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
- 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;
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
  }
@@ -1,187 +1,189 @@
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
- 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 */
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
- 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
- // 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
- 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();
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
- 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];
42
+ if (metaData.dbType === oracledb.DB_TYPE_BLOB) {
43
+ return {
44
+ type: oracledb.BUFFER,
45
+ };
99
46
  }
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 });
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
- /** @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
- }
86
+ if (isRaw(query)) {
87
+ params = query.params;
88
+ query = query.sql;
135
89
  }
136
- stripTrailingSemicolon(sql) {
137
- if (sql.endsWith(';') && !/end(\s+\w+)?;$/i.test(sql)) {
138
- return sql.slice(0, -1);
139
- }
140
- return sql;
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
- transformRawResult(res, method) {
143
- if (method === 'get') {
144
- return res.rows[0];
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
- 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;
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
- 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
- };
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 { 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';
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
- 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>;
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, } 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,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
- constructor(config) {
10
- super(config, new OraclePlatform(), OracleConnection, ['kysely', 'oracledb']);
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
- 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;
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
- 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;
44
+ for (let i = 0; i < collections.length; i++) {
45
+ await this.processManyToMany(meta, pk[i], collections[i], false, options);
47
46
  }
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;
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
- 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
- });
59
+ }
76
60
  }
77
- /** @inheritDoc */
78
- getORMClass() {
79
- return OracleMikroORM;
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
- * @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
  }