fix: multiple assignments to same column on UPDATE #2651 (#5598) · typeorm/typeorm@334e17e

3 files changed

lines changed

Original file line numberDiff line numberDiff line change

@@ -1,5 +1,6 @@

11

import {CockroachDriver} from "../driver/cockroachdb/CockroachDriver";

22

import {SapDriver} from "../driver/sap/SapDriver";

3+

import { ColumnMetadata } from "../metadata/ColumnMetadata";

34

import {QueryBuilder} from "./QueryBuilder";

45

import {ObjectLiteral} from "../common/ObjectLiteral";

56

import {Connection} from "../connection/Connection";

@@ -381,6 +382,7 @@ export class UpdateQueryBuilder<Entity> extends QueryBuilder<Entity> implements

381382
382383

// prepare columns and values to be updated

383384

const updateColumnAndValues: string[] = [];

385+

const updatedColumns: ColumnMetadata[] = [];

384386

const newParameters: ObjectLiteral = {};

385387

let parametersCount = this.connection.driver instanceof MysqlDriver ||

386388

this.connection.driver instanceof AuroraDataApiDriver ||

@@ -399,6 +401,7 @@ export class UpdateQueryBuilder<Entity> extends QueryBuilder<Entity> implements

399401
400402

columns.forEach(column => {

401403

if (!column.isUpdate) { return; }

404+

updatedColumns.push(column);

402405
403406

const paramName = "upd_" + column.databaseName;

404407

@@ -458,9 +461,9 @@ export class UpdateQueryBuilder<Entity> extends QueryBuilder<Entity> implements

458461

});

459462

});

460463
461-

if (metadata.versionColumn)

464+

if (metadata.versionColumn && updatedColumns.indexOf(metadata.versionColumn) === -1)

462465

updateColumnAndValues.push(this.escape(metadata.versionColumn.databaseName) + " = " + this.escape(metadata.versionColumn.databaseName) + " + 1");

463-

if (metadata.updateDateColumn)

466+

if (metadata.updateDateColumn && updatedColumns.indexOf(metadata.updateDateColumn) === -1)

464467

updateColumnAndValues.push(this.escape(metadata.updateDateColumn.databaseName) + " = CURRENT_TIMESTAMP"); // todo: fix issue with CURRENT_TIMESTAMP(6) being used, can "DEFAULT" be used?!

465468
466469

} else {

Original file line numberDiff line numberDiff line change

@@ -0,0 +1,17 @@

1+

import { UpdateDateColumn } from "../../../../src";

2+

import {Entity} from "../../../../src/decorator/entity/Entity";

3+

import {PrimaryGeneratedColumn} from "../../../../src/decorator/columns/PrimaryGeneratedColumn";

4+

import {Column} from "../../../../src/decorator/columns/Column";

5+
6+

@Entity()

7+

export class Post {

8+

@PrimaryGeneratedColumn()

9+

id: number;

10+
11+

@Column()

12+

title: string;

13+
14+

@UpdateDateColumn({ type: "timestamptz" })

15+

updatedAt: Date;

16+
17+

}

Original file line numberDiff line numberDiff line change

@@ -0,0 +1,36 @@

1+

import "reflect-metadata";

2+

import { expect } from "chai";

3+

import {createTestingConnections, closeTestingConnections, reloadTestingDatabases} from "../../utils/test-utils";

4+

import {Connection} from "../../../src/connection/Connection";

5+

import {Post} from "./entity/Post";

6+
7+

describe.only("github issues > #2651 set shouldn't have update statements twice when UpdateDate is in use", () => {

8+
9+

let connections: Connection[];

10+

before(async () => connections = await createTestingConnections({

11+

entities: [__dirname + "/entity/*{.js,.ts}"],

12+

enabledDrivers: ["postgres"]

13+

}));

14+

beforeEach(() => reloadTestingDatabases(connections));

15+

after(() => closeTestingConnections(connections));

16+
17+

it.only("should add and remove relations of an entity if given a mix of ids and objects", () => Promise.all(connections.map(async connection => {

18+
19+

const post1 = new Post();

20+

post1.title = "post #1";

21+

await connection.manager.save(post1);

22+
23+

// within this issue update was failing

24+

await connection.manager.update(Post, {

25+

id: 1

26+

}, {

27+

title: "updated post",

28+

updatedAt: new Date()

29+

});

30+
31+

const loadedPost1 = await connection.manager.findOneOrFail(Post, { id: 1 });

32+

expect(loadedPost1.title).to.be.eql("updated post");

33+
34+

})));

35+
36+

});