Logical "or" works not correcly when field is @Id and first position

#1

The following code doesn't respect the logical "or" correctly. Instead of returns all 2 datasets it returns only this one, which matches the first predicate in the or. BUT: this happens only, if the field for the "or" is the first one defined as @Id.

public class OrTest {
    @Entity
    static class Data {
        Data(String a, String b) {
            this.a = a;
            this.b = b;
        }
        @Id
        String a;
        @Id
        String b;
        public Data() {
        }
    }

    public static void main(String[] args) {
        EntityManagerFactory emf = Persistence.createEntityManagerFactory("or_test.odb");
        EntityManager em = emf.createEntityManager();
        em.getTransaction().begin();
        em.persist(new Data("1", "x"));
        em.persist(new Data("12", "y"));
        em.getTransaction().commit();
        CriteriaBuilder builder = em.getCriteriaBuilder();
        CriteriaQuery<Data> query = builder.createQuery(Data.class);
        Root<Data> root = query.from(Data.class);
        query.select(root);
        query.where((builder.or(
            builder.equal(root.get("a"), "1"),
            builder.like(root.get("a"), "1%")
        )));
        System.out.println(em.createQuery(query).getResultList().size());
    }
}

This outputs instead of 2 only:

1

If you change the order:

        @Id         
        String b;
        @Id      
        String a;

the code outputs:

2

What is wrong? I'm afraid that the order of @Id changes query behaviour to wrong.

#2

One more hours of research later it seems, whenever an indexed field (means b-tree can used) is inside an or condition, the query optimizer using only the b-tree for the query and the other part of the or is ignored.

For the database created with the example code above, this query also returns only the object matches the b-tree (field "a"). The condition regarding the "b" field is ignored.

select from Data where b = 'x' or a = '12'

The ObjectDB Explorer says:

Query plan 1/1 description
============================

[Step 1]
Scan type org.example.OrTest$Data
locating OrTest$Data (this) instances that satisfy:
  or((this.a='12'),(this.b='x')).

[Step 2]
Apply selection and prepare final results.

<btreePlan 3.6393 1,18/1,18 this(OrTest$Data) type(OrTest$Data[or(['12'->'12':notNull],[pos<1>'x'->'x':notNull])]) />

This means, everybody using or conditions for indexed fields went into wrong results.

#3

Thank you for this report. Version 2.8.9 should fix the issue.

ObjectDB Support
#4

Thanks to the support 🤟 It works now!

Reply