-
-
Notifications
You must be signed in to change notification settings - Fork 6.2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
fix: materialized hints support for cte (#9605)
Fix implementation of materialized hints in common table expressions Previous behavior did not account for NOT MATERIALIZED hints, also placed materialized hints in wrong place (before "AS") Co-authored-by: Adrian Parry <adrian.parry@reign.cl>
- Loading branch information
1 parent
8668c29
commit 67973b4
Showing
2 changed files
with
149 additions
and
5 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,140 @@ | ||
import "reflect-metadata" | ||
import { expect } from "chai" | ||
import { | ||
createTestingConnections, | ||
closeTestingConnections, | ||
reloadTestingDatabases, | ||
} from "../../../utils/test-utils" | ||
import { Connection } from "../../../../src/connection/Connection" | ||
import { Foo } from "./entity/foo" | ||
import { filterByCteCapabilities } from "./helpers" | ||
import { QueryBuilderCteOptions } from "../../../../src/query-builder/QueryBuilderCte" | ||
|
||
describe("query builder > cte > materialized", () => { | ||
let connections: Connection[] | ||
before( | ||
async () => | ||
(connections = await createTestingConnections({ | ||
entities: [__dirname + "/entity/*{.js,.ts}"], | ||
schemaCreate: true, | ||
dropSchema: true, | ||
// enabledDrivers: ['] | ||
})), | ||
) | ||
beforeEach(() => reloadTestingDatabases(connections)) | ||
after(() => closeTestingConnections(connections)) | ||
|
||
it("should allow MATERIALIZED hint", () => | ||
Promise.all( | ||
connections | ||
.filter(filterByCteCapabilities("enabled")) | ||
.filter(filterByCteCapabilities("materializedHint")) | ||
.map(async (connection) => { | ||
await connection | ||
.getRepository(Foo) | ||
.insert( | ||
[1, 2, 3].map((i) => ({ id: i, bar: String(i) })), | ||
) | ||
const cteQuery = connection | ||
.createQueryBuilder() | ||
.select() | ||
.addSelect(`foo.bar`, "bar") | ||
.from(Foo, "foo") | ||
.where(`foo.bar = :value`, { value: "2" }) | ||
|
||
const cteOptions: QueryBuilderCteOptions = { | ||
columnNames: ["raz"], | ||
materialized: true, | ||
} | ||
|
||
const cteSelection = "qaz.raz" | ||
|
||
const qb = await connection | ||
.createQueryBuilder() | ||
.addCommonTableExpression(cteQuery, "qaz", cteOptions) | ||
.from("qaz", "qaz") | ||
.select([]) | ||
.addSelect(cteSelection, "raz") | ||
|
||
expect(qb.getQuery()).to.contain( | ||
`WITH "qaz"("raz") AS MATERIALIZED (`, | ||
) | ||
expect(await qb.getRawMany()).to.deep.equal([{ raz: "2" }]) | ||
}), | ||
)) | ||
|
||
it("should allow NOT MATERIALIZED hint", () => | ||
Promise.all( | ||
connections | ||
.filter(filterByCteCapabilities("enabled")) | ||
.filter(filterByCteCapabilities("materializedHint")) | ||
.map(async (connection) => { | ||
await connection | ||
.getRepository(Foo) | ||
.insert( | ||
[1, 2, 3].map((i) => ({ id: i, bar: String(i) })), | ||
) | ||
const cteQuery = connection | ||
.createQueryBuilder() | ||
.select() | ||
.addSelect(`foo.bar`, "bar") | ||
.from(Foo, "foo") | ||
.where(`foo.bar = :value`, { value: "2" }) | ||
|
||
const cteOptions: QueryBuilderCteOptions = { | ||
columnNames: ["raz"], | ||
materialized: false, | ||
} | ||
|
||
const cteSelection = "qaz.raz" | ||
|
||
const qb = await connection | ||
.createQueryBuilder() | ||
.addCommonTableExpression(cteQuery, "qaz", cteOptions) | ||
.from("qaz", "qaz") | ||
.select([]) | ||
.addSelect(cteSelection, "raz") | ||
|
||
expect(qb.getQuery()).to.contain( | ||
`WITH "qaz"("raz") AS NOT MATERIALIZED (`, | ||
) | ||
expect(await qb.getRawMany()).to.deep.equal([{ raz: "2" }]) | ||
}), | ||
)) | ||
|
||
it("should omit hint if materialized option is not set", () => | ||
Promise.all( | ||
connections | ||
.filter(filterByCteCapabilities("enabled")) | ||
.filter(filterByCteCapabilities("materializedHint")) | ||
.map(async (connection) => { | ||
await connection | ||
.getRepository(Foo) | ||
.insert( | ||
[1, 2, 3].map((i) => ({ id: i, bar: String(i) })), | ||
) | ||
const cteQuery = connection | ||
.createQueryBuilder() | ||
.select() | ||
.addSelect(`foo.bar`, "bar") | ||
.from(Foo, "foo") | ||
.where(`foo.bar = :value`, { value: "2" }) | ||
|
||
const cteOptions: QueryBuilderCteOptions = { | ||
columnNames: ["raz"], | ||
} | ||
|
||
const cteSelection = "qaz.raz" | ||
|
||
const qb = await connection | ||
.createQueryBuilder() | ||
.addCommonTableExpression(cteQuery, "qaz", cteOptions) | ||
.from("qaz", "qaz") | ||
.select([]) | ||
.addSelect(cteSelection, "raz") | ||
|
||
expect(qb.getQuery()).to.contain(`WITH "qaz"("raz") AS (`) | ||
expect(await qb.getRawMany()).to.deep.equal([{ raz: "2" }]) | ||
}), | ||
)) | ||
}) |