Skip to content

Commit

Permalink
fix(query-builder): do not alias formula expressions used in `qb.grou…
Browse files Browse the repository at this point in the history
…pBy()`

Related: #2929
  • Loading branch information
B4nan committed Oct 23, 2023
1 parent 9dc659b commit e27e4b9
Show file tree
Hide file tree
Showing 2 changed files with 17 additions and 6 deletions.
18 changes: 12 additions & 6 deletions packages/knex/src/query/QueryBuilder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -900,6 +900,13 @@ export class QueryBuilder<T extends object = AnyEntity> {

private prepareFields<T, U extends string | Knex.Raw>(fields: Field<T>[], type: 'where' | 'groupBy' | 'sub-query' = 'where'): U[] {
const ret: Field<T>[] = [];
const getFieldName = (name: string) => {
if (type === 'groupBy') {
return this.helper.mapper(name, this.type, undefined, null);
}

return this.helper.mapper(name, this.type);
};

fields.forEach(field => {
if (!Utils.isString(field)) {
Expand All @@ -922,19 +929,18 @@ export class QueryBuilder<T extends object = AnyEntity> {

if (prop?.embedded) {
const name = this._aliases[a] ? `${a}.${prop.fieldNames[0]}` : prop.fieldNames[0];
const fieldName = this.helper.mapper(name, this.type) as string;
ret.push(fieldName);
ret.push(getFieldName(name));
return;
}

if (prop?.reference === ReferenceType.EMBEDDED) {
if (prop.object) {
ret.push(this.helper.mapper(prop.fieldNames[0], this.type) as string);
ret.push(getFieldName(prop.fieldNames[0]));
} else {
const nest = (prop: EntityProperty): void => {
for (const childProp of Object.values(prop.embeddedProps)) {
if (childProp.fieldNames) {
ret.push(this.helper.mapper(childProp.fieldNames[0], this.type) as string);
ret.push(getFieldName(childProp.fieldNames[0]));
} else {
nest(childProp);
}
Expand All @@ -947,11 +953,11 @@ export class QueryBuilder<T extends object = AnyEntity> {
}

if (prop && prop.fieldNames.length > 1) {
ret.push(...prop.fieldNames.map(f => this.helper.mapper(f, this.type) as string));
ret.push(...prop.fieldNames.map(f => getFieldName(f)));
return;
}

ret.push(this.helper.mapper(field, this.type) as string);
ret.push(getFieldName(field));
});

const meta = this.mainAlias.metadata;
Expand Down
5 changes: 5 additions & 0 deletions tests/QueryBuilder.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3044,6 +3044,11 @@ describe('QueryBuilder', () => {
expect(sql).toBe('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(`books`.price * 1.19) desc, min(`e0`.`id`) desc limit 10) as `e0`) order by `books`.price * 1.19 desc, `e0`.`id` desc');
});

test(`sub-query group-by fields should not include 'as'`, async () => {
const sql = orm.em.createQueryBuilder(Author2).select(['id', 'books.priceTaxed']).join('books', 'books').groupBy('books.priceTaxed').limit(10).getFormattedQuery();
expect(sql).toBe('select `e0`.`id`, `books`.price * 1.19 as `price_taxed` from `author2` as `e0` inner join `book2` as `books` on `e0`.`id` = `books`.`author_id` group by `books`.price * 1.19 limit 10');
});

test('select via fulltext search', async () => {
const qb1 = orm.em.createQueryBuilder(Author2, 'a');
qb1.select('*').where({ name: { $fulltext: 'test' } });
Expand Down

0 comments on commit e27e4b9

Please sign in to comment.