Re: ColumnSelect API + Persistent objects

2017-03-21 Thread Nikita Timofeev
Here is latest version that already committed and can be tested:

ObjectSelect
.columnQuery(Artist.class,
Property.createSelf(Artist.class),
 // query root
Artist.PAINTING_ARRAY.dot(Painting.GALLERY),  // toOne relationship
Artist.PAINTING_ARRAY.flat(Painting.class))  //
flattened toMany relationship
.select(context);

On Thu, Mar 16, 2017 at 11:48 AM, Andrus Adamchik
 wrote:
>
>
>> On Mar 16, 2017, at 11:14 AM, Nikita Timofeev  
>> wrote:
>>
>> On Mon, Mar 13, 2017 at 3:05 PM, Aristedes Maniatis  
>> wrote:
>>> On 13/3/17 9:53pm, Andrus Adamchik wrote:

> On Mar 13, 2017, at 1:46 PM, Aristedes Maniatis  wrote:
>
>
> Just a wild thought, but would this syntax be helpful...
>
> List result = ObjectSelect.query(Artist.class)
>.addColumns(Artist.PAINTING_COUNT)
>.select(context);
>
> So then we are adding more columns to the existing DataObject query 
> rather than having to define the DataObjects as properties in themselves. 
> The syntax above might be simpler to understand and write.

 So "addColumns" vs "columns"? IIRC we tried something similar with 
 orderings (override all orderings vs add to the existing orderings), and 
 that confused everybody (including me as the author), so that was undone 
 between the milestones.
>>>
>>>
>>> Except in this case it is very different result since with this syntax you 
>>> get the mixed columns/DataObject results and avoid needing to create 
>>> properties for 'self' or some other confusing construct.
>>>
>>
>> I think we can add Property SELF to default cgen
>> templates, then everything will be pretty simple:
>>
>>ObjectSelect
>>.columnQuery(Artist.class, Artist.SELF, Artist.PAINTING_ARRAY.count())
>>.select(context);
>>
>
> A good idea except for a possible naming conflict if a Java object has a 
> persistent property called "self".
>
> Andrus



-- 
Best regards,
Nikita Timofeev


Re: ColumnSelect API + Persistent objects

2017-03-16 Thread Andrus Adamchik


> On Mar 16, 2017, at 11:14 AM, Nikita Timofeev  
> wrote:
> 
> On Mon, Mar 13, 2017 at 3:05 PM, Aristedes Maniatis  wrote:
>> On 13/3/17 9:53pm, Andrus Adamchik wrote:
>>> 
 On Mar 13, 2017, at 1:46 PM, Aristedes Maniatis  wrote:
 
 
 Just a wild thought, but would this syntax be helpful...
 
 List result = ObjectSelect.query(Artist.class)
.addColumns(Artist.PAINTING_COUNT)
.select(context);
 
 So then we are adding more columns to the existing DataObject query rather 
 than having to define the DataObjects as properties in themselves. The 
 syntax above might be simpler to understand and write.
>>> 
>>> So "addColumns" vs "columns"? IIRC we tried something similar with 
>>> orderings (override all orderings vs add to the existing orderings), and 
>>> that confused everybody (including me as the author), so that was undone 
>>> between the milestones.
>> 
>> 
>> Except in this case it is very different result since with this syntax you 
>> get the mixed columns/DataObject results and avoid needing to create 
>> properties for 'self' or some other confusing construct.
>> 
> 
> I think we can add Property SELF to default cgen
> templates, then everything will be pretty simple:
> 
>ObjectSelect
>.columnQuery(Artist.class, Artist.SELF, Artist.PAINTING_ARRAY.count())
>.select(context);
> 

A good idea except for a possible naming conflict if a Java object has a 
persistent property called "self".

Andrus

Re: ColumnSelect API + Persistent objects

2017-03-16 Thread Nikita Timofeev
On Mon, Mar 13, 2017 at 3:05 PM, Aristedes Maniatis  wrote:
> On 13/3/17 9:53pm, Andrus Adamchik wrote:
>>
>>> On Mar 13, 2017, at 1:46 PM, Aristedes Maniatis  wrote:
>>>
>>>
>>> Just a wild thought, but would this syntax be helpful...
>>>
>>> List result = ObjectSelect.query(Artist.class)
>>> .addColumns(Artist.PAINTING_COUNT)
>>> .select(context);
>>>
>>> So then we are adding more columns to the existing DataObject query rather 
>>> than having to define the DataObjects as properties in themselves. The 
>>> syntax above might be simpler to understand and write.
>>
>> So "addColumns" vs "columns"? IIRC we tried something similar with orderings 
>> (override all orderings vs add to the existing orderings), and that confused 
>> everybody (including me as the author), so that was undone between the 
>> milestones.
>
>
> Except in this case it is very different result since with this syntax you 
> get the mixed columns/DataObject results and avoid needing to create 
> properties for 'self' or some other confusing construct.
>

I think we can add Property SELF to default cgen
templates, then everything will be pretty simple:

ObjectSelect
.columnQuery(Artist.class, Artist.SELF, Artist.PAINTING_ARRAY.count())
.select(context);


-- 
Best regards,
Nikita Timofeev


Re: ColumnSelect API + Persistent objects

2017-03-13 Thread Aristedes Maniatis
On 13/3/17 9:53pm, Andrus Adamchik wrote:
> 
>> On Mar 13, 2017, at 1:46 PM, Aristedes Maniatis  wrote:
>>
>>
>> Just a wild thought, but would this syntax be helpful...
>>
>> List result = ObjectSelect.query(Artist.class)
>> .addColumns(Artist.PAINTING_COUNT)
>> .select(context);
>>
>> So then we are adding more columns to the existing DataObject query rather 
>> than having to define the DataObjects as properties in themselves. The 
>> syntax above might be simpler to understand and write.
> 
> So "addColumns" vs "columns"? IIRC we tried something similar with orderings 
> (override all orderings vs add to the existing orderings), and that confused 
> everybody (including me as the author), so that was undone between the 
> milestones.


Except in this case it is very different result since with this syntax you get 
the mixed columns/DataObject results and avoid needing to create properties for 
'self' or some other confusing construct.


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


Re: ColumnSelect API + Persistent objects

2017-03-13 Thread Andrus Adamchik

> On Mar 13, 2017, at 1:46 PM, Aristedes Maniatis  wrote:
> 
> 
> Just a wild thought, but would this syntax be helpful...
> 
> List result = ObjectSelect.query(Artist.class)
> .addColumns(Artist.PAINTING_COUNT)
> .select(context);
> 
> So then we are adding more columns to the existing DataObject query rather 
> than having to define the DataObjects as properties in themselves. The syntax 
> above might be simpler to understand and write.

So "addColumns" vs "columns"? IIRC we tried something similar with orderings 
(override all orderings vs add to the existing orderings), and that confused 
everybody (including me as the author), so that was undone between the 
milestones.

Andrus



Re: ColumnSelect API + Persistent objects

2017-03-13 Thread Aristedes Maniatis
On 13/3/17 7:26pm, Andrus Adamchik wrote:
> 
> Yep. A typical use case for intermixing DataObjects and scalars in the result 
> is this: [, ] that gives us each object's to-many 
> counts without resolving to-many relationships. What I am unsure though is 
> whether [, ] result is of any use to anyone.


Just a wild thought, but would this syntax be helpful...

List result = ObjectSelect.query(Artist.class)
 .addColumns(Artist.PAINTING_COUNT)
 .select(context);

So then we are adding more columns to the existing DataObject query rather than 
having to define the DataObjects as properties in themselves. The syntax above 
might be simpler to understand and write.


