From f435d991eb4a1ee32a3823e763ab0b47366d55b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Emilio=20Velasco=20S=C3=A1nchez?= Date: Tue, 7 May 2019 14:01:25 +0200 Subject: [PATCH 1/3] Support orUpdate for SQLite --- CHANGELOG.md | 1 + src/query-builder/InsertQueryBuilder.ts | 2 +- test/github-issues/4096/entity/User.ts | 13 ++++++ test/github-issues/4096/issue-4096.ts | 61 +++++++++++++++++++++++++ 4 files changed, 76 insertions(+), 1 deletion(-) create mode 100644 test/github-issues/4096/entity/User.ts create mode 100644 test/github-issues/4096/issue-4096.ts diff --git a/CHANGELOG.md b/CHANGELOG.md index 94bfdcdbdc..297efb2e50 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ feel free to ask us and community. ### Features * deprecate column `readonly` option in favor of `update` and `insert` options ([#4035](https://github.com/typeorm/typeorm/pull/4035)) +* added support for `orUpdate` in SQLlite ([#4097](https://github.com/typeorm/typeorm/pull/4097)) ## 0.2.17 (2019-05-01) diff --git a/src/query-builder/InsertQueryBuilder.ts b/src/query-builder/InsertQueryBuilder.ts index 6bac7091d9..a720c14621 100644 --- a/src/query-builder/InsertQueryBuilder.ts +++ b/src/query-builder/InsertQueryBuilder.ts @@ -249,7 +249,7 @@ export class InsertQueryBuilder extends QueryBuilder { if (statement && statement.overwrite instanceof Array) { if (this.connection.driver instanceof MysqlDriver) { this.expressionMap.onUpdate.overwrite = statement.overwrite.map(column => `${column} = VALUES(${column})`).join(", "); - } else if (this.connection.driver instanceof PostgresDriver) { + } else if (this.connection.driver instanceof PostgresDriver || this.connection.driver instanceof AbstractSqliteDriver) { this.expressionMap.onUpdate.overwrite = statement.overwrite.map(column => `${column} = EXCLUDED.${column}`).join(", "); } } diff --git a/test/github-issues/4096/entity/User.ts b/test/github-issues/4096/entity/User.ts new file mode 100644 index 0000000000..3dbb3bb1c3 --- /dev/null +++ b/test/github-issues/4096/entity/User.ts @@ -0,0 +1,13 @@ +import { Entity, PrimaryColumn, Column } from "../../../../src"; + +@Entity() +export class User { + @PrimaryColumn() + email: string; + + @PrimaryColumn() + username: string; + + @Column() + bio: string; +} diff --git a/test/github-issues/4096/issue-4096.ts b/test/github-issues/4096/issue-4096.ts new file mode 100644 index 0000000000..c84e029b9a --- /dev/null +++ b/test/github-issues/4096/issue-4096.ts @@ -0,0 +1,61 @@ +import "reflect-metadata"; +import {createTestingConnections, closeTestingConnections, reloadTestingDatabases} from "../../utils/test-utils"; +import {Connection} from "../../../src/connection/Connection"; +import {expect} from "chai"; +import {User} from "./entity/User"; + +describe("github issues > #4096 SQLite support for orUpdate", () => { + let connections: Connection[]; + + before(async () => connections = await createTestingConnections({ + entities: [User], + enabledDrivers: ["sqlite"], + schemaCreate: true, + dropSchema: true, + })); + + beforeEach(() => reloadTestingDatabases(connections)); + + after(() => closeTestingConnections(connections)); + + const user1 = new User(); + user1.email = "example@example.org"; + user1.username = "example"; + user1.bio = "My bio"; + + const user2 = new User(); + user2.email = "example@example.org"; + user2.username = "example"; + user2.bio = "Updated bio"; + + it("should overwrite using current value in SQLite", () => Promise.all(connections.map(async connection => { + try { + const UserRepository = connection.manager.getRepository(User); + + await UserRepository + .createQueryBuilder() + .insert() + .into(User) + .values(user1) + .execute(); + + await UserRepository + .createQueryBuilder() + .insert() + .into(User) + .values(user2) + .orUpdate({ + conflict_target: [ "email", "username" ], + overwrite: ["bio"], + }) + .execute(); + + const users = await UserRepository.find(); + expect(users).not.to.be.undefined; + expect(users).to.have.lengthOf(1); + expect(users[0]).to.includes({ bio: "Updated bio" }); + } catch (err) { + throw new Error(err); + } + }))); + }); From 565e1cf50d9a369553f9f1098d2258765e6fa337 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Emilio=20Velasco=20S=C3=A1nchez?= Date: Tue, 7 May 2019 16:46:56 +0200 Subject: [PATCH 2/3] Move user creation within it block --- test/github-issues/4096/issue-4096.ts | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/test/github-issues/4096/issue-4096.ts b/test/github-issues/4096/issue-4096.ts index c84e029b9a..b81263a07e 100644 --- a/test/github-issues/4096/issue-4096.ts +++ b/test/github-issues/4096/issue-4096.ts @@ -18,18 +18,18 @@ describe("github issues > #4096 SQLite support for orUpdate", () => { after(() => closeTestingConnections(connections)); - const user1 = new User(); - user1.email = "example@example.org"; - user1.username = "example"; - user1.bio = "My bio"; - - const user2 = new User(); - user2.email = "example@example.org"; - user2.username = "example"; - user2.bio = "Updated bio"; - it("should overwrite using current value in SQLite", () => Promise.all(connections.map(async connection => { try { + const user1 = new User(); + user1.email = "example@example.org"; + user1.username = "example"; + user1.bio = "My bio"; + + const user2 = new User(); + user2.email = "example@example.org"; + user2.username = "example"; + user2.bio = "Updated bio"; + const UserRepository = connection.manager.getRepository(User); await UserRepository From 18e2292ce6d9820e83d6f10dd4a7885ac4adc9b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Emilio=20Velasco=20S=C3=A1nchez?= Date: Tue, 7 May 2019 16:50:27 +0200 Subject: [PATCH 3/3] Remove try and catch within test --- test/github-issues/4096/issue-4096.ts | 72 +++++++++++++-------------- 1 file changed, 34 insertions(+), 38 deletions(-) diff --git a/test/github-issues/4096/issue-4096.ts b/test/github-issues/4096/issue-4096.ts index b81263a07e..3685d0d17a 100644 --- a/test/github-issues/4096/issue-4096.ts +++ b/test/github-issues/4096/issue-4096.ts @@ -19,43 +19,39 @@ describe("github issues > #4096 SQLite support for orUpdate", () => { after(() => closeTestingConnections(connections)); it("should overwrite using current value in SQLite", () => Promise.all(connections.map(async connection => { - try { - const user1 = new User(); - user1.email = "example@example.org"; - user1.username = "example"; - user1.bio = "My bio"; - - const user2 = new User(); - user2.email = "example@example.org"; - user2.username = "example"; - user2.bio = "Updated bio"; - - const UserRepository = connection.manager.getRepository(User); - - await UserRepository - .createQueryBuilder() - .insert() - .into(User) - .values(user1) - .execute(); - - await UserRepository - .createQueryBuilder() - .insert() - .into(User) - .values(user2) - .orUpdate({ - conflict_target: [ "email", "username" ], - overwrite: ["bio"], - }) - .execute(); - - const users = await UserRepository.find(); - expect(users).not.to.be.undefined; - expect(users).to.have.lengthOf(1); - expect(users[0]).to.includes({ bio: "Updated bio" }); - } catch (err) { - throw new Error(err); - } + const user1 = new User(); + user1.email = "example@example.org"; + user1.username = "example"; + user1.bio = "My bio"; + + const user2 = new User(); + user2.email = "example@example.org"; + user2.username = "example"; + user2.bio = "Updated bio"; + + const UserRepository = connection.manager.getRepository(User); + + await UserRepository + .createQueryBuilder() + .insert() + .into(User) + .values(user1) + .execute(); + + await UserRepository + .createQueryBuilder() + .insert() + .into(User) + .values(user2) + .orUpdate({ + conflict_target: [ "email", "username" ], + overwrite: ["bio"], + }) + .execute(); + + const users = await UserRepository.find(); + expect(users).not.to.be.undefined; + expect(users).to.have.lengthOf(1); + expect(users[0]).to.includes({ bio: "Updated bio" }); }))); });