Skip to content

Commit

Permalink
fix(core): fix aliasing of formula properties in complex conditions (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
B4nan committed May 19, 2022
1 parent 43e1d0b commit 071846e
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 1 deletion.
3 changes: 2 additions & 1 deletion packages/knex/src/query/ObjectCriteriaNode.ts
Expand Up @@ -26,7 +26,8 @@ export class ObjectCriteriaNode extends CriteriaNode {
const payload = childNode.process(qb, this.prop ? alias : ownerAlias);
const operator = Utils.isOperator(field);
const customExpression = ObjectCriteriaNode.isCustomExpression(field);
const virtual = childNode.prop?.persist === false;
// we need to keep the prefixing for formulas otherwise we would lose aliasing context when nesting inside group operators
const virtual = childNode.prop?.persist === false && !childNode.prop?.formula;
// if key is missing, we are inside group operator and we need to prefix with alias
const primaryKey = this.key && this.metadata.find(this.entityName)!.primaryKeys.includes(field);

Expand Down
46 changes: 46 additions & 0 deletions tests/EntityManager.mysql.test.ts
Expand Up @@ -2207,6 +2207,52 @@ describe('EntityManagerMySql', () => {
expect(mock.mock.calls[1][0]).toMatch('select `f0`.*, (select 123) as `random`, (select 456) as `lazy_random` from `foo_bar2` as `f0` where `f0`.`id` = ? limit ?');
});

test('search by formulas (gh #3048)', async () => {
const god = new Author2('God', 'hello@heaven.god');
const bible = new Book2('Bible', god);
bible.price = 1000;
god.favouriteBook = bible;
await orm.em.persistAndFlush(bible);

const mock = mockLogger(orm, ['query']);

const b = await orm.em.fork().findOneOrFail(Book2, { priceTaxed: '1190.0000' });
expect(b.price).toBe('1000.00');
expect(b.priceTaxed).toBe('1190.0000');
expect(mock.mock.calls[0][0]).toMatch('select `b0`.`uuid_pk`, `b0`.`created_at`, `b0`.`title`, `b0`.`price`, `b0`.`double`, `b0`.`meta`, `b0`.`author_id`, `b0`.`publisher_id`, `b0`.price * 1.19 as `price_taxed`, `t1`.`id` as `test_id` ' +
'from `book2` as `b0` ' +
'left join `test2` as `t1` on `b0`.`uuid_pk` = `t1`.`book_uuid_pk` ' +
'where `b0`.`author_id` is not null and `b0`.price * 1.19 = ? limit ?');

const a1 = await orm.em.fork().find(Author2, { $or: [{ favouriteBook: { priceTaxed: '1190.0000' } }] }, { populate: ['books'] });
expect(a1[0].books[0].price).toBe('1000.00');
expect(a1[0].books[0].priceTaxed).toBe('1190.0000');
expect(mock.mock.calls[1][0]).toMatch('select `a0`.*, `a2`.`author_id` as `address_author_id` ' +
'from `author2` as `a0` ' +
'left join `book2` as `b1` on `a0`.`favourite_book_uuid_pk` = `b1`.`uuid_pk` ' +
'left join `address2` as `a2` on `a0`.`id` = `a2`.`author_id` ' +
'where `b1`.price * 1.19 = ?');
expect(mock.mock.calls[2][0]).toMatch('select `b0`.`uuid_pk`, `b0`.`created_at`, `b0`.`title`, `b0`.`price`, `b0`.`double`, `b0`.`meta`, `b0`.`author_id`, `b0`.`publisher_id`, `b0`.price * 1.19 as `price_taxed`, `t1`.`id` as `test_id` ' +
'from `book2` as `b0` ' +
'left join `test2` as `t1` on `b0`.`uuid_pk` = `t1`.`book_uuid_pk` ' +
'where `b0`.`author_id` is not null and `b0`.`author_id` in (?) ' +
'order by `b0`.`title` asc, `b0`.`author_id` asc');

const a2 = await orm.em.fork().find(Author2, { favouriteBook: { $or: [{ priceTaxed: '1190.0000' }] } }, { populate: ['books'] });
expect(a2[0].books[0].price).toBe('1000.00');
expect(a2[0].books[0].priceTaxed).toBe('1190.0000');
expect(mock.mock.calls[3][0]).toMatch('select `a0`.*, `a2`.`author_id` as `address_author_id` ' +
'from `author2` as `a0` ' +
'left join `book2` as `b1` on `a0`.`favourite_book_uuid_pk` = `b1`.`uuid_pk` ' +
'left join `address2` as `a2` on `a0`.`id` = `a2`.`author_id` ' +
'where `b1`.price * 1.19 = ?');
expect(mock.mock.calls[4][0]).toMatch('select `b0`.`uuid_pk`, `b0`.`created_at`, `b0`.`title`, `b0`.`price`, `b0`.`double`, `b0`.`meta`, `b0`.`author_id`, `b0`.`publisher_id`, `b0`.price * 1.19 as `price_taxed`, `t1`.`id` as `test_id` ' +
'from `book2` as `b0` ' +
'left join `test2` as `t1` on `b0`.`uuid_pk` = `t1`.`book_uuid_pk` ' +
'where `b0`.`author_id` is not null and `b0`.`author_id` in (?) ' +
'order by `b0`.`title` asc, `b0`.`author_id` asc');
});

test('refreshing already loaded entity', async () => {
const god = new Author2('God', 'hello@heaven.god');
new Book2('Bible 1', god);
Expand Down

0 comments on commit 071846e

Please sign in to comment.