>> Are users going to be confused that the ObjEntities are bound to a context 
>> and editable/committable, but the raw columns are not?
> I am not concerned about this. I think everyone should understand that only 
> DataObjects can be committed. Any other representations is non-updateable 
> data.

Perhaps, but this is the first time these two things are inter-mingled in one 
list. And I've always thought of contexts as 'owning' the items within the 
result list. But as long as users are clear that contexts control the elements 
in the result and not the list itself, then I'm probably overthinking it.


Ari



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


Re: ColumnSelect API + Persistent objects

2017-03-13 Thread Nikita Timofeev
>
> What is the output of this:
>
> result = ObjectSelect.query(Artist.class)
>.columns(createSelf(Artist.class))
>.select(context);
>
> Is that the same as
>
> result = ObjectSelect.query(Artist.class)
>.select(context);
>
> would the generated SQL be the same?
>

Small comment on this.

With columns() method the result will be List (where
Object[0] is an Artist object).
And with column() method both results will be identical (List).

Generated SQL should be the same too, though direct query apparently
is more efficient,
as it will use some shortcuts based on assumption that it will get
only one type of objects.

-- 
Best regards,
Nikita Timofeev


Re: ColumnSelect API + Persistent objects

2017-03-13 Thread Andrus Adamchik
> Oh, I get it now. You are suggesting in option (2) that Cayenne creates a 
> CROSS JOIN in sql.

Actually not a CROSS join. It will be a regular INNER JOIN based on 
relationship from the query root. JPA spec defines CROSS join operations. We 
don't (yet?).

> Sometimes you want to fetch specific columns as read-only for performance 
> reasons. I get that. You save on fetching data and you save time on 
> constructing full ObjEntities.


Yep. A typical use case for intermixing DataObjects and scalars in the result 
is this: [, ] that gives us each object's to-many 
counts without resolving to-many relationships. What I am unsure though is 
whether [, ] result is of any use to anyone.

> Are users going to be confused that the ObjEntities are bound to a context 
> and editable/committable, but the raw columns are not?

I am not concerned about this. I think everyone should understand that only 
DataObjects can be committed. Any other representations is non-updateable data.

Andrus


> On Mar 13, 2017, at 10:29 AM, Aristedes Maniatis  wrote:
> 
> On 13/3/17 5:57pm, Andrus Adamchik wrote:
>> 
> 
> List result = ObjectSelect.query(Artist.class)
>  .columns(Artist.ARTIST_NAME, Artist.PAINTING_ARRAY)
>  .select(context);
>> 
>> 
 For me it's not clear when do we need direct List result for toMany
 relationship instead of using Prefetch (or even selecting related
 entities explicitly).
>> 
>> Let's ponder on this some more. In the example above there are two possible 
>> result mappings of to-many - each cell at index 1 can store either (1) a 
>> List or (2) a Painting. Of course in the second case Artist name 
>> at index 0 will be repeated for each painting of a given Artist (so the 
>> result is flattened). 
>> 
>> In the proposed solution we throw in the first case and support the second. 
>> I'd like to hear opinions on the usefulness of either of the cases, and 
>> maybe some real life examples.
> 
> 
> Oh, I get it now. You are suggesting in option (2) that Cayenne creates a 
> CROSS JOIN in sql.
> 
> Surely most of the time we are steering users to creating ObjEntities where 
> possible; then they have the full access to follow relations, prefetching, 
> pagination, etc, etc.
> 
> Sometimes you want to fetch specific columns as read-only for performance 
> reasons. I get that. You save on fetching data and you save time on 
> constructing full ObjEntities. But then why would you want to embed full 
> ObjEntities in the result? Any performance benefits are surely out the 
> window. So what's the point and the use-case?
> 
> 
> 
> Are users going to be confused that the ObjEntities are bound to a context 
> and editable/committable, but the raw columns are not?
> 
> result.get(0)[3][1].setName("The scream")
> result.get(0)[2] = "Munch"
> context.commit()
> 
> 
> 
> What is the output of this:
> 
> result = ObjectSelect.query(Artist.class)
>   .columns(createSelf(Artist.class))
>   .select(context);
> 
> Is that the same as 
> 
> result = ObjectSelect.query(Artist.class)
>   .select(context);
> 
> would the generated SQL be the same?
> 
> Ari
> 
> 
> 
> 
> -- 
> -->
> Aristedes Maniatis
> GPG fingerprint CBFB 84B4 738D 4E87 5E5C  5EFA EF6A 7D2E 3E49 102A



