cayenne-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Aristedes Maniatis <...@maniatis.org>
Subject Re: split expressions
Date Thu, 14 Jan 2010 09:40:56 GMT
On 14/01/10 8:10 PM, Andrus Adamchik wrote:
>
> On Jan 13, 2010, at 2:38 PM, Aristedes Maniatis wrote:
>
>> I've tried to explain the current usage better in the docs, given what
>> I now understand. Please let me know if I misunderstood something. I
>> had originally thought they were there as shortcuts to a path string.
>
> Actually we may start using them that purpose as well in 3.1 when and if
> we merge SelectQuery and EJBQLQuery into a new SuperSelectQuery. Now I
> think I remember that a possibility of unifying expressions with EJBQL
> was considered when designing the API for splits. Hence aliases were
> suggested.
>
>
>> A way think of aliases is that they are markers within part of an
>> expression which give Cayenne hints about merging. Like a query cache
>> key, they are important only if you use the same key twice. But
>> because aliases are created when you create the Expression path
>> string, and then expanded when you construct the query, they can be
>> awkward to use. It would be nicer if the Expression carried not only
>> the idea of the key, but also how it expands and passed that onto the
>> query.
>>
>> Expression e1 = ExpressionFactory.like("path1|paintings.gallery.name",
>> "foo");
>> Expression e2 = ExpressionFactory.like("path2|paintings.gallery.name",
>> "bar");
>>
>> This puts the definition of the alias and the expansion in the same
>> logical place. It would also allow
>>
>> Expression e2 = ExpressionFactory.like("path2|", "bar");
>>
>> to use the alias previously defined. Or to have Cayenne construct an
>> arbitrary random, non-reusable alias:
>>
>> Expression e1 = ExpressionFactory.like("|paintings.gallery.name", "foo");
>>
>> Then you could even define an expression
>>
>> Expression e1 = Expression.fromString("|paintings.gallery.name = foo
>> and |paintings.gallery.name = bar")
>
>
> So the name before the pipe is an alias, right? Then how do we create
> splits in the middle of the path?

   paintings.|gallery.name

You could even this which uses an existing alias:

   paintings.path2|.name

or this which makes a named alias:

   paintings.path2|gallery.name


But the syntax is prone to confusion because it is hard to read. On the plus side though,
I can't imagine why anyone would want to use named aliases in this way, so they are likely
to be rare.


>  I guess we can have a more complex
> notation:
>
> Artist.PAINTINGS.dot(Painting.EXHIBITS).alias("X").dot(Exhibit.GALLERIES).eq("Y");


This is a long way from obvious for the most common use of the syntax: combining AND queries
across a to-many join. Sure named aliases might be useful in themselves, maybe, for someone.
I can't personally think of a reason. But the following seems clearer to me:

   Artist.PAINTINGS.join(Painting.EXHIBITS, Expression.SPLIT_PATH).join(Exhibit.GALLERIES).like("Y")

My overall preference is to make the expression functions slightly more SQL-like, with words
like join and like. Avoiding abstract ideas like 'alias' where they aren't relevant to the
user is part of that same goal. In fact 'alias' has a specific SQL common meaning (table aliases)
which is only going to confuse new users.

If you really want to name an alias:

   Artist.PAINTINGS.join(Painting.EXHIBITS, "aliasX").join(Exhibit.GALLERIES).like("Y")


> or setting the path, specifying the number of segments:
>
> Artist.PAINTINGS.dot(Painting.EXHIBITS).dot(Exhibit.GALLERIES).alias("X", 2);


Maybe as an option, but I'd never use it. Consider the method:

performAQuery(Expression e) {
   e1 = e.and(somequalifier);
   performMyQuery(e1.alias("X", 2); // what did that just do? How long was the path expression
passed to the method?
}


>
>
> (s/dot/join/ or whatever)
>
> or the old way:
>
> // this will probably require defining a special Expression subclass -
> KeyValueCondition or something
> // that ensures there's only a single path inside
> ExpressionFactory.like("paintings.gallery.name", "foo").split("X", 2);

Just throw a runtime exception...

Or if you really wanted to, promote 'path expression' from being just a String to having its
own class. Then alias is just a special case of Path. Come to think of it, what is the difference
between your new Key typesafe class and Path, other than a few dots...


> So yeah, we are definitely making progress. One remaining case that is
> still not accommodated is when subexpressions are created "in the
> vacuum" with no knowledge of the overall query context. So we need to
> take an existing (possibly nested) conditional expression and setup
> correct splits for one or more of its paths. I guess some expression
> transformer is needed here.

My guess is that 99% of use cases would be met with a parameter to pass into the query which
splits ALL paths. It would actually solve every instance of why we started this conversation
in the first splace.

Ari



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

Mime
View raw message