You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@cayenne.apache.org by Andrus Adamchik <an...@objectstyle.org> on 2014/11/15 11:39:54 UTC

Re: Chainable SelectQuery

> On Oct 11, 2014, at 4:06 AM, Andrus Adamchik <an...@objectstyle.org> wrote:
> 
> 1. Instead of drastically redoing good old SelectQuery, we'll create a separate class called ObjectSelect featuring fluent API. No deprecations in SelectQuery.

> [..]

> Also cases when you need to reset/replace previous settings. So both styles have their use. 
> 
> 2. Instead of "qualifier" the new query might just use "exp" (in addition to "and" and "or"). 
> 
> 3. ExpressionFactory.exp(..) and ObjectSelect.exp(..) should allow for both named parameter binding as well as vararg positional binding.
> 
> 4. Still need to come up with fluent API for orderings and prefetches. Separation from SelectQuery should simplify this task.
> 
> 5. The last method in a chain doesn't have to be limited to "select" and "selectOne". It can be query-specific, depending on what operations a given query supports. E.g. we can have queries with "count(context)", etc. This is something we should explore.
> 
> 6. Corollary to #5, we should explore iterator methods in query chains (need to make sure that we don't reinvent the wheels invented in Java 8).
> 
> 7. Non-selecting queries should use such API too. E.g. in addition to SQLSelect we might have SQLOperation with chain terminating with "int update(context)" or "int[] batchUpdate(context)" or "QueryResponse exec(context)". Same goes for ProcedureQuery.

The new query is checked in. It supports all the options of SelectQuery (including more exotic ones like generic query of fetching by DbEntity name), and is fully fluent. So you can do this: 

  List<Artist> artists = 
	ObjectSelect.query(Artist.class)
	.exp(Artist.ARTIST_NAME.eq("me"))
	.orderBy(Artist.DATE_OF_BIRTH.asc(), Artist.ARTIST_NAME.desc())
	.prefetch(Artist.PAINTING_ARRAY.joint())
	.localCache("cg2", "cg1").select(context);

or this (kinda shows why chains are cool) :

  for(Artist a  : ObjectSelect.query(Artist.class).select(context)) {
  	...
  }

or this:

  Artist a = ObjectSelect.query(Artist.class, Artist.ARTIST_NAME.eq("me")).selectOne(context);

Also Expression, SQLSelect and SQLTemplate now fully support positional parameters. Items 5,6,7 still need to be explored. 

Enjoy!

Andrus


Re: Chainable SelectQuery

Posted by Aristedes Maniatis <ar...@maniatis.org>.
On 17/11/2014 5:30pm, Andrus Adamchik wrote:
> What is everyone's thought on "select" -> "find" change?

I think "find" is slightly better than "select". But only slightly. Far more important is consistency and if we have a dozen other places where we still use 'select' terminology than we should keep that. SelectQuery class will probably still be called SelectQuery and not FindQuery.

Ari

-- 
-------------------------->
Aristedes Maniatis
GPG fingerprint CBFB 84B4 738D 4E87 5E5C  5EFA EF6A 7D2E 3E49 102A

Re: Chainable SelectQuery

Posted by Andrus Adamchik <an...@objectstyle.org>.
I am personally of the same opinion re: milestone API evolution.

So we have "exp" -> "where" change, which I'll make. What is everyone's thought on "select" -> "find" change?

Andrus


> On Nov 17, 2014, at 3:00 AM, Aristedes Maniatis <ar...@maniatis.org> wrote:
> 
> On 17/11/2014 1:13am, Andrus Adamchik wrote:
>> It depends. Most of the new API is very new and can be changed with no consequences. Some was already present in 3.2M1 a year ago (ObjectContext.select(..), Property). Still can change, but early adopters will be affected.
> 
> I'm a big +1 on breaking things for early adopters where the result is better naming and a better API. I think the method names chosen are very important to the usability of a library for a newcomer.
> 
> I also think we should not leave too much deprecated mess around from milestone releases. A one off change when a user goes from M1 to M2 is really not that painful. Obviously we need to be more conservative about breaking things from 3.1 release, so I'm only talking about the milestone releases here.
> 
> "where" is much clearer than "exp" and we've already discussed that there is a bit of confusion between 'qualifier', 'expression' and 'filter'.
> 
> 
> Ari
> 
> 
> -- 
> -------------------------->
> Aristedes Maniatis
> GPG fingerprint CBFB 84B4 738D 4E87 5E5C  5EFA EF6A 7D2E 3E49 102A
> 


