Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
fix: adding/removing @generated() will now generate a migration to ad…
…d/remove the DEFAULT value (#8274) * fix(8273) Adding @generated('uuid') will now generate a migration to add the DEFAULT value * implemented fix for "increment" generation type; implemented fix for generation removal; improved tests; * added test for #5898 Co-authored-by: AlexMesser
- Loading branch information
Ed Mitchell
committed
Feb 12, 2022
1 parent
6316e26
commit 4208393
Showing
8 changed files
with
321 additions
and
14 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
import {Entity, OneToMany, PrimaryGeneratedColumn} from "../../../../src"; | ||
import {Photo} from "./Photo"; | ||
|
||
@Entity() | ||
export class Album { | ||
@PrimaryGeneratedColumn() | ||
id: string | ||
|
||
@OneToMany(() => Photo, (photo) => photo.album, { onDelete: "CASCADE" }) | ||
photos: Photo[] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
import {Entity, JoinColumn, ManyToOne, PrimaryColumn} from "../../../../src"; | ||
import {User} from "./User"; | ||
|
||
@Entity() | ||
export class Document { | ||
@PrimaryColumn("uuid") | ||
id: string | ||
|
||
@ManyToOne(() => User, (user) => user.docs, {onDelete: "CASCADE"}) | ||
@JoinColumn({name: "ownerId"}) | ||
owner: User | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
import {Entity, JoinColumn, ManyToOne, PrimaryColumn} from "../../../../src"; | ||
import {Album} from "./Album"; | ||
|
||
@Entity() | ||
export class Photo { | ||
@PrimaryColumn() | ||
id: string | ||
|
||
@ManyToOne(() => Album, (album) => album.photos, {onDelete: "CASCADE"}) | ||
@JoinColumn({name: "albumId"}) | ||
album: Album | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
import {Entity, OneToMany, PrimaryGeneratedColumn} from "../../../../src"; | ||
import {Document} from "./Document"; | ||
|
||
@Entity() | ||
export class User { | ||
@PrimaryGeneratedColumn("uuid") | ||
id: string | ||
|
||
@OneToMany(() => Document, (doc) => doc.owner, { onDelete: "CASCADE" }) | ||
docs: Document[] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,110 @@ | ||
import "reflect-metadata"; | ||
import {expect} from "chai"; | ||
import {Connection, QueryRunner} from "../../../src"; | ||
import {createTestingConnections, closeTestingConnections} from "../../utils/test-utils"; | ||
import {User} from "./entity/User"; | ||
import {Document} from "./entity/Document"; | ||
import {Album} from "./entity/Album"; | ||
import {Photo} from "./entity/Photo"; | ||
|
||
describe("github issues > #5898 Postgres primary key of type uuid: default value migration/sync not working", () => { | ||
let connections: Connection[]; | ||
const getColumnDefault = async (queryRunner: QueryRunner, tableName: string, columnName: string): Promise<string|null> => { | ||
const query = `SELECT "column_default"` + | ||
` FROM "information_schema"."columns"` + | ||
` WHERE "table_schema" = 'public' AND "table_name" = '${tableName}' AND "column_name" = '${columnName}'` | ||
const res = await queryRunner.query(query) | ||
return res.length ? res[0]["column_default"] : null | ||
} | ||
before(async () => connections = await createTestingConnections({ | ||
enabledDrivers: ["postgres"], | ||
schemaCreate: true, | ||
dropSchema: true, | ||
entities: [User, Document, Album, Photo], | ||
})); | ||
after(() => closeTestingConnections(connections)); | ||
|
||
it("should add DEFAULT value when @PrimaryGeneratedColumn('increment') is added", () => Promise.all(connections.map(async connection => { | ||
const queryRunner = connection.createQueryRunner(); | ||
let table = await queryRunner.getTable("photo"); | ||
const column = table!.findColumnByName("id")!; | ||
const newColumn = column.clone(); | ||
newColumn.isGenerated = true; | ||
newColumn.generationStrategy = "increment"; | ||
|
||
await queryRunner.changeColumn(table!, column, newColumn) | ||
|
||
let columnDefault = await getColumnDefault(queryRunner, "photo", "id") | ||
expect(columnDefault).to.equal("nextval('photo_id_seq'::regclass)") | ||
|
||
await queryRunner.executeMemoryDownSql(); | ||
|
||
columnDefault = await getColumnDefault(queryRunner, "photo", "id") | ||
expect(columnDefault).to.null | ||
|
||
await queryRunner.release() | ||
}))); | ||
|
||
it("should remove DEFAULT value when @PrimaryGeneratedColumn('increment') is removed", () => Promise.all(connections.map(async connection => { | ||
const queryRunner = connection.createQueryRunner(); | ||
let table = await queryRunner.getTable("album"); | ||
const column = table!.findColumnByName("id")!; | ||
const newColumn = column.clone(); | ||
newColumn.isGenerated = false; | ||
newColumn.generationStrategy = undefined; | ||
|
||
await queryRunner.changeColumn(table!, column, newColumn) | ||
|
||
let columnDefault = await getColumnDefault(queryRunner, "album", "id") | ||
expect(columnDefault).to.null | ||
|
||
await queryRunner.executeMemoryDownSql(); | ||
|
||
columnDefault = await getColumnDefault(queryRunner, "album", "id") | ||
expect(columnDefault).to.equal(`nextval('album_id_seq'::regclass)`) | ||
|
||
await queryRunner.release() | ||
}))); | ||
|
||
it("should add DEFAULT value when @PrimaryGeneratedColumn('uuid') is added", () => Promise.all(connections.map(async connection => { | ||
const queryRunner = connection.createQueryRunner(); | ||
let table = await queryRunner.getTable("document"); | ||
const column = table!.findColumnByName("id")!; | ||
const newColumn = column.clone(); | ||
newColumn.isGenerated = true; | ||
newColumn.generationStrategy = "uuid"; | ||
|
||
await queryRunner.changeColumn(table!, column, newColumn) | ||
|
||
let columnDefault = await getColumnDefault(queryRunner, "document", "id") | ||
expect(columnDefault).to.equal("uuid_generate_v4()") | ||
|
||
await queryRunner.executeMemoryDownSql(); | ||
|
||
columnDefault = await getColumnDefault(queryRunner, "document", "id") | ||
expect(columnDefault).to.null | ||
|
||
await queryRunner.release() | ||
}))); | ||
|
||
it("should remove DEFAULT value when @PrimaryGeneratedColumn('uuid') is removed", () => Promise.all(connections.map(async connection => { | ||
const queryRunner = connection.createQueryRunner(); | ||
let table = await queryRunner.getTable("user"); | ||
const column = table!.findColumnByName("id")!; | ||
const newColumn = column.clone(); | ||
newColumn.isGenerated = false; | ||
newColumn.generationStrategy = undefined; | ||
|
||
await queryRunner.changeColumn(table!, column, newColumn) | ||
|
||
let columnDefault = await getColumnDefault(queryRunner, "user", "id") | ||
expect(columnDefault).to.null | ||
|
||
await queryRunner.executeMemoryDownSql(); | ||
|
||
columnDefault = await getColumnDefault(queryRunner, "user", "id") | ||
expect(columnDefault).to.equal("uuid_generate_v4()") | ||
|
||
await queryRunner.release() | ||
}))); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
import { Entity, PrimaryColumn, Column, Generated } from "../../../../src"; | ||
|
||
@Entity() | ||
export class User { | ||
|
||
@PrimaryColumn() | ||
id: number; | ||
|
||
@Column({ type: "uuid" }) | ||
uuid: string; | ||
|
||
@Column({ type: "uuid" }) | ||
@Generated("uuid") | ||
uuidWithGenerated: string; | ||
|
||
@Column() | ||
increment: number; | ||
|
||
@Column() | ||
@Generated("increment") | ||
incrementWithGenerated: number; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,107 @@ | ||
import "reflect-metadata"; | ||
import {expect} from "chai"; | ||
import {Connection, QueryRunner} from "../../../src"; | ||
import {createTestingConnections, closeTestingConnections} from "../../utils/test-utils"; | ||
import {User} from "./entity/User"; | ||
|
||
describe("github issues > #8273 Adding @Generated('uuid') doesn't update column default in PostgreSQL", () => { | ||
let connections: Connection[]; | ||
const getColumnDefault = async (queryRunner: QueryRunner, columnName: string): Promise<string|null> => { | ||
const query = `SELECT "column_default"`+ | ||
` FROM "information_schema"."columns"`+ | ||
` WHERE "table_schema" = 'public' AND "table_name" = 'user' AND "column_name" = '${columnName}'` | ||
const res = await queryRunner.query(query) | ||
return res.length ? res[0]["column_default"] : null | ||
} | ||
before(async () => connections = await createTestingConnections({ | ||
enabledDrivers: ["postgres"], | ||
schemaCreate: true, | ||
dropSchema: true, | ||
entities: [User], | ||
})); | ||
after(() => closeTestingConnections(connections)); | ||
|
||
it("should add DEFAULT value when @Generated('increment') is added", () => Promise.all(connections.map(async connection => { | ||
const queryRunner = connection.createQueryRunner(); | ||
let table = await queryRunner.getTable("user"); | ||
const column = table!.findColumnByName("increment")!; | ||
const newColumn = column.clone(); | ||
newColumn.isGenerated = true; | ||
newColumn.generationStrategy = "increment"; | ||
|
||
await queryRunner.changeColumn(table!, column, newColumn) | ||
|
||
let columnDefault = await getColumnDefault(queryRunner, "increment") | ||
expect(columnDefault).to.equal("nextval('user_increment_seq'::regclass)") | ||
|
||
await queryRunner.executeMemoryDownSql(); | ||
|
||
columnDefault = await getColumnDefault(queryRunner, "increment") | ||
expect(columnDefault).to.null | ||
|
||
await queryRunner.release() | ||
}))); | ||
|
||
it("should remove DEFAULT value when @Generated('increment') is removed", () => Promise.all(connections.map(async connection => { | ||
const queryRunner = connection.createQueryRunner(); | ||
let table = await queryRunner.getTable("user"); | ||
const column = table!.findColumnByName("incrementWithGenerated")!; | ||
const newColumn = column.clone(); | ||
newColumn.isGenerated = false; | ||
newColumn.generationStrategy = undefined; | ||
|
||
await queryRunner.changeColumn(table!, column, newColumn) | ||
|
||
let columnDefault = await getColumnDefault(queryRunner, "incrementWithGenerated") | ||
expect(columnDefault).to.null | ||
|
||
await queryRunner.executeMemoryDownSql(); | ||
|
||
columnDefault = await getColumnDefault(queryRunner, "incrementWithGenerated") | ||
expect(columnDefault).to.equal(`nextval('"user_incrementWithGenerated_seq"'::regclass)`) | ||
|
||
await queryRunner.release() | ||
}))); | ||
|
||
it("should add DEFAULT value when @Generated('uuid') is added", () => Promise.all(connections.map(async connection => { | ||
const queryRunner = connection.createQueryRunner(); | ||
let table = await queryRunner.getTable("user"); | ||
const column = table!.findColumnByName("uuid")!; | ||
const newColumn = column.clone(); | ||
newColumn.isGenerated = true; | ||
newColumn.generationStrategy = "uuid"; | ||
|
||
await queryRunner.changeColumn(table!, column, newColumn) | ||
|
||
let columnDefault = await getColumnDefault(queryRunner, "uuid") | ||
expect(columnDefault).to.equal("uuid_generate_v4()") | ||
|
||
await queryRunner.executeMemoryDownSql(); | ||
|
||
columnDefault = await getColumnDefault(queryRunner, "uuid") | ||
expect(columnDefault).to.null | ||
|
||
await queryRunner.release() | ||
}))); | ||
|
||
it("should remove DEFAULT value when @Generated('uuid') is removed", () => Promise.all(connections.map(async connection => { | ||
const queryRunner = connection.createQueryRunner(); | ||
let table = await queryRunner.getTable("user"); | ||
const column = table!.findColumnByName("uuidWithGenerated")!; | ||
const newColumn = column.clone(); | ||
newColumn.isGenerated = false; | ||
newColumn.generationStrategy = undefined; | ||
|
||
await queryRunner.changeColumn(table!, column, newColumn) | ||
|
||
let columnDefault = await getColumnDefault(queryRunner, "uuidWithGenerated") | ||
expect(columnDefault).to.null | ||
|
||
await queryRunner.executeMemoryDownSql(); | ||
|
||
columnDefault = await getColumnDefault(queryRunner, "uuidWithGenerated") | ||
expect(columnDefault).to.equal("uuid_generate_v4()") | ||
|
||
await queryRunner.release() | ||
}))); | ||
}); |