mirror of
https://github.com/typeorm/typeorm.git
synced 2025-12-08 21:26:23 +00:00
feat: naming strategy for legacy Oracle (#9703)
* feat: naming strategy for legacy Oracle This feature is LegacyOracleNamingStrategy which can be used to handle Oracle error ORA-00972. * feat: naming strategy for legacy Oracle This feature is LegacyOracleNamingStrategy which can be used to handle Oracle error ORA-00972.
This commit is contained in:
parent
7df2ccf69d
commit
0eb74411d6
@ -161,6 +161,7 @@ export { MigrationExecutor } from "./migration/MigrationExecutor"
|
||||
export { MigrationInterface } from "./migration/MigrationInterface"
|
||||
export { DefaultNamingStrategy } from "./naming-strategy/DefaultNamingStrategy"
|
||||
export { NamingStrategyInterface } from "./naming-strategy/NamingStrategyInterface"
|
||||
export { LegacyOracleNamingStrategy } from "./naming-strategy/LegacyOracleNamingStrategy"
|
||||
export { InsertEvent } from "./subscriber/event/InsertEvent"
|
||||
export { LoadEvent } from "./subscriber/event/LoadEvent"
|
||||
export { UpdateEvent } from "./subscriber/event/UpdateEvent"
|
||||
|
||||
71
src/naming-strategy/LegacyOracleNamingStrategy.ts
Normal file
71
src/naming-strategy/LegacyOracleNamingStrategy.ts
Normal file
@ -0,0 +1,71 @@
|
||||
import { NamingStrategyInterface } from "./NamingStrategyInterface"
|
||||
import { RandomGenerator } from "../util/RandomGenerator"
|
||||
import { DefaultNamingStrategy } from "./DefaultNamingStrategy"
|
||||
import { TypeORMError } from "../error"
|
||||
|
||||
/**
|
||||
* Shorten strategy
|
||||
*/
|
||||
export type ShortenStrategy = "truncate" | "hash"
|
||||
|
||||
/**
|
||||
* Naming strategy for legacy Oracle database with 30 bytes identifier limit.
|
||||
*
|
||||
* Currently, only column name must be shorten in order to avoid ORA-00972.
|
||||
* Issues with other identifiers were fixed.
|
||||
*/
|
||||
export class LegacyOracleNamingStrategy
|
||||
extends DefaultNamingStrategy
|
||||
implements NamingStrategyInterface
|
||||
{
|
||||
public readonly IDENTIFIER_MAX_SIZE = 30
|
||||
public readonly DEFAULT_COLUMN_PREFIX = "COL_"
|
||||
protected shortenStrategy: ShortenStrategy
|
||||
|
||||
constructor(shortenStrategy: ShortenStrategy = "hash") {
|
||||
super()
|
||||
this.shortenStrategy = shortenStrategy
|
||||
}
|
||||
|
||||
columnName(
|
||||
propertyName: string,
|
||||
customName: string,
|
||||
embeddedPrefixes: string[],
|
||||
): string {
|
||||
const longName: string = super.columnName(
|
||||
propertyName,
|
||||
customName,
|
||||
embeddedPrefixes,
|
||||
)
|
||||
if (this.shortenStrategy === "truncate") {
|
||||
return this.truncateIdentifier(longName)
|
||||
} else if (this.shortenStrategy === "hash") {
|
||||
return this.hashIdentifier(longName, this.DEFAULT_COLUMN_PREFIX)
|
||||
} else {
|
||||
throw new TypeORMError(`Invalid shortenStrategy`)
|
||||
}
|
||||
}
|
||||
|
||||
protected hashIdentifier(input: string, prefix: string): string {
|
||||
if (prefix.length >= this.IDENTIFIER_MAX_SIZE) {
|
||||
throw new TypeORMError(
|
||||
`Prefix must be shorter than IDENTIFIER_MAX_SIZE`,
|
||||
)
|
||||
}
|
||||
return (
|
||||
prefix +
|
||||
RandomGenerator.sha1(input).substring(
|
||||
0,
|
||||
this.IDENTIFIER_MAX_SIZE - prefix.length,
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
protected truncateIdentifier(input: string): string {
|
||||
if (input.length > this.IDENTIFIER_MAX_SIZE) {
|
||||
return input.substring(0, this.IDENTIFIER_MAX_SIZE)
|
||||
} else {
|
||||
return input
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,52 @@
|
||||
import "reflect-metadata"
|
||||
import { expect } from "chai"
|
||||
import { LegacyOracleNamingStrategy } from "../../../../../src/naming-strategy/LegacyOracleNamingStrategy"
|
||||
import { RandomGenerator } from "../../../../../src/util/RandomGenerator"
|
||||
|
||||
describe("LegacyOracleNamingStrategy > column shortening", () => {
|
||||
it("should truncate column names to the limit", () => {
|
||||
const legacyOracleNamingStrategy = new LegacyOracleNamingStrategy(
|
||||
"truncate",
|
||||
)
|
||||
expect(
|
||||
legacyOracleNamingStrategy.columnName("shortName", "", []),
|
||||
).to.equal("shortName")
|
||||
expect(
|
||||
legacyOracleNamingStrategy.columnName(
|
||||
"veryVeryVeryLongLongLongLongName",
|
||||
"",
|
||||
[],
|
||||
),
|
||||
).to.equal("veryVeryVeryLongLongLongLongNa")
|
||||
expect(
|
||||
legacyOracleNamingStrategy.columnName(
|
||||
RandomGenerator.sha1("seed1"),
|
||||
"",
|
||||
[],
|
||||
).length,
|
||||
).to.lessThanOrEqual(legacyOracleNamingStrategy.IDENTIFIER_MAX_SIZE)
|
||||
})
|
||||
|
||||
it("should change column names to hashes within the limit", () => {
|
||||
const legacyOracleNamingStrategy = new LegacyOracleNamingStrategy(
|
||||
"hash",
|
||||
)
|
||||
const columnName: string =
|
||||
"veryVeryVeryLongLongLongLongName" + RandomGenerator.sha1("seed2")
|
||||
const hashedColumnName: string = legacyOracleNamingStrategy.columnName(
|
||||
columnName,
|
||||
"",
|
||||
[],
|
||||
)
|
||||
expect(hashedColumnName.length).to.lessThanOrEqual(
|
||||
legacyOracleNamingStrategy.IDENTIFIER_MAX_SIZE,
|
||||
)
|
||||
expect(hashedColumnName)
|
||||
.to.be.a("string")
|
||||
.and.satisfy((name: string) =>
|
||||
name.startsWith(
|
||||
legacyOracleNamingStrategy.DEFAULT_COLUMN_PREFIX,
|
||||
),
|
||||
)
|
||||
})
|
||||
})
|
||||
@ -0,0 +1,31 @@
|
||||
import "reflect-metadata"
|
||||
import { expect } from "chai"
|
||||
import {
|
||||
closeTestingConnections,
|
||||
createTestingConnections,
|
||||
reloadTestingDatabases,
|
||||
} from "../../../../utils/test-utils"
|
||||
import { DataSource } from "../../../../../src/data-source"
|
||||
import { LegacyOracleNamingStrategy } from "../../../../../src/naming-strategy/LegacyOracleNamingStrategy"
|
||||
|
||||
describe("LegacyOracleNamingStrategy > create table using this naming strategy", () => {
|
||||
let connections: DataSource[]
|
||||
before(
|
||||
async () =>
|
||||
(connections = await createTestingConnections({
|
||||
entities: [__dirname + "/entity/*{.js,.ts}"],
|
||||
enabledDrivers: ["oracle"],
|
||||
namingStrategy: new LegacyOracleNamingStrategy("hash"),
|
||||
})),
|
||||
)
|
||||
// without reloadTestingDatabases(connections) -> tables should be created later
|
||||
after(() => closeTestingConnections(connections))
|
||||
|
||||
it("should create the table", () =>
|
||||
Promise.all(
|
||||
connections.map(async (connection) => {
|
||||
await expect(reloadTestingDatabases([connection])).to.be
|
||||
.fulfilled
|
||||
}),
|
||||
))
|
||||
})
|
||||
@ -0,0 +1,30 @@
|
||||
import "reflect-metadata"
|
||||
import { expect } from "chai"
|
||||
import {
|
||||
closeTestingConnections,
|
||||
createTestingConnections,
|
||||
reloadTestingDatabases,
|
||||
} from "../../../../utils/test-utils"
|
||||
import { DataSource } from "../../../../../src/data-source"
|
||||
|
||||
describe("LegacyOracleNamingStrategy > create table using default naming strategy", () => {
|
||||
let connections: DataSource[]
|
||||
before(
|
||||
async () =>
|
||||
(connections = await createTestingConnections({
|
||||
entities: [__dirname + "/entity/*{.js,.ts}"],
|
||||
enabledDrivers: ["oracle"],
|
||||
})),
|
||||
)
|
||||
// without reloadTestingDatabases(connections) -> tables should be created later
|
||||
after(() => closeTestingConnections(connections))
|
||||
|
||||
it("should not create the table and fail due to ORA-00972", () =>
|
||||
Promise.all(
|
||||
connections.map(async (connection) => {
|
||||
await expect(
|
||||
reloadTestingDatabases([connection]),
|
||||
).to.be.rejectedWith(/ORA-00972/gi)
|
||||
}),
|
||||
))
|
||||
})
|
||||
@ -0,0 +1,12 @@
|
||||
import { Entity } from "../../../../../../src/decorator/entity/Entity"
|
||||
import { PrimaryGeneratedColumn } from "../../../../../../src/decorator/columns/PrimaryGeneratedColumn"
|
||||
import { Column } from "../../../../../../src/decorator/columns/Column"
|
||||
|
||||
@Entity()
|
||||
export class Post {
|
||||
@PrimaryGeneratedColumn()
|
||||
id: number
|
||||
|
||||
@Column()
|
||||
veryLongveryLongveryLongveryLongveryLongveryLongveryLongName: string
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user