Skip to content

Virtual entity findByCursor not working #5922

@Kazma830124

Description

@Kazma830124

Describe the bug

In packages/knex/src/AbstractSqlDriver.ts, the find function will check meta.virtual, and use findVirtual for virtual entity.

async find<T extends object, P extends string = never, F extends string = PopulatePath.ALL, E extends string = never>(entityName: string, where: FilterQuery<T>, options: FindOptions<T, P, F, E> = {}): Promise<EntityData<T>[]> {
options = { populate: [], orderBy: [], ...options };
const meta = this.metadata.find<T>(entityName)!;
if (meta?.virtual) {
return this.findVirtual<T>(entityName, where, options);
}
const populate = this.autoJoinOneToOneOwner(meta, options.populate as unknown as PopulateOptions<T>[], options.fields);
const joinedProps = this.joinedProps(meta, populate, options);
const qb = this.createQueryBuilder<T>(entityName, options.ctx, options.connectionType, false, options.logging);
const fields = this.buildFields(meta, populate, joinedProps, qb, qb.alias, options);
const orderBy = this.buildOrderBy(qb, meta, populate, options);
const populateWhere = this.buildPopulateWhere(meta, joinedProps, options);
Utils.asArray(options.flags).forEach(flag => qb.setFlag(flag));
if (Utils.isPrimaryKey(where, meta.compositePK)) {
where = { [Utils.getPrimaryKeyHash(meta.primaryKeys)]: where } as FilterQuery<T>;
}
const { first, last, before, after } = options as FindByCursorOptions<T>;
const isCursorPagination = [first, last, before, after].some(v => v != null);
qb.__populateWhere = (options as Dictionary)._populateWhere;
qb.select(fields)
// only add populateWhere if we are populate-joining, as this will be used to add `on` conditions
.populate(populate, joinedProps.length > 0 ? populateWhere : undefined)
.where(where)
.groupBy(options.groupBy!)
.having(options.having!)
.indexHint(options.indexHint!)
.comment(options.comments!)
.hintComment(options.hintComments!)
.withSchema(this.getSchemaName(meta, options));
if (isCursorPagination) {
const { orderBy: newOrderBy, where } = this.processCursorOptions(meta, options, orderBy);
qb.andWhere(where).orderBy(newOrderBy);
} else {
qb.orderBy(orderBy);
}

But cursor pagination part is under the return, it doesn't handle the cursor option, so we cannot fetch the correctly amount data.

Reproduction

minimal reproduction

expect:

select * from ( SELECT "user".id, "user".name, "user".age, COUNT(b.id) AS book_count FROM "user" LEFT JOIN "book" b ON b.owner_id = "user".id GROUP BY "user".id ) as "u0" where "u0"."age" >= 1 order by "u0"."id" asc limit 4 

actual:

select * from ( SELECT "user".id, "user".name, "user".age, COUNT(b.id) AS book_count FROM "user" LEFT JOIN "book" b ON b.owner_id = "user".id GROUP BY "user".id ) as "u0" where "u0"."age" >= 1 order by "u0"."id" asc

What driver are you using?

@mikro-orm/postgresql

MikroORM version

6.3.5-dev.9

Node.js version

20

Operating system

linux

Validations

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions