Approach to construct queries

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
22 messages Options
12
Reply | Threaded
Open this post in threaded view
|

Approach to construct queries

jtuchel
Dear Glorp Community,

I am wondering about an approach to construct Glorp Queries from Filter objects. Let me tell you a bit what I mean by that...

In many web shops and sites you find things like sliders for a price range, a few clickable options like "on stock", "blue/red/greed", "rated higher that x stars" and whatever. And there are nice GUIs for combining these, like using a slider, date pickers, input fields etc. You can add these filters and remove them and then start a search.

We need to build these and the result should end up as a Glorp Query returning objects. We currently only have a few such places in our app and use code like this (from my head, not actual code) to construct queries:

self session read: Product where: [:p| p active = true AND: (self onlyOnStock = false OR: (p onStock=true))].

This work quite well for, say, up to 5 filters, but it doesn't really scale up to 10 or more. The code becomes extremely hard to maintain.

I'd rather like to use something like a visitor pattern, where each filter knows how to add its condition(s) to a query. Somthing like:

|query|
query := Query returningManyOf: Product.
self filters do: [:f|

  query addToWhereCondition: f condition.

].
products := self session execute: query.


Glorp is such a nice framework, but I cannot find a way to do this. Has anybody solved this or found something that could help me on my journey? The idea is that I define Filter objects for concrete values, NULL, ranges (between and) etc. and each of them constructs its little part of the query.

Any ideas? Any code samples?

Joachim

--
You received this message because you are subscribed to the Google Groups "glorp-group" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
To post to this group, send email to [hidden email].
Visit this group at https://groups.google.com/group/glorp-group.
For more options, visit https://groups.google.com/d/optout.
Reply | Threaded
Open this post in threaded view
|

Re: Approach to construct queries