Re: Chainable SelectQuery

Posted by Aristedes Maniatis <ar...@maniatis.org>.
On 17/11/2014 1:13am, Andrus Adamchik wrote:
> It depends. Most of the new API is very new and can be changed with no consequences. Some was already present in 3.2M1 a year ago (ObjectContext.select(..), Property). Still can change, but early adopters will be affected.

I'm a big +1 on breaking things for early adopters where the result is better naming and a better API. I think the method names chosen are very important to the usability of a library for a newcomer.

I also think we should not leave too much deprecated mess around from milestone releases. A one off change when a user goes from M1 to M2 is really not that painful. Obviously we need to be more conservative about breaking things from 3.1 release, so I'm only talking about the milestone releases here.

"where" is much clearer than "exp" and we've already discussed that there is a bit of confusion between 'qualifier', 'expression' and 'filter'.


Ari


-- 
-------------------------->
Aristedes Maniatis
GPG fingerprint CBFB 84B4 738D 4E87 5E5C  5EFA EF6A 7D2E 3E49 102A

Re: Chainable SelectQuery

Posted by Andrus Adamchik <an...@objectstyle.org>.
It is kind of hard for us to detect and prevent all possible conflicts in the *downstream* code like this. Hope this is not something that completely prevents the use of Cayenne with Scala though.

Andrus


> On Nov 17, 2014, at 7:59 PM, David Feshbach <dj...@gmail.com> wrote:
> 
> One possible reason to avoid "eq" and "ne" is that they are already methods on Scala's AnyRef. When using Cayenne in Scala, I get errors like this in my IDE:
>> org.apache.cayenne.exp.Property[String] and String are unrelated: they will most likely never compare equal
> 
> On Nov 17, 2014, at 9:09 AM, John Huss <jo...@gmail.com> wrote:
> 
>> I definitely do not want "is", especially since the the negated operation
>> has to be consistent - "eq" and "ne" works.
>> 
>> I like "where".
>> 
>> I would stick with "select" since we have SQLSelect and ObjectSelect.
>> Unless we have good alternatives names for those too.
>> 
>> 
>> On Mon, Nov 17, 2014 at 8:42 AM, Andrus Adamchik <an...@objectstyle.org>
>> wrote:
>> 
>>> Cayenne Property class is using 'eq' for the same reason.
>>> 
>>>> On Nov 17, 2014, at 5:07 PM, Mike Kienenberger <mk...@gmail.com>
>>> wrote:
>>>> 
>>>> Chainable fest testing assertions use "isEqualTo" to avoid confusion
>>>> with "equals"
>>>> 
>>>> 
>>>> On Mon, Nov 17, 2014 at 9:01 AM, Michael Gentry <mg...@masslight.net>
>>> wrote:
>>>>> On Sun, Nov 16, 2014 at 9:13 AM, Andrus Adamchik <
>>> andrus@objectstyle.org> wrote:
>>>>>>> "eq" with "is",
>>>>>> 
>>>>>> I actually prefer "eq[uals]". Considering all other operations in the
>>> Property class, "is" creates a bit of asymmetry IMO.
>>>>> 
>>>>> The problem with "equals" is it has other connotations in Java,
>>>>> otherwise I'd like it just fine.  Of course, you could argue that "is"
>>>>> also has other Java connotations (JavaBeans is* method naming
>>>>> convention).
>>>>> 
>>>>> mrg
>>>> 
>>> 
>>> 
> 
> 


Re: Chainable SelectQuery

Posted by David Feshbach <dj...@gmail.com>.
One possible reason to avoid "eq" and "ne" is that they are already methods on Scala's AnyRef. When using Cayenne in Scala, I get errors like this in my IDE:
> org.apache.cayenne.exp.Property[String] and String are unrelated: they will most likely never compare equal

On Nov 17, 2014, at 9:09 AM, John Huss <jo...@gmail.com> wrote:

> I definitely do not want "is", especially since the the negated operation
> has to be consistent - "eq" and "ne" works.
> 
> I like "where".
> 
> I would stick with "select" since we have SQLSelect and ObjectSelect.
> Unless we have good alternatives names for those too.
> 
> 
> On Mon, Nov 17, 2014 at 8:42 AM, Andrus Adamchik <an...@objectstyle.org>
> wrote:
> 
>> Cayenne Property class is using 'eq' for the same reason.
>> 
>>> On Nov 17, 2014, at 5:07 PM, Mike Kienenberger <mk...@gmail.com>
>> wrote:
>>> 
>>> Chainable fest testing assertions use "isEqualTo" to avoid confusion
>>> with "equals"
>>> 
>>> 
>>> On Mon, Nov 17, 2014 at 9:01 AM, Michael Gentry <mg...@masslight.net>
>> wrote:
>>>> On Sun, Nov 16, 2014 at 9:13 AM, Andrus Adamchik <
>> andrus@objectstyle.org> wrote:
>>>>>> "eq" with "is",
>>>>> 
>>>>> I actually prefer "eq[uals]". Considering all other operations in the
>> Property class, "is" creates a bit of asymmetry IMO.
>>>> 
>>>> The problem with "equals" is it has other connotations in Java,
>>>> otherwise I'd like it just fine.  Of course, you could argue that "is"
>>>> also has other Java connotations (JavaBeans is* method naming
>>>> convention).
>>>> 
>>>> mrg
>>> 
>> 
>> 


Re: Chainable SelectQuery

Posted by John Huss <jo...@gmail.com>.
I definitely do not want "is", especially since the the negated operation
has to be consistent - "eq" and "ne" works.

I like "where".

I would stick with "select" since we have SQLSelect and ObjectSelect.
Unless we have good alternatives names for those too.


On Mon, Nov 17, 2014 at 8:42 AM, Andrus Adamchik <an...@objectstyle.org>
wrote:

> Cayenne Property class is using 'eq' for the same reason.
>
> > On Nov 17, 2014, at 5:07 PM, Mike Kienenberger <mk...@gmail.com>
> wrote:
> >
> > Chainable fest testing assertions use "isEqualTo" to avoid confusion
> > with "equals"
> >
> >
> > On Mon, Nov 17, 2014 at 9:01 AM, Michael Gentry <mg...@masslight.net>
> wrote:
> >> On Sun, Nov 16, 2014 at 9:13 AM, Andrus Adamchik <
> andrus@objectstyle.org> wrote:
> >>>> "eq" with "is",
> >>>
> >>> I actually prefer "eq[uals]". Considering all other operations in the
> Property class, "is" creates a bit of asymmetry IMO.
> >>
> >> The problem with "equals" is it has other connotations in Java,
> >> otherwise I'd like it just fine.  Of course, you could argue that "is"
> >> also has other Java connotations (JavaBeans is* method naming
> >> convention).
> >>
> >> mrg
> >
>
>

Re: Chainable SelectQuery

Posted by Andrus Adamchik <an...@objectstyle.org>.
Cayenne Property class is using 'eq' for the same reason. 

> On Nov 17, 2014, at 5:07 PM, Mike Kienenberger <mk...@gmail.com> wrote:
> 
> Chainable fest testing assertions use "isEqualTo" to avoid confusion
> with "equals"
> 
> 
> On Mon, Nov 17, 2014 at 9:01 AM, Michael Gentry <mg...@masslight.net> wrote:
>> On Sun, Nov 16, 2014 at 9:13 AM, Andrus Adamchik <an...@objectstyle.org> wrote:
>>>> "eq" with "is",
>>> 
>>> I actually prefer "eq[uals]". Considering all other operations in the Property class, "is" creates a bit of asymmetry IMO.
>> 
>> The problem with "equals" is it has other connotations in Java,
>> otherwise I'd like it just fine.  Of course, you could argue that "is"
>> also has other Java connotations (JavaBeans is* method naming
>> convention).
>> 
>> mrg
> 


Re: Chainable SelectQuery

Posted by Mike Kienenberger <mk...@gmail.com>.
Chainable fest testing assertions use "isEqualTo" to avoid confusion
with "equals"


On Mon, Nov 17, 2014 at 9:01 AM, Michael Gentry <mg...@masslight.net> wrote:
> On Sun, Nov 16, 2014 at 9:13 AM, Andrus Adamchik <an...@objectstyle.org> wrote:
>>> "eq" with "is",
>>
>> I actually prefer "eq[uals]". Considering all other operations in the Property class, "is" creates a bit of asymmetry IMO.
>
> The problem with "equals" is it has other connotations in Java,
> otherwise I'd like it just fine.  Of course, you could argue that "is"
> also has other Java connotations (JavaBeans is* method naming
> convention).
>
> mrg

Re: Chainable SelectQuery

Posted by Michael Gentry <mg...@masslight.net>.
On Sun, Nov 16, 2014 at 9:13 AM, Andrus Adamchik <an...@objectstyle.org> wrote:
>> "eq" with "is",
>
> I actually prefer "eq[uals]". Considering all other operations in the Property class, "is" creates a bit of asymmetry IMO.

The problem with "equals" is it has other connotations in Java,
otherwise I'd like it just fine.  Of course, you could argue that "is"
also has other Java connotations (JavaBeans is* method naming
convention).

mrg

Re: Chainable SelectQuery

Posted by Andrus Adamchik <an...@objectstyle.org>.
> On Nov 16, 2014, at 4:49 PM, Michael Gentry <mg...@masslight.net> wrote:
> Perhaps I've missed the boat on this one

It depends. Most of the new API is very new and can be changed with no consequences. Some was already present in 3.2M1 a year ago (ObjectContext.select(..), Property). Still can change, but early adopters will be affected.

> Replace "exp" with "where",

I am ok with "where". We have complimentary methods in ObjectSelect: "and" and "or". Where..and...or mirrors SQL, which is probably a good thing.

> "eq" with "is",

I actually prefer "eq[uals]". Considering all other operations in the Property class, "is" creates a bit of asymmetry IMO.

> "select" with "fetch" (since it is actually fetching your records), etc.  

I am open to it, though we'll need to review the API across the board. E.g. "select" / "selectOne" is already used in ObjectContext and originated from the new "Select" interface. I think "find*" is often used in other frameworks/languages, and sounds better than "select". We may refactor to use find/findFirst/findAll.

> PS. Yesterday afternoon I was going through some of the JIRA issues
> and saw some interesting screenshots for modeler changes where
> attributes and relationships were being merged.  Quite interested in
> checking that out, too.

Yep. That's committed to master.

Andrus

Re: Chainable SelectQuery

Posted by Michael Gentry <mg...@masslight.net>.
Hi Andrus,

Perhaps I've missed the boat on this one (been too busy at work, etc),
but I think it might be more readable to not abbreviate names and
perhaps make it read more like a sentence.  Given your example,
perhaps something like:

List<Artist> artists =
  ObjectSelect.query(Artist.class)
  .where(Artist.ARTIST_NAME.is("me"))
  .orderBy(Artist.DATE_OF_BIRTH.ascending(), Artist.ARTIST_NAME.descending())
  .prefetch(Artist.PAINTING_ARRAY.joint())
  .localCache("cg2", "cg1").fetch(context);

Replace "exp" with "where", "eq" with "is", "select" with "fetch"
(since it is actually fetching your records), etc.  (Choosing good
names is quite difficult -- I'm just tossing some ideas out.)

So: Create a query for Artist where name is "me", order by date of
birth (ascending), name (descending), prefetching paintings and use
local cache.  OK, fetch them into this context.

I really need to update and try the new code.

Thanks,

mrg

PS. Yesterday afternoon I was going through some of the JIRA issues
and saw some interesting screenshots for modeler changes where
attributes and relationships were being merged.  Quite interested in
checking that out, too.


On Sat, Nov 15, 2014 at 5:39 AM, Andrus Adamchik <an...@objectstyle.org> wrote:
>
>> On Oct 11, 2014, at 4:06 AM, Andrus Adamchik <an...@objectstyle.org> wrote:
>>
>> 1. Instead of drastically redoing good old SelectQuery, we'll create a separate class called ObjectSelect featuring fluent API. No deprecations in SelectQuery.
>
>> [..]
>
>> Also cases when you need to reset/replace previous settings. So both styles have their use.
>>
>> 2. Instead of "qualifier" the new query might just use "exp" (in addition to "and" and "or").
>>
>> 3. ExpressionFactory.exp(..) and ObjectSelect.exp(..) should allow for both named parameter binding as well as vararg positional binding.
>>
>> 4. Still need to come up with fluent API for orderings and prefetches. Separation from SelectQuery should simplify this task.
>>
>> 5. The last method in a chain doesn't have to be limited to "select" and "selectOne". It can be query-specific, depending on what operations a given query supports. E.g. we can have queries with "count(context)", etc. This is something we should explore.
>>
>> 6. Corollary to #5, we should explore iterator methods in query chains (need to make sure that we don't reinvent the wheels invented in Java 8).
>>
>> 7. Non-selecting queries should use such API too. E.g. in addition to SQLSelect we might have SQLOperation with chain terminating with "int update(context)" or "int[] batchUpdate(context)" or "QueryResponse exec(context)". Same goes for ProcedureQuery.
>
> The new query is checked in. It supports all the options of SelectQuery (including more exotic ones like generic query of fetching by DbEntity name), and is fully fluent. So you can do this:
>
>   List<Artist> artists =
>         ObjectSelect.query(Artist.class)
>         .exp(Artist.ARTIST_NAME.eq("me"))
>         .orderBy(Artist.DATE_OF_BIRTH.asc(), Artist.ARTIST_NAME.desc())
>         .prefetch(Artist.PAINTING_ARRAY.joint())
>         .localCache("cg2", "cg1").select(context);
>
> or this (kinda shows why chains are cool) :
>
>   for(Artist a  : ObjectSelect.query(Artist.class).select(context)) {
>         ...
>   }
>
> or this:
>
>   Artist a = ObjectSelect.query(Artist.class, Artist.ARTIST_NAME.eq("me")).selectOne(context);
>
> Also Expression, SQLSelect and SQLTemplate now fully support positional parameters. Items 5,6,7 still need to be explored.
>
> Enjoy!
>
> Andrus
>

Re: Chainable SelectQuery

Posted by Andrus Adamchik <an...@objectstyle.org>.
> On Nov 29, 2014, at 4:09 AM, Aristedes Maniatis <ar...@maniatis.org> wrote:
> 
> On 29/11/2014 1:01am, Andrus Adamchik wrote:
>> Just added another flavor of select method - 'selectFirst'. Unlike 'selectOne' intended for queries that expect at most one row back, 'selectFirst' is a quick way to get the top-of-the-list object, even if the query matched many objects. I.e. it is equivalent to "limit(1).selectOne(context)".
> 
> * Does selectOne() throw an exception if it gets back more than one row? Is that the main difference between the functions for a user?

Correct.

> * For performance reasons, should selectOne put LIMIT 2 into the SQL since it will only discard additional objects anyway?

We may. Though since it throws in such cases, it would only be relevant if there's a programmer error (query syntax implies > 1 row) or ref integrity problem in DB (no unique constraint where it is expected), so this has never been a problem in practice.

Andrus

Re: Chainable SelectQuery

Posted by Aristedes Maniatis <ar...@maniatis.org>.
On 29/11/2014 1:01am, Andrus Adamchik wrote:
> Just added another flavor of select method - 'selectFirst'. Unlike 'selectOne' intended for queries that expect at most one row back, 'selectFirst' is a quick way to get the top-of-the-list object, even if the query matched many objects. I.e. it is equivalent to "limit(1).selectOne(context)".

* Does selectOne() throw an exception if it gets back more than one row? Is that the main difference between the functions for a user?
* For performance reasons, should selectOne put LIMIT 2 into the SQL since it will only discard additional objects anyway?


Ari



-- 
-------------------------->
Aristedes Maniatis
GPG fingerprint CBFB 84B4 738D 4E87 5E5C  5EFA EF6A 7D2E 3E49 102A

Re: Chainable SelectQuery

Posted by Andrus Adamchik <an...@objectstyle.org>.
Just added another flavor of select method - 'selectFirst'. Unlike 'selectOne' intended for queries that expect at most one row back, 'selectFirst' is a quick way to get the top-of-the-list object, even if the query matched many objects. I.e. it is equivalent to "limit(1).selectOne(context)".

Andrus