Skip to content

Commit

Permalink
fix: enable explicitly inserting IDENTITY values into mssql
Browse files Browse the repository at this point in the history
Allow explicit insertion of preset values for mssql IDENTITY columns. These are the equivalent to
auto-incrementing primary keys in MySQL, but require special conditional treatment.

Closes: typeorm#2199 for mssql
  • Loading branch information
Daniel Klischies authored and Daniel Klischies committed Jun 4, 2020
1 parent a595fed commit a14b9d9
Show file tree
Hide file tree
Showing 2 changed files with 17 additions and 3 deletions.
16 changes: 15 additions & 1 deletion src/query-builder/InsertQueryBuilder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -335,6 +335,19 @@ export class InsertQueryBuilder<Entity> extends QueryBuilder<Entity> {
query += ` RETURNING ${returningExpression}`;
}


// Inserting a specific value for an auto-increment primary key in mssql requires enabling IDENTITY_INSERT
// IDENTITY_INSERT can only be enabled for tables where there is an IDENTITY column and only if there is a value to be inserted (i.e. supplying DEFAULT is prohibited if IDENTITY_INSERT is enabled)
if (this.connection.driver instanceof SqlServerDriver
&& this.expressionMap.mainAlias!.hasMetadata
&& this.expressionMap.mainAlias!.metadata.columns
.filter((column) => this.expressionMap.insertColumns.length > 0 ? this.expressionMap.insertColumns.indexOf(column.propertyPath) !== -1 : column.isInsert)
.some((column) => column.isPrimary && column.isGenerated && column.generationStrategy === "increment"
&& this.getValueSets().some((valueSet) => column.getEntityValue(valueSet) !== undefined && column.getEntityValue(valueSet) !== null))
) {
query = `SET IDENTITY_INSERT ${tableName} ON; ${query}; SET IDENTITY_INSERT ${tableName} OFF`;
}

return query;
}

Expand All @@ -360,7 +373,8 @@ export class InsertQueryBuilder<Entity> extends QueryBuilder<Entity> {
&& !(this.connection.driver instanceof OracleDriver)
&& !(this.connection.driver instanceof AbstractSqliteDriver)
&& !(this.connection.driver instanceof MysqlDriver)
&& !(this.connection.driver instanceof AuroraDataApiDriver))
&& !(this.connection.driver instanceof AuroraDataApiDriver)
&& !(this.connection.driver instanceof SqlServerDriver && this.getValueSets().some((valueSet) => column.getEntityValue(valueSet) !== undefined && column.getEntityValue(valueSet) !== null)))
return false;

return true;
Expand Down
4 changes: 2 additions & 2 deletions test/github-issues/2199/issue-2199.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@ import { Connection } from "../../../src/connection/Connection";
import { closeTestingConnections, createTestingConnections, reloadTestingDatabases } from "../../utils/test-utils";
import { Bar } from "./entity/Bar";

describe("github issues > #2199 - Inserting value for @PrimaryGeneratedColumn() for mysql and sqlite", () => {
describe("github issues > #2199 - Inserting value for @PrimaryGeneratedColumn() for mysql, sqlite and mssql", () => {

let connections: Connection[];
before(async () => connections = await createTestingConnections({
entities: [__dirname + "/entity/*{.js,.ts}"],
enabledDrivers: ["mysql", "mariadb", "sqlite"],
enabledDrivers: ["mysql", "mariadb", "sqlite", "mssql"],
schemaCreate: true,
dropSchema: true
}));
Expand Down

0 comments on commit a14b9d9

Please sign in to comment.