@mikro-orm/oracledb 7.1.0-dev.3 → 7.1.0-dev.30
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/OracleMikroORM.d.ts +3 -3
- package/OracleMikroORM.js +3 -2
- package/OraclePlatform.js +1 -1
- package/OracleSchemaHelper.d.ts +10 -0
- package/OracleSchemaHelper.js +83 -8
- package/package.json +5 -5
package/OracleMikroORM.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { MikroORM, type Options, type IDatabaseDriver, type EntityManager, type EntityManagerType, type EntityClass, type AnyEntity, type EntitySchema } from '@mikro-orm/core';
|
|
2
|
-
import type
|
|
1
|
+
import { type MikroORM, type Options, type IDatabaseDriver, type EntityManager, type EntityManagerType, type EntityClass, type AnyEntity, type EntitySchema } from '@mikro-orm/core';
|
|
2
|
+
import { SqlMikroORM, type SqlEntityManager } from '@mikro-orm/sql';
|
|
3
3
|
import { OracleDriver } from './OracleDriver.js';
|
|
4
4
|
/** Configuration options for the Oracle driver. */
|
|
5
5
|
export type OracleOptions<EM extends SqlEntityManager<OracleDriver> = SqlEntityManager<OracleDriver>, Entities extends readonly (string | EntityClass<AnyEntity> | EntitySchema)[] = (string | EntityClass<AnyEntity> | EntitySchema)[]> = Partial<Options<OracleDriver, EM, Entities>>;
|
|
@@ -8,7 +8,7 @@ export declare function defineOracleConfig<EM extends SqlEntityManager<OracleDri
|
|
|
8
8
|
/**
|
|
9
9
|
* @inheritDoc
|
|
10
10
|
*/
|
|
11
|
-
export declare class OracleMikroORM<EM extends SqlEntityManager<OracleDriver> = SqlEntityManager<OracleDriver>, Entities extends readonly (string | EntityClass<AnyEntity> | EntitySchema)[] = (string | EntityClass<AnyEntity> | EntitySchema)[]> extends
|
|
11
|
+
export declare class OracleMikroORM<EM extends SqlEntityManager<OracleDriver> = SqlEntityManager<OracleDriver>, Entities extends readonly (string | EntityClass<AnyEntity> | EntitySchema)[] = (string | EntityClass<AnyEntity> | EntitySchema)[]> extends SqlMikroORM<OracleDriver, EM, Entities> {
|
|
12
12
|
/**
|
|
13
13
|
* @inheritDoc
|
|
14
14
|
*/
|
package/OracleMikroORM.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { defineConfig,
|
|
1
|
+
import { defineConfig, } from '@mikro-orm/core';
|
|
2
|
+
import { SqlMikroORM } from '@mikro-orm/sql';
|
|
2
3
|
import { OracleDriver } from './OracleDriver.js';
|
|
3
4
|
/** Creates a type-safe configuration object for the Oracle driver. */
|
|
4
5
|
export function defineOracleConfig(options) {
|
|
@@ -7,7 +8,7 @@ export function defineOracleConfig(options) {
|
|
|
7
8
|
/**
|
|
8
9
|
* @inheritDoc
|
|
9
10
|
*/
|
|
10
|
-
export class OracleMikroORM extends
|
|
11
|
+
export class OracleMikroORM extends SqlMikroORM {
|
|
11
12
|
/**
|
|
12
13
|
* @inheritDoc
|
|
13
14
|
*/
|
package/OraclePlatform.js
CHANGED
|
@@ -203,7 +203,7 @@ export class OraclePlatform extends AbstractSqlPlatform {
|
|
|
203
203
|
if (b.length === 0) {
|
|
204
204
|
return raw(`json_equal(${root}, json(?))`, [value]);
|
|
205
205
|
}
|
|
206
|
-
return raw(`json_value(${root},
|
|
206
|
+
return raw(`json_value(${root}, ${this.quoteValue(`$.${b.map(this.quoteJsonKey).join('.')}`)})`);
|
|
207
207
|
}
|
|
208
208
|
processJsonCondition(o, value, path, alias) {
|
|
209
209
|
if (Utils.isPlainObject(value) && !Object.keys(value).some(k => Utils.isOperator(k))) {
|
package/OracleSchemaHelper.d.ts
CHANGED
|
@@ -2,7 +2,13 @@ import { type AbstractSqlConnection, type CheckDef, type Column, type DatabaseSc
|
|
|
2
2
|
/** Schema introspection helper for Oracle Database. */
|
|
3
3
|
export declare class OracleSchemaHelper extends SchemaHelper {
|
|
4
4
|
static readonly DEFAULT_VALUES: Record<string, string[]>;
|
|
5
|
+
private static readonly AUTO_NOT_NULL_RE;
|
|
6
|
+
private static readonly PARTIAL_INDEX_RE;
|
|
5
7
|
getDatabaseExistsSQL(name: string): string;
|
|
8
|
+
getSetSchemaSQL(schema: string): string;
|
|
9
|
+
getResetSchemaSQL(defaultSchema: string): string;
|
|
10
|
+
supportsMigrationSchema(): boolean;
|
|
11
|
+
tableExists(connection: AbstractSqlConnection, tableName: string, schemaName: string | undefined, ctx?: Transaction): Promise<boolean>;
|
|
6
12
|
getAllTables(connection: AbstractSqlConnection, schemas?: string[], ctx?: Transaction): Promise<Table[]>;
|
|
7
13
|
getListTablesSQL(schemaName?: string): string;
|
|
8
14
|
getListViewsSQL(): string;
|
|
@@ -19,6 +25,7 @@ export declare class OracleSchemaHelper extends SchemaHelper {
|
|
|
19
25
|
private getEnumDefinitions;
|
|
20
26
|
private getChecksSQL;
|
|
21
27
|
getAllChecks(connection: AbstractSqlConnection, tablesBySchemas: Map<string | undefined, Table[]>, ctx?: Transaction): Promise<Dictionary<CheckDef[]>>;
|
|
28
|
+
getDatabaseCollation(connection: AbstractSqlConnection, ctx?: Transaction): Promise<string | undefined>;
|
|
22
29
|
loadInformationSchema(schema: DatabaseSchema, connection: AbstractSqlConnection, tables: Table[], schemas?: string[], ctx?: Transaction): Promise<void>;
|
|
23
30
|
getPreAlterTable(tableDiff: TableDifference, safe: boolean): string[];
|
|
24
31
|
getPostAlterTable(tableDiff: TableDifference, safe: boolean): string[];
|
|
@@ -35,6 +42,9 @@ export declare class OracleSchemaHelper extends SchemaHelper {
|
|
|
35
42
|
createTableColumn(column: Column, table: DatabaseTable, changedProperties?: Set<string>): string | undefined;
|
|
36
43
|
alterTableColumn(column: Column, table: DatabaseTable, changedProperties: Set<string>): string[];
|
|
37
44
|
getCreateIndexSQL(tableName: string, index: IndexDef, partialExpression?: boolean): string;
|
|
45
|
+
protected getIndexColumns(index: IndexDef): string;
|
|
46
|
+
/** Oracle has no native WHERE clause for indexes; the predicate is folded into CASE-WHEN columns. */
|
|
47
|
+
protected getIndexWhereClause(_index: IndexDef): string;
|
|
38
48
|
createIndex(index: IndexDef, table: DatabaseTable, createPrimary?: boolean): string;
|
|
39
49
|
dropForeignKey(tableName: string, constraintName: string): string;
|
|
40
50
|
dropViewIfExists(name: string, schema?: string): string;
|
package/OracleSchemaHelper.js
CHANGED
|
@@ -7,9 +7,29 @@ export class OracleSchemaHelper extends SchemaHelper {
|
|
|
7
7
|
systimestamp: ['current_timestamp'],
|
|
8
8
|
sysdate: ['current_timestamp'],
|
|
9
9
|
};
|
|
10
|
+
// `stripAutoNotNullFilter` unwraps balanced per-clause parens before calling `.exec`, so we
|
|
11
|
+
// only need to match the bare form here.
|
|
12
|
+
static AUTO_NOT_NULL_RE = /^"?([^"\s()]+)"?\s+is\s+not\s+null$/i;
|
|
13
|
+
// Greedy `(.+)` so nested CASE expressions inside the predicate don't trip the match on
|
|
14
|
+
// an inner `then <col> end`.
|
|
15
|
+
static PARTIAL_INDEX_RE = /^\s*\(?\s*case\s+when\s+(.+)\s+then\s+"?([^"\s)]+)"?\s+end\s*\)?\s*$/is;
|
|
10
16
|
getDatabaseExistsSQL(name) {
|
|
11
17
|
return `select 1 from all_users where username = ${this.platform.quoteValue(name)}`;
|
|
12
18
|
}
|
|
19
|
+
getSetSchemaSQL(schema) {
|
|
20
|
+
return `alter session set current_schema = ${this.quote(schema)}`;
|
|
21
|
+
}
|
|
22
|
+
getResetSchemaSQL(defaultSchema) {
|
|
23
|
+
return `alter session set current_schema = ${this.quote(defaultSchema)}`;
|
|
24
|
+
}
|
|
25
|
+
supportsMigrationSchema() {
|
|
26
|
+
return true;
|
|
27
|
+
}
|
|
28
|
+
async tableExists(connection, tableName, schemaName, ctx) {
|
|
29
|
+
const schema = schemaName ?? this.platform.getDefaultSchemaName();
|
|
30
|
+
const rows = await connection.execute(`select 1 from all_tables where owner = ${this.platform.quoteValue(schema)} and table_name = ${this.platform.quoteValue(tableName)}`, [], 'all', ctx);
|
|
31
|
+
return rows.length > 0;
|
|
32
|
+
}
|
|
13
33
|
async getAllTables(connection, schemas, ctx) {
|
|
14
34
|
if (!schemas || schemas.length === 0) {
|
|
15
35
|
return connection.execute(this.getListTablesSQL(), [], 'all', ctx);
|
|
@@ -121,7 +141,8 @@ export class OracleSchemaHelper extends SchemaHelper {
|
|
|
121
141
|
atc.char_length as character_maximum_length,
|
|
122
142
|
atc.data_length as data_length,
|
|
123
143
|
atc.identity_column as is_identity,
|
|
124
|
-
atc.column_id as ordinal_position
|
|
144
|
+
atc.column_id as ordinal_position,
|
|
145
|
+
atc.collation as collation_name
|
|
125
146
|
from all_tab_cols atc
|
|
126
147
|
left join all_col_comments acc on atc.owner = acc.owner and atc.table_name = acc.table_name and atc.column_name = acc.column_name
|
|
127
148
|
where atc.hidden_column = 'NO'
|
|
@@ -177,6 +198,11 @@ export class OracleSchemaHelper extends SchemaHelper {
|
|
|
177
198
|
precision: col.numeric_precision,
|
|
178
199
|
scale: col.numeric_scale,
|
|
179
200
|
comment: col.column_comment,
|
|
201
|
+
// `USING_NLS_COMP` is the Oracle sentinel for "inherit from the session NLS settings", so
|
|
202
|
+
// a column without an explicit `COLLATE` clause introspects as `USING_NLS_COMP` rather
|
|
203
|
+
// than NULL. Treat it as "no explicit collation" so the comparator doesn't flag every
|
|
204
|
+
// string column as changed when the database default is something else (e.g. `BINARY`).
|
|
205
|
+
collation: col.collation_name && col.collation_name !== 'USING_NLS_COMP' ? col.collation_name : undefined,
|
|
180
206
|
generated,
|
|
181
207
|
});
|
|
182
208
|
}
|
|
@@ -210,16 +236,19 @@ export class OracleSchemaHelper extends SchemaHelper {
|
|
|
210
236
|
if (isPrimary) {
|
|
211
237
|
continue;
|
|
212
238
|
}
|
|
239
|
+
const partialMatch = typeof index.expression === 'string' ? OracleSchemaHelper.PARTIAL_INDEX_RE.exec(index.expression) : null;
|
|
213
240
|
const indexDef = {
|
|
214
|
-
columnNames: [index.column_name],
|
|
241
|
+
columnNames: [partialMatch ? partialMatch[2] : index.column_name],
|
|
215
242
|
keyName: index.index_name,
|
|
216
243
|
unique: index.is_unique === 'YES',
|
|
217
|
-
primary: false,
|
|
244
|
+
primary: false,
|
|
218
245
|
constraint: isConstraintIndex || index.is_unique === 'YES',
|
|
219
246
|
};
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
247
|
+
/* v8 ignore start: function-based (non-partial) index branches */
|
|
248
|
+
if (partialMatch) {
|
|
249
|
+
indexDef.where = partialMatch[1].trim();
|
|
250
|
+
}
|
|
251
|
+
else if (index.expression) {
|
|
223
252
|
indexDef.expression = index.expression;
|
|
224
253
|
}
|
|
225
254
|
else if (index.column_name?.match(/[(): ,"'`]/)) {
|
|
@@ -231,6 +260,17 @@ export class OracleSchemaHelper extends SchemaHelper {
|
|
|
231
260
|
}
|
|
232
261
|
for (const key of Object.keys(ret)) {
|
|
233
262
|
ret[key] = await this.mapIndexes(ret[key]);
|
|
263
|
+
for (const idx of ret[key]) {
|
|
264
|
+
if (idx.where) {
|
|
265
|
+
const stripped = this.stripAutoNotNullFilter(idx.where, idx.columnNames, OracleSchemaHelper.AUTO_NOT_NULL_RE);
|
|
266
|
+
if (stripped === '') {
|
|
267
|
+
delete idx.where;
|
|
268
|
+
}
|
|
269
|
+
else {
|
|
270
|
+
idx.where = stripped;
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
}
|
|
234
274
|
}
|
|
235
275
|
return ret;
|
|
236
276
|
}
|
|
@@ -338,6 +378,10 @@ export class OracleSchemaHelper extends SchemaHelper {
|
|
|
338
378
|
}
|
|
339
379
|
return ret;
|
|
340
380
|
}
|
|
381
|
+
async getDatabaseCollation(connection, ctx) {
|
|
382
|
+
const [row] = await connection.execute(`select property_value as collation from database_properties where property_name = 'DEFAULT_COLLATION'`, [], 'all', ctx);
|
|
383
|
+
return row?.collation;
|
|
384
|
+
}
|
|
341
385
|
async loadInformationSchema(schema, connection, tables, schemas, ctx) {
|
|
342
386
|
if (tables.length === 0) {
|
|
343
387
|
return;
|
|
@@ -347,9 +391,11 @@ export class OracleSchemaHelper extends SchemaHelper {
|
|
|
347
391
|
const indexes = await this.getAllIndexes(connection, tablesBySchema, ctx);
|
|
348
392
|
const checks = await this.getAllChecks(connection, tablesBySchema, ctx);
|
|
349
393
|
const fks = await this.getAllForeignKeys(connection, tablesBySchema, ctx);
|
|
394
|
+
const dbCollation = await this.getDatabaseCollation(connection, ctx);
|
|
350
395
|
for (const t of tables) {
|
|
351
396
|
const key = this.getTableKey(t);
|
|
352
397
|
const table = schema.addTable(t.table_name, t.schema_name, t.table_comment);
|
|
398
|
+
table.collation = dbCollation;
|
|
353
399
|
const pks = await this.getPrimaryKeys(connection, indexes[key], table.name, table.schema);
|
|
354
400
|
const enums = this.getEnumDefinitions(checks[key] ?? []);
|
|
355
401
|
table.init(columns[key], indexes[key], checks[key], pks, fks[key], enums);
|
|
@@ -450,6 +496,7 @@ export class OracleSchemaHelper extends SchemaHelper {
|
|
|
450
496
|
/* v8 ignore next: generated column branch */
|
|
451
497
|
const columnType = column.generated ? `as ${column.generated}` : column.type;
|
|
452
498
|
const col = [this.quote(column.name), columnType];
|
|
499
|
+
Utils.runIfNotEmpty(() => col.push(this.getCollateSQL(column.collation)), column.collation);
|
|
453
500
|
Utils.runIfNotEmpty(() => col.push('generated by default as identity'), column.autoincrement);
|
|
454
501
|
/* v8 ignore next 3: default value branch */
|
|
455
502
|
const useDefault = changedProperties
|
|
@@ -473,8 +520,15 @@ export class OracleSchemaHelper extends SchemaHelper {
|
|
|
473
520
|
const parts = [];
|
|
474
521
|
const quotedTableName = table.getQuotedName();
|
|
475
522
|
// Oracle uses MODIFY for column changes, and always requires the column type
|
|
476
|
-
if (changedProperties.has('type') ||
|
|
523
|
+
if (changedProperties.has('type') ||
|
|
524
|
+
changedProperties.has('nullable') ||
|
|
525
|
+
changedProperties.has('default') ||
|
|
526
|
+
changedProperties.has('collation')) {
|
|
477
527
|
const colParts = [this.quote(column.name), column.type];
|
|
528
|
+
// Oracle's MODIFY restates the column type, so re-emit COLLATE whenever the column has
|
|
529
|
+
// one — even if the trigger was a nullable/default change — so we can't accidentally
|
|
530
|
+
// drop the column collation by omitting it from the new type spec.
|
|
531
|
+
Utils.runIfNotEmpty(() => colParts.push(this.getCollateSQL(column.collation)), column.collation);
|
|
478
532
|
if (changedProperties.has('default')) {
|
|
479
533
|
if (column.default != null && column.default !== 'null') {
|
|
480
534
|
colParts.push(`default ${column.default}`);
|
|
@@ -503,6 +557,16 @@ export class OracleSchemaHelper extends SchemaHelper {
|
|
|
503
557
|
}
|
|
504
558
|
return super.getCreateIndexSQL(tableName, index);
|
|
505
559
|
}
|
|
560
|
+
getIndexColumns(index) {
|
|
561
|
+
if (index.where) {
|
|
562
|
+
return this.emulatePartialIndexColumns(index);
|
|
563
|
+
}
|
|
564
|
+
return super.getIndexColumns(index);
|
|
565
|
+
}
|
|
566
|
+
/** Oracle has no native WHERE clause for indexes; the predicate is folded into CASE-WHEN columns. */
|
|
567
|
+
getIndexWhereClause(_index) {
|
|
568
|
+
return '';
|
|
569
|
+
}
|
|
506
570
|
createIndex(index, table, createPrimary = false) {
|
|
507
571
|
if (index.primary) {
|
|
508
572
|
return '';
|
|
@@ -524,10 +588,21 @@ export class OracleSchemaHelper extends SchemaHelper {
|
|
|
524
588
|
const quotedTableName = table.getQuotedName();
|
|
525
589
|
if (index.unique) {
|
|
526
590
|
const nullableCols = index.columnNames.filter(column => table.getColumn(column)?.nullable);
|
|
591
|
+
const autoNotNull = nullableCols.length
|
|
592
|
+
? nullableCols.map(c => `${this.quote(c)} is not null`).join(' and ')
|
|
593
|
+
: '';
|
|
594
|
+
if (index.where) {
|
|
595
|
+
// Wrap the user predicate in parens before ANDing the auto-NOT-NULL guard — otherwise a
|
|
596
|
+
// disjunctive `a = 1 or b = 2` would rebind as `a = 1 or (b = 2 and <col> is not null)`.
|
|
597
|
+
const predicate = autoNotNull ? `(${index.where}) and ${autoNotNull}` : index.where;
|
|
598
|
+
return `create unique index ${this.quote(index.keyName)} on ${quotedTableName} (${index.columnNames
|
|
599
|
+
.map(c => `case when ${predicate} then ${this.quote(c)} end`)
|
|
600
|
+
.join(', ')})`;
|
|
601
|
+
}
|
|
527
602
|
return `create unique index ${this.quote(index.keyName)} on ${quotedTableName} (${index.columnNames
|
|
528
603
|
.map(c => {
|
|
529
604
|
if (table.getColumn(c)?.nullable) {
|
|
530
|
-
return `case when ${
|
|
605
|
+
return `case when ${autoNotNull} then ${this.quote(c)} end`;
|
|
531
606
|
}
|
|
532
607
|
return this.quote(c);
|
|
533
608
|
})
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mikro-orm/oracledb",
|
|
3
|
-
"version": "7.1.0-dev.
|
|
3
|
+
"version": "7.1.0-dev.30",
|
|
4
4
|
"description": "TypeScript ORM for Node.js based on Data Mapper, Unit of Work and Identity Map patterns. Supports MongoDB, MySQL, MariaDB, PostgreSQL, SQLite, MSSQL and Oracle databases.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"data-mapper",
|
|
@@ -42,15 +42,15 @@
|
|
|
42
42
|
"copy": "node ../../scripts/copy.mjs"
|
|
43
43
|
},
|
|
44
44
|
"dependencies": {
|
|
45
|
-
"@mikro-orm/sql": "7.1.0-dev.
|
|
46
|
-
"kysely": "0.28.
|
|
45
|
+
"@mikro-orm/sql": "7.1.0-dev.30",
|
|
46
|
+
"kysely": "0.28.17",
|
|
47
47
|
"oracledb": "6.10.0"
|
|
48
48
|
},
|
|
49
49
|
"devDependencies": {
|
|
50
|
-
"@mikro-orm/core": "^7.0.
|
|
50
|
+
"@mikro-orm/core": "^7.0.15"
|
|
51
51
|
},
|
|
52
52
|
"peerDependencies": {
|
|
53
|
-
"@mikro-orm/core": "7.1.0-dev.
|
|
53
|
+
"@mikro-orm/core": "7.1.0-dev.30"
|
|
54
54
|
},
|
|
55
55
|
"engines": {
|
|
56
56
|
"node": ">= 22.17.0"
|