Skip to content

Commit dd49a25

Browse files
fix: don't escape indexPredicate (#10618)
* fix: don't escape indexPredicate * style: npm run format
1 parent 032f535 commit dd49a25

File tree

7 files changed

+100
-18
lines changed

7 files changed

+100
-18
lines changed

src/driver/sqlite/SqliteQueryRunner.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ export class SqliteQueryRunner extends AbstractSqliteQueryRunner {
8888
}
8989
}
9090

91-
const self = this;
91+
const self = this
9292
const handler = function (this: any, err: any, rows: any) {
9393
if (err && err.toString().indexOf("SQLITE_BUSY:") !== -1) {
9494
if (

src/query-builder/InsertQueryBuilder.ts

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -519,9 +519,7 @@ export class InsertQueryBuilder<
519519
indexPredicate &&
520520
DriverUtils.isPostgresFamily(this.connection.driver)
521521
) {
522-
conflictTarget += ` WHERE ( ${this.escape(
523-
indexPredicate,
524-
)} )`
522+
conflictTarget += ` WHERE ( ${indexPredicate} )`
525523
}
526524
} else if (conflict) {
527525
conflictTarget += ` ON CONSTRAINT ${this.escape(

test/functional/repository/find-options-locking/find-options-locking.ts

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,9 @@ describe("repository > find options > locking", () => {
136136
const originalQuery = entityManager.queryRunner!.query.bind(
137137
entityManager.queryRunner,
138138
)
139-
entityManager.queryRunner!.query = (...args: Parameters<QueryRunner['query']>) => {
139+
entityManager.queryRunner!.query = (
140+
...args: Parameters<QueryRunner["query"]>
141+
) => {
140142
executedSql.push(args[0])
141143
return originalQuery(...args)
142144
}
@@ -176,7 +178,9 @@ describe("repository > find options > locking", () => {
176178
const originalQuery = entityManager.queryRunner!.query.bind(
177179
entityManager.queryRunner,
178180
)
179-
entityManager.queryRunner!.query = (...args: Parameters<QueryRunner['query']>) => {
181+
entityManager.queryRunner!.query = (
182+
...args: Parameters<QueryRunner["query"]>
183+
) => {
180184
executedSql.push(args[0])
181185
return originalQuery(...args)
182186
}
@@ -205,7 +209,9 @@ describe("repository > find options > locking", () => {
205209
const originalQuery = entityManager.queryRunner!.query.bind(
206210
entityManager.queryRunner,
207211
)
208-
entityManager.queryRunner!.query = (...args: Parameters<QueryRunner['query']>) => {
212+
entityManager.queryRunner!.query = (
213+
...args: Parameters<QueryRunner["query"]>
214+
) => {
209215
executedSql.push(args[0])
210216
return originalQuery(...args)
211217
}
@@ -244,7 +250,9 @@ describe("repository > find options > locking", () => {
244250
const originalQuery = entityManager.queryRunner!.query.bind(
245251
entityManager.queryRunner,
246252
)
247-
entityManager.queryRunner!.query = (...args: Parameters<QueryRunner['query']>) => {
253+
entityManager.queryRunner!.query = (
254+
...args: Parameters<QueryRunner["query"]>
255+
) => {
248256
executedSql.push(args[0])
249257
return originalQuery(...args)
250258
}
@@ -286,7 +294,9 @@ describe("repository > find options > locking", () => {
286294
const originalQuery = entityManager.queryRunner!.query.bind(
287295
entityManager.queryRunner,
288296
)
289-
entityManager.queryRunner!.query = (...args: Parameters<QueryRunner['query']>) => {
297+
entityManager.queryRunner!.query = (
298+
...args: Parameters<QueryRunner["query"]>
299+
) => {
290300
executedSql.push(args[0])
291301
return originalQuery(...args)
292302
}
@@ -323,7 +333,9 @@ describe("repository > find options > locking", () => {
323333
const originalQuery = entityManager.queryRunner!.query.bind(
324334
entityManager.queryRunner,
325335
)
326-
entityManager.queryRunner!.query = (...args: Parameters<QueryRunner['query']>) => {
336+
entityManager.queryRunner!.query = (
337+
...args: Parameters<QueryRunner["query"]>
338+
) => {
327339
executedSql.push(args[0])
328340
return originalQuery(...args)
329341
}
@@ -361,7 +373,9 @@ describe("repository > find options > locking", () => {
361373
const originalQuery = entityManager.queryRunner!.query.bind(
362374
entityManager.queryRunner,
363375
)
364-
entityManager.queryRunner!.query = (...args: Parameters<QueryRunner['query']>) => {
376+
entityManager.queryRunner!.query = (
377+
...args: Parameters<QueryRunner["query"]>
378+
) => {
365379
executedSql.push(args[0])
366380
return originalQuery(...args)
367381
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import { Column, Entity, Index, PrimaryGeneratedColumn } from "../../../../src"
2+
3+
@Entity()
4+
@Index(["nonNullable", "nullable"], {
5+
unique: true,
6+
where: '"nullable" IS NOT NULL',
7+
})
8+
export class Example {
9+
@PrimaryGeneratedColumn("uuid")
10+
id?: string
11+
12+
@Column({ type: "text" })
13+
nonNullable: string
14+
15+
@Column({ type: "text", nullable: true })
16+
nullable: string | null
17+
18+
@Column({ type: "text" })
19+
value: string
20+
}
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
import "reflect-metadata"
2+
import { DataSource } from "../../../src"
3+
import {
4+
closeTestingConnections,
5+
createTestingConnections,
6+
reloadTestingDatabases,
7+
} from "../../utils/test-utils"
8+
import { Example } from "./entity/Example"
9+
10+
describe("github issues > #10191 incorrect escaping of indexPredicate", () => {
11+
let connections: DataSource[]
12+
13+
before(
14+
async () =>
15+
(connections = await createTestingConnections({
16+
entities: [Example],
17+
enabledDrivers: ["postgres"],
18+
})),
19+
)
20+
beforeEach(() => reloadTestingDatabases(connections))
21+
after(() => closeTestingConnections(connections))
22+
23+
it("should not fail", () =>
24+
Promise.all(
25+
connections.map(async (connection) => {
26+
await connection.manager.upsert(
27+
Example,
28+
{
29+
nonNullable: "nonNullable",
30+
nullable: "nullable",
31+
value: "value",
32+
},
33+
{
34+
conflictPaths: {
35+
nonNullable: true,
36+
nullable: true,
37+
},
38+
skipUpdateIfNoValuesChanged: true,
39+
indexPredicate: '"nullable" IS NOT NULL',
40+
},
41+
)
42+
}),
43+
))
44+
})

test/github-issues/9988/issue-9988.ts

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -39,11 +39,12 @@ describe("github issues > #9988 RelationIdLoader reuses the same queryplanner wi
3939
const productTwoId = 2
4040
await categoryRepo.save(categoryOne)
4141
await categoryRepo.save(categoryTwo)
42-
const options = (id: number) => ({
43-
relationLoadStrategy: "query",
44-
where: { id },
45-
relations: { categories: true },
46-
} as FindManyOptions<Product>)
42+
const options = (id: number) =>
43+
({
44+
relationLoadStrategy: "query",
45+
where: { id },
46+
relations: { categories: true },
47+
} as FindManyOptions<Product>)
4748

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

9094
await customProductRepo.save(product)

test/utils/xfail.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,9 @@ const wrap = (
2121

2222
return new Promise<void>((ok, fail) => {
2323
if (fn.length > 1) {
24-
(fn as Func).call(context as unknown as Context, (err: any) => (err ? fail(err) : ok()))
24+
;(fn as Func).call(context as unknown as Context, (err: any) =>
25+
err ? fail(err) : ok(),
26+
)
2527
} else {
2628
ok((fn as AsyncFunc).call(context as unknown as Context))
2729
}

0 commit comments

Comments
 (0)