Re: ColumnSelect API + Persistent objects

2017-03-13 Thread Aristedes Maniatis
On 13/3/17 5:57pm, Andrus Adamchik wrote:
> 

 List result = ObjectSelect.query(Artist.class)
   .columns(Artist.ARTIST_NAME, Artist.PAINTING_ARRAY)
   .select(context);
> 
> 
>>> For me it's not clear when do we need direct List result for toMany
>>> relationship instead of using Prefetch (or even selecting related
>>> entities explicitly).
> 
> Let's ponder on this some more. In the example above there are two possible 
> result mappings of to-many - each cell at index 1 can store either (1) a 
> List or (2) a Painting. Of course in the second case Artist name at 
> index 0 will be repeated for each painting of a given Artist (so the result 
> is flattened). 
> 
> In the proposed solution we throw in the first case and support the second. 
> I'd like to hear opinions on the usefulness of either of the cases, and maybe 
> some real life examples.


Oh, I get it now. You are suggesting in option (2) that Cayenne creates a CROSS 
JOIN in sql.

Surely most of the time we are steering users to creating ObjEntities where 
possible; then they have the full access to follow relations, prefetching, 
pagination, etc, etc.

Sometimes you want to fetch specific columns as read-only for performance 
reasons. I get that. You save on fetching data and you save time on 
constructing full ObjEntities. But then why would you want to embed full 
ObjEntities in the result? Any performance benefits are surely out the window. 
So what's the point and the use-case?



Are users going to be confused that the ObjEntities are bound to a context and 
editable/committable, but the raw columns are not?

result.get(0)[3][1].setName("The scream")
result.get(0)[2] = "Munch"
context.commit()



What is the output of this:

result = ObjectSelect.query(Artist.class)
   .columns(createSelf(Artist.class))
   .select(context);

Is that the same as 

result = ObjectSelect.query(Artist.class)
   .select(context);

would the generated SQL be the same?

Ari




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


Re: ColumnSelect API + Persistent objects

2017-03-12 Thread Andrus Adamchik

>>> 
>>> List result = ObjectSelect.query(Artist.class)
>>>   .columns(Artist.ARTIST_NAME, Artist.PAINTING_ARRAY)
>>>   .select(context);


>> For me it's not clear when do we need direct List result for toMany
>> relationship instead of using Prefetch (or even selecting related
>> entities explicitly).

Let's ponder on this some more. In the example above there are two possible 
result mappings of to-many - each cell at index 1 can store either (1) a 
List or (2) a Painting. Of course in the second case Artist name at 
index 0 will be repeated for each painting of a given Artist (so the result is 
flattened). 

In the proposed solution we throw in the first case and support the second. I'd 
like to hear opinions on the usefulness of either of the cases, and maybe some 
real life examples.

Andrus



Re: ColumnSelect API + Persistent objects

2017-03-12 Thread Andrus Adamchik

> On Mar 9, 2017, at 10:17 AM, Nikita Timofeev  
> wrote:
> 
> On Wed, Mar 8, 2017 at 3:48 AM, Aristedes Maniatis  wrote:
>> On 7/3/17 11:12pm, Nikita Timofeev wrote:
>>> 2) Add new factory methods in Property class:
>>> 
>>> Property createSelf(Class type);
>> 
>> Why wouldn't we just use normal constructors?
>> 
>> a = new Property(Artist.class);
> 
> That's because createSelf() method will create expression needed for
> this to work.
> And as mentioned in the first mail this new expression can later be
> used in other ways.

