cayenne-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Durchholz, Joachim" <Joachim.Durchh...@hennig-fahrzeugteile.de>
Subject RE: SelectQuery + Orderings
Date Mon, 30 Jan 2012 11:57:59 GMT
 

-----Original Message-----
From: Aristedes Maniatis [mailto:ari@maniatis.org] 
Sent: Monday, January 30, 2012 12:21 PM
To: dev@cayenne.apache.org
Subject: Re: SelectQuery + Orderings

On 30/01/12 9:12 PM, Durchholz, Joachim wrote:

>> giving
>>    new QualifierList ()
>>    .like("name", "b%")
>>    .or (
>>      new Greater("age", 23)
>>      .less("age", 27)
>>    )
>>
>
> I am not sure you have achieved any more readability over the plain string version.
> Compare:
>
>    new SelectQuery().query("age < 27")
>
>    new SelectQuery().less("age", 27)


Oh, that was more a presentational afterthought, not the actual issue.
The background is that if you allow literals in query strings, it's getting seductive to write
conditions like
  new SelectQuery().query("age < " + userInput)
and get an SQL injection problem.

> Which parameter is supposed to be less than which?

Left side is less than right side.
Hibernate is using this idiom in its Criteria queries, and while I have many gripes with Hibernate,
this particular decision never causes any problem for me.

> A more radical approach was also discussed before.

Aww, the last weeks were a bit busy, so I probably missed that one.

> Something like (from memory):
> 
> new SelectQuery().and(Artist.AGE.under(23))

I'd introduce a standard abbreviation that SelectQuery() is automatically accepting conditions
just like and() does.

> It reads nicely and can be made type-safe, but is a bit messy
> in that it moves many Expression methods into the ObjAttribute class.

I can't say much about messiness - I have done my part in writing ORM code, but I haven't
had the time to take an actual look at Cayenne's sources, so in the end, my perspective is
more that of an application programmer (Cayenne user) than that of a Cayenne developer.

However, I like that idiom very much, though I'd like to make it more concise.
My last example would look like this:

  SelectQuery(Artist.class)
  .and(
    .Artist.NAME.isLike("b%")
    .or(
      Artist.AGE.above(23),
      Artist.AGE.below(27)
    )
  )
  .join(Gallery.class)
  .Gallery.COUNTRY.eq("UK")
  .limit(10)
  .order(Artist.name)
  .perform()

Hm. What's nice about this is that it can be made type-safe and everything.
What's not so nice is that we have to repeat Artist. all over the place.

How about this one:

  Artist.query()
    .and(
      .NAME.isLike("b%")
      .or(
        Artist.conditions() // FAIL
        .AGE.above(23),
        .AGE.below(27)
      )
  .join(Gallery.class)
    .COUNTRY.eq("UK")
  .limit(10)
  .order(Artist.name)
  .perform()

I don't like the line marked FAIL, it's two tokens (Artist and conditions) just to make Java
happy.
I'll have to come up with something better. Maybe make the nesting structure explicit with
an .end() call:

  Artist.query()
  .and()
    .NAME.isLike("b%")
    .or()
      .AGE.above(23)
      .AGE.below(27)
    .end()
  .end() // redundant
  .order()
    .NAME
  .end() // redundant
  .join(Gallery.class)
  .COUNTRY.eq("UK")
  .perform()

Some of the .end() calls are redundant and could be eliminated.
It's still relatively compact, at the price of the occasional end() - those marked with "redundant"
probably could be eliminated, so it's not so bad.

This all smells like a generalized type-safe expression builder trying to get out.

Unfortunately, I won't be able make this into a proof of concept, much less program it, so
I'm limited to providing food for thought. Hope it helps - if not, please ignore :-)

Regards,
Jo

Mime
View raw message