Benoit St-Jean
I remember that in TOPLink (Glorp's ancestor), we had filtered reads (or something named similarly)...  Basically, we could stack WHERE conditions and the final query would be built at the very last moment before execution.  Perhaps, Glorp needs this (it was a useful feature as I remember it).  Alan, are you listening?  ;)


-----------------
Benoît St-Jean
Yahoo! Messenger: bstjean
Twitter: @BenLeChialeux
Pinterest: benoitstjean
Instagram: Chef_Benito
IRC: lamneth
Blogue: endormitoire.wordpress.com
"A standpoint is an intellectual horizon of radius zero".  (A. Einstein)


On Tuesday, January 30, 2018, 2:26:01 AM EST, jtuchel <[hidden email]> wrote:


Dear Glorp Community,

I am wondering about an approach to construct Glorp Queries from Filter objects. Let me tell you a bit what I mean by that...

In many web shops and sites you find things like sliders for a price range, a few clickable options like "on stock", "blue/red/greed", "rated higher that x stars" and whatever. And there are nice GUIs for combining these, like using a slider, date pickers, input fields etc. You can add these filters and remove them and then start a search.

We need to build these and the result should end up as a Glorp Query returning objects. We currently only have a few such places in our app and use code like this (from my head, not actual code) to construct queries:

self session read: Product where: [:p| p active = true AND: (self onlyOnStock = false OR: (p onStock=true))].

This work quite well for, say, up to 5 filters, but it doesn't really scale up to 10 or more. The code becomes extremely hard to maintain.

I'd rather like to use something like a visitor pattern, where each filter knows how to add its condition(s) to a query. Somthing like:

|query|
query := Query returningManyOf: Product.
self filters do: [:f|

  query addToWhereCondition: f condition.

].
products := self session execute: query.


Glorp is such a nice framework, but I cannot find a way to do this. Has anybody solved this or found something that could help me on my journey? The idea is that I define Filter objects for concrete values, NULL, ranges (between and) etc. and each of them constructs its little part of the query.

Any ideas? Any code samples?

Joachim

--
You received this message because you are subscribed to the Google Groups "glorp-group" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
To post to this group, send email to [hidden email].
Visit this group at https://groups.google.com/group/glorp-group.
For more options, visit https://groups.google.com/d/optout.

--
You received this message because you are subscribed to the Google Groups "glorp-group" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
To post to this group, send email to [hidden email].
Visit this group at https://groups.google.com/group/glorp-group.
For more options, visit https://groups.google.com/d/optout.
Reply | Threaded
Open this post in threaded view
|

Re: Approach to construct queries

jtuchel
Benoît,


sounds like what I am looking for.
I took another tour of the Query subclasses.

I found Query subclass FilteringQuery. Its class comment says:

This is a query that expects all the objects it might return to already be in memory, and in a collection from which it can pick them out by evaluating a block. This is used to implement filtered reads on a mapping. When one of the mappings fires, it reads all the relevant results, and so each instance  using that mapping can get the results out of memory without going to the database again.

So this is not what I am looking for.
Just to be sure I am not overlooking the obvious I checked for implementors of #where: and only found one. It directly sets an instance variable, so the feature you mention seems not to have made its way into "normal" Queries ;-)

So any more ideas?

Joachim



Am Dienstag, 30. Januar 2018 15:32:48 UTC+1 schrieb bstjean:
I remember that in TOPLink (Glorp's ancestor), we had filtered reads (or something named similarly)...  Basically, we could stack WHERE conditions and the final query would be built at the very last moment before execution.  Perhaps, Glorp needs this (it was a useful feature as I remember it).  Alan, are you listening?  ;)


-----------------
Benoît St-Jean
Yahoo! Messenger: bstjean
Twitter: @BenLeChialeux
Pinterest: benoitstjean
Instagram: Chef_Benito
IRC: lamneth
Blogue: <a href="http://endormitoire.wordpress.com" target="_blank" rel="nofollow" onmousedown="this.href=&#39;http://www.google.com/url?q\x3dhttp%3A%2F%2Fendormitoire.wordpress.com\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNFVTrJOgWx4wljrvY17-qXr_fvEPw&#39;;return true;" onclick="this.href=&#39;http://www.google.com/url?q\x3dhttp%3A%2F%2Fendormitoire.wordpress.com\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNFVTrJOgWx4wljrvY17-qXr_fvEPw&#39;;return true;">endormitoire.wordpress.com
"A standpoint is an intellectual horizon of radius zero".  (A. Einstein)


On Tuesday, January 30, 2018, 2:26:01 AM EST, jtuchel <<a href="javascript:" target="_blank" gdf-obfuscated-mailto="j51oe679AgAJ" rel="nofollow" onmousedown="this.href=&#39;javascript:&#39;;return true;" onclick="this.href=&#39;javascript:&#39;;return true;">jtu...@...> wrote:


Dear Glorp Community,

I am wondering about an approach to construct Glorp Queries from Filter objects. Let me tell you a bit what I mean by that...

In many web shops and sites you find things like sliders for a price range, a few clickable options like "on stock", "blue/red/greed", "rated higher that x stars" and whatever. And there are nice GUIs for combining these, like using a slider, date pickers, input fields etc. You can add these filters and remove them and then start a search.

We need to build these and the result should end up as a Glorp Query returning objects. We currently only have a few such places in our app and use code like this (from my head, not actual code) to construct queries:

self session read: Product where: [:p| p active = true AND: (self onlyOnStock = false OR: (p onStock=true))].

This work quite well for, say, up to 5 filters, but it doesn't really scale up to 10 or more. The code becomes extremely hard to maintain.

I'd rather like to use something like a visitor pattern, where each filter knows how to add its condition(s) to a query. Somthing like:

|query|
query := Query returningManyOf: Product.
self filters do: [:f|

  query addToWhereCondition: f condition.

].
products := self session execute: query.


Glorp is such a nice framework, but I cannot find a way to do this. Has anybody solved this or found something that could help me on my journey? The idea is that I define Filter objects for concrete values, NULL, ranges (between and) etc. and each of them constructs its little part of the query.

Any ideas? Any code samples?

Joachim

--
You received this message because you are subscribed to the Google Groups "glorp-group" group.
To unsubscribe from this group and stop receiving emails from it, send an email to <a href="javascript:" rel="nofollow" target="_blank" gdf-obfuscated-mailto="j51oe679AgAJ" onmousedown="this.href=&#39;javascript:&#39;;return true;" onclick="this.href=&#39;javascript:&#39;;return true;">glorp-group...@googlegroups.com.
To post to this group, send email to <a href="javascript:" rel="nofollow" target="_blank" gdf-obfuscated-mailto="j51oe679AgAJ" onmousedown="this.href=&#39;javascript:&#39;;return true;" onclick="this.href=&#39;javascript:&#39;;return true;">glorp...@....
Visit this group at <a href="https://groups.google.com/group/glorp-group" rel="nofollow" target="_blank" onmousedown="this.href=&#39;https://groups.google.com/group/glorp-group&#39;;return true;" onclick="this.href=&#39;https://groups.google.com/group/glorp-group&#39;;return true;">https://groups.google.com/group/glorp-group.
For more options, visit <a href="https://groups.google.com/d/optout" rel="nofollow" target="_blank" onmousedown="this.href=&#39;https://groups.google.com/d/optout&#39;;return true;" onclick="this.href=&#39;https://groups.google.com/d/optout&#39;;return true;">https://groups.google.com/d/optout.

--
You received this message because you are subscribed to the Google Groups "glorp-group" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
To post to this group, send email to [hidden email].
Visit this group at https://groups.google.com/group/glorp-group.
For more options, visit https://groups.google.com/d/optout.
Reply | Threaded
Open this post in threaded view
|

Re: Approach to construct queries

Alan Knight
This is a very common usage, and one that's definitely supported, though apparently not as easy to find as it might be.

Filtered reads are something different. What you want is probably either virtual collection, or just that AND: and OR: are implemented on query.

The former lets you get a collection to which you can send reject:/select: and it just returns a new virtual collection which adds the new query criteria. It doesn't actually issue the query until you start iterating over the result. And the way this is implemented is just that you can send AND: to a query (with a where clause, not another query) and it gives you another query whose where clause is the AND of the two where clauses.


On Tue, Jan 30, 2018 at 7:57 AM jtuchel <[hidden email]> wrote:
Benoît,


sounds like what I am looking for.
I took another tour of the Query subclasses.

I found Query subclass FilteringQuery. Its class comment says:

This is a query that expects all the objects it might return to already be in memory, and in a collection from which it can pick them out by evaluating a block. This is used to implement filtered reads on a mapping. When one of the mappings fires, it reads all the relevant results, and so each instance  using that mapping can get the results out of memory without going to the database again.

So this is not what I am looking for.
Just to be sure I am not overlooking the obvious I checked for implementors of #where: and only found one. It directly sets an instance variable, so the feature you mention seems not to have made its way into "normal" Queries ;-)

So any more ideas?

Joachim




Am Dienstag, 30. Januar 2018 15:32:48 UTC+1 schrieb bstjean:
I remember that in TOPLink (Glorp's ancestor), we had filtered reads (or something named similarly)...  Basically, we could stack WHERE conditions and the final query would be built at the very last moment before execution.  Perhaps, Glorp needs this (it was a useful feature as I remember it).  Alan, are you listening?  ;)


-----------------
Benoît St-Jean
Yahoo! Messenger: bstjean
Twitter: @BenLeChialeux
Pinterest: benoitstjean
Instagram: Chef_Benito
IRC: lamneth
Blogue: endormitoire.wordpress.com
"A standpoint is an intellectual horizon of radius zero".  (A. Einstein)


On Tuesday, January 30, 2018, 2:26:01 AM EST, jtuchel <[hidden email]> wrote:


Dear Glorp Community,

I am wondering about an approach to construct Glorp Queries from Filter objects. Let me tell you a bit what I mean by that...

In many web shops and sites you find things like sliders for a price range, a few clickable options like "on stock", "blue/red/greed", "rated higher that x stars" and whatever. And there are nice GUIs for combining these, like using a slider, date pickers, input fields etc. You can add these filters and remove them and then start a search.

We need to build these and the result should end up as a Glorp Query returning objects. We currently only have a few such places in our app and use code like this (from my head, not actual code) to construct queries:

self session read: Product where: [:p| p active = true AND: (self onlyOnStock = false OR: (p onStock=true))].

This work quite well for, say, up to 5 filters, but it doesn't really scale up to 10 or more. The code becomes extremely hard to maintain.

I'd rather like to use something like a visitor pattern, where each filter knows how to add its condition(s) to a query. Somthing like:

|query|
query := Query returningManyOf: Product.
self filters do: [:f|

  query addToWhereCondition: f condition.

].
products := self session execute: query.


Glorp is such a nice framework, but I cannot find a way to do this. Has anybody solved this or found something that could help me on my journey? The idea is that I define Filter objects for concrete values, NULL, ranges (between and) etc. and each of them constructs its little part of the query.

Any ideas? Any code samples?

Joachim

--
You received this message because you are subscribed to the Google Groups "glorp-group" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
To post to this group, send email to [hidden email].

--
You received this message because you are subscribed to the Google Groups "glorp-group" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
To post to this group, send email to [hidden email].
Visit this group at https://groups.google.com/group/glorp-group.
For more options, visit https://groups.google.com/d/optout.

--
You received this message because you are subscribed to the Google Groups "glorp-group" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
To post to this group, send email to [hidden email].
Visit this group at https://groups.google.com/group/glorp-group.
For more options, visit https://groups.google.com/d/optout.
Reply | Threaded
Open this post in threaded view
|

Re: Approach to construct queries

jtuchel
Alan,

do you happen to know if there are samples or some documentation on virtual collections or the AND:/OR:.
From looking at teh implementors of AND: it seems like everything is right in front of me, I just couldn't see it...

I will try playing with the AND: stuff. Starting point will be somethind along the lines of:

|query products|
query := SimpleQuery returningManyOf: Product.
query where: [:prod| prod color = 'blue'].
query AND: [:prod| prod price <= 1.00].
products := self session execute: query.

If this is the way to go, the rest is easy: just let the filter objects generate these blocks and visit each of them for the query building.

That would be great. I'll keep you updated ;-)


Joachim






Am Dienstag, 30. Januar 2018 18:04:55 UTC+1 schrieb alan.knight:
This is a very common usage, and one that's definitely supported, though apparently not as easy to find as it might be.

Filtered reads are something different. What you want is probably either virtual collection, or just that AND: and OR: are implemented on query.

The former lets you get a collection to which you can send reject:/select: and it just returns a new virtual collection which adds the new query criteria. It doesn't actually issue the query until you start iterating over the result. And the way this is implemented is just that you can send AND: to a query (with a where clause, not another query) and it gives you another query whose where clause is the AND of the two where clauses.


On Tue, Jan 30, 2018 at 7:57 AM jtuchel <<a href="javascript:" target="_blank" gdf-obfuscated-mailto="0nJRnvsFAwAJ" rel="nofollow" onmousedown="this.href=&#39;javascript:&#39;;return true;" onclick="this.href=&#39;javascript:&#39;;return true;">jtu...@...> wrote:
Benoît,


sounds like what I am looking for.
I took another tour of the Query subclasses.

I found Query subclass FilteringQuery. Its class comment says:

This is a query that expects all the objects it might return to already be in memory, and in a collection from which it can pick them out by evaluating a block. This is used to implement filtered reads on a mapping. When one of the mappings fires, it reads all the relevant results, and so each instance  using that mapping can get the results out of memory without going to the database again.

So this is not what I am looking for.
Just to be sure I am not overlooking the obvious I checked for implementors of #where: and only found one. It directly sets an instance variable, so the feature you mention seems not to have made its way into "normal" Queries ;-)

So any more ideas?

Joachim




Am Dienstag, 30. Januar 2018 15:32:48 UTC+1 schrieb bstjean:
I remember that in TOPLink (Glorp's ancestor), we had filtered reads (or something named similarly)...  Basically, we could stack WHERE conditions and the final query would be built at the very last moment before execution.  Perhaps, Glorp needs this (it was a useful feature as I remember it).  Alan, are you listening?  ;)


-----------------
Benoît St-Jean
Yahoo! Messenger: bstjean
Twitter: @BenLeChialeux
Pinterest: benoitstjean
Instagram: Chef_Benito
IRC: lamneth
Blogue: <a href="http://endormitoire.wordpress.com" rel="nofollow" target="_blank" onmousedown="this.href=&#39;http://www.google.com/url?q\x3dhttp%3A%2F%2Fendormitoire.wordpress.com\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNFVTrJOgWx4wljrvY17-qXr_fvEPw&#39;;return true;" onclick="this.href=&#39;http://www.google.com/url?q\x3dhttp%3A%2F%2Fendormitoire.wordpress.com\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNFVTrJOgWx4wljrvY17-qXr_fvEPw&#39;;return true;">endormitoire.wordpress.com
"A standpoint is an intellectual horizon of radius zero".  (A. Einstein)


On Tuesday, January 30, 2018, 2:26:01 AM EST, jtuchel <[hidden email]> wrote:


Dear Glorp Community,

I am wondering about an approach to construct Glorp Queries from Filter objects. Let me tell you a bit what I mean by that...

In many web shops and sites you find things like sliders for a price range, a few clickable options like "on stock", "blue/red/greed", "rated higher that x stars" and whatever. And there are nice GUIs for combining these, like using a slider, date pickers, input fields etc. You can add these filters and remove them and then start a search.

We need to build these and the result should end up as a Glorp Query returning objects. We currently only have a few such places in our app and use code like this (from my head, not actual code) to construct queries:

self session read: Product where: [:p| p active = true AND: (self onlyOnStock = false OR: (p onStock=true))].

This work quite well for, say, up to 5 filters, but it doesn't really scale up to 10 or more. The code becomes extremely hard to maintain.

I'd rather like to use something like a visitor pattern, where each filter knows how to add its condition(s) to a query. Somthing like:

|query|
query := Query returningManyOf: Product.
self filters do: [:f|

  query addToWhereCondition: f condition.

].
products := self session execute: query.


Glorp is such a nice framework, but I cannot find a way to do this. Has anybody solved this or found something that could help me on my journey? The idea is that I define Filter objects for concrete values, NULL, ranges (between and) etc. and each of them constructs its little part of the query.

Any ideas? Any code samples?

Joachim

--
You received this message because you are subscribed to the Google Groups "glorp-group" group.
To unsubscribe from this group and stop receiving emails from it, send an email to glorp-group...@googlegroups.com.
To post to this group, send email to [hidden email].

Visit this group at <a href="https://groups.google.com/group/glorp-group" rel="nofollow" target="_blank" onmousedown="this.href=&#39;https://groups.google.com/group/glorp-group&#39;;return true;" onclick="this.href=&#39;https://groups.google.com/group/glorp-group&#39;;return true;">https://groups.google.com/group/glorp-group.
For more options, visit <a href="https://groups.google.com/d/optout" rel="nofollow" target="_blank" onmousedown="this.href=&#39;https://groups.google.com/d/optout&#39;;return true;" onclick="this.href=&#39;https://groups.google.com/d/optout&#39;;return true;">https://groups.google.com/d/optout.

--
You received this message because you are subscribed to the Google Groups "glorp-group" group.
To unsubscribe from this group and stop receiving emails from it, send an email to <a href="javascript:" target="_blank" gdf-obfuscated-mailto="0nJRnvsFAwAJ" rel="nofollow" onmousedown="this.href=&#39;javascript:&#39;;return true;" onclick="this.href=&#39;javascript:&#39;;return true;">glorp-group...@googlegroups.com.
To post to this group, send email to <a href="javascript:" target="_blank" gdf-obfuscated-mailto="0nJRnvsFAwAJ" rel="nofollow" onmousedown="this.href=&#39;javascript:&#39;;return true;" onclick="this.href=&#39;javascript:&#39;;return true;">glorp...@....
Visit this group at <a href="https://groups.google.com/group/glorp-group" target="_blank" rel="nofollow" onmousedown="this.href=&#39;https://groups.google.com/group/glorp-group&#39;;return true;" onclick="this.href=&#39;https://groups.google.com/group/glorp-group&#39;;return true;">https://groups.google.com/group/glorp-group.
For more options, visit <a href="https://groups.google.com/d/optout" target="_blank" rel="nofollow" onmousedown="this.href=&#39;https://groups.google.com/d/optout&#39;;return true;" onclick="this.href=&#39;https://groups.google.com/d/optout&#39;;return true;">https://groups.google.com/d/optout.

--
You received this message because you are subscribed to the Google Groups "glorp-group" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
To post to this group, send email to [hidden email].
Visit this group at https://groups.google.com/group/glorp-group.
For more options, visit https://groups.google.com/d/optout.
Reply | Threaded
Open this post in threaded view
|

Re: Approach to construct queries

jtuchel
Okay, this is FANTASTIC!

thanks Alan. This AND: / OR: thingie works perfectly. Why didn't I see this?

Joachim



Am Mittwoch, 31. Januar 2018 09:17:35 UTC+1 schrieb jtuchel:
Alan,

do you happen to know if there are samples or some documentation on virtual collections or the AND:/OR:.
From looking at teh implementors of AND: it seems like everything is right in front of me, I just couldn't see it...

I will try playing with the AND: stuff. Starting point will be somethind along the lines of:

|query products|
query := SimpleQuery returningManyOf: Product.
query where: [:prod| prod color = 'blue'].
query AND: [:prod| prod price <= 1.00].
products := self session execute: query.

If this is the way to go, the rest is easy: just let the filter objects generate these blocks and visit each of them for the query building.

That would be great. I'll keep you updated ;-)


Joachim






Am Dienstag, 30. Januar 2018 18:04:55 UTC+1 schrieb alan.knight:
This is a very common usage, and one that's definitely supported, though apparently not as easy to find as it might be.

Filtered reads are something different. What you want is probably either virtual collection, or just that AND: and OR: are implemented on query.

The former lets you get a collection to which you can send reject:/select: and it just returns a new virtual collection which adds the new query criteria. It doesn't actually issue the query until you start iterating over the result. And the way this is implemented is just that you can send AND: to a query (with a where clause, not another query) and it gives you another query whose where clause is the AND of the two where clauses.


On Tue, Jan 30, 2018 at 7:57 AM jtuchel <[hidden email]> wrote:
Benoît,


sounds like what I am looking for.
I took another tour of the Query subclasses.

I found Query subclass FilteringQuery. Its class comment says:

This is a query that expects all the objects it might return to already be in memory, and in a collection from which it can pick them out by evaluating a block. This is used to implement filtered reads on a mapping. When one of the mappings fires, it reads all the relevant results, and so each instance  using that mapping can get the results out of memory without going to the database again.

So this is not what I am looking for.
Just to be sure I am not overlooking the obvious I checked for implementors of #where: and only found one. It directly sets an instance variable, so the feature you mention seems not to have made its way into "normal" Queries ;-)

So any more ideas?

Joachim




Am Dienstag, 30. Januar 2018 15:32:48 UTC+1 schrieb bstjean:
I remember that in TOPLink (Glorp's ancestor), we had filtered reads (or something named similarly)...  Basically, we could stack WHERE conditions and the final query would be built at the very last moment before execution.  Perhaps, Glorp needs this (it was a useful feature as I remember it).  Alan, are you listening?  ;)


-----------------
Benoît St-Jean
Yahoo! Messenger: bstjean
Twitter: @BenLeChialeux
Pinterest: benoitstjean
Instagram: Chef_Benito
IRC: lamneth
Blogue: <a href="http://endormitoire.wordpress.com" rel="nofollow" target="_blank" onmousedown="this.href=&#39;http://www.google.com/url?q\x3dhttp%3A%2F%2Fendormitoire.wordpress.com\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNFVTrJOgWx4wljrvY17-qXr_fvEPw&#39;;return true;" onclick="this.href=&#39;http://www.google.com/url?q\x3dhttp%3A%2F%2Fendormitoire.wordpress.com\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNFVTrJOgWx4wljrvY17-qXr_fvEPw&#39;;return true;">endormitoire.wordpress.com
"A standpoint is an intellectual horizon of radius zero".  (A. Einstein)


On Tuesday, January 30, 2018, 2:26:01 AM EST, jtuchel <[hidden email]> wrote:


Dear Glorp Community,

I am wondering about an approach to construct Glorp Queries from Filter objects. Let me tell you a bit what I mean by that...

In many web shops and sites you find things like sliders for a price range, a few clickable options like "on stock", "blue/red/greed", "rated higher that x stars" and whatever. And there are nice GUIs for combining these, like using a slider, date pickers, input fields etc. You can add these filters and remove them and then start a search.

We need to build these and the result should end up as a Glorp Query returning objects. We currently only have a few such places in our app and use code like this (from my head, not actual code) to construct queries:

self session read: Product where: [:p| p active = true AND: (self onlyOnStock = false OR: (p onStock=true))].

This work quite well for, say, up to 5 filters, but it doesn't really scale up to 10 or more. The code becomes extremely hard to maintain.

I'd rather like to use something like a visitor pattern, where each filter knows how to add its condition(s) to a query. Somthing like:

|query|
query := Query returningManyOf: Product.
self filters do: [:f|

  query addToWhereCondition: f condition.

].
products := self session execute: query.


Glorp is such a nice framework, but I cannot find a way to do this. Has anybody solved this or found something that could help me on my journey? The idea is that I define Filter objects for concrete values, NULL, ranges (between and) etc. and each of them constructs its little part of the query.

Any ideas? Any code samples?

Joachim

--
You received this message because you are subscribed to the Google Groups "glorp-group" group.
To unsubscribe from this group and stop receiving emails from it, send an email to glorp-group...@googlegroups.com.
To post to this group, send email to [hidden email].

Visit this group at <a href="https://groups.google.com/group/glorp-group" rel="nofollow" target="_blank" onmousedown="this.href=&#39;https://groups.google.com/group/glorp-group&#39;;return true;" onclick="this.href=&#39;https://groups.google.com/group/glorp-group&#39;;return true;">https://groups.google.com/group/glorp-group.
For more options, visit <a href="https://groups.google.com/d/optout" rel="nofollow" target="_blank" onmousedown="this.href=&#39;https://groups.google.com/d/optout&#39;;return true;" onclick="this.href=&#39;https://groups.google.com/d/optout&#39;;return true;">https://groups.google.com/d/optout.

--
You received this message because you are subscribed to the Google Groups "glorp-group" group.
To unsubscribe from this group and stop receiving emails from it, send an email to glorp-group...@googlegroups.com.
To post to this group, send email to [hidden email].
Visit this group at <a href="https://groups.google.com/group/glorp-group" rel="nofollow" target="_blank" onmousedown="this.href=&#39;https://groups.google.com/group/glorp-group&#39;;return true;" onclick="this.href=&#39;https://groups.google.com/group/glorp-group&#39;;return true;">https://groups.google.com/group/glorp-group.
For more options, visit <a href="https://groups.google.com/d/optout" rel="nofollow" target="_blank" onmousedown="this.href=&#39;https://groups.google.com/d/optout&#39;;return true;" onclick="this.href=&#39;https://groups.google.com/d/optout&#39;;return true;">https://groups.google.com/d/optout.

--
You received this message because you are subscribed to the Google Groups "glorp-group" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
To post to this group, send email to [hidden email].
Visit this group at https://groups.google.com/group/glorp-group.
For more options, visit https://groups.google.com/d/optout.
Reply | Threaded
Open this post in threaded view
|

Re: Approach to construct queries

jtuchel
In reply to this post by Alan Knight
I'm coming back to this topic because I'm having problems getting my head around something here....

Let's say I have a EqualitiyFilter which tests for equality and can be configured to hold an attribute  along with a user-provided value to compare to name which will be used to construct an SQL query.
I'd like to configure it for use in our application doing something like:

self possibleFilters add: ((EqualityFilter for attributeNamed: #birthday) .
The user can then select the filter and enter a value for comparison (like today's date).

Later, when the user presses the "search" button, I want to do something like:

query := SimpleQuery read: Person.
query where: [:person| person isAlive].
self selectedFilters do: [:filter| query AND: filter selectBlock].

Sounds great, doesn't it?
Not yet, because I see a problem I cannot solve on my own: how do I use the attribute name to put it into the query block....?

How do I implement #selectBlock?

selectBlock

   ^[:eachRow| eachRow whatDoIPutHere??? = self valueToCompare]

Any ideas? I guess #perform: doesn't really work in this context...


Joachim












Am Dienstag, 30. Januar 2018 18:04:55 UTC+1 schrieb alan.knight:
This is a very common usage, and one that's definitely supported, though apparently not as easy to find as it might be.

Filtered reads are something different. What you want is probably either virtual collection, or just that AND: and OR: are implemented on query.

The former lets you get a collection to which you can send reject:/select: and it just returns a new virtual collection which adds the new query criteria. It doesn't actually issue the query until you start iterating over the result. And the way this is implemented is just that you can send AND: to a query (with a where clause, not another query) and it gives you another query whose where clause is the AND of the two where clauses.


On Tue, Jan 30, 2018 at 7:57 AM jtuchel <<a href="javascript:" target="_blank" gdf-obfuscated-mailto="0nJRnvsFAwAJ" rel="nofollow" onmousedown="this.href=&#39;javascript:&#39;;return true;" onclick="this.href=&#39;javascript:&#39;;return true;">jtu...@...> wrote:
Benoît,


sounds like what I am looking for.
I took another tour of the Query subclasses.

I found Query subclass FilteringQuery. Its class comment says:

This is a query that expects all the objects it might return to already be in memory, and in a collection from which it can pick them out by evaluating a block. This is used to implement filtered reads on a mapping. When one of the mappings fires, it reads all the relevant results, and so each instance  using that mapping can get the results out of memory without going to the database again.

So this is not what I am looking for.
Just to be sure I am not overlooking the obvious I checked for implementors of #where: and only found one. It directly sets an instance variable, so the feature you mention seems not to have made its way into "normal" Queries ;-)

So any more ideas?

Joachim




Am Dienstag, 30. Januar 2018 15:32:48 UTC+1 schrieb bstjean:
I remember that in TOPLink (Glorp's ancestor), we had filtered reads (or something named similarly)...  Basically, we could stack WHERE conditions and the final query would be built at the very last moment before execution.  Perhaps, Glorp needs this (it was a useful feature as I remember it).  Alan, are you listening?  ;)


-----------------
Benoît St-Jean
Yahoo! Messenger: bstjean
Twitter: @BenLeChialeux
Pinterest: benoitstjean
Instagram: Chef_Benito
IRC: lamneth
Blogue: <a href="http://endormitoire.wordpress.com" rel="nofollow" target="_blank" onmousedown="this.href=&#39;http://www.google.com/url?q\x3dhttp%3A%2F%2Fendormitoire.wordpress.com\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNFVTrJOgWx4wljrvY17-qXr_fvEPw&#39;;return true;" onclick="this.href=&#39;http://www.google.com/url?q\x3dhttp%3A%2F%2Fendormitoire.wordpress.com\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNFVTrJOgWx4wljrvY17-qXr_fvEPw&#39;;return true;">endormitoire.wordpress.com
"A standpoint is an intellectual horizon of radius zero".  (A. Einstein)


On Tuesday, January 30, 2018, 2:26:01 AM EST, jtuchel <[hidden email]> wrote:


Dear Glorp Community,

I am wondering about an approach to construct Glorp Queries from Filter objects. Let me tell you a bit what I mean by that...

In many web shops and sites you find things like sliders for a price range, a few clickable options like "on stock", "blue/red/greed", "rated higher that x stars" and whatever. And there are nice GUIs for combining these, like using a slider, date pickers, input fields etc. You can add these filters and remove them and then start a search.

We need to build these and the result should end up as a Glorp Query returning objects. We currently only have a few such places in our app and use code like this (from my head, not actual code) to construct queries:

self session read: Product where: [:p| p active = true AND: (self onlyOnStock = false OR: (p onStock=true))].

This work quite well for, say, up to 5 filters, but it doesn't really scale up to 10 or more. The code becomes extremely hard to maintain.

I'd rather like to use something like a visitor pattern, where each filter knows how to add its condition(s) to a query. Somthing like:

|query|
query := Query returningManyOf: Product.
self filters do: [:f|

  query addToWhereCondition: f condition.

].
products := self session execute: query.


Glorp is such a nice framework, but I cannot find a way to do this. Has anybody solved this or found something that could help me on my journey? The idea is that I define Filter objects for concrete values, NULL, ranges (between and) etc. and each of them constructs its little part of the query.

Any ideas? Any code samples?

Joachim

--
You received this message because you are subscribed to the Google Groups "glorp-group" group.
To unsubscribe from this group and stop receiving emails from it, send an email to glorp-group...@googlegroups.com.
To post to this group, send email to [hidden email].

Visit this group at <a href="https://groups.google.com/group/glorp-group" rel="nofollow" target="_blank" onmousedown="this.href=&#39;https://groups.google.com/group/glorp-group&#39;;return true;" onclick="this.href=&#39;https://groups.google.com/group/glorp-group&#39;;return true;">https://groups.google.com/group/glorp-group.
For more options, visit <a href="https://groups.google.com/d/optout" rel="nofollow" target="_blank" onmousedown="this.href=&#39;https://groups.google.com/d/optout&#39;;return true;" onclick="this.href=&#39;https://groups.google.com/d/optout&#39;;return true;">https://groups.google.com/d/optout.

--
You received this message because you are subscribed to the Google Groups "glorp-group" group.
To unsubscribe from this group and stop receiving emails from it, send an email to <a href="javascript:" target="_blank" gdf-obfuscated-mailto="0nJRnvsFAwAJ" rel="nofollow" onmousedown="this.href=&#39;javascript:&#39;;return true;" onclick="this.href=&#39;javascript:&#39;;return true;">glorp-group...@googlegroups.com.
To post to this group, send email to <a href="javascript:" target="_blank" gdf-obfuscated-mailto="0nJRnvsFAwAJ" rel="nofollow" onmousedown="this.href=&#39;javascript:&#39;;return true;" onclick="this.href=&#39;javascript:&#39;;return true;">glorp...@....
Visit this group at <a href="https://groups.google.com/group/glorp-group" target="_blank" rel="nofollow" onmousedown="this.href=&#39;https://groups.google.com/group/glorp-group&#39;;return true;" onclick="this.href=&#39;https://groups.google.com/group/glorp-group&#39;;return true;">https://groups.google.com/group/glorp-group.
For more options, visit <a href="https://groups.google.com/d/optout" target="_blank" rel="nofollow" onmousedown="this.href=&#39;https://groups.google.com/d/optout&#39;;return true;" onclick="this.href=&#39;https://groups.google.com/d/optout&#39;;return true;">https://groups.google.com/d/optout.

--
You received this message because you are subscribed to the Google Groups "glorp-group" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
To post to this group, send email to [hidden email].
Visit this group at https://groups.google.com/group/glorp-group.
For more options, visit https://groups.google.com/d/optout.
Reply | Threaded
Open this post in threaded view
|

Re: Approach to construct queries

jtuchel
Sorry, I edited this too fast:

>Let's say I have a EqualitiyFilter which tests for equality and can be configured to hold an attribute  along with a user-provided value to compare to name which will be used to >construct an SQL query.

Should be

Let's say I have a EqualitiyFilter which tests for equality and can be configured to hold an attribute name along with a user-provided value to compare to which will be used to construct an SQL query.






Am Mittwoch, 7. Februar 2018 13:43:54 UTC+1 schrieb jtuchel:
I'm coming back to this topic because I'm having problems getting my head around something here....

Let's say I have a EqualitiyFilter which tests for equality and can be configured to hold an attribute  along with a user-provided value to compare to name which will be used to construct an SQL query.
I'd like to configure it for use in our application doing something like:

self possibleFilters add: ((EqualityFilter for attributeNamed: #birthday) .
The user can then select the filter and enter a value for comparison (like today's date).

Later, when the user presses the "search" button, I want to do something like:

query := SimpleQuery read: Person.
query where: [:person| person isAlive].
self selectedFilters do: [:filter| query AND: filter selectBlock].

Sounds great, doesn't it?
Not yet, because I see a problem I cannot solve on my own: how do I use the attribute name to put it into the query block....?

How do I implement #selectBlock?

selectBlock

   ^[:eachRow| eachRow whatDoIPutHere??? = self valueToCompare]

Any ideas? I guess #perform: doesn't really work in this context...


Joachim












Am Dienstag, 30. Januar 2018 18:04:55 UTC+1 schrieb alan.knight:
This is a very common usage, and one that's definitely supported, though apparently not as easy to find as it might be.

Filtered reads are something different. What you want is probably either virtual collection, or just that AND: and OR: are implemented on query.

The former lets you get a collection to which you can send reject:/select: and it just returns a new virtual collection which adds the new query criteria. It doesn't actually issue the query until you start iterating over the result. And the way this is implemented is just that you can send AND: to a query (with a where clause, not another query) and it gives you another query whose where clause is the AND of the two where clauses.


On Tue, Jan 30, 2018 at 7:57 AM jtuchel <[hidden email]> wrote:
Benoît,


sounds like what I am looking for.
I took another tour of the Query subclasses.

I found Query subclass FilteringQuery. Its class comment says:

This is a query that expects all the objects it might return to already be in memory, and in a collection from which it can pick them out by evaluating a block. This is used to implement filtered reads on a mapping. When one of the mappings fires, it reads all the relevant results, and so each instance  using that mapping can get the results out of memory without going to the database again.

So this is not what I am looking for.
Just to be sure I am not overlooking the obvious I checked for implementors of #where: and only found one. It directly sets an instance variable, so the feature you mention seems not to have made its way into "normal" Queries ;-)

So any more ideas?

Joachim




Am Dienstag, 30. Januar 2018 15:32:48 UTC+1 schrieb bstjean:
I remember that in TOPLink (Glorp's ancestor), we had filtered reads (or something named similarly)...  Basically, we could stack WHERE conditions and the final query would be built at the very last moment before execution.  Perhaps, Glorp needs this (it was a useful feature as I remember it).  Alan, are you listening?  ;)


-----------------
Benoît St-Jean
Yahoo! Messenger: bstjean
Twitter: @BenLeChialeux
Pinterest: benoitstjean
Instagram: Chef_Benito
IRC: lamneth
Blogue: <a href="http://endormitoire.wordpress.com" rel="nofollow" target="_blank" onmousedown="this.href=&#39;http://www.google.com/url?q\x3dhttp%3A%2F%2Fendormitoire.wordpress.com\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNFVTrJOgWx4wljrvY17-qXr_fvEPw&#39;;return true;" onclick="this.href=&#39;http://www.google.com/url?q\x3dhttp%3A%2F%2Fendormitoire.wordpress.com\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNFVTrJOgWx4wljrvY17-qXr_fvEPw&#39;;return true;">endormitoire.wordpress.com
"A standpoint is an intellectual horizon of radius zero".  (A. Einstein)


On Tuesday, January 30, 2018, 2:26:01 AM EST, jtuchel <[hidden email]> wrote:


Dear Glorp Community,

I am wondering about an approach to construct Glorp Queries from Filter objects. Let me tell you a bit what I mean by that...

In many web shops and sites you find things like sliders for a price range, a few clickable options like "on stock", "blue/red/greed", "rated higher that x stars" and whatever. And there are nice GUIs for combining these, like using a slider, date pickers, input fields etc. You can add these filters and remove them and then start a search.

We need to build these and the result should end up as a Glorp Query returning objects. We currently only have a few such places in our app and use code like this (from my head, not actual code) to construct queries:

self session read: Product where: [:p| p active = true AND: (self onlyOnStock = false OR: (p onStock=true))].

This work quite well for, say, up to 5 filters, but it doesn't really scale up to 10 or more. The code becomes extremely hard to maintain.

I'd rather like to use something like a visitor pattern, where each filter knows how to add its condition(s) to a query. Somthing like:

|query|
query := Query returningManyOf: Product.
self filters do: [:f|

  query addToWhereCondition: f condition.

].
products := self session execute: query.


Glorp is such a nice framework, but I cannot find a way to do this. Has anybody solved this or found something that could help me on my journey? The idea is that I define Filter objects for concrete values, NULL, ranges (between and) etc. and each of them constructs its little part of the query.

Any ideas? Any code samples?

Joachim

--
You received this message because you are subscribed to the Google Groups "glorp-group" group.
To unsubscribe from this group and stop receiving emails from it, send an email to glorp-group...@googlegroups.com.
To post to this group, send email to [hidden email].

Visit this group at <a href="https://groups.google.com/group/glorp-group" rel="nofollow" target="_blank" onmousedown="this.href=&#39;https://groups.google.com/group/glorp-group&#39;;return true;" onclick="this.href=&#39;https://groups.google.com/group/glorp-group&#39;;return true;">https://groups.google.com/group/glorp-group.
For more options, visit <a href="https://groups.google.com/d/optout" rel="nofollow" target="_blank" onmousedown="this.href=&#39;https://groups.google.com/d/optout&#39;;return true;" onclick="this.href=&#39;https://groups.google.com/d/optout&#39;;return true;">https://groups.google.com/d/optout.

--
You received this message because you are subscribed to the Google Groups "glorp-group" group.
To unsubscribe from this group and stop receiving emails from it, send an email to glorp-group...@googlegroups.com.
To post to this group, send email to [hidden email].
Visit this group at <a href="https://groups.google.com/group/glorp-group" rel="nofollow" target="_blank" onmousedown="this.href=&#39;https://groups.google.com/group/glorp-group&#39;;return true;" onclick="this.href=&#39;https://groups.google.com/group/glorp-group&#39;;return true;">https://groups.google.com/group/glorp-group.
For more options, visit <a href="https://groups.google.com/d/optout" rel="nofollow" target="_blank" onmousedown="this.href=&#39;https://groups.google.com/d/optout&#39;;return true;" onclick="this.href=&#39;https://groups.google.com/d/optout&#39;;return true;">https://groups.google.com/d/optout.

--
You received this message because you are subscribed to the Google Groups "glorp-group" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
To post to this group, send email to [hidden email].
Visit this group at https://groups.google.com/group/glorp-group.
For more options, visit https://groups.google.com/d/optout.
Reply | Threaded
Open this post in threaded view
|

Re: Approach to construct queries

Alan Knight
In reply to this post by jtuchel
Actually I think perform: might well work. What's happening is that there's a proxy passed into the block and it just notes what messages were sent, essentially constructing a tree of the expression. If the proxy understands perform: normally then I think it would work. Alternatively, you could provide a block that just fetched the attribute and evaluate it passing in the proxy. Sorry, mobile keyboard that won't let me type square brackets easily. I also think you could construct a BaseExpression and sent a query to it, but that's probably more complicated.

On Wed, Feb 7, 2018, 04:43 jtuchel <[hidden email]> wrote:
I'm coming back to this topic because I'm having problems getting my head around something here....

Let's say I have a EqualitiyFilter which tests for equality and can be configured to hold an attribute  along with a user-provided value to compare to name which will be used to construct an SQL query.
I'd like to configure it for use in our application doing something like:

self possibleFilters add: ((EqualityFilter for attributeNamed: #birthday) .
The user can then select the filter and enter a value for comparison (like today's date).

Later, when the user presses the "search" button, I want to do something like:

query := SimpleQuery read: Person.
query where: [:person| person isAlive].
self selectedFilters do: [:filter| query AND: filter selectBlock].

Sounds great, doesn't it?
Not yet, because I see a problem I cannot solve on my own: how do I use the attribute name to put it into the query block....?

How do I implement #selectBlock?

selectBlock

   ^[:eachRow| eachRow whatDoIPutHere??? = self valueToCompare]

Any ideas? I guess #perform: doesn't really work in this context...


Joachim












Am Dienstag, 30. Januar 2018 18:04:55 UTC+1 schrieb alan.knight:
This is a very common usage, and one that's definitely supported, though apparently not as easy to find as it might be.

Filtered reads are something different. What you want is probably either virtual collection, or just that AND: and OR: are implemented on query.

The former lets you get a collection to which you can send reject:/select: and it just returns a new virtual collection which adds the new query criteria. It doesn't actually issue the query until you start iterating over the result. And the way this is implemented is just that you can send AND: to a query (with a where clause, not another query) and it gives you another query whose where clause is the AND of the two where clauses.


On Tue, Jan 30, 2018 at 7:57 AM jtuchel <[hidden email]> wrote:
Benoît,


sounds like what I am looking for.
I took another tour of the Query subclasses.

I found Query subclass FilteringQuery. Its class comment says:

This is a query that expects all the objects it might return to already be in memory, and in a collection from which it can pick them out by evaluating a block. This is used to implement filtered reads on a mapping. When one of the mappings fires, it reads all the relevant results, and so each instance  using that mapping can get the results out of memory without going to the database again.

So this is not what I am looking for.
Just to be sure I am not overlooking the obvious I checked for implementors of #where: and only found one. It directly sets an instance variable, so the feature you mention seems not to have made its way into "normal" Queries ;-)

So any more ideas?

Joachim




Am Dienstag, 30. Januar 2018 15:32:48 UTC+1 schrieb bstjean:
I remember that in TOPLink (Glorp's ancestor), we had filtered reads (or something named similarly)...  Basically, we could stack WHERE conditions and the final query would be built at the very last moment before execution.  Perhaps, Glorp needs this (it was a useful feature as I remember it).  Alan, are you listening?  ;)


-----------------
Benoît St-Jean
Yahoo! Messenger: bstjean
Twitter: @BenLeChialeux
Pinterest: benoitstjean
Instagram: Chef_Benito
IRC: lamneth
Blogue: endormitoire.wordpress.com
"A standpoint is an intellectual horizon of radius zero".  (A. Einstein)


On Tuesday, January 30, 2018, 2:26:01 AM EST, jtuchel <[hidden email]> wrote:


Dear Glorp Community,

I am wondering about an approach to construct Glorp Queries from Filter objects. Let me tell you a bit what I mean by that...

In many web shops and sites you find things like sliders for a price range, a few clickable options like "on stock", "blue/red/greed", "rated higher that x stars" and whatever. And there are nice GUIs for combining these, like using a slider, date pickers, input fields etc. You can add these filters and remove them and then start a search.

We need to build these and the result should end up as a Glorp Query returning objects. We currently only have a few such places in our app and use code like this (from my head, not actual code) to construct queries:

self session read: Product where: [:p| p active = true AND: (self onlyOnStock = false OR: (p onStock=true))].

This work quite well for, say, up to 5 filters, but it doesn't really scale up to 10 or more. The code becomes extremely hard to maintain.

I'd rather like to use something like a visitor pattern, where each filter knows how to add its condition(s) to a query. Somthing like:

|query|
query := Query returningManyOf: Product.
self filters do: [:f|

  query addToWhereCondition: f condition.

].
products := self session execute: query.


Glorp is such a nice framework, but I cannot find a way to do this. Has anybody solved this or found something that could help me on my journey? The idea is that I define Filter objects for concrete values, NULL, ranges (between and) etc. and each of them constructs its little part of the query.

Any ideas? Any code samples?

Joachim

--
You received this message because you are subscribed to the Google Groups "glorp-group" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
To post to this group, send email to [hidden email].

--
You received this message because you are subscribed to the Google Groups "glorp-group" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
To post to this group, send email to [hidden email].
Visit this group at https://groups.google.com/group/glorp-group.
For more options, visit https://groups.google.com/d/optout.

--
You received this message because you are subscribed to the Google Groups "glorp-group" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
To post to this group, send email to [hidden email].
Visit this group at https://groups.google.com/group/glorp-group.
For more options, visit https://groups.google.com/d/optout.

--
You received this message because you are subscribed to the Google Groups "glorp-group" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
To post to this group, send email to [hidden email].
Visit this group at https://groups.google.com/group/glorp-group.
For more options, visit https://groups.google.com/d/optout.
Reply | Threaded
Open this post in threaded view
|

Re: Approach to construct queries

jtuchel
This is so incredibly fantastic!
The follwong expression actually really works and thus absolutely blows my mind ;-)

session read: Person where: [:ea| (ea perform: #id)   = 1017 ].

I was so sure this can't possibly work I even didn't dare to try ;-)))) Of course, once you think about it, there is no magic involved. Both sending #id and doing a #perform: #id send the message #id to the receiver. So I am hopping around the room celebrating something lame and boring. It's Smalltalk, so what...? (Eat this, static fanboys!)

So all I need is right there in front of me ;-) Thanks a lot, Alan!

Now we need a solution for the #refresh: anomaly I described on this group a few days ago and we're back in full steam with Glorp on our production web server.

Joachim



 

Am Mittwoch, 7. Februar 2018 16:50:33 UTC+1 schrieb alan.knight:
Actually I think perform: might well work. What's happening is that there's a proxy passed into the block and it just notes what messages were sent, essentially constructing a tree of the expression. If the proxy understands perform: normally then I think it would work. Alternatively, you could provide a block that just fetched the attribute and evaluate it passing in the proxy. Sorry, mobile keyboard that won't let me type square brackets easily. I also think you could construct a BaseExpression and sent a query to it, but that's probably more complicated.

On Wed, Feb 7, 2018, 04:43 jtuchel <<a href="javascript:" target="_blank" gdf-obfuscated-mailto="od4Yg1f0AwAJ" rel="nofollow" onmousedown="this.href=&#39;javascript:&#39;;return true;" onclick="this.href=&#39;javascript:&#39;;return true;">jtu...@...> wrote:
I'm coming back to this topic because I'm having problems getting my head around something here....

Let's say I have a EqualitiyFilter which tests for equality and can be configured to hold an attribute  along with a user-provided value to compare to name which will be used to construct an SQL query.
I'd like to configure it for use in our application doing something like:

self possibleFilters add: ((EqualityFilter for attributeNamed: #birthday) .
The user can then select the filter and enter a value for comparison (like today's date).

Later, when the user presses the "search" button, I want to do something like:

query := SimpleQuery read: Person.
query where: [:person| person isAlive].
self selectedFilters do: [:filter| query AND: filter selectBlock].

Sounds great, doesn't it?
Not yet, because I see a problem I cannot solve on my own: how do I use the attribute name to put it into the query block....?

How do I implement #selectBlock?

selectBlock

   ^[:eachRow| eachRow whatDoIPutHere??? = self valueToCompare]

Any ideas? I guess #perform: doesn't really work in this context...


Joachim












Am Dienstag, 30. Januar 2018 18:04:55 UTC+1 schrieb alan.knight:
This is a very common usage, and one that's definitely supported, though apparently not as easy to find as it might be.

Filtered reads are something different. What you want is probably either virtual collection, or just that AND: and OR: are implemented on query.

The former lets you get a collection to which you can send reject:/select: and it just returns a new virtual collection which adds the new query criteria. It doesn't actually issue the query until you start iterating over the result. And the way this is implemented is just that you can send AND: to a query (with a where clause, not another query) and it gives you another query whose where clause is the AND of the two where clauses.


On Tue, Jan 30, 2018 at 7:57 AM jtuchel <[hidden email]> wrote:
Benoît,


sounds like what I am looking for.
I took another tour of the Query subclasses.

I found Query subclass FilteringQuery. Its class comment says:

This is a query that expects all the objects it might return to already be in memory, and in a collection from which it can pick them out by evaluating a block. This is used to implement filtered reads on a mapping. When one of the mappings fires, it reads all the relevant results, and so each instance  using that mapping can get the results out of memory without going to the database again.

So this is not what I am looking for.
Just to be sure I am not overlooking the obvious I checked for implementors of #where: and only found one. It directly sets an instance variable, so the feature you mention seems not to have made its way into "normal" Queries ;-)

So any more ideas?

Joachim




Am Dienstag, 30. Januar 2018 15:32:48 UTC+1 schrieb bstjean:
I remember that in TOPLink (Glorp's ancestor), we had filtered reads (or something named similarly)...  Basically, we could stack WHERE conditions and the final query would be built at the very last moment before execution.  Perhaps, Glorp needs this (it was a useful feature as I remember it).  Alan, are you listening?  ;)


-----------------
Benoît St-Jean
Yahoo! Messenger: bstjean
Twitter: @BenLeChialeux
Pinterest: benoitstjean
Instagram: Chef_Benito
IRC: lamneth
Blogue: <a href="http://endormitoire.wordpress.com" rel="nofollow" target="_blank" onmousedown="this.href=&#39;http://www.google.com/url?q\x3dhttp%3A%2F%2Fendormitoire.wordpress.com\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNFVTrJOgWx4wljrvY17-qXr_fvEPw&#39;;return true;" onclick="this.href=&#39;http://www.google.com/url?q\x3dhttp%3A%2F%2Fendormitoire.wordpress.com\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNFVTrJOgWx4wljrvY17-qXr_fvEPw&#39;;return true;">endormitoire.wordpress.com
"A standpoint is an intellectual horizon of radius zero".  (A. Einstein)


On Tuesday, January 30, 2018, 2:26:01 AM EST, jtuchel <[hidden email]> wrote:


Dear Glorp Community,

I am wondering about an approach to construct Glorp Queries from Filter objects. Let me tell you a bit what I mean by that...

In many web shops and sites you find things like sliders for a price range, a few clickable options like "on stock", "blue/red/greed", "rated higher that x stars" and whatever. And there are nice GUIs for combining these, like using a slider, date pickers, input fields etc. You can add these filters and remove them and then start a search.

We need to build these and the result should end up as a Glorp Query returning objects. We currently only have a few such places in our app and use code like this (from my head, not actual code) to construct queries:

self session read: Product where: [:p| p active = true AND: (self onlyOnStock = false OR: (p onStock=true))].

This work quite well for, say, up to 5 filters, but it doesn't really scale up to 10 or more. The code becomes extremely hard to maintain.

I'd rather like to use something like a visitor pattern, where each filter knows how to add its condition(s) to a query. Somthing like:

|query|
query := Query returningManyOf: Product.
self filters do: [:f|

  query addToWhereCondition: f condition.

].
products := self session execute: query.


Glorp is such a nice framework, but I cannot find a way to do this. Has anybody solved this or found something that could help me on my journey? The idea is that I define Filter objects for concrete values, NULL, ranges (between and) etc. and each of them constructs its little part of the query.

Any ideas? Any code samples?

Joachim

--
You received this message because you are subscribed to the Google Groups "glorp-group" group.
To unsubscribe from this group and stop receiving emails from it, send an email to glorp-group...@googlegroups.com.
To post to this group, send email to [hidden email].

Visit this group at <a href="https://groups.google.com/group/glorp-group" rel="nofollow" target="_blank" onmousedown="this.href=&#39;https://groups.google.com/group/glorp-group&#39;;return true;" onclick="this.href=&#39;https://groups.google.com/group/glorp-group&#39;;return true;">https://groups.google.com/group/glorp-group.
For more options, visit <a href="https://groups.google.com/d/optout" rel="nofollow" target="_blank" onmousedown="this.href=&#39;https://groups.google.com/d/optout&#39;;return true;" onclick="this.href=&#39;https://groups.google.com/d/optout&#39;;return true;">https://groups.google.com/d/optout.

--
You received this message because you are subscribed to the Google Groups "glorp-group" group.
To unsubscribe from this group and stop receiving emails from it, send an email to glorp-group...@googlegroups.com.
To post to this group, send email to [hidden email].
Visit this group at <a href="https://groups.google.com/group/glorp-group" rel="nofollow" target="_blank" onmousedown="this.href=&#39;https://groups.google.com/group/glorp-group&#39;;return true;" onclick="this.href=&#39;https://groups.google.com/group/glorp-group&#39;;return true;">https://groups.google.com/group/glorp-group.
For more options, visit <a href="https://groups.google.com/d/optout" rel="nofollow" target="_blank" onmousedown="this.href=&#39;https://groups.google.com/d/optout&#39;;return true;" onclick="this.href=&#39;https://groups.google.com/d/optout&#39;;return true;">https://groups.google.com/d/optout.

--
You received this message because you are subscribed to the Google Groups "glorp-group" group.
To unsubscribe from this group and stop receiving emails from it, send an email to <a href="javascript:" target="_blank" gdf-obfuscated-mailto="od4Yg1f0AwAJ" rel="nofollow" onmousedown="this.href=&#39;javascript:&#39;;return true;" onclick="this.href=&#39;javascript:&#39;;return true;">glorp-group...@googlegroups.com.
To post to this group, send email to <a href="javascript:" target="_blank" gdf-obfuscated-mailto="od4Yg1f0AwAJ" rel="nofollow" onmousedown="this.href=&#39;javascript:&#39;;return true;" onclick="this.href=&#39;javascript:&#39;;return true;">glorp...@....
Visit this group at <a href="https://groups.google.com/group/glorp-group" target="_blank" rel="nofollow" onmousedown="this.href=&#39;https://groups.google.com/group/glorp-group&#39;;return true;" onclick="this.href=&#39;https://groups.google.com/group/glorp-group&#39;;return true;">https://groups.google.com/group/glorp-group.
For more options, visit <a href="https://groups.google.com/d/optout" target="_blank" rel="nofollow" onmousedown="this.href=&#39;https://groups.google.com/d/optout&#39;;return true;" onclick="this.href=&#39;https://groups.google.com/d/optout&#39;;return true;">https://groups.google.com/d/optout.

--
You received this message because you are subscribed to the Google Groups "glorp-group" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
To post to this group, send email to [hidden email].
Visit this group at https://groups.google.com/group/glorp-group.
For more options, visit https://groups.google.com/d/optout.
Reply | Threaded
Open this post in threaded view
|

Re: Approach to construct queries

jtuchel
This is really fun. I am in the middle of putting together a flexible GUI in which you configure a number or filters and when the user clicks "Search", I construct a query out of Blocks which each of the filters provides.

The beginning was smooth and I was very enthusiastic. Until I had to see if an invoice has payments, so I needed to navigate to related objects, which, in general is not a problem. But now I am stuck with this:

|q|
q := SimpleQuery read: Invoice .
q where: [:inv | (inv sum: [:ea | ea claim payments amount]) > inv claim amount].
dbSession execute: q

--> This works fine.

... But:


|q|
q := SimpleQuery read: Invoice .
q where: [:inv| inv date < Date today].
q AND: [:inv | (inv sum: [:ea | ea claim payments amount]) > inv claim amount].
KontolinoSession instance dbSession execute: q

fails with: UndefinedObject doesNotUnderstand isRelatiponship
in: BaseExpression>>aggregate: anExpression as: aggregateFunctionName where: whereExpression.

What am I doing wrong?

Joachim






--
You received this message because you are subscribed to the Google Groups "glorp-group" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
To post to this group, send email to [hidden email].
Visit this group at https://groups.google.com/group/glorp-group.
For more options, visit https://groups.google.com/d/optout.
Reply | Threaded
Open this post in threaded view
|

Re: Approach to construct queries

Alan Knight
I'm guessing here, but one of the unresolved issues in Glorp is timing of rebuilding expressions. There are times, especially when making complex queries, where you need information about the query before it's normally available. Two things you could try - rather than making a new query, ask the session for one. Then it will have access to the descriptors. The other is that you could convert the block to an expression explicitly, passing in the baseExpression of the query. Again, that will know about the descriptors already.


On Thu, Mar 8, 2018 at 9:17 AM jtuchel <[hidden email]> wrote:
This is really fun. I am in the middle of putting together a flexible GUI in which you configure a number or filters and when the user clicks "Search", I construct a query out of Blocks which each of the filters provides.

The beginning was smooth and I was very enthusiastic. Until I had to see if an invoice has payments, so I needed to navigate to related objects, which, in general is not a problem. But now I am stuck with this:

|q|
q := SimpleQuery read: Invoice .
q where: [:inv | (inv sum: [:ea | ea claim payments amount]) > inv claim amount].
dbSession execute: q

--> This works fine.

... But:


|q|
q := SimpleQuery read: Invoice .
q where: [:inv| inv date < Date today].
q AND: [:inv | (inv sum: [:ea | ea claim payments amount]) > inv claim amount].
KontolinoSession instance dbSession execute: q

fails with: UndefinedObject doesNotUnderstand isRelatiponship
in: BaseExpression>>aggregate: anExpression as: aggregateFunctionName where: whereExpression.

What am I doing wrong?

Joachim






--
You received this message because you are subscribed to the Google Groups "glorp-group" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
To post to this group, send email to [hidden email].
Visit this group at https://groups.google.com/group/glorp-group.
For more options, visit https://groups.google.com/d/optout.

--
You received this message because you are subscribed to the Google Groups "glorp-group" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
To post to this group, send email to [hidden email].
Visit this group at https://groups.google.com/group/glorp-group.
For more options, visit https://groups.google.com/d/optout.
Reply | Threaded
Open this post in threaded view
|

Re: Approach to construct queries

jtuchel
Alan,

I must admit I am a bit lost at trying either of your suggestion.

Asking the session for an existing session to me implies there should be some QueryCache or methods like getQueryNamed: or anything. I can't find such a thing.

The seond I guess would be using some of the methods in the asGlorpExpression* family. Most likely  asGlorpExpressionOn:in: or asGlorpExpressionForDescriptor:. I will start my experiments with the second one...

Any additional hints are welcome ;-)

Joachim



Am 08.03.18 um 15:21 schrieb Alan Knight:
I'm guessing here, but one of the unresolved issues in Glorp is timing of rebuilding expressions. There are times, especially when making complex queries, where you need information about the query before it's normally available. Two things you could try - rather than making a new query, ask the session for one. Then it will have access to the descriptors. The other is that you could convert the block to an expression explicitly, passing in the baseExpression of the query. Again, that will know about the descriptors already.


On Thu, Mar 8, 2018 at 9:17 AM jtuchel <[hidden email]> wrote:
This is really fun. I am in the middle of putting together a flexible GUI in which you configure a number or filters and when the user clicks "Search", I construct a query out of Blocks which each of the filters provides.

The beginning was smooth and I was very enthusiastic. Until I had to see if an invoice has payments, so I needed to navigate to related objects, which, in general is not a problem. But now I am stuck with this:

|q|
q := SimpleQuery read: Invoice .
q where: [:inv | (inv sum: [:ea | ea claim payments amount]) > inv claim amount].
dbSession execute: q

--> This works fine.

... But:


|q|
q := SimpleQuery read: Invoice .
q where: [:inv| inv date < Date today].
q AND: [:inv | (inv sum: [:ea | ea claim payments amount]) > inv claim amount].
KontolinoSession instance dbSession execute: q

fails with: UndefinedObject doesNotUnderstand isRelatiponship
in: BaseExpression>>aggregate: anExpression as: aggregateFunctionName where: whereExpression.

What am I doing wrong?

Joachim






--
You received this message because you are subscribed to the Google Groups "glorp-group" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
To post to this group, send email to [hidden email].
Visit this group at https://groups.google.com/group/glorp-group.
For more options, visit https://groups.google.com/d/optout.
--
You received this message because you are subscribed to a topic in the Google Groups "glorp-group" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/glorp-group/MHCdAZ9AzMg/unsubscribe.
To unsubscribe from this group and all its topics, send an email to [hidden email].
To post to this group, send email to [hidden email].
Visit this group at https://groups.google.com/group/glorp-group.
For more options, visit https://groups.google.com/d/optout.


-- 
-----------------------------------------------------------------------
Objektfabrik Joachim Tuchel          [hidden email]
Fliederweg 1                         http://www.objektfabrik.de
D-71640 Ludwigsburg                  http://joachimtuchel.wordpress.com
Telefon: +49 7141 56 10 86 0         Fax: +49 7141 56 10 86 1

--
You received this message because you are subscribed to the Google Groups "glorp-group" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
To post to this group, send email to [hidden email].
Visit this group at https://groups.google.com/group/glorp-group.
For more options, visit https://groups.google.com/d/optout.
Reply | Threaded
Open this post in threaded view
|

Re: Approach to construct queries

jtuchel
So the first thing I tried is this:


|q sess|
sess := KontolinoSession  instance logout dbSession.
q := ReadQuery read: Invoice .
q baseExpression:  (BaseExpression new descriptor: (sess descriptorFor: Invoice new)).
q where: [:re | (re sum: [:ea | ea claim payments]) > re claim amount].
q AND: [:re| re date < Date today].
 sess execute: q


Same error as before. Funnily, if I comment out the AND: line, it works and returns the correct results...








Am Donnerstag, 8. März 2018 16:16:56 UTC+1 schrieb jtuchel:
Alan,

I must admit I am a bit lost at trying either of your suggestion.

Asking the session for an existing session to me implies there should be some QueryCache or methods like getQueryNamed: or anything. I can't find such a thing.

The seond I guess would be using some of the methods in the asGlorpExpression* family. Most likely  asGlorpExpressionOn:in: or asGlorpExpressionForDescriptor:. I will start my experiments with the second one...

Any additional hints are welcome ;-)

Joachim



Am 08.03.18 um 15:21 schrieb Alan Knight:
I'm guessing here, but one of the unresolved issues in Glorp is timing of rebuilding expressions. There are times, especially when making complex queries, where you need information about the query before it's normally available. Two things you could try - rather than making a new query, ask the session for one. Then it will have access to the descriptors. The other is that you could convert the block to an expression explicitly, passing in the baseExpression of the query. Again, that will know about the descriptors already.


On Thu, Mar 8, 2018 at 9:17 AM jtuchel <[hidden email]> wrote:
This is really fun. I am in the middle of putting together a flexible GUI in which you configure a number or filters and when the user clicks "Search", I construct a query out of Blocks which each of the filters provides.

The beginning was smooth and I was very enthusiastic. Until I had to see if an invoice has payments, so I needed to navigate to related objects, which, in general is not a problem. But now I am stuck with this:

|q|
q := SimpleQuery read: Invoice .
q where: [:inv | (inv sum: [:ea | ea claim payments amount]) > inv claim amount].
dbSession execute: q

--> This works fine.

... But:


|q|
q := SimpleQuery read: Invoice .
q where: [:inv| inv date < Date today].
q AND: [:inv | (inv sum: [:ea | ea claim payments amount]) > inv claim amount].
KontolinoSession instance dbSession execute: q

fails with: UndefinedObject doesNotUnderstand isRelatiponship
in: BaseExpression>>aggregate: anExpression as: aggregateFunctionName where: whereExpression.

What am I doing wrong?

Joachim






--
You received this message because you are subscribed to the Google Groups "glorp-group" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
To post to this group, send email to [hidden email].
Visit this group at <a href="https://groups.google.com/group/glorp-group" target="_blank" rel="nofollow" onmousedown="this.href=&#39;https://groups.google.com/group/glorp-group&#39;;return true;" onclick="this.href=&#39;https://groups.google.com/group/glorp-group&#39;;return true;">https://groups.google.com/group/glorp-group.
For more options, visit <a href="https://groups.google.com/d/optout" target="_blank" rel="nofollow" onmousedown="this.href=&#39;https://groups.google.com/d/optout&#39;;return true;" onclick="this.href=&#39;https://groups.google.com/d/optout&#39;;return true;">https://groups.google.com/d/optout.
--
You received this message because you are subscribed to a topic in the Google Groups "glorp-group" group.
To unsubscribe from this topic, visit <a href="https://groups.google.com/d/topic/glorp-group/MHCdAZ9AzMg/unsubscribe" target="_blank" rel="nofollow" onmousedown="this.href=&#39;https://groups.google.com/d/topic/glorp-group/MHCdAZ9AzMg/unsubscribe&#39;;return true;" onclick="this.href=&#39;https://groups.google.com/d/topic/glorp-group/MHCdAZ9AzMg/unsubscribe&#39;;return true;">https://groups.google.com/d/topic/glorp-group/MHCdAZ9AzMg/unsubscribe.
To unsubscribe from this group and all its topics, send an email to [hidden email].
To post to this group, send email to [hidden email].
Visit this group at <a href="https://groups.google.com/group/glorp-group" target="_blank" rel="nofollow" onmousedown="this.href=&#39;https://groups.google.com/group/glorp-group&#39;;return true;" onclick="this.href=&#39;https://groups.google.com/group/glorp-group&#39;;return true;">https://groups.google.com/group/glorp-group.
For more options, visit <a href="https://groups.google.com/d/optout" target="_blank" rel="nofollow" onmousedown="this.href=&#39;https://groups.google.com/d/optout&#39;;return true;" onclick="this.href=&#39;https://groups.google.com/d/optout&#39;;return true;">https://groups.google.com/d/optout.


-- 
-----------------------------------------------------------------------
Objektfabrik Joachim Tuchel          [hidden email]
Fliederweg 1                         <a href="http://www.objektfabrik.de" target="_blank" rel="nofollow" onmousedown="this.href=&#39;http://www.google.com/url?q\x3dhttp%3A%2F%2Fwww.objektfabrik.de\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNGHeyxMjM5BXvR5qw85qSPuClmpEg&#39;;return true;" onclick="this.href=&#39;http://www.google.com/url?q\x3dhttp%3A%2F%2Fwww.objektfabrik.de\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNGHeyxMjM5BXvR5qw85qSPuClmpEg&#39;;return true;">http://www.objektfabrik.de
D-71640 Ludwigsburg                  <a href="http://joachimtuchel.wordpress.com" target="_blank" rel="nofollow" onmousedown="this.href=&#39;http://www.google.com/url?q\x3dhttp%3A%2F%2Fjoachimtuchel.wordpress.com\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNF4lN1gz9j6BhOOltuFRTSnjfL65w&#39;;return true;" onclick="this.href=&#39;http://www.google.com/url?q\x3dhttp%3A%2F%2Fjoachimtuchel.wordpress.com\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNF4lN1gz9j6BhOOltuFRTSnjfL65w&#39;;return true;">http://joachimtuchel.wordpress.com
Telefon: +49 7141 56 10 86 0         Fax: +49 7141 56 10 86 1

--
You received this message because you are subscribed to the Google Groups "glorp-group" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
To post to this group, send email to [hidden email].
Visit this group at https://groups.google.com/group/glorp-group.
For more options, visit https://groups.google.com/d/optout.
Reply | Threaded
Open this post in threaded view
|

Re: Approach to construct queries

Alan Knight
It's been a while, and I don't have a proper computer here, but I think it might just be session query: ..., corresponding to read:

And if that works, it'd be more like

  q AND: ([...] asGlorpExpressionOn: q baseExpression)


On Thu, Mar 8, 2018 at 10:51 AM jtuchel <[hidden email]> wrote:
So the first thing I tried is this:


|q sess|
sess := KontolinoSession  instance logout dbSession.
q := ReadQuery read: Invoice .
q baseExpression:  (BaseExpression new descriptor: (sess descriptorFor: Invoice new)).
q where: [:re | (re sum: [:ea | ea claim payments]) > re claim amount].
q AND: [:re| re date < Date today].
 sess execute: q


Same error as before. Funnily, if I comment out the AND: line, it works and returns the correct results...









Am Donnerstag, 8. März 2018 16:16:56 UTC+1 schrieb jtuchel:
Alan,

I must admit I am a bit lost at trying either of your suggestion.

Asking the session for an existing session to me implies there should be some QueryCache or methods like getQueryNamed: or anything. I can't find such a thing.

The seond I guess would be using some of the methods in the asGlorpExpression* family. Most likely  asGlorpExpressionOn:in: or asGlorpExpressionForDescriptor:. I will start my experiments with the second one...

Any additional hints are welcome ;-)

Joachim



Am 08.03.18 um 15:21 schrieb Alan Knight:
I'm guessing here, but one of the unresolved issues in Glorp is timing of rebuilding expressions. There are times, especially when making complex queries, where you need information about the query before it's normally available. Two things you could try - rather than making a new query, ask the session for one. Then it will have access to the descriptors. The other is that you could convert the block to an expression explicitly, passing in the baseExpression of the query. Again, that will know about the descriptors already.


On Thu, Mar 8, 2018 at 9:17 AM jtuchel <[hidden email]> wrote:
This is really fun. I am in the middle of putting together a flexible GUI in which you configure a number or filters and when the user clicks "Search", I construct a query out of Blocks which each of the filters provides.

The beginning was smooth and I was very enthusiastic. Until I had to see if an invoice has payments, so I needed to navigate to related objects, which, in general is not a problem. But now I am stuck with this:

|q|
q := SimpleQuery read: Invoice .
q where: [:inv | (inv sum: [:ea | ea claim payments amount]) > inv claim amount].
dbSession execute: q

--> This works fine.

... But:


|q|
q := SimpleQuery read: Invoice .
q where: [:inv| inv date < Date today].
q AND: [:inv | (inv sum: [:ea | ea claim payments amount]) > inv claim amount].
KontolinoSession instance dbSession execute: q

fails with: UndefinedObject doesNotUnderstand isRelatiponship
in: BaseExpression>>aggregate: anExpression as: aggregateFunctionName where: whereExpression.

What am I doing wrong?

Joachim






--
You received this message because you are subscribed to the Google Groups "glorp-group" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
To post to this group, send email to [hidden email].
Visit this group at https://groups.google.com/group/glorp-group.
For more options, visit https://groups.google.com/d/optout.
--
You received this message because you are subscribed to a topic in the Google Groups "glorp-group" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/glorp-group/MHCdAZ9AzMg/unsubscribe.
To unsubscribe from this group and all its topics, send an email to [hidden email].
To post to this group, send email to [hidden email].
Visit this group at https://groups.google.com/group/glorp-group.
For more options, visit https://groups.google.com/d/optout.


-- 
-----------------------------------------------------------------------
Objektfabrik Joachim Tuchel          [hidden email]
Fliederweg 1                         http://www.objektfabrik.de
D-71640 Ludwigsburg                  http://joachimtuchel.wordpress.com
Telefon: +49 7141 56 10 86 0         Fax: +49 7141 56 10 86 1

--
You received this message because you are subscribed to the Google Groups "glorp-group" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
To post to this group, send email to [hidden email].
Visit this group at https://groups.google.com/group/glorp-group.
For more options, visit https://groups.google.com/d/optout.

--
You received this message because you are subscribed to the Google Groups "glorp-group" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
To post to this group, send email to [hidden email].
Visit this group at https://groups.google.com/group/glorp-group.
For more options, visit https://groups.google.com/d/optout.
Reply | Threaded
Open this post in threaded view
|

Re: Approach to construct queries

jtuchel
Alan,





Am Donnerstag, 8. März 2018 17:20:00 UTC+1 schrieb alan.knight:
It's been a while, and I don't have a proper computer here, but I think it might just be session query: ..., corresponding to read:


I only find the possibility to assign a #session: to a query, but GlorpSession has nothing like #query:, #create*Query*, #privateGet*Query* or anything like that. I also checked in VisualWorks 8.2 to be sure it is not something that's missing from the VA port.


 
And if that works, it'd be more like

  q AND: ([...] asGlorpExpressionOn: q baseExpression)


Tried it (with Queries created without the involvement of the session, of course) and got the same error:

UndefinedObject does not understand isRealtionship in  ObjectExpression>>#aggregate:as:where:

Any other ideas?

Joachim



 

On Thu, Mar 8, 2018 at 10:51 AM jtuchel <<a href="javascript:" target="_blank" gdf-obfuscated-mailto="ioJ4Ni9IBwAJ" rel="nofollow" onmousedown="this.href=&#39;javascript:&#39;;return true;" onclick="this.href=&#39;javascript:&#39;;return true;">jtu...@...> wrote:
So the first thing I tried is this:


|q sess|
sess := KontolinoSession  instance logout dbSession.
q := ReadQuery read: Invoice .
q baseExpression:  (BaseExpression new descriptor: (sess descriptorFor: Invoice new)).
q where: [:re | (re sum: [:ea | ea claim payments]) > re claim amount].
q AND: [:re| re date < Date today].
 sess execute: q


Same error as before. Funnily, if I comment out the AND: line, it works and returns the correct results...









Am Donnerstag, 8. März 2018 16:16:56 UTC+1 schrieb jtuchel:
Alan,

I must admit I am a bit lost at trying either of your suggestion.

Asking the session for an existing session to me implies there should be some QueryCache or methods like getQueryNamed: or anything. I can't find such a thing.

The seond I guess would be using some of the methods in the asGlorpExpression* family. Most likely  asGlorpExpressionOn:in: or asGlorpExpressionForDescriptor:. I will start my experiments with the second one...

Any additional hints are welcome ;-)

Joachim



Am 08.03.18 um 15:21 schrieb Alan Knight:
I'm guessing here, but one of the unresolved issues in Glorp is timing of rebuilding expressions. There are times, especially when making complex queries, where you need information about the query before it's normally available. Two things you could try - rather than making a new query, ask the session for one. Then it will have access to the descriptors. The other is that you could convert the block to an expression explicitly, passing in the baseExpression of the query. Again, that will know about the descriptors already.


On Thu, Mar 8, 2018 at 9:17 AM jtuchel <<a href="javascript:" rel="nofollow" target="_blank" gdf-obfuscated-mailto="ioJ4Ni9IBwAJ" onmousedown="this.href=&#39;javascript:&#39;;return true;" onclick="this.href=&#39;javascript:&#39;;return true;">jtu...@...> wrote:
This is really fun. I am in the middle of putting together a flexible GUI in which you configure a number or filters and when the user clicks "Search", I construct a query out of Blocks which each of the filters provides.

The beginning was smooth and I was very enthusiastic. Until I had to see if an invoice has payments, so I needed to navigate to related objects, which, in general is not a problem. But now I am stuck with this:

|q|
q := SimpleQuery read: Invoice .
q where: [:inv | (inv sum: [:ea | ea claim payments amount]) > inv claim amount].
dbSession execute: q

--> This works fine.

... But:


|q|
q := SimpleQuery read: Invoice .
q where: [:inv| inv date < Date today].
q AND: [:inv | (inv sum: [:ea | ea claim payments amount]) > inv claim amount].
KontolinoSession instance dbSession execute: q

fails with: UndefinedObject doesNotUnderstand isRelatiponship
in: BaseExpression>>aggregate: anExpression as: aggregateFunctionName where: whereExpression.

What am I doing wrong?

Joachim






--
You received this message because you are subscribed to the Google Groups "glorp-group" group.
To unsubscribe from this group and stop receiving emails from it, send an email to <a href="javascript:" rel="nofollow" target="_blank" gdf-obfuscated-mailto="ioJ4Ni9IBwAJ" onmousedown="this.href=&#39;javascript:&#39;;return true;" onclick="this.href=&#39;javascript:&#39;;return true;">glorp-group...@googlegroups.com.
To post to this group, send email to <a href="javascript:" rel="nofollow" target="_blank" gdf-obfuscated-mailto="ioJ4Ni9IBwAJ" onmousedown="this.href=&#39;javascript:&#39;;return true;" onclick="this.href=&#39;javascript:&#39;;return true;">glorp...@....
Visit this group at <a href="https://groups.google.com/group/glorp-group" rel="nofollow" target="_blank" onmousedown="this.href=&#39;https://groups.google.com/group/glorp-group&#39;;return true;" onclick="this.href=&#39;https://groups.google.com/group/glorp-group&#39;;return true;">https://groups.google.com/group/glorp-group.
For more options, visit <a href="https://groups.google.com/d/optout" rel="nofollow" target="_blank" onmousedown="this.href=&#39;https://groups.google.com/d/optout&#39;;return true;" onclick="this.href=&#39;https://groups.google.com/d/optout&#39;;return true;">https://groups.google.com/d/optout.
--
You received this message because you are subscribed to a topic in the Google Groups "glorp-group" group.
To unsubscribe from this topic, visit <a href="https://groups.google.com/d/topic/glorp-group/MHCdAZ9AzMg/unsubscribe" rel="nofollow" target="_blank" onmousedown="this.href=&#39;https://groups.google.com/d/topic/glorp-group/MHCdAZ9AzMg/unsubscribe&#39;;return true;" onclick="this.href=&#39;https://groups.google.com/d/topic/glorp-group/MHCdAZ9AzMg/unsubscribe&#39;;return true;">https://groups.google.com/d/topic/glorp-group/MHCdAZ9AzMg/unsubscribe.
To unsubscribe from this group and all its topics, send an email to <a href="javascript:" rel="nofollow" target="_blank" gdf-obfuscated-mailto="ioJ4Ni9IBwAJ" onmousedown="this.href=&#39;javascript:&#39;;return true;" onclick="this.href=&#39;javascript:&#39;;return true;">glorp-group...@googlegroups.com.
To post to this group, send email to <a href="javascript:" rel="nofollow" target="_blank" gdf-obfuscated-mailto="ioJ4Ni9IBwAJ" onmousedown="this.href=&#39;javascript:&#39;;return true;" onclick="this.href=&#39;javascript:&#39;;return true;">glorp...@....
Visit this group at <a href="https://groups.google.com/group/glorp-group" rel="nofollow" target="_blank" onmousedown="this.href=&#39;https://groups.google.com/group/glorp-group&#39;;return true;" onclick="this.href=&#39;https://groups.google.com/group/glorp-group&#39;;return true;">https://groups.google.com/group/glorp-group.
For more options, visit <a href="https://groups.google.com/d/optout" rel="nofollow" target="_blank" onmousedown="this.href=&#39;https://groups.google.com/d/optout&#39;;return true;" onclick="this.href=&#39;https://groups.google.com/d/optout&#39;;return true;">https://groups.google.com/d/optout.


-- 
-----------------------------------------------------------------------
Objektfabrik Joachim Tuchel          <a href="javascript:" rel="nofollow" target="_blank" gdf-obfuscated-mailto="ioJ4Ni9IBwAJ" onmousedown="this.href=&#39;javascript:&#39;;return true;" onclick="this.href=&#39;javascript:&#39;;return true;">mailto:...@objektfabrik.de
Fliederweg 1                         <a href="http://www.objektfabrik.de" rel="nofollow" target="_blank" onmousedown="this.href=&#39;http://www.google.com/url?q\x3dhttp%3A%2F%2Fwww.objektfabrik.de\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNGHeyxMjM5BXvR5qw85qSPuClmpEg&#39;;return true;" onclick="this.href=&#39;http://www.google.com/url?q\x3dhttp%3A%2F%2Fwww.objektfabrik.de\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNGHeyxMjM5BXvR5qw85qSPuClmpEg&#39;;return true;">http://www.objektfabrik.de
D-71640 Ludwigsburg                  <a href="http://joachimtuchel.wordpress.com" rel="nofollow" target="_blank" onmousedown="this.href=&#39;http://www.google.com/url?q\x3dhttp%3A%2F%2Fjoachimtuchel.wordpress.com\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNF4lN1gz9j6BhOOltuFRTSnjfL65w&#39;;return true;" onclick="this.href=&#39;http://www.google.com/url?q\x3dhttp%3A%2F%2Fjoachimtuchel.wordpress.com\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNF4lN1gz9j6BhOOltuFRTSnjfL65w&#39;;return true;">http://joachimtuchel.wordpress.com
Telefon: +49 7141 56 10 86 0         Fax: +49 7141 56 10 86 1

--
You received this message because you are subscribed to the Google Groups "glorp-group" group.
To unsubscribe from this group and stop receiving emails from it, send an email to <a href="javascript:" target="_blank" gdf-obfuscated-mailto="ioJ4Ni9IBwAJ" rel="nofollow" onmousedown="this.href=&#39;javascript:&#39;;return true;" onclick="this.href=&#39;javascript:&#39;;return true;">glorp-group...@googlegroups.com.
To post to this group, send email to <a href="javascript:" target="_blank" gdf-obfuscated-mailto="ioJ4Ni9IBwAJ" rel="nofollow" onmousedown="this.href=&#39;javascript:&#39;;return true;" onclick="this.href=&#39;javascript:&#39;;return true;">glorp...@....
Visit this group at <a href="https://groups.google.com/group/glorp-group" target="_blank" rel="nofollow" onmousedown="this.href=&#39;https://groups.google.com/group/glorp-group&#39;;return true;" onclick="this.href=&#39;https://groups.google.com/group/glorp-group&#39;;return true;">https://groups.google.com/group/glorp-group.
For more options, visit <a href="https://groups.google.com/d/optout" target="_blank" rel="nofollow" onmousedown="this.href=&#39;https://groups.google.com/d/optout&#39;;return true;" onclick="this.href=&#39;https://groups.google.com/d/optout&#39;;return true;">https://groups.google.com/d/optout.

--
You received this message because you are subscribed to the Google Groups "glorp-group" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
To post to this group, send email to [hidden email].
Visit this group at https://groups.google.com/group/glorp-group.
For more options, visit https://groups.google.com/d/optout.
Reply | Threaded
Open this post in threaded view
|

Re: Approach to construct queries

jtuchel
Alan,

I finally had success with this:

|q sess exp |
sess := KontolinoSession  instance dbSession.
q := SimpleQuery read: Invoice.
q session: sess.
q baseExpression:  (exp := BaseExpression new descriptor: (sess descriptorFor: Invoice new)).
q where: ([:re | (re sum: [:ea | ea claim payments amount]) > re claim amount] asGlorpExpressionOn: exp).
q AND: ([:re| re date < Date today] asGlorpExpressionOn: exp).
 sess execute: q.


The important parts:

  • It is not enough to just do the asGlorpExpression for the AND: parameters, at least the one that aggregates needs it.
  • The temp var for the base expression! always asking the query for its base expression returns Base(Invoice) for the first statemet (where:) but Base(nil) for the second.


I am not sure I understand all that, but at least things work now ;-)



Thanks (in Capital Letters: THANKS!)


Joachim






--
You received this message because you are subscribed to the Google Groups "glorp-group" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
To post to this group, send email to [hidden email].
Visit this group at https://groups.google.com/group/glorp-group.
For more options, visit https://groups.google.com/d/optout.
Reply | Threaded
Open this post in threaded view
|

Re: Approach to construct queries

Madhu
Joachim,

Just in case if you don't want to use asGlorpExpressionOn: all over, try:

|q sess|
sess := KontolinoSession instance dbSession.
q := SimpleQuery read: Invoice.
q where: [:inv| inv date < Date today].
q baseExpression descriptor: (sess descriptorFor: Invoice). "Initialize descriptor before the first call to AND:"
q AND: [:inv | (inv sum: [:ea | ea claim payments amount]) > inv claim amount].
sess execute: q.

Regards,
Madhu.

On Fri, Mar 9, 2018 at 10:43 AM, jtuchel <[hidden email]> wrote:
Alan,

I finally had success with this:

|q sess exp |
sess := KontolinoSession  instance dbSession.
q := SimpleQuery read: Invoice.
q session: sess.
q baseExpression:  (exp := BaseExpression new descriptor: (sess descriptorFor: Invoice new)).
q where: ([:re | (re sum: [:ea | ea claim payments amount]) > re claim amount] asGlorpExpressionOn: exp).
q AND: ([:re| re date < Date today] asGlorpExpressionOn: exp).
 sess execute: q.


The important parts:

  • It is not enough to just do the asGlorpExpression for the AND: parameters, at least the one that aggregates needs it.
  • The temp var for the base expression! always asking the query for its base expression returns Base(Invoice) for the first statemet (where:) but Base(nil) for the second.


I am not sure I understand all that, but at least things work now ;-)



Thanks (in Capital Letters: THANKS!)


Joachim






--
You received this message because you are subscribed to the Google Groups "glorp-group" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
To post to this group, send email to [hidden email].
Visit this group at https://groups.google.com/group/glorp-group.
For more options, visit https://groups.google.com/d/optout.

--
You received this message because you are subscribed to the Google Groups "glorp-group" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
To post to this group, send email to [hidden email].
Visit this group at https://groups.google.com/group/glorp-group.
For more options, visit https://groups.google.com/d/optout.
Reply | Threaded
Open this post in threaded view
|

Re: Approach to construct queries

jtuchel
Madhu.

I remember trying that before the first #where: with no luck. If I remember correctly, the effect also was that after the first (or maybe each) #AND: or #where: the Query's baseExpression was again Base(nil). So I guess what you suggest works for this code snippet, but very likely doesn't work if you append another #AND:   ...  ?

Since I want to work an a list of unknown size of filters that add queryBlocks to the query, I will probably just stick with what I have now.


Joachim


Am Freitag, 9. März 2018 13:39:24 UTC+1 schrieb Madhu:
Joachim,

Just in case if you don't want to use asGlorpExpressionOn: all over, try:

|q sess|
sess := KontolinoSession instance dbSession.
q := SimpleQuery read: Invoice.
q where: [:inv| inv date < Date today].
q baseExpression descriptor: (sess descriptorFor: Invoice). "Initialize descriptor before the first call to AND:"
q AND: [:inv | (inv sum: [:ea | ea claim payments amount]) > inv claim amount].
sess execute: q.

Regards,
Madhu.

On Fri, Mar 9, 2018 at 10:43 AM, jtuchel <<a href="javascript:" target="_blank" gdf-obfuscated-mailto="OBGUBbqKBwAJ" rel="nofollow" onmousedown="this.href=&#39;javascript:&#39;;return true;" onclick="this.href=&#39;javascript:&#39;;return true;">jtu...@...> wrote:
Alan,

I finally had success with this:

|q sess exp |
sess := KontolinoSession  instance dbSession.
q := SimpleQuery read: Invoice.
q session: sess.
q baseExpression:  (exp := BaseExpression new descriptor: (sess descriptorFor: Invoice new)).
q where: ([:re | (re sum: [:ea | ea claim payments amount]) > re claim amount] asGlorpExpressionOn: exp).
q AND: ([:re| re date < Date today] asGlorpExpressionOn: exp).
 sess execute: q.


The important parts:

  • It is not enough to just do the asGlorpExpression for the AND: parameters, at least the one that aggregates needs it.
  • The temp var for the base expression! always asking the query for its base expression returns Base(Invoice) for the first statemet (where:) but Base(nil) for the second.


I am not sure I understand all that, but at least things work now ;-)



Thanks (in Capital Letters: THANKS!)


Joachim






--
You received this message because you are subscribed to the Google Groups "glorp-group" group.
To unsubscribe from this group and stop receiving emails from it, send an email to <a href="javascript:" target="_blank" gdf-obfuscated-mailto="OBGUBbqKBwAJ" rel="nofollow" onmousedown="this.href=&#39;javascript:&#39;;return true;" onclick="this.href=&#39;javascript:&#39;;return true;">glorp-group...@googlegroups.com.
To post to this group, send email to <a href="javascript:" target="_blank" gdf-obfuscated-mailto="OBGUBbqKBwAJ" rel="nofollow" onmousedown="this.href=&#39;javascript:&#39;;return true;" onclick="this.href=&#39;javascript:&#39;;return true;">glorp...@....
Visit this group at <a href="https://groups.google.com/group/glorp-group" target="_blank" rel="nofollow" onmousedown="this.href=&#39;https://groups.google.com/group/glorp-group&#39;;return true;" onclick="this.href=&#39;https://groups.google.com/group/glorp-group&#39;;return true;">https://groups.google.com/group/glorp-group.
For more options, visit <a href="https://groups.google.com/d/optout" target="_blank" rel="nofollow" onmousedown="this.href=&#39;https://groups.google.com/d/optout&#39;;return true;" onclick="this.href=&#39;https://groups.google.com/d/optout&#39;;return true;">https://groups.google.com/d/optout.

--
You received this message because you are subscribed to the Google Groups "glorp-group" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
To post to this group, send email to [hidden email].
Visit this group at https://groups.google.com/group/glorp-group.
For more options, visit https://groups.google.com/d/optout.
Reply | Threaded
Open this post in threaded view
|

Re: Approach to construct queries

Wolfgang Eder
In reply to this post by jtuchel
Hi Joachim,
you can try to put the AND: into the block,
instead of sending it to the query.

q where: [:inv| inv date < Date today AND: [ (inv sum: [:ea | ea claim payments amount]) > inv claim amount]].

just my 2c
Wolfgang

Am 08.03.2018 um 15:17 schrieb jtuchel <[hidden email]>:

|q|
q := SimpleQuery read: Invoice .
q where: [:inv| inv date < Date today].
q AND: [:inv | (inv sum: [:ea | ea claim payments amount]) > inv claim amount].
KontolinoSession instance dbSession execute: q

--
You received this message because you are subscribed to the Google Groups "glorp-group" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
To post to this group, send email to [hidden email].
Visit this group at https://groups.google.com/group/glorp-group.
For more options, visit https://groups.google.com/d/optout.

signature.asc (541 bytes) Download Attachment
12