So if we call it just "create(Class)" instead of "createSelf", will it cause 
any ambiguity?


>>> Property createForRelationship(
>>>   Property property, Class type)
>> 
>>> 3) Prohibit direct usages of properties mapped on toMany
>>> relationships, so that the following code will throw a
>>> CayenneRuntimeException
>>> 
>>> List result = ObjectSelect.query(Artist.class)
>>>.columns(Artist.ARTIST_NAME, Artist.PAINTING_ARRAY)
>>>.select(context);
>> 
>> I'm confused about why we need a new type of property for this rather than 
>> just using Artist.PAINTING_ARRAY
>> 
> 
> This is because PAINTING_ARRAY have List type and we
> currently can provide only Painting.
> So to have proper type we need another Property to be created.
> Thou it is indeed a question whether we need this at all:
> a ColumnSelect result as it will be is raw SQL, i.e. in this example
> Paintings not folded into a List.
> 
> For me it's not clear when do we need direct List result for toMany
> relationship instead of using Prefetch (or even selecting related
> entities explicitly).


So while I understand what we are trying to do with "createForRelationship" 
(this is a "flatMap"-like transformation), I am wondering how we can make the 
semantics more transparent? Perhaps we add "flat()" method to the Property 
itself:

Property> listProperty = Artist.PAINTING_ARRAY;
Property objectProperty = listProperty.flat(); // or 'flatMap'?

Andrus





Re: ColumnSelect API + Persistent objects

2017-03-08 Thread Nikita Timofeev
On Wed, Mar 8, 2017 at 3:48 AM, Aristedes Maniatis  wrote:
> On 7/3/17 11:12pm, Nikita Timofeev wrote:
>> 2) Add new factory methods in Property class:
>>
>>  Property createSelf(Class type);
>
> Why wouldn't we just use normal constructors?
>
> a = new Property(Artist.class);

That's because createSelf() method will create expression needed for
this to work.
And as mentioned in the first mail this new expression can later be
used in other ways.

>
>>  Property createForRelationship(
>>Property property, Class type)
>
>> 3) Prohibit direct usages of properties mapped on toMany
>> relationships, so that the following code will throw a
>> CayenneRuntimeException
>>
>> List result = ObjectSelect.query(Artist.class)
>> .columns(Artist.ARTIST_NAME, Artist.PAINTING_ARRAY)
>> .select(context);
>
> I'm confused about why we need a new type of property for this rather than 
> just using Artist.PAINTING_ARRAY
>

This is because PAINTING_ARRAY have List type and we
currently can provide only Painting.
So to have proper type we need another Property to be created.
Thou it is indeed a question whether we need this at all:
a ColumnSelect result as it will be is raw SQL, i.e. in this example
Paintings not folded into a List.

For me it's not clear when do we need direct List result for toMany
relationship instead of using Prefetch (or even selecting related
entities explicitly).

-- 
Best regards,
Nikita Timofeev


Re: ColumnSelect API + Persistent objects

2017-03-07 Thread Aristedes Maniatis
On 7/3/17 11:12pm, Nikita Timofeev wrote:
> 2) Add new factory methods in Property class:
> 
>  Property createSelf(Class type);

Why wouldn't we just use normal constructors?

a = new Property(Artist.class);


>  Property createForRelationship(
>Property property, Class type)

> 3) Prohibit direct usages of properties mapped on toMany
> relationships, so that the following code will throw a
> CayenneRuntimeException
> 
> List result = ObjectSelect.query(Artist.class)
> .columns(Artist.ARTIST_NAME, Artist.PAINTING_ARRAY)
> .select(context);

I'm confused about why we need a new type of property for this rather than just 
using Artist.PAINTING_ARRAY


Ari


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