Skip to content

Commit

Permalink
feat: "And" operator in FindOptions (#9489)
Browse files Browse the repository at this point in the history
Closes #3113
  • Loading branch information
iJhefe committed Dec 3, 2022
1 parent d71e9c4 commit fc3b4f8
Show file tree
Hide file tree
Showing 7 changed files with 100 additions and 0 deletions.
1 change: 1 addition & 0 deletions src/find-options/FindOperatorType.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,4 @@ export type FindOperatorType =
| "arrayContains"
| "arrayContainedBy"
| "arrayOverlap"
| "and"
5 changes: 5 additions & 0 deletions src/find-options/operator/And.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { FindOperator } from "../FindOperator"

export function And<T>(...values: FindOperator<T>[]): FindOperator<T> {
return new FindOperator("and", values as any, true, true)
}
1 change: 1 addition & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ export * from "./decorator/Check"
export * from "./decorator/Exclusion"
export * from "./decorator/Generated"
export * from "./decorator/EntityRepository"
export * from "./find-options/operator/And"
export * from "./find-options/operator/Any"
export * from "./find-options/operator/ArrayContainedBy"
export * from "./find-options/operator/ArrayContains"
Expand Down
16 changes: 16 additions & 0 deletions src/query-builder/QueryBuilder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1055,6 +1055,8 @@ export abstract class QueryBuilder<Entity extends ObjectLiteral> {
condition.condition,
true,
)}`
case "and":
return condition.parameters.join(" AND ")
}

throw new TypeError(
Expand Down Expand Up @@ -1448,6 +1450,20 @@ export abstract class QueryBuilder<Entity extends ObjectLiteral> {
parameters: [aliasPath, ...parameters],
}
}
} else if (parameterValue.type === "and") {
const values: FindOperator<any>[] = parameterValue.value

return {
operator: parameterValue.type,
parameters: values.map((operator) =>
this.createWhereConditionExpression(
this.getWherePredicateCondition(
aliasPath,
operator,
),
),
),
}
} else {
return {
operator: parameterValue.type,
Expand Down
1 change: 1 addition & 0 deletions src/query-builder/WhereClause.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ type PredicateOperator =
| "arrayContains"
| "arrayContainedBy"
| "arrayOverlap"
| "and"

export interface WherePredicateOperator {
operator: PredicateOperator
Expand Down
13 changes: 13 additions & 0 deletions test/github-issues/3113/entities/User.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { Column, Entity, PrimaryGeneratedColumn } from "../../../../src"

@Entity()
export class User {
@PrimaryGeneratedColumn()
id: number

@Column()
name: string

@Column({ type: "int", nullable: true })
money: number | null
}
63 changes: 63 additions & 0 deletions test/github-issues/3113/issue-3113.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import { And, DataSource, IsNull, LessThan, MoreThan, Not } from "../../../src"
import {
closeTestingConnections,
createTestingConnections,
reloadTestingDatabases,
} from "../../utils/test-utils"
import { User } from "./entities/User"
import { expect } from "chai"

describe("github issues > #9316 specify how should interpret null and undefined values in conditions ", () => {
let dataSources: DataSource[]

before(async () => {
dataSources = await createTestingConnections({
entities: [User],
enabledDrivers: ["postgres", "mysql"],
schemaCreate: true,
dropSchema: true,
})
})

beforeEach(() => reloadTestingDatabases(dataSources))
after(() => closeTestingConnections(dataSources))

it("should find users what money is not null and money is more than 10 and money is less than 100", async () => {
await Promise.all(
dataSources.map(async (dataSource) => {
const foo = new User()
foo.name = "Foo"
foo.money = null

const john = new User()
john.name = "John"
john.money = 11

const jane = new User()
jane.name = "Jane"
jane.money = 90

const bar = new User()
bar.name = "Bar"
bar.money = 101

await dataSource.manager.save([foo, john, jane, bar])

const users = await dataSource.manager.find(User, {
where: {
money: And(Not(IsNull()), MoreThan(10), LessThan(100)),
},
})

// assert users
expect(users).to.have.length(2)

expect(users.find((user) => user.name === "John")).to.be.not
.undefined

expect(users.find((user) => user.name === "Jane")).to.be.not
.undefined
}),
)
})
})

0 comments on commit fc3b4f8

Please sign in to comment.