Skip to content

Commit

Permalink
fix(core): allow joining a formula property
Browse files Browse the repository at this point in the history
Closes #4759
  • Loading branch information
B4nan committed Sep 28, 2023
1 parent 8ac5563 commit 1200e5b
Show file tree
Hide file tree
Showing 2 changed files with 109 additions and 1 deletion.
9 changes: 8 additions & 1 deletion packages/knex/src/query/QueryBuilderHelper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -226,8 +226,15 @@ export class QueryBuilderHelper {
const params: Knex.Value[] = [];

join.primaryKeys!.forEach((primaryKey, idx) => {
const left = `${join.ownerAlias}.${primaryKey}`;
const right = `${join.alias}.${join.joinColumns![idx]}`;

if (join.prop.formula) {
const left = join.prop.formula(join.ownerAlias);
conditions.push(`${left} = ${this.knex.ref(right)}`);
return;
}

const left = join.prop.persist === false ? primaryKey : `${join.ownerAlias}.${primaryKey}`;
conditions.push(`${this.knex.ref(left)} = ${this.knex.ref(right)}`);
});

Expand Down
101 changes: 101 additions & 0 deletions tests/issues/GH4759.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
import {
Collection,
DateType,
Entity,
ManyToOne,
OneToMany,
OneToOne,
PrimaryKey,
Property,
Ref,
ref,
} from '@mikro-orm/core';
import { MikroORM } from '@mikro-orm/postgresql';
import { v4 } from 'uuid';

@Entity()
class Author {

@PrimaryKey()
id = v4();

@Property()
name!: string;

@OneToMany({
entity: () => Book,
mappedBy: 'author',
})
books = new Collection<Book>(this);

@OneToOne({
entity: () => Book,
ref: true,
formula: alias =>
`(select "b"."id"
from (
select "b"."author_id", min("b"."release_date") "release_date"
from "book" "b"
where "b"."author_id" = ${alias}."id"
group by "b"."author_id"
) "s1"
join "book" "b"
on "b"."author_id" = "s1"."author_id"
and "b"."release_date" = "s1"."release_date")`,
})
firstBook?: Ref<Book>;

constructor(name: string) {
this.name = name;
}

}

@Entity()
class Book {

@PrimaryKey()
id = v4();

@Property({ type: DateType })
releaseDate!: Date;

@Property()
name!: string;

@ManyToOne({
entity: () => Author,
ref: true,
inversedBy: 'books',
})
author!: Ref<Author>;

constructor(releaseDate: Date = new Date(), name: string, author: Author) {
this.releaseDate = releaseDate;
this.name = name;
this.author = ref((author));
}

}

let orm: MikroORM;

beforeAll(async () => {
orm = await MikroORM.init({
entities: [Book, Author],
dbName: '4759',
});
await orm.schema.refreshDatabase();
});

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

test(`GH issue 4759`, async () => {
const author = new Author('John');
const book1 = new Book(new Date('2023-09-01'), 'My second book', author);
const book2 = new Book(new Date('2023-01-01'), 'My first book', author);
await orm.em.fork().persistAndFlush([author, book1, book2]);

const authorFound = await orm.em.find(Author, { firstBook: { name: 'My first book' } }, { populate: ['books', 'firstBook'] });
expect(authorFound[0].firstBook?.$.name).toBe('My first book');
});

0 comments on commit 1200e5b

Please sign in to comment.