Skip to content
This repository was archived by the owner on Apr 4, 2023. It is now read-only.

Commit beea2e1

Browse files
authored
fix: @unique constraint is not created with specified name
1 parent 8edc634 commit beea2e1

File tree

3 files changed

+73
-2
lines changed

3 files changed

+73
-2
lines changed

src/driver/sqlite-abstract/AbstractSqliteQueryRunner.ts

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -899,6 +899,17 @@ export abstract class AbstractSqliteQueryRunner extends BaseQueryRunner implemen
899899
});
900900
});
901901

902+
// find unique constraints from CREATE TABLE sql
903+
let uniqueRegexResult;
904+
const uniqueMappings: { name: string, columns: string[] }[] = []
905+
const uniqueRegex = /CONSTRAINT "([^"]*)" UNIQUE \((.*?)\)/g;
906+
while ((uniqueRegexResult = uniqueRegex.exec(sql)) !== null) {
907+
uniqueMappings.push({
908+
name: uniqueRegexResult[1],
909+
columns: uniqueRegexResult[2].substr(1, uniqueRegexResult[2].length - 2).split(`", "`)
910+
});
911+
}
912+
902913
// build unique constraints
903914
const tableUniquePromises = dbIndices
904915
.filter(dbIndex => dbIndex["origin"] === "u")
@@ -919,9 +930,15 @@ export abstract class AbstractSqliteQueryRunner extends BaseQueryRunner implemen
919930
column.isUnique = true;
920931
}
921932

922-
// Sqlite does not store unique constraint name, so we generate its name manually.
933+
// find existent mapping by a column names
934+
const foundMapping = uniqueMappings.find(mapping => {
935+
return mapping!.columns.every(column =>
936+
indexColumns.indexOf(column) !== -1
937+
)
938+
})
939+
923940
return new TableUnique({
924-
name: this.connection.namingStrategy.uniqueConstraintName(table, indexColumns),
941+
name: foundMapping ? foundMapping.name : this.connection.namingStrategy.uniqueConstraintName(table, indexColumns),
925942
columnNames: indexColumns
926943
});
927944
});
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import {Column, Entity, PrimaryGeneratedColumn, Unique} from "../../../../src";
2+
3+
@Entity()
4+
@Unique(["age"])
5+
@Unique("unique-email", ["email"])
6+
@Unique("unique-email-nickname", ["email", "nickname"])
7+
export class User {
8+
@PrimaryGeneratedColumn()
9+
id: number;
10+
11+
@Column()
12+
email: string;
13+
14+
@Column()
15+
nickname: string;
16+
17+
@Column()
18+
age: number;
19+
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import "reflect-metadata";
2+
import {Connection} from "../../../src";
3+
import {createTestingConnections, closeTestingConnections} from "../../utils/test-utils";
4+
import {User} from "./entity/User";
5+
import {expect} from "chai";
6+
import {MysqlDriver} from "../../../src/driver/mysql/MysqlDriver";
7+
8+
describe("github issues > #2376 Naming single column unique constraint with decorator not working as expected", () => {
9+
let connections: Connection[];
10+
before(async () => connections = await createTestingConnections({
11+
schemaCreate: true,
12+
dropSchema: true,
13+
entities: [User],
14+
}));
15+
after(() => closeTestingConnections(connections));
16+
17+
it("should keep user-specified Unique constraint name", () => Promise.all(connections.map(async connection => {
18+
const queryRunner = connection.createQueryRunner();
19+
20+
const table = await queryRunner.getTable("user");
21+
await queryRunner.release()
22+
23+
let unique1 = table!.uniques.find(it => it.name === "unique-email");
24+
let unique2 = table!.uniques.find(it => it.name === "unique-email-nickname");
25+
26+
if (connection.driver instanceof MysqlDriver) {
27+
unique1 = table!.indices.find(it => it.name === "unique-email");
28+
unique2 = table!.indices.find(it => it.name === "unique-email-nickname");
29+
}
30+
31+
expect(unique1).to.be.not.undefined
32+
expect(unique2).to.be.not.undefined
33+
34+
})));
35+
});

0 commit comments

Comments
 (0)