Skip to content

Commit

Permalink
fix: don't escape indexPredicate (#10618)
Browse files Browse the repository at this point in the history
* fix: don't escape indexPredicate

* style: npm run format
  • Loading branch information
alexey-pelykh committed Jan 26, 2024
1 parent 032f535 commit dd49a25
Show file tree
Hide file tree
Showing 7 changed files with 100 additions and 18 deletions.
2 changes: 1 addition & 1 deletion src/driver/sqlite/SqliteQueryRunner.ts
Expand Up @@ -88,7 +88,7 @@ export class SqliteQueryRunner extends AbstractSqliteQueryRunner {
}
}

const self = this;
const self = this
const handler = function (this: any, err: any, rows: any) {
if (err && err.toString().indexOf("SQLITE_BUSY:") !== -1) {
if (
Expand Down
4 changes: 1 addition & 3 deletions src/query-builder/InsertQueryBuilder.ts
Expand Up @@ -519,9 +519,7 @@ export class InsertQueryBuilder<
indexPredicate &&
DriverUtils.isPostgresFamily(this.connection.driver)
) {
conflictTarget += ` WHERE ( ${this.escape(
indexPredicate,
)} )`
conflictTarget += ` WHERE ( ${indexPredicate} )`
}
} else if (conflict) {
conflictTarget += ` ON CONSTRAINT ${this.escape(
Expand Down
Expand Up @@ -136,7 +136,9 @@ describe("repository > find options > locking", () => {
const originalQuery = entityManager.queryRunner!.query.bind(
entityManager.queryRunner,
)
entityManager.queryRunner!.query = (...args: Parameters<QueryRunner['query']>) => {
entityManager.queryRunner!.query = (
...args: Parameters<QueryRunner["query"]>
) => {
executedSql.push(args[0])
return originalQuery(...args)
}
Expand Down Expand Up @@ -176,7 +178,9 @@ describe("repository > find options > locking", () => {
const originalQuery = entityManager.queryRunner!.query.bind(
entityManager.queryRunner,
)
entityManager.queryRunner!.query = (...args: Parameters<QueryRunner['query']>) => {
entityManager.queryRunner!.query = (
...args: Parameters<QueryRunner["query"]>
) => {
executedSql.push(args[0])
return originalQuery(...args)
}
Expand Down Expand Up @@ -205,7 +209,9 @@ describe("repository > find options > locking", () => {
const originalQuery = entityManager.queryRunner!.query.bind(
entityManager.queryRunner,
)
entityManager.queryRunner!.query = (...args: Parameters<QueryRunner['query']>) => {
entityManager.queryRunner!.query = (
...args: Parameters<QueryRunner["query"]>
) => {
executedSql.push(args[0])
return originalQuery(...args)
}
Expand Down Expand Up @@ -244,7 +250,9 @@ describe("repository > find options > locking", () => {
const originalQuery = entityManager.queryRunner!.query.bind(
entityManager.queryRunner,
)
entityManager.queryRunner!.query = (...args: Parameters<QueryRunner['query']>) => {
entityManager.queryRunner!.query = (
...args: Parameters<QueryRunner["query"]>
) => {
executedSql.push(args[0])
return originalQuery(...args)
}
Expand Down Expand Up @@ -286,7 +294,9 @@ describe("repository > find options > locking", () => {
const originalQuery = entityManager.queryRunner!.query.bind(
entityManager.queryRunner,
)
entityManager.queryRunner!.query = (...args: Parameters<QueryRunner['query']>) => {
entityManager.queryRunner!.query = (
...args: Parameters<QueryRunner["query"]>
) => {
executedSql.push(args[0])
return originalQuery(...args)
}
Expand Down Expand Up @@ -323,7 +333,9 @@ describe("repository > find options > locking", () => {
const originalQuery = entityManager.queryRunner!.query.bind(
entityManager.queryRunner,
)
entityManager.queryRunner!.query = (...args: Parameters<QueryRunner['query']>) => {
entityManager.queryRunner!.query = (
...args: Parameters<QueryRunner["query"]>
) => {
executedSql.push(args[0])
return originalQuery(...args)
}
Expand Down Expand Up @@ -361,7 +373,9 @@ describe("repository > find options > locking", () => {
const originalQuery = entityManager.queryRunner!.query.bind(
entityManager.queryRunner,
)
entityManager.queryRunner!.query = (...args: Parameters<QueryRunner['query']>) => {
entityManager.queryRunner!.query = (
...args: Parameters<QueryRunner["query"]>
) => {
executedSql.push(args[0])
return originalQuery(...args)
}
Expand Down
20 changes: 20 additions & 0 deletions test/github-issues/10191/entity/Example.ts
@@ -0,0 +1,20 @@
import { Column, Entity, Index, PrimaryGeneratedColumn } from "../../../../src"

@Entity()
@Index(["nonNullable", "nullable"], {
unique: true,
where: '"nullable" IS NOT NULL',
})
export class Example {
@PrimaryGeneratedColumn("uuid")
id?: string

@Column({ type: "text" })
nonNullable: string

@Column({ type: "text", nullable: true })
nullable: string | null

@Column({ type: "text" })
value: string
}
44 changes: 44 additions & 0 deletions test/github-issues/10191/index-10191.ts
@@ -0,0 +1,44 @@
import "reflect-metadata"
import { DataSource } from "../../../src"
import {
closeTestingConnections,
createTestingConnections,
reloadTestingDatabases,
} from "../../utils/test-utils"
import { Example } from "./entity/Example"

describe("github issues > #10191 incorrect escaping of indexPredicate", () => {
let connections: DataSource[]

before(
async () =>
(connections = await createTestingConnections({
entities: [Example],
enabledDrivers: ["postgres"],
})),
)
beforeEach(() => reloadTestingDatabases(connections))
after(() => closeTestingConnections(connections))

it("should not fail", () =>
Promise.all(
connections.map(async (connection) => {
await connection.manager.upsert(
Example,
{
nonNullable: "nonNullable",
nullable: "nullable",
value: "value",
},
{
conflictPaths: {
nonNullable: true,
nullable: true,
},
skipUpdateIfNoValuesChanged: true,
indexPredicate: '"nullable" IS NOT NULL',
},
)
}),
))
})
16 changes: 10 additions & 6 deletions test/github-issues/9988/issue-9988.ts
Expand Up @@ -39,11 +39,12 @@ describe("github issues > #9988 RelationIdLoader reuses the same queryplanner wi
const productTwoId = 2
await categoryRepo.save(categoryOne)
await categoryRepo.save(categoryTwo)
const options = (id: number) => ({
relationLoadStrategy: "query",
where: { id },
relations: { categories: true },
} as FindManyOptions<Product>)
const options = (id: number) =>
({
relationLoadStrategy: "query",
where: { id },
relations: { categories: true },
} as FindManyOptions<Product>)

// Create a custom repository that uses a query builder without query planner
// For both methods, relationLoadStrategy is set to "query", where the bug lies.
Expand Down Expand Up @@ -84,7 +85,10 @@ describe("github issues > #9988 RelationIdLoader reuses the same queryplanner wi
txnManager.withRepository(productRepo)
const product = customProductRepo.create({
id: productTwoId,
categories: [{ id: categoryOne.id }, { id: categoryTwo.id }],
categories: [
{ id: categoryOne.id },
{ id: categoryTwo.id },
],
})

await customProductRepo.save(product)
Expand Down
4 changes: 3 additions & 1 deletion test/utils/xfail.ts
Expand Up @@ -21,7 +21,9 @@ const wrap = (

return new Promise<void>((ok, fail) => {
if (fn.length > 1) {
(fn as Func).call(context as unknown as Context, (err: any) => (err ? fail(err) : ok()))
;(fn as Func).call(context as unknown as Context, (err: any) =>
err ? fail(err) : ok(),
)
} else {
ok((fn as AsyncFunc).call(context as unknown as Context))
}
Expand Down

0 comments on commit dd49a25

Please sign in to comment.