Environment
Jmix version: 2.8.999-SNAPSHOT
Bug Description
When a to-one reference is both eagerly fetched (present in the loader's fetch plan, e.g. to show it as a data grid column) and used in a filter condition, it is joined with an INNER join. Entities whose reference value is null are then dropped from the whole result —including when the condition is an OR and the entity matches the other branch.
Minimal reproduction project: inner-join-bug.zip
Steps to reproduce
Entities:
Project (id, name)
Task (id, name, project) — project is @ManyToOne(fetch = LAZY), optional.
Data — two tasks whose names both contain Task; one has a project, the other has project = null.
Load Task with project in the fetch plan and an OR condition that references project:
dataManager.load(Task.class)
.condition(LogicalCondition.or(
PropertyCondition.equal("project", jmixProject),
PropertyCondition.contains("name", "Task")))
.fetchPlan(fp -> fp.addFetchPlan(FetchPlan.BASE).add("project", FetchPlan.BASE))
.list();
In the UI: a Task list view with a Project column (so project is fetched) and a GenericFilter group project = Jmix OR name contains 'Task'.
Actual behavior
Only the task that has a project is returned; the task with project = null is dropped, although it matches the name contains 'Task' branch.
Generated SQL — comma-style INNER join whose correlation is placed at the top level of
WHERE (outside the OR):
SELECT t1.*, t0.* FROM PROJECT t0, TASK t1
WHERE (((t1.PROJECT_ID = ?) OR LOWER(t1.NAME) LIKE ?) AND (t0.ID = t1.PROJECT_ID))
The row is lost only when the reference is both fetched and used in the condition:
-- fetched, NOT used in the condition -> LEFT OUTER JOIN (correct, keeps null-reference rows)
SELECT t1.*, t0.* FROM TASK t1 LEFT OUTER JOIN PROJECT t0 ON (t0.ID = t1.PROJECT_ID)
WHERE LOWER(t1.NAME) LIKE ?
-- used in the condition, NOT fetched -> FK comparison, no join (correct)
SELECT * FROM TASK WHERE ((PROJECT_ID = ?) OR LOWER(NAME) LIKE ?)
Expected behavior
The task with project = null must be returned (it matches the OR branch). The fetched reference should be joined with a LEFT (outer) join —as it already is when the reference is not used in the condition — so that filtering does not drop rows.
Environment
Jmix version: 2.8.999-SNAPSHOT
Bug Description
When a to-one reference is both eagerly fetched (present in the loader's fetch plan, e.g. to show it as a data grid column) and used in a filter condition, it is joined with an INNER join. Entities whose reference value is
nullare then dropped from the whole result —including when the condition is anORand the entity matches the other branch.Minimal reproduction project: inner-join-bug.zip
Steps to reproduce
Entities:
Project (id, name)Task (id, name, project)—projectis@ManyToOne(fetch = LAZY), optional.Data — two tasks whose names both contain
Task; one has a project, the other hasproject = null.Load
Taskwithprojectin the fetch plan and anORcondition that referencesproject:In the UI: a Task list view with a Project column (so project is fetched) and a GenericFilter group project = Jmix OR name contains 'Task'.
Actual behavior
Only the task that has a project is returned; the task with project = null is dropped, although it matches the name contains 'Task' branch.
Generated SQL — comma-style INNER join whose correlation is placed at the top level of
WHERE (outside the OR):
The row is lost only when the reference is both fetched and used in the condition:
Expected behavior
The task with project = null must be returned (it matches the OR branch). The fetched reference should be joined with a LEFT (outer) join —as it already is when the reference is not used in the condition — so that filtering does not drop rows.