From 334e17e73015136a7f980841175ec29a78f63ff9 Mon Sep 17 00:00:00 2001 From: Umed Khudoiberdiev Date: Tue, 3 Mar 2020 00:02:50 +0500 Subject: [PATCH] fix: multiple assignments to same column on UPDATE #2651 (#5598) --- src/query-builder/UpdateQueryBuilder.ts | 7 +++-- test/github-issues/2651/entity/Post.ts | 17 ++++++++++++ test/github-issues/2651/issue-2651.ts | 36 +++++++++++++++++++++++++ 3 files changed, 58 insertions(+), 2 deletions(-) create mode 100644 test/github-issues/2651/entity/Post.ts create mode 100644 test/github-issues/2651/issue-2651.ts diff --git a/src/query-builder/UpdateQueryBuilder.ts b/src/query-builder/UpdateQueryBuilder.ts index fb7b0a3e0e..1bf6c68b6d 100644 --- a/src/query-builder/UpdateQueryBuilder.ts +++ b/src/query-builder/UpdateQueryBuilder.ts @@ -1,5 +1,6 @@ import {CockroachDriver} from "../driver/cockroachdb/CockroachDriver"; import {SapDriver} from "../driver/sap/SapDriver"; +import { ColumnMetadata } from "../metadata/ColumnMetadata"; import {QueryBuilder} from "./QueryBuilder"; import {ObjectLiteral} from "../common/ObjectLiteral"; import {Connection} from "../connection/Connection"; @@ -381,6 +382,7 @@ export class UpdateQueryBuilder extends QueryBuilder implements // prepare columns and values to be updated const updateColumnAndValues: string[] = []; + const updatedColumns: ColumnMetadata[] = []; const newParameters: ObjectLiteral = {}; let parametersCount = this.connection.driver instanceof MysqlDriver || this.connection.driver instanceof AuroraDataApiDriver || @@ -399,6 +401,7 @@ export class UpdateQueryBuilder extends QueryBuilder implements columns.forEach(column => { if (!column.isUpdate) { return; } + updatedColumns.push(column); const paramName = "upd_" + column.databaseName; @@ -458,9 +461,9 @@ export class UpdateQueryBuilder extends QueryBuilder implements }); }); - if (metadata.versionColumn) + if (metadata.versionColumn && updatedColumns.indexOf(metadata.versionColumn) === -1) updateColumnAndValues.push(this.escape(metadata.versionColumn.databaseName) + " = " + this.escape(metadata.versionColumn.databaseName) + " + 1"); - if (metadata.updateDateColumn) + if (metadata.updateDateColumn && updatedColumns.indexOf(metadata.updateDateColumn) === -1) updateColumnAndValues.push(this.escape(metadata.updateDateColumn.databaseName) + " = CURRENT_TIMESTAMP"); // todo: fix issue with CURRENT_TIMESTAMP(6) being used, can "DEFAULT" be used?! } else { diff --git a/test/github-issues/2651/entity/Post.ts b/test/github-issues/2651/entity/Post.ts new file mode 100644 index 0000000000..42d58aaafa --- /dev/null +++ b/test/github-issues/2651/entity/Post.ts @@ -0,0 +1,17 @@ +import { UpdateDateColumn } from "../../../../src"; +import {Entity} from "../../../../src/decorator/entity/Entity"; +import {PrimaryGeneratedColumn} from "../../../../src/decorator/columns/PrimaryGeneratedColumn"; +import {Column} from "../../../../src/decorator/columns/Column"; + +@Entity() +export class Post { + @PrimaryGeneratedColumn() + id: number; + + @Column() + title: string; + + @UpdateDateColumn({ type: "timestamptz" }) + updatedAt: Date; + +} diff --git a/test/github-issues/2651/issue-2651.ts b/test/github-issues/2651/issue-2651.ts new file mode 100644 index 0000000000..7f1fa281af --- /dev/null +++ b/test/github-issues/2651/issue-2651.ts @@ -0,0 +1,36 @@ +import "reflect-metadata"; +import { expect } from "chai"; +import {createTestingConnections, closeTestingConnections, reloadTestingDatabases} from "../../utils/test-utils"; +import {Connection} from "../../../src/connection/Connection"; +import {Post} from "./entity/Post"; + +describe.only("github issues > #2651 set shouldn't have update statements twice when UpdateDate is in use", () => { + + let connections: Connection[]; + before(async () => connections = await createTestingConnections({ + entities: [__dirname + "/entity/*{.js,.ts}"], + enabledDrivers: ["postgres"] + })); + beforeEach(() => reloadTestingDatabases(connections)); + after(() => closeTestingConnections(connections)); + + it.only("should add and remove relations of an entity if given a mix of ids and objects", () => Promise.all(connections.map(async connection => { + + const post1 = new Post(); + post1.title = "post #1"; + await connection.manager.save(post1); + + // within this issue update was failing + await connection.manager.update(Post, { + id: 1 + }, { + title: "updated post", + updatedAt: new Date() + }); + + const loadedPost1 = await connection.manager.findOneOrFail(Post, { id: 1 }); + expect(loadedPost1.title).to.be.eql("updated post"); + + }))); + +});