Skip to content

Commit

Permalink
fix(query-builder): apply join condition to the target entity in M:N …
Browse files Browse the repository at this point in the history
…relations

Closes #4644
  • Loading branch information
B4nan committed Aug 24, 2023
1 parent 44d973e commit c78d812
Show file tree
Hide file tree
Showing 2 changed files with 20 additions and 2 deletions.
5 changes: 3 additions & 2 deletions packages/knex/src/query/QueryBuilderHelper.ts
Expand Up @@ -176,12 +176,13 @@ export class QueryBuilderHelper {
const pivotMeta = this.metadata.find(prop.pivotEntity)!;
const ret = {
[`${ownerAlias}.${prop.name}#${pivotAlias}`]: {
prop, type, cond, ownerAlias,
prop, type, ownerAlias,
alias: pivotAlias,
inverseAlias: alias,
joinColumns: prop.joinColumns,
inverseJoinColumns: prop.inverseJoinColumns,
primaryKeys: prop.referencedColumnNames,
cond: {},
table: pivotMeta.tableName,
schema: this.driver.getSchemaName(pivotMeta),
path: path.endsWith('[pivot]') ? path : `${path}[pivot]`,
Expand All @@ -193,7 +194,7 @@ export class QueryBuilderHelper {
}

const prop2 = prop.owner ? pivotMeta.relations[1] : pivotMeta.relations[0];
ret[`${pivotAlias}.${prop2.name}#${alias}`] = this.joinManyToOneReference(prop2, pivotAlias, alias, type);
ret[`${pivotAlias}.${prop2.name}#${alias}`] = this.joinManyToOneReference(prop2, pivotAlias, alias, type, cond);
ret[`${pivotAlias}.${prop2.name}#${alias}`].path = path;

return ret;
Expand Down
17 changes: 17 additions & 0 deletions tests/QueryBuilder.test.ts
Expand Up @@ -2963,6 +2963,23 @@ describe('QueryBuilder', () => {
expect(sql2).toBe("select `b`.*, `a`.`id` as `a__id`, `a`.`created_at` as `a__created_at`, `a`.`updated_at` as `a__updated_at`, `a`.`name` as `a__name`, `a`.`email` as `a__email`, `a`.`age` as `a__age`, `a`.`terms_accepted` as `a__terms_accepted`, `a`.`optional` as `a__optional`, `a`.`identities` as `a__identities`, `a`.`born` as `a__born`, `a`.`born_time` as `a__born_time`, `a`.`favourite_book_uuid_pk` as `a__favourite_book_uuid_pk`, `a`.`favourite_author_id` as `a__favourite_author_id`, `b`.price * 1.19 as `price_taxed` from `book2` as `b` inner join `author2` as `a` on `b`.`author_id` = `a`.`id` and `a`.`born` = '1990-03-23'");
});

test('join condition with M:N (GH #4644)', () => {
const sql1 = orm.em.createQueryBuilder(Book2, 'b')
.select('*')
.leftJoin('tags', 't', { 't.name': 't1' })
.getFormattedQuery();
expect(sql1).toBe('select `b`.*, `b`.price * 1.19 as `price_taxed` ' +
'from `book2` as `b` ' +
'left join `book2_tags` as `e1` on `b`.`uuid_pk` = `e1`.`book2_uuid_pk` ' +
'left join `book_tag2` as `t` on `e1`.`book_tag2_id` = `t`.`id` and `t`.`name` = \'t1\'');

// const sql2 = orm.em.createQueryBuilder(Book2, 'b')
// .select('*')
// .joinAndSelect('author', 'a', { 'a.born': new Date('1990-03-23') })
// .getFormattedQuery();
// expect(sql2).toBe("select `b`.*, `a`.`id` as `a__id`, `a`.`created_at` as `a__created_at`, `a`.`updated_at` as `a__updated_at`, `a`.`name` as `a__name`, `a`.`email` as `a__email`, `a`.`age` as `a__age`, `a`.`terms_accepted` as `a__terms_accepted`, `a`.`optional` as `a__optional`, `a`.`identities` as `a__identities`, `a`.`born` as `a__born`, `a`.`born_time` as `a__born_time`, `a`.`favourite_book_uuid_pk` as `a__favourite_book_uuid_pk`, `a`.`favourite_author_id` as `a__favourite_author_id`, `b`.price * 1.19 as `price_taxed` from `book2` as `b` inner join `author2` as `a` on `b`.`author_id` = `a`.`id` and `a`.`born` = '1990-03-23'");
});

test('sub-query order-by fields are always fully qualified', () => {
const expected = 'select `e0`.*, `books`.`uuid_pk` as `books__uuid_pk`, `books`.`created_at` as `books__created_at`, `books`.`title` as `books__title`, `books`.`price` as `books__price`, `books`.price * 1.19 as `books__price_taxed`, `books`.`double` as `books__double`, `books`.`meta` as `books__meta`, `books`.`author_id` as `books__author_id`, `books`.`publisher_id` as `books__publisher_id` from `author2` as `e0` inner join `book2` as `books` on `e0`.`id` = `books`.`author_id` where `e0`.`id` in (select `e0`.`id` from (select `e0`.`id` from `author2` as `e0` inner join `book2` as `books` on `e0`.`id` = `books`.`author_id` group by `e0`.`id` order by min(`e0`.`id`) desc limit 10) as `e0`) order by `e0`.`id` desc';
const sql = orm.em.createQueryBuilder(Author2).select('*').joinAndSelect('books', 'books').orderBy({ id: QueryOrder.DESC }).limit(10).getFormattedQuery();
Expand Down

0 comments on commit c78d812

Please sign in to comment.