@mikro-orm/oracledb 7.0.0-dev.316
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/LICENSE +21 -0
- package/OracleConnection.d.ts +11 -0
- package/OracleConnection.js +176 -0
- package/OracleDriver.d.ts +14 -0
- package/OracleDriver.js +80 -0
- package/OracleExceptionConverter.d.ts +7 -0
- package/OracleExceptionConverter.js +145 -0
- package/OracleMikroORM.d.ts +18 -0
- package/OracleMikroORM.js +22 -0
- package/OraclePlatform.d.ts +120 -0
- package/OraclePlatform.js +283 -0
- package/OracleQueryBuilder.d.ts +9 -0
- package/OracleQueryBuilder.js +85 -0
- package/OracleSchemaGenerator.d.ts +41 -0
- package/OracleSchemaGenerator.js +395 -0
- package/OracleSchemaHelper.d.ts +45 -0
- package/OracleSchemaHelper.js +591 -0
- package/README.md +391 -0
- package/index.d.ts +10 -0
- package/index.js +9 -0
- package/package.json +58 -0
- package/tsconfig.build.tsbuildinfo +1 -0
|
@@ -0,0 +1,395 @@
|
|
|
1
|
+
import { SchemaGenerator, SchemaComparator, DatabaseSchema, } from '@mikro-orm/sql';
|
|
2
|
+
export class OracleSchemaGenerator extends SchemaGenerator {
|
|
3
|
+
/** Tracks whether the main user has been granted DBA (or equivalent) privileges. */
|
|
4
|
+
hasDbaGrant = false;
|
|
5
|
+
static register(orm) {
|
|
6
|
+
orm.config.registerExtension('@mikro-orm/schema-generator', () => new OracleSchemaGenerator(orm.em));
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* creates new database and connects to it
|
|
10
|
+
*/
|
|
11
|
+
async createDatabase(name) {
|
|
12
|
+
name ??= this.config.get('user');
|
|
13
|
+
/* v8 ignore next: tableSpace fallback */
|
|
14
|
+
const tableSpace = this.config.get('schemaGenerator').tableSpace ?? 'mikro_orm';
|
|
15
|
+
const password = this.connection.mapOptions({}).password;
|
|
16
|
+
try {
|
|
17
|
+
await this.execute(`create tablespace ${this.platform.quoteIdentifier(tableSpace)} datafile '${tableSpace.replaceAll(`'`, `''`)}.dbf' size 100M autoextend on`);
|
|
18
|
+
}
|
|
19
|
+
catch (e) {
|
|
20
|
+
if (e.code !== 'ORA-01543') {
|
|
21
|
+
throw e;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
const sql = [
|
|
25
|
+
`create user ${this.platform.quoteIdentifier(name)}`,
|
|
26
|
+
`identified by ${this.platform.quoteIdentifier(password)}`,
|
|
27
|
+
`default tablespace ${this.platform.quoteIdentifier(tableSpace)}`,
|
|
28
|
+
`quota unlimited on ${this.platform.quoteIdentifier(tableSpace)}`,
|
|
29
|
+
].join(' ');
|
|
30
|
+
await this.execute(sql);
|
|
31
|
+
await this.execute(`grant connect, resource to ${this.platform.quoteIdentifier(name)}`);
|
|
32
|
+
this.config.set('user', name);
|
|
33
|
+
await this.driver.reconnect();
|
|
34
|
+
}
|
|
35
|
+
async dropDatabase(name) {
|
|
36
|
+
name ??= this.config.get('dbName');
|
|
37
|
+
this.config.set('user', this.helper.getManagementDbName());
|
|
38
|
+
await this.driver.reconnect();
|
|
39
|
+
await this.execute(this.helper.getDropDatabaseSQL(name));
|
|
40
|
+
this.config.set('user', name);
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Oracle uses CASCADE CONSTRAINT in DROP TABLE and has no native enums,
|
|
44
|
+
* so we can generate drop SQL from metadata alone — no DB introspection needed.
|
|
45
|
+
*/
|
|
46
|
+
async getDropSchemaSQL(options = {}) {
|
|
47
|
+
await this.ensureDatabase();
|
|
48
|
+
const metadata = this.getOrderedMetadata(options.schema).reverse();
|
|
49
|
+
const ret = [];
|
|
50
|
+
for (const meta of metadata) {
|
|
51
|
+
const schemaName = options.schema ?? this.config.get('schema');
|
|
52
|
+
/* v8 ignore next: wildcard schema branch */
|
|
53
|
+
const resolved = meta.schema === '*' ? schemaName : (meta.schema ?? schemaName);
|
|
54
|
+
/* v8 ignore next: default schema resolution */
|
|
55
|
+
const schema = resolved === this.platform.getDefaultSchemaName() ? undefined : resolved;
|
|
56
|
+
this.helper.append(ret, this.helper.dropTableIfExists(meta.tableName, schema));
|
|
57
|
+
}
|
|
58
|
+
if (options.dropMigrationsTable) {
|
|
59
|
+
this.helper.append(ret, this.helper.dropTableIfExists(this.config.get('migrations').tableName, this.config.get('schema')));
|
|
60
|
+
}
|
|
61
|
+
/* v8 ignore next: empty result branch */
|
|
62
|
+
return ret.join('\n') + (ret.length ? '\n' : '');
|
|
63
|
+
}
|
|
64
|
+
async ensureDatabase(options) {
|
|
65
|
+
const dbName = this.config.get('dbName');
|
|
66
|
+
if (this.lastEnsuredDatabase === dbName && !options?.forceCheck) {
|
|
67
|
+
return true;
|
|
68
|
+
}
|
|
69
|
+
let exists = false;
|
|
70
|
+
try {
|
|
71
|
+
exists = await this.helper.databaseExists(this.connection, dbName);
|
|
72
|
+
}
|
|
73
|
+
catch (e) {
|
|
74
|
+
if (e.code === 'ORA-01017' && this.config.get('user') !== this.helper.getManagementDbName()) {
|
|
75
|
+
this.config.set('user', this.helper.getManagementDbName());
|
|
76
|
+
await this.driver.reconnect();
|
|
77
|
+
const result = await this.ensureDatabase();
|
|
78
|
+
// Restore connection to the original user (createDatabase does this
|
|
79
|
+
// when the user doesn't exist, but we must handle the case where
|
|
80
|
+
// the user already exists and ensureDatabase returned early)
|
|
81
|
+
if (this.config.get('user') !== dbName) {
|
|
82
|
+
this.config.set('user', dbName);
|
|
83
|
+
await this.driver.reconnect();
|
|
84
|
+
}
|
|
85
|
+
return result;
|
|
86
|
+
}
|
|
87
|
+
throw e;
|
|
88
|
+
}
|
|
89
|
+
this.lastEnsuredDatabase = dbName;
|
|
90
|
+
if (!exists) {
|
|
91
|
+
this.config.set('user', this.helper.getManagementDbName());
|
|
92
|
+
await this.driver.reconnect();
|
|
93
|
+
await this.createDatabase(dbName);
|
|
94
|
+
if (options?.create) {
|
|
95
|
+
await this.create(options);
|
|
96
|
+
}
|
|
97
|
+
return true;
|
|
98
|
+
}
|
|
99
|
+
if (options?.clear) {
|
|
100
|
+
await this.clear(options);
|
|
101
|
+
}
|
|
102
|
+
return false;
|
|
103
|
+
}
|
|
104
|
+
getOriginalUser() {
|
|
105
|
+
return this.config.get('user') ?? this.config.get('dbName');
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Connects as the management (system) user if not already connected as admin.
|
|
109
|
+
* Returns the original user to restore later, or undefined if no reconnect was needed.
|
|
110
|
+
*/
|
|
111
|
+
async connectAsAdmin() {
|
|
112
|
+
if (this.hasDbaGrant) {
|
|
113
|
+
return undefined;
|
|
114
|
+
}
|
|
115
|
+
// Check if the current user already has DBA privileges (avoids pool reconnect churn)
|
|
116
|
+
const res = await this.connection.execute(`select granted_role from user_role_privs where granted_role = 'DBA'`);
|
|
117
|
+
if (res.length > 0) {
|
|
118
|
+
this.hasDbaGrant = true;
|
|
119
|
+
return undefined;
|
|
120
|
+
}
|
|
121
|
+
const originalUser = this.getOriginalUser();
|
|
122
|
+
this.config.set('user', this.helper.getManagementDbName());
|
|
123
|
+
await this.driver.reconnect();
|
|
124
|
+
return originalUser;
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Restores the connection to the original user after admin operations.
|
|
128
|
+
*/
|
|
129
|
+
async restoreConnection(originalUser) {
|
|
130
|
+
if (originalUser == null) {
|
|
131
|
+
return;
|
|
132
|
+
}
|
|
133
|
+
this.config.set('user', originalUser);
|
|
134
|
+
await this.driver.reconnect();
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Grants DBA (or fallback individual privileges) to the main user.
|
|
138
|
+
* Only executed once — subsequent calls are no-ops.
|
|
139
|
+
*/
|
|
140
|
+
async ensureDbaGrant(originalUser) {
|
|
141
|
+
if (this.hasDbaGrant) {
|
|
142
|
+
return;
|
|
143
|
+
}
|
|
144
|
+
try {
|
|
145
|
+
await this.execute(`grant dba to ${this.platform.quoteIdentifier(originalUser)}`);
|
|
146
|
+
}
|
|
147
|
+
catch {
|
|
148
|
+
await this.execute(`grant create any table to ${this.platform.quoteIdentifier(originalUser)}`);
|
|
149
|
+
await this.execute(`grant alter any table to ${this.platform.quoteIdentifier(originalUser)}`);
|
|
150
|
+
await this.execute(`grant drop any table to ${this.platform.quoteIdentifier(originalUser)}`);
|
|
151
|
+
await this.execute(`grant create any index to ${this.platform.quoteIdentifier(originalUser)}`);
|
|
152
|
+
await this.execute(`grant drop any index to ${this.platform.quoteIdentifier(originalUser)}`);
|
|
153
|
+
}
|
|
154
|
+
this.hasDbaGrant = true;
|
|
155
|
+
}
|
|
156
|
+
async createNamespace(name) {
|
|
157
|
+
const originalUser = this.getOriginalUser();
|
|
158
|
+
const reconnectUser = await this.connectAsAdmin();
|
|
159
|
+
try {
|
|
160
|
+
await this.execute(this.helper.getCreateNamespaceSQL(name));
|
|
161
|
+
}
|
|
162
|
+
catch (e) {
|
|
163
|
+
/* v8 ignore next 3: unexpected createNamespace error rethrow */
|
|
164
|
+
if (e.code !== 'ORA-01920') {
|
|
165
|
+
throw e;
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
await this.execute(`grant connect, resource to ${this.platform.quoteIdentifier(name)}`);
|
|
169
|
+
await this.ensureDbaGrant(originalUser);
|
|
170
|
+
await this.grantReferencesForSchema(name);
|
|
171
|
+
await this.restoreConnection(reconnectUser);
|
|
172
|
+
}
|
|
173
|
+
async dropNamespace(name) {
|
|
174
|
+
const reconnectUser = await this.connectAsAdmin();
|
|
175
|
+
// Try drop first; only kill sessions if the user is currently connected
|
|
176
|
+
try {
|
|
177
|
+
await this.execute(this.helper.getDropNamespaceSQL(name));
|
|
178
|
+
}
|
|
179
|
+
catch (e) {
|
|
180
|
+
if (e.code === 'ORA-01918') {
|
|
181
|
+
// User does not exist — nothing to do
|
|
182
|
+
}
|
|
183
|
+
else if (e.code === 'ORA-01940') {
|
|
184
|
+
try {
|
|
185
|
+
const sessions = await this.connection.execute(`select sid, serial# as "serial" from v$session where username = ${this.platform.quoteValue(name.toUpperCase())}`);
|
|
186
|
+
for (const session of sessions) {
|
|
187
|
+
try {
|
|
188
|
+
await this.execute(`alter system kill session '${session.sid},${session.serial}' immediate`);
|
|
189
|
+
}
|
|
190
|
+
catch (e3) {
|
|
191
|
+
this.config
|
|
192
|
+
.getLogger()
|
|
193
|
+
.warn('schema', `Failed to kill session ${session.sid},${session.serial}: ${e3.message}`);
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
catch (e3) {
|
|
198
|
+
this.config.getLogger().warn('schema', `Cannot query v$session: ${e3.message}`);
|
|
199
|
+
}
|
|
200
|
+
try {
|
|
201
|
+
await this.execute(this.helper.getDropNamespaceSQL(name));
|
|
202
|
+
}
|
|
203
|
+
catch (e2) {
|
|
204
|
+
if (e2.code !== 'ORA-01918' && e2.code !== 'ORA-01940') {
|
|
205
|
+
throw e2;
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
else {
|
|
210
|
+
throw e;
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
await this.restoreConnection(reconnectUser);
|
|
214
|
+
}
|
|
215
|
+
async update(options = {}) {
|
|
216
|
+
await this.ensureDatabase();
|
|
217
|
+
options.safe ??= false;
|
|
218
|
+
options.dropTables ??= true;
|
|
219
|
+
const toSchema = this.getTargetSchema(options.schema);
|
|
220
|
+
const schemas = toSchema.getNamespaces();
|
|
221
|
+
const fromSchema = options.fromSchema ??
|
|
222
|
+
(await DatabaseSchema.create(this.connection, this.platform, this.config, options.schema, schemas, undefined, this.options.skipTables, this.options.skipViews));
|
|
223
|
+
const wildcardSchemaTables = [...this.metadata.getAll().values()]
|
|
224
|
+
.filter(meta => meta.schema === '*')
|
|
225
|
+
.map(/* v8 ignore next */ /* v8 ignore next */ meta => meta.tableName);
|
|
226
|
+
fromSchema.prune(options.schema, wildcardSchemaTables);
|
|
227
|
+
toSchema.prune(options.schema, wildcardSchemaTables);
|
|
228
|
+
const comparator = new SchemaComparator(this.platform);
|
|
229
|
+
const diff = comparator.compare(fromSchema, toSchema);
|
|
230
|
+
// Phase 1: Create namespaces — requires elevated privileges.
|
|
231
|
+
// After granting DBA, we reconnect back to the original user so that
|
|
232
|
+
// unqualified object names (e.g. indexes) are created in the correct schema.
|
|
233
|
+
/* v8 ignore start: requires multi-schema Oracle setup */
|
|
234
|
+
if (diff.newNamespaces.size > 0) {
|
|
235
|
+
const originalUser = this.getOriginalUser();
|
|
236
|
+
const reconnectUser = await this.connectAsAdmin();
|
|
237
|
+
for (const ns of diff.newNamespaces) {
|
|
238
|
+
try {
|
|
239
|
+
await this.execute(this.helper.getCreateNamespaceSQL(ns));
|
|
240
|
+
}
|
|
241
|
+
catch (e) {
|
|
242
|
+
if (e.code !== 'ORA-01920') {
|
|
243
|
+
throw e;
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
await this.execute(`grant connect, resource to ${this.platform.quoteIdentifier(ns)}`);
|
|
247
|
+
}
|
|
248
|
+
await this.ensureDbaGrant(originalUser);
|
|
249
|
+
for (const ns of diff.newNamespaces) {
|
|
250
|
+
await this.grantReferencesForSchema(ns);
|
|
251
|
+
}
|
|
252
|
+
await this.restoreConnection(reconnectUser);
|
|
253
|
+
}
|
|
254
|
+
/* v8 ignore stop */
|
|
255
|
+
// Phase 2: Execute table creation and alterations (without FKs)
|
|
256
|
+
// Build SQL without FK-related parts, and clear newNamespaces since we handled them in Phase 1
|
|
257
|
+
const tableOnlyDiff = { ...diff, orphanedForeignKeys: [], newNamespaces: new Set() };
|
|
258
|
+
const savedChangedTables = { ...diff.changedTables };
|
|
259
|
+
// Strip FK additions from changedTables for Phase 2
|
|
260
|
+
// Keep removedForeignKeys so old FKs are dropped before column changes (via preAlterTable)
|
|
261
|
+
// changedForeignKeys are dropped in preAlterTable but re-created in alterTable,
|
|
262
|
+
// so we move them to removedForeignKeys for drop-only and handle re-creation in Phase 3
|
|
263
|
+
const strippedChangedTables = {};
|
|
264
|
+
for (const [key, table] of Object.entries(savedChangedTables)) {
|
|
265
|
+
strippedChangedTables[key] = {
|
|
266
|
+
...table,
|
|
267
|
+
addedForeignKeys: {},
|
|
268
|
+
changedForeignKeys: {},
|
|
269
|
+
removedForeignKeys: {
|
|
270
|
+
...table.removedForeignKeys,
|
|
271
|
+
...table.changedForeignKeys,
|
|
272
|
+
},
|
|
273
|
+
};
|
|
274
|
+
}
|
|
275
|
+
tableOnlyDiff.changedTables = strippedChangedTables;
|
|
276
|
+
// Strip FKs from newTables so diffToSQL won't generate FK constraints in Phase 2
|
|
277
|
+
// (Oracle requires REFERENCES grants before FK creation, handled in Phase 2.5 / Phase 3)
|
|
278
|
+
const strippedNewTables = {};
|
|
279
|
+
for (const [key, table] of Object.entries(diff.newTables)) {
|
|
280
|
+
const proxy = Object.create(table);
|
|
281
|
+
proxy.getForeignKeys = () => ({});
|
|
282
|
+
strippedNewTables[key] = proxy;
|
|
283
|
+
}
|
|
284
|
+
tableOnlyDiff.newTables = strippedNewTables;
|
|
285
|
+
const tableSQL = this.diffToSQL(tableOnlyDiff, options);
|
|
286
|
+
if (tableSQL) {
|
|
287
|
+
await this.execute(tableSQL);
|
|
288
|
+
}
|
|
289
|
+
// Phase 2.5: Grant REFERENCES on newly created tables to all other schemas
|
|
290
|
+
const allSchemas = [...schemas];
|
|
291
|
+
for (const table of Object.values(diff.newTables)) {
|
|
292
|
+
/* v8 ignore next: schema fallback chain */
|
|
293
|
+
const tableSchema = table.schema ?? this.platform.getDefaultSchemaName() ?? '';
|
|
294
|
+
for (const schema of allSchemas) {
|
|
295
|
+
if (schema === tableSchema || schema === this.platform.getDefaultSchemaName()) {
|
|
296
|
+
continue;
|
|
297
|
+
}
|
|
298
|
+
/* v8 ignore start: requires multi-schema Oracle setup */
|
|
299
|
+
try {
|
|
300
|
+
await this.execute(`grant references on ${this.platform.quoteIdentifier(tableSchema)}.${this.platform.quoteIdentifier(table.name)} to ${this.platform.quoteIdentifier(schema)}`);
|
|
301
|
+
}
|
|
302
|
+
catch {
|
|
303
|
+
// ignore errors (e.g., table doesn't exist yet in that schema)
|
|
304
|
+
}
|
|
305
|
+
/* v8 ignore stop */
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
// Phase 3: Execute FK creation for new tables and FK changes for altered tables
|
|
309
|
+
const fkStatements = [];
|
|
310
|
+
// FK constraints for new tables
|
|
311
|
+
for (const table of Object.values(diff.newTables)) {
|
|
312
|
+
for (const fk of Object.values(table.getForeignKeys())) {
|
|
313
|
+
fkStatements.push(this.helper.createForeignKey(table, fk));
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
// FK drop for orphaned foreign keys (FKs pointing to removed tables)
|
|
317
|
+
/* v8 ignore next 5: orphaned FKs are cascade-dropped with their referenced tables in Phase 2 */
|
|
318
|
+
for (const orphanedForeignKey of diff.orphanedForeignKeys) {
|
|
319
|
+
const [schemaName, tableName] = this.helper.splitTableName(orphanedForeignKey.localTableName, true);
|
|
320
|
+
const name = (schemaName ? schemaName + '.' : '') + tableName;
|
|
321
|
+
fkStatements.push(this.helper.dropForeignKey(name, orphanedForeignKey.constraintName));
|
|
322
|
+
}
|
|
323
|
+
// FK additions and re-creation of changed FKs (drops already handled in Phase 2)
|
|
324
|
+
/* v8 ignore next 9: FK change branches depend on schema diff state */
|
|
325
|
+
for (const table of Object.values(savedChangedTables)) {
|
|
326
|
+
for (const fk of Object.values(table.addedForeignKeys ?? {})) {
|
|
327
|
+
fkStatements.push(this.helper.createForeignKey(table.toTable, fk));
|
|
328
|
+
}
|
|
329
|
+
for (const fk of Object.values(table.changedForeignKeys ?? {})) {
|
|
330
|
+
fkStatements.push(this.helper.createForeignKey(table.toTable, fk));
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
for (const stmt of fkStatements.filter(s => s)) {
|
|
334
|
+
await this.execute(stmt);
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
async clear(options) {
|
|
338
|
+
// truncate by default, so no value is considered as true
|
|
339
|
+
if (options?.truncate === false) {
|
|
340
|
+
return super.clear(options);
|
|
341
|
+
}
|
|
342
|
+
const stmts = [];
|
|
343
|
+
for (const meta of this.getOrderedMetadata(options?.schema).reverse()) {
|
|
344
|
+
const schema = meta.schema && meta.schema !== '*'
|
|
345
|
+
? meta.schema
|
|
346
|
+
: (options?.schema ?? this.config.get('schema', this.platform.getDefaultSchemaName()));
|
|
347
|
+
const tableName = this.driver.getTableName(meta, { schema }, false);
|
|
348
|
+
const quoted = tableName
|
|
349
|
+
.split('.')
|
|
350
|
+
.map(p => this.platform.quoteIdentifier(p))
|
|
351
|
+
.join('.');
|
|
352
|
+
// Use DELETE instead of TRUNCATE to avoid ORA-02266 (FK constraint check regardless of data)
|
|
353
|
+
stmts.push(`begin execute immediate 'delete from ${quoted}'; exception when others then if sqlcode != -942 then raise; end if; end;`);
|
|
354
|
+
for (const pk of meta.getPrimaryProps().filter(p => p.autoincrement)) {
|
|
355
|
+
stmts.push(`begin execute immediate 'alter table ${quoted} modify ${this.platform.quoteIdentifier(pk.fieldNames[0])} generated by default as identity (start with limit value)'; exception when others then null; end;`);
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
/* v8 ignore next 5: empty stmts branch */
|
|
359
|
+
if (stmts.length > 0) {
|
|
360
|
+
// Use driver.execute directly to bypass the ;\n splitting in this.execute()
|
|
361
|
+
// DELETE is DML (not DDL), so we must commit explicitly
|
|
362
|
+
await this.driver.execute(`begin ${stmts.join(' ')} commit; end;`);
|
|
363
|
+
}
|
|
364
|
+
this.clearIdentityMap();
|
|
365
|
+
}
|
|
366
|
+
async grantReferencesForSchema(schemaName) {
|
|
367
|
+
const defaultSchema = this.platform.getDefaultSchemaName();
|
|
368
|
+
const allSchemas = [...this.getTargetSchema().getNamespaces()];
|
|
369
|
+
for (const otherSchema of allSchemas) {
|
|
370
|
+
if (otherSchema === schemaName || otherSchema === defaultSchema) {
|
|
371
|
+
continue;
|
|
372
|
+
}
|
|
373
|
+
// Get tables in the other schema and grant REFERENCES to the new schema
|
|
374
|
+
const tables = await this.connection.execute(`select table_name from all_tables where owner = ${this.platform.quoteValue(otherSchema)}`);
|
|
375
|
+
for (const table of tables) {
|
|
376
|
+
try {
|
|
377
|
+
await this.execute(`grant references on ${this.platform.quoteIdentifier(otherSchema)}.${this.platform.quoteIdentifier(table.table_name)} to ${this.platform.quoteIdentifier(schemaName)}`);
|
|
378
|
+
}
|
|
379
|
+
catch {
|
|
380
|
+
// ignore errors
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
// Also grant REFERENCES on new schema's tables to the other schema
|
|
384
|
+
const newTables = await this.connection.execute(`select table_name from all_tables where owner = ${this.platform.quoteValue(schemaName)}`);
|
|
385
|
+
for (const table of newTables) {
|
|
386
|
+
try {
|
|
387
|
+
await this.execute(`grant references on ${this.platform.quoteIdentifier(schemaName)}.${this.platform.quoteIdentifier(table.table_name)} to ${this.platform.quoteIdentifier(otherSchema)}`);
|
|
388
|
+
}
|
|
389
|
+
catch {
|
|
390
|
+
// ignore errors
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { type AbstractSqlConnection, type CheckDef, type Column, type DatabaseSchema, type DatabaseTable, type Dictionary, type ForeignKey, type IndexDef, SchemaHelper, type Table, type TableDifference, type Type } from '@mikro-orm/sql';
|
|
2
|
+
export declare class OracleSchemaHelper extends SchemaHelper {
|
|
3
|
+
static readonly DEFAULT_VALUES: Record<string, string[]>;
|
|
4
|
+
getDatabaseExistsSQL(name: string): string;
|
|
5
|
+
getAllTables(connection: AbstractSqlConnection, schemas?: string[]): Promise<Table[]>;
|
|
6
|
+
getListTablesSQL(schemaName?: string): string;
|
|
7
|
+
getListViewsSQL(): string;
|
|
8
|
+
loadViews(schema: DatabaseSchema, connection: AbstractSqlConnection): Promise<void>;
|
|
9
|
+
getNamespaces(connection: AbstractSqlConnection): Promise<string[]>;
|
|
10
|
+
private getIgnoredNamespacesConditionSQL;
|
|
11
|
+
getDefaultEmptyString(): string;
|
|
12
|
+
normalizeDefaultValue(defaultValue: string, length: number, defaultValues?: Dictionary<string[]>, stripQuotes?: boolean): string | number;
|
|
13
|
+
getAllColumns(connection: AbstractSqlConnection, tablesBySchemas: Map<string | undefined, Table[]>): Promise<Dictionary<Column[]>>;
|
|
14
|
+
getAllIndexes(connection: AbstractSqlConnection, tablesBySchemas: Map<string | undefined, Table[]>): Promise<Dictionary<IndexDef[]>>;
|
|
15
|
+
mapForeignKeys(fks: any[], tableName: string, schemaName?: string): Dictionary;
|
|
16
|
+
createForeignKey(table: DatabaseTable, foreignKey: ForeignKey, alterTable?: boolean, inline?: boolean): string;
|
|
17
|
+
getAllForeignKeys(connection: AbstractSqlConnection, tablesBySchemas: Map<string | undefined, Table[]>): Promise<Dictionary<Dictionary<ForeignKey>>>;
|
|
18
|
+
private getEnumDefinitions;
|
|
19
|
+
private getChecksSQL;
|
|
20
|
+
getAllChecks(connection: AbstractSqlConnection, tablesBySchemas: Map<string | undefined, Table[]>): Promise<Dictionary<CheckDef[]>>;
|
|
21
|
+
loadInformationSchema(schema: DatabaseSchema, connection: AbstractSqlConnection, tables: Table[]): Promise<void>;
|
|
22
|
+
getPreAlterTable(tableDiff: TableDifference, safe: boolean): string[];
|
|
23
|
+
getPostAlterTable(tableDiff: TableDifference, safe: boolean): string[];
|
|
24
|
+
getCreateNamespaceSQL(name: string): string;
|
|
25
|
+
getDropNamespaceSQL(name: string): string;
|
|
26
|
+
getDropIndexSQL(tableName: string, index: IndexDef): string;
|
|
27
|
+
dropIndex(table: string, index: IndexDef, oldIndexName?: string): string;
|
|
28
|
+
getManagementDbName(): string;
|
|
29
|
+
getDatabaseNotExistsError(dbName: string): string;
|
|
30
|
+
getCreateDatabaseSQL(name: string): string;
|
|
31
|
+
getDropDatabaseSQL(name: string): string;
|
|
32
|
+
getDropColumnsSQL(tableName: string, columns: Column[], schemaName?: string): string;
|
|
33
|
+
getRenameColumnSQL(tableName: string, oldColumnName: string, to: Column, schemaName?: string): string;
|
|
34
|
+
createTableColumn(column: Column, table: DatabaseTable, changedProperties?: Set<string>): string | undefined;
|
|
35
|
+
alterTableColumn(column: Column, table: DatabaseTable, changedProperties: Set<string>): string[];
|
|
36
|
+
getCreateIndexSQL(tableName: string, index: IndexDef, partialExpression?: boolean): string;
|
|
37
|
+
createIndex(index: IndexDef, table: DatabaseTable, createPrimary?: boolean): string;
|
|
38
|
+
dropForeignKey(tableName: string, constraintName: string): string;
|
|
39
|
+
dropViewIfExists(name: string, schema?: string): string;
|
|
40
|
+
dropTableIfExists(name: string, schema?: string): string;
|
|
41
|
+
getAddColumnsSQL(table: DatabaseTable, columns: Column[]): string[];
|
|
42
|
+
appendComments(table: DatabaseTable): string[];
|
|
43
|
+
inferLengthFromColumnType(type: string): number | undefined;
|
|
44
|
+
protected wrap(val: string | undefined, type: Type<unknown>): string | undefined;
|
|
45
|
+
}
|