mirror of
https://github.com/typeorm/typeorm.git
synced 2025-12-08 21:26:23 +00:00
fix: prevent foreign key support during migration batch under sqlite (#9775)
* fix: prevent foreign keys support during migration batch under sqlite Schema changes in migrations batch cannot be done on table which has referring foreign keys with ON DELETE CASCADE without deleting its content. Closes: #9770 * Update MigrationExecutor.ts * Update command.ts --------- Co-authored-by: Umed Khudoiberdiev <pleerock.me@gmail.com>
This commit is contained in:
parent
4ac8c00117
commit
197cc05e90
@ -311,6 +311,7 @@ export class MigrationExecutor {
|
||||
// start transaction if its not started yet
|
||||
let transactionStartedByUs = false
|
||||
if (this.transaction === "all" && !queryRunner.isTransactionActive) {
|
||||
await queryRunner.beforeMigration()
|
||||
await queryRunner.startTransaction()
|
||||
transactionStartedByUs = true
|
||||
}
|
||||
@ -327,6 +328,7 @@ export class MigrationExecutor {
|
||||
}
|
||||
|
||||
if (migration.transaction && !queryRunner.isTransactionActive) {
|
||||
await queryRunner.beforeMigration()
|
||||
await queryRunner.startTransaction()
|
||||
transactionStartedByUs = true
|
||||
}
|
||||
@ -347,8 +349,10 @@ export class MigrationExecutor {
|
||||
migration,
|
||||
)
|
||||
// commit transaction if we started it
|
||||
if (migration.transaction && transactionStartedByUs)
|
||||
if (migration.transaction && transactionStartedByUs) {
|
||||
await queryRunner.commitTransaction()
|
||||
await queryRunner.afterMigration()
|
||||
}
|
||||
})
|
||||
.then(() => {
|
||||
// informative log about migration success
|
||||
@ -362,8 +366,10 @@ export class MigrationExecutor {
|
||||
}
|
||||
|
||||
// commit transaction if we started it
|
||||
if (this.transaction === "all" && transactionStartedByUs)
|
||||
if (this.transaction === "all" && transactionStartedByUs) {
|
||||
await queryRunner.commitTransaction()
|
||||
await queryRunner.afterMigration()
|
||||
}
|
||||
} catch (err) {
|
||||
// rollback transaction if we started it
|
||||
if (transactionStartedByUs) {
|
||||
|
||||
@ -12,7 +12,7 @@ describe("migrations > show command", () => {
|
||||
async () =>
|
||||
(connections = await createTestingConnections({
|
||||
migrations: [__dirname + "/migration/*.js"],
|
||||
enabledDrivers: ["postgres"],
|
||||
enabledDrivers: ["postgres", "sqlite"],
|
||||
schemaCreate: true,
|
||||
dropSchema: true,
|
||||
})),
|
||||
|
||||
26
test/github-issues/9770/entity/Bar.ts
Normal file
26
test/github-issues/9770/entity/Bar.ts
Normal file
@ -0,0 +1,26 @@
|
||||
import {
|
||||
Entity,
|
||||
Column,
|
||||
ManyToOne,
|
||||
JoinColumn,
|
||||
PrimaryGeneratedColumn,
|
||||
} from "../../../../src"
|
||||
|
||||
import { Foo } from "./Foo"
|
||||
|
||||
@Entity()
|
||||
export class Bar {
|
||||
@PrimaryGeneratedColumn()
|
||||
id: number
|
||||
|
||||
@ManyToOne(() => Foo, {
|
||||
cascade: true,
|
||||
onDelete: "CASCADE",
|
||||
nullable: false,
|
||||
})
|
||||
@JoinColumn()
|
||||
foo!: Foo
|
||||
|
||||
@Column()
|
||||
data: string
|
||||
}
|
||||
9
test/github-issues/9770/entity/Foo.ts
Normal file
9
test/github-issues/9770/entity/Foo.ts
Normal file
@ -0,0 +1,9 @@
|
||||
import { Entity, Column, PrimaryGeneratedColumn } from "../../../../src"
|
||||
|
||||
@Entity()
|
||||
export class Foo {
|
||||
@PrimaryGeneratedColumn() id: number
|
||||
|
||||
@Column()
|
||||
data: string
|
||||
}
|
||||
87
test/github-issues/9770/issue-9770.ts
Normal file
87
test/github-issues/9770/issue-9770.ts
Normal file
@ -0,0 +1,87 @@
|
||||
import "reflect-metadata"
|
||||
import { expect } from "chai"
|
||||
|
||||
import { DataSource } from "../../../src"
|
||||
//import { DataSource, TableColumn } from "../../../src"
|
||||
import {
|
||||
closeTestingConnections,
|
||||
createTestingConnections,
|
||||
reloadTestingDatabases,
|
||||
} from "../../utils/test-utils"
|
||||
|
||||
import { Foo } from "./entity/Foo"
|
||||
import { Bar } from "./entity/Bar"
|
||||
|
||||
describe("github issues > #9770 check for referencing foreign keys when altering a table using sqlite", () => {
|
||||
let dataSources: DataSource[]
|
||||
before(async () => {
|
||||
dataSources = await createTestingConnections({
|
||||
entities: [__dirname + "/entity/*{.js,.ts}"],
|
||||
migrations: [__dirname + "/migration/*{.js,.ts}"],
|
||||
enabledDrivers: ["sqlite", "better-sqlite3"],
|
||||
schemaCreate: true,
|
||||
dropSchema: true,
|
||||
logging: true,
|
||||
})
|
||||
})
|
||||
beforeEach(() => reloadTestingDatabases(dataSources))
|
||||
after(() => closeTestingConnections(dataSources))
|
||||
|
||||
it("shouldn't loose dependant table data", () =>
|
||||
Promise.all(
|
||||
dataSources.map(async (dataSource) => {
|
||||
const manager = dataSource.manager
|
||||
|
||||
// Insert records in the tables
|
||||
const foo = new Foo()
|
||||
foo.data = "foo"
|
||||
await manager.save(foo)
|
||||
const foundFoo = await manager.findOne(Foo, {
|
||||
where: {
|
||||
id: 1,
|
||||
},
|
||||
})
|
||||
expect(foundFoo).not.to.be.null
|
||||
|
||||
if (!foundFoo) return
|
||||
|
||||
const bar = new Bar()
|
||||
bar.foo = foundFoo
|
||||
bar.data = "bar"
|
||||
await manager.save(bar)
|
||||
|
||||
const foundBar = await manager.findOne(Bar, {
|
||||
where: {
|
||||
foo: {
|
||||
id: foundFoo.id,
|
||||
},
|
||||
},
|
||||
})
|
||||
expect(foundBar).not.to.be.null
|
||||
|
||||
// check current state (migrations pending and entries in db)
|
||||
const migrations = await dataSource.showMigrations()
|
||||
migrations.should.be.equal(true)
|
||||
|
||||
const queryRunner = dataSource.createQueryRunner()
|
||||
let barRecords = await queryRunner.query(`SELECT * FROM "bar"`)
|
||||
expect(barRecords).to.have.lengthOf.above(0)
|
||||
|
||||
// run migrations which contains a table drop
|
||||
await dataSource.runMigrations()
|
||||
|
||||
// check post migration (no more pending migration and data still in db)
|
||||
const migrations2 = await dataSource.showMigrations()
|
||||
migrations2.should.be.equal(false)
|
||||
|
||||
// check if data still exists in dependant table
|
||||
barRecords = await queryRunner.query(`SELECT * FROM "bar"`)
|
||||
expect(barRecords).to.have.lengthOf.above(0)
|
||||
|
||||
// revert changes
|
||||
await queryRunner.executeMemoryDownSql()
|
||||
|
||||
await queryRunner.release()
|
||||
}),
|
||||
))
|
||||
})
|
||||
19
test/github-issues/9770/migration/1675779246631-amendFoo.ts
Normal file
19
test/github-issues/9770/migration/1675779246631-amendFoo.ts
Normal file
@ -0,0 +1,19 @@
|
||||
import { MigrationInterface, QueryRunner, TableColumn } from "../../../../src"
|
||||
|
||||
export class amendFoo1675779246631 implements MigrationInterface {
|
||||
public async up(q: QueryRunner): Promise<void> {
|
||||
await q.addColumn(
|
||||
"foo",
|
||||
new TableColumn({
|
||||
name: "comment",
|
||||
type: "varchar",
|
||||
isNullable: true,
|
||||
default: null,
|
||||
}),
|
||||
)
|
||||
}
|
||||
|
||||
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.dropColumn("foo", "comment")
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user