diff --git a/package.json b/package.json index 164080529..95c8252b5 100644 --- a/package.json +++ b/package.json @@ -115,4 +115,4 @@ "typescript": "5.2.2" }, "packageManager": "yarn@3.2.1" -} +} \ No newline at end of file diff --git a/packages/query-typeorm/__tests__/query/__snapshots__/filter-query.builder.spec.ts.snap b/packages/query-typeorm/__tests__/query/__snapshots__/filter-query.builder.spec.ts.snap index 3744c01fc..cb22f1d29 100644 --- a/packages/query-typeorm/__tests__/query/__snapshots__/filter-query.builder.spec.ts.snap +++ b/packages/query-typeorm/__tests__/query/__snapshots__/filter-query.builder.spec.ts.snap @@ -10,6 +10,29 @@ exports[`FilterQueryBuilder #delete with paging should ignore paging args 1`] = exports[`FilterQueryBuilder #delete with sorting should ignore sorting 1`] = `"DELETE FROM "test_entity""`; +exports[`FilterQueryBuilder #select with filter should apply filtering from relations query filter 1`] = ` +"SELECT + "TestEntity"."test_entity_pk" AS "TestEntity_test_entity_pk", + "TestEntity"."string_type" AS "TestEntity_string_type", + "TestEntity"."bool_type" AS "TestEntity_bool_type", + "TestEntity"."number_type" AS "TestEntity_number_type", + "TestEntity"."date_type" AS "TestEntity_date_type", + "TestEntity"."many_to_one_relation_id" AS "TestEntity_many_to_one_relation_id", + "TestEntity"."many_to_one_soft_delete_relation_id" AS "TestEntity_many_to_one_soft_delete_relation_id", + "TestEntity"."oneTestRelationTestRelationPk" AS "TestEntity_oneTestRelationTestRelationPk", + "oneTestRelation"."test_relation_pk" AS "oneTestRelation_test_relation_pk", + "oneTestRelation"."relation_name" AS "oneTestRelation_relation_name", + "oneTestRelation"."test_entity_id" AS "oneTestRelation_test_entity_id", + "oneTestRelation"."uni_directional_test_entity_id" AS "oneTestRelation_uni_directional_test_entity_id", + "oneTestRelation"."uni_directional_relation_test_entity_id" AS "oneTestRelation_uni_directional_relation_test_entity_id" +FROM + "test_entity" "TestEntity" + LEFT JOIN "test_relation" "oneTestRelation" ON "oneTestRelation"."test_relation_pk" = "TestEntity"."oneTestRelationTestRelationPk" +WHERE + (oneTestRelation.numberType = 123) + AND ("TestEntity"."string_type" = test)" +`; + exports[`FilterQueryBuilder #select with filter should call whereBuilder#build if there is a filter 1`] = ` "SELECT "TestEntity"."test_entity_pk" AS "TestEntity_test_entity_pk", diff --git a/packages/query-typeorm/__tests__/query/filter-query.builder.spec.ts b/packages/query-typeorm/__tests__/query/filter-query.builder.spec.ts index 734bbf25e..f894271c3 100644 --- a/packages/query-typeorm/__tests__/query/filter-query.builder.spec.ts +++ b/packages/query-typeorm/__tests__/query/filter-query.builder.spec.ts @@ -252,6 +252,32 @@ describe('FilterQueryBuilder', (): void => { ) expectSelectSQLSnapshot(query, instance(mockWhereBuilder)) }) + + it('should apply filtering from relations query filter', () => { + const expectSQLSnapshotUsingQuery = (EntityClass: Class, query: Query): void => { + const geFilterQueryBuilder = (e: Class): FilterQueryBuilder => + new FilterQueryBuilder(connection.getRepository(e)) + + const selectQueryBuilder = geFilterQueryBuilder(EntityClass).select(query) + const [sql, params] = selectQueryBuilder.getQueryAndParameters() + expect(formatSql(sql, { params })).toMatchSnapshot() + } + + expectSQLSnapshotUsingQuery(TestEntity, { + filter: { stringType: { eq: 'test' } }, // note that this is the 'normal' filter. + relations: [ + { + name: 'oneTestRelation', + query: { + // and this filter gets applied to the query as well. + filter: { + numberType: { eq: 123 } + } + } + } + ] + } as any) + }) }) describe('with paging', () => { diff --git a/packages/query-typeorm/src/query/filter-query.builder.ts b/packages/query-typeorm/src/query/filter-query.builder.ts index 2c92e482f..a740c47b6 100644 --- a/packages/query-typeorm/src/query/filter-query.builder.ts +++ b/packages/query-typeorm/src/query/filter-query.builder.ts @@ -278,17 +278,14 @@ export class FilterQueryBuilder { const relationAlias = relation.alias const relationChildren = relation.relations - // TODO:: Change to find and also apply the query for the relation const selectRelation = selectRelations && selectRelations.find(({ name }) => name === relationKey) // eslint-disable-next-line @typescript-eslint/no-non-null-assertion if (selectRelation) { - return this.applyRelationJoinsRecursive( - rqb.leftJoinAndSelect(`${alias ?? rqb.alias}.${relationKey}`, relationAlias), - relationChildren, - selectRelation.query.relations, - relationAlias - ) + rqb = rqb.leftJoinAndSelect(`${alias ?? rqb.alias}.${relationKey}`, relationAlias) + // Apply filter for the current relation + rqb = this.applyFilter(rqb, selectRelation.query.filter, relationAlias) + return this.applyRelationJoinsRecursive(rqb, relationChildren, selectRelation.query.relations, relationAlias) } return this.applyRelationJoinsRecursive(