mirror of
https://github.com/typeorm/typeorm.git
synced 2025-12-08 21:26:23 +00:00
fix(postgres): resolve alias or table name in upsert/insert or update conditionally (#11452)
* fix: resolve regression in upsert and orUpdate for PostgreSQL driver This fix addresses a regression introduced in pull request #11082 by ensuring correct handling of alias names and table names when they are equal or distinct when entities use schema Closes: #11440 * style: code formatted * chore: run tests by running through all the drivers * chore: set enabledDrivers as postgres * chore: added postgres family members as enabled drivers * chore: accepted suggestion to remove extra comments Co-authored-by: Mike Guida <mike@mguida.com> --------- Co-authored-by: Mike Guida <mike@mguida.com>
This commit is contained in:
parent
5003aaa7c5
commit
2bfa300996
@ -406,6 +406,10 @@ export class InsertQueryBuilder<
|
||||
*/
|
||||
protected createInsertExpression() {
|
||||
const tableName = this.getTableName(this.getMainTableName())
|
||||
const tableOrAliasName =
|
||||
this.alias !== this.getMainTableName()
|
||||
? this.escape(this.alias)
|
||||
: tableName
|
||||
const valuesExpression = this.createValuesExpression() // its important to get values before returning expression because oracle rely on native parameters and ordering of them is important
|
||||
const returningExpression =
|
||||
this.connection.driver.options.type === "oracle" &&
|
||||
@ -590,7 +594,7 @@ export class InsertQueryBuilder<
|
||||
query += overwrite
|
||||
.map(
|
||||
(column) =>
|
||||
`${this.escape(this.alias)}.${this.escape(
|
||||
`${tableOrAliasName}.${this.escape(
|
||||
column,
|
||||
)} IS DISTINCT FROM EXCLUDED.${this.escape(
|
||||
column,
|
||||
|
||||
13
test/github-issues/11440/entity/Post.ts
Normal file
13
test/github-issues/11440/entity/Post.ts
Normal file
@ -0,0 +1,13 @@
|
||||
import { Column, Entity } from "../../../../src"
|
||||
|
||||
@Entity({
|
||||
schema: "typeorm_test",
|
||||
name: "post",
|
||||
})
|
||||
export class Post {
|
||||
@Column({ primary: true })
|
||||
id: number
|
||||
|
||||
@Column({ nullable: true })
|
||||
title: string
|
||||
}
|
||||
110
test/github-issues/11440/issue-11440.ts
Normal file
110
test/github-issues/11440/issue-11440.ts
Normal file
@ -0,0 +1,110 @@
|
||||
import { expect } from "chai"
|
||||
import "reflect-metadata"
|
||||
|
||||
import { DataSource } from "../../../src"
|
||||
import {
|
||||
closeTestingConnections,
|
||||
createTestingConnections,
|
||||
reloadTestingDatabases,
|
||||
} from "../../utils/test-utils"
|
||||
import { Post } from "./entity/Post"
|
||||
|
||||
describe("github issues > #11440", () => {
|
||||
let dataSources: DataSource[]
|
||||
|
||||
before(async () => {
|
||||
dataSources = await createTestingConnections({
|
||||
entities: [Post],
|
||||
enabledDrivers: ["postgres", "aurora-postgres", "cockroachdb"],
|
||||
})
|
||||
})
|
||||
beforeEach(() => reloadTestingDatabases(dataSources))
|
||||
after(() => closeTestingConnections(dataSources))
|
||||
|
||||
it("should use table or alias name during upsert or doUpdate when both schema name and skipUpdateIfNoValuesChanged supplied", async () => {
|
||||
Promise.all(
|
||||
dataSources.map(async (dataSource) => {
|
||||
const repository = dataSource.getRepository(Post)
|
||||
await repository.save([
|
||||
{
|
||||
id: 1,
|
||||
title: "First Post",
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
title: "Second Post",
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
title: "Third Post",
|
||||
},
|
||||
])
|
||||
|
||||
// upsert does not cast alias as class name
|
||||
await repository.upsert(
|
||||
[
|
||||
{
|
||||
id: 1,
|
||||
title: "First Post",
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
title: "Second Post UPSERTED",
|
||||
},
|
||||
],
|
||||
{
|
||||
conflictPaths: ["id"],
|
||||
upsertType: "on-conflict-do-update",
|
||||
skipUpdateIfNoValuesChanged: true,
|
||||
},
|
||||
)
|
||||
|
||||
const query = repository
|
||||
.createQueryBuilder()
|
||||
.insert()
|
||||
.values([
|
||||
{
|
||||
id: 1,
|
||||
title: "First Post",
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
title: "Third Post OR_UPDATED",
|
||||
},
|
||||
])
|
||||
.orUpdate(["title"], ["id"], {
|
||||
skipUpdateIfNoValuesChanged: true,
|
||||
})
|
||||
|
||||
// orUpdate cast alias as class name
|
||||
expect(query.getSql()).to.equal(
|
||||
`INSERT INTO "typeorm_test"."post" AS "Post"("id", "title") ` +
|
||||
`VALUES ($1, $2), ($3, $4) ` +
|
||||
`ON CONFLICT ( "id" ) DO UPDATE ` +
|
||||
`SET "title" = EXCLUDED."title" ` +
|
||||
`WHERE ("Post"."title" IS DISTINCT FROM EXCLUDED."title")`,
|
||||
)
|
||||
await query.execute()
|
||||
|
||||
const posts = await repository.find({
|
||||
order: { id: "ASC" },
|
||||
})
|
||||
|
||||
expect(posts).to.deep.equal([
|
||||
{
|
||||
id: 1,
|
||||
title: "First Post",
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
title: "Second Post UPSERTED",
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
title: "Third Post OR_UPDATED",
|
||||
},
|
||||
])
|
||||
}),
|
||||
)
|
||||
})
|
||||
})
|
||||
Loading…
x
Reference in New Issue
Block a user