Re: ColumnSelect API + Persistent objects
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
> 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
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
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
> 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
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
> > 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
> 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
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
>>> >>> 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
> 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
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
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
