Hello, 

I have another use case.  For example, let’s say Artist "Leonardo da Vinci" has 
these paintings:

    * Mona Lisa
    * The Last Supper
    * Vitruvian Man

I need to build a qualifier / expression to obtain the artists with a painting 
that starts with the letter V *and* another painting that starts with the 
letter T.  Artist Leonardo da Vinci would meet such criteria.

In EOF, I can do it as follows:
———————————————————

EOQualifier qual = Artist.PAINTINGS.exists(Painting.NAME.like(“V*”))
    .and(Artist.PAINTINGS.exists(Painting.NAME.like(“T*”)));

var fetchSpec = new ERXFetchSpecification<Artist>(“Artist”, qual, null);
NSArray<Artist> artists = fetchSpec.fetchObjects(ec);

The qualifier qual works in memory and when fetching.

In Cayenne, I’m doing it as follows:
———————————————————

Expression exp1 = exp(“paintings.name like 'V%’”);
Expression exp2 = exp(“paintings.name like ’T%’”);

List<Artist> artists = ObjectSelect
    .query(Artist.class)
    .where(exp1.exists().andExp(exp2.exists()))
    .select(oc);

which generates the following SQL (formatted by me for readability):

INFO: --- transaction started.
INFO: SELECT t0.DATE_OF_BIRTH, t0.NAME, t0.ID FROM ARTIST t0 
      WHERE
          EXISTS (
              SELECT t1.ID FROM PAINTING t1 
              WHERE t1.NAME LIKE ? AND ( t1.ARTIST_ID = t0.ID )
          ) 
          AND 
          EXISTS (
              SELECT t2.ID FROM PAINTING t2 
              WHERE t2.NAME LIKE ? AND ( t2.ARTIST_ID = t0.ID )
          ) 
      [bind: 1->NAME:'M%', 2->NAME:'V%']
INFO: === returned 1 row. - took 360 ms.
INFO: +++ transaction committed.

It would be nice if cayenne would allow building an Expression that uses exists 
when fetching and have the same expression work for filtering objects in memory.

Has that been considered? For example, the API would be nicer if you could do 
this:

Expression exp = Artist.PAINTINGS.exists(Painting.NAME.like(“M%”))
        .andExp(Artist.PAINTINGS.exists(Painting.NAME.like(“V%”)));

List<Artist> artists = ObjectSelect
    .query(Artist.class)
    .where(exp)
    .select(oc);

If that does not fit the current design then how about EXISTS expressions 
working for filtering objects in memory?

For example:

Expression exp = Artist.PAINTINGS.dot(Painting.NAME).like(“M%”).exists()
   .andExp(Artist.PAINTINGS.dot(Painting.NAME).like(“V%”).exists());

// Fetch from database
List<Artist> artists = ObjectSelect
    .query(Artist.class)
    .where(exp)
    .select(oc);

// Or in memory filtering
List<Artist> artists = exp.filterObjects(allArtists);

Thank you,
Ricardo Parada




Reply via email to