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
This archive was generated by hypermail 2.0.0 : Thu Jan 14 2010 - 04:41:37 EST