Skip to content

Commit

Permalink
fix(knex): fix $or over 1:m and m:1 auto-joined relations (#3307)
Browse files Browse the repository at this point in the history
  • Loading branch information
diffcunha committed Jul 18, 2022
1 parent c5e6306 commit b6f12b2
Show file tree
Hide file tree
Showing 2 changed files with 136 additions and 1 deletion.
12 changes: 11 additions & 1 deletion packages/knex/src/query/ObjectCriteriaNode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,17 @@ export class ObjectCriteriaNode extends CriteriaNode {
delete o[key];
o.$and = $and;
} else {
o[key] = payload[k];
if (Utils.isOperator(k) && Array.isArray(payload[k])) {
o[key] = payload[k].map((child: Dictionary) => Object.keys(child).reduce((o, childKey) => {
const key = (this.isPrefixed(childKey) || Utils.isOperator(childKey))
? childKey
: `${childAlias}.${childKey}`;
o[key] = child[childKey];
return o;
}, {}));
} else {
o[key] = payload[k];
}
}
} else if (ObjectCriteriaNode.isCustomExpression(k)) {
o[k] = payload[k];
Expand Down
125 changes: 125 additions & 0 deletions tests/issues/GH3301.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
import { Collection, Entity, OneToMany, ManyToOne, MikroORM, PrimaryKey } from '@mikro-orm/core';
import type { SqliteDriver } from '@mikro-orm/sqlite';

@Entity()
export class Collector {

@PrimaryKey()
id!: number;

@OneToMany({
entity: 'Collect',
mappedBy: 'collector',
})
collecting = new Collection<Collect>(this);

}

@Entity()
export class Collectable {

@PrimaryKey()
id!: number;

@OneToMany({
entity: 'Collect',
mappedBy: 'collectable',
})
collectors = new Collection<Collect>(this);

}

@Entity()
export class Collect {

@PrimaryKey()
id!: number;

@ManyToOne()
collector?: Collector;

@ManyToOne()
collectable?: Collectable;

}

let orm: MikroORM<SqliteDriver>;

beforeAll(async () => {
orm = await MikroORM.init({
entities: [
Collect,
Collector,
Collectable,
],
dbName: ':memory:',
type: 'better-sqlite',
});
await orm.getSchemaGenerator().createSchema();
});

afterAll(() => orm.close(true));

describe('GH issue #3301', () => {
test('select with $or on 1:m and m:1 auto-joined relation', () => {
const query = {
$or: [{
collecting: {
collectable: { id: 1 },
},
}, {
collecting: {
collectable: { id: { $eq: 2 } },
},
}],
};
const expected = 'select `c0`.* from `collector` as `c0` ' +
'left join `collect` as `c1` on `c0`.`id` = `c1`.`collector_id` ' +
'where (`c1`.`collectable_id` = 1 or `c1`.`collectable_id` = 2)';
const sql1 = orm.em.createQueryBuilder(Collector).select('*').where(query).getFormattedQuery();
expect(sql1).toBe(expected);
const sql2 = orm.em.createQueryBuilder(Collector).where(query).getFormattedQuery();
expect(sql2).toBe(expected);
});

test('select 1:m auto-joined relation with $or on m:1 auto-joined relation', () => {
const query = {
collecting: {
$or: [
{ collectable: { id: 1 } },
{ collectable: { id: { $eq: 2 } } },
],
},
};
const expected = 'select `c0`.* from `collector` as `c0` ' +
'left join `collect` as `c1` on `c0`.`id` = `c1`.`collector_id` ' +
'where (`c1`.`collectable_id` = 1 or `c1`.`collectable_id` = 2)';
const sql1 = orm.em.createQueryBuilder(Collector).select('*').where(query).getFormattedQuery();
expect(sql1).toBe(expected);
const sql2 = orm.em.createQueryBuilder(Collector).where(query).getFormattedQuery();
expect(sql2).toBe(expected);
});

test('select 1:m and m:1 auto-joined relation with $or', () => {
const query = {
collecting: {
collectable: {
$or: [{
id: 1,
}, {
id: { $eq: 2 },
}],
},
},
};
const expected = 'select `c0`.* from `collector` as `c0` '+
'left join `collect` as `c1` on `c0`.`id` = `c1`.`collector_id` ' +
'left join `collectable` as `c2` on `c1`.`collectable_id` = `c2`.`id` ' +
'where (`c2`.`id` = 1 or `c2`.`id` = 2)';
const sql1 = orm.em.createQueryBuilder(Collector).select('*').where(query).getFormattedQuery();
expect(sql1).toBe(expected);
const sql2 = orm.em.createQueryBuilder(Collector).where(query).getFormattedQuery();
expect(sql2).toBe(expected);
});

});

0 comments on commit b6f12b2

Please sign in to comment.