Question about filtering using object methods

6 views
Skip to first unread message

Mariano Martinez Peck

unread,
Jul 23, 2013, 11:44:48 AM7/23/13
to glorp...@googlegroups.com, dbx...@googlegroups.com
Hi.  I know I can have 2 scenarios when writing queries:

1) Compare instance variables that have been mapped to fields. Example:
session readManyOf: XXX where: [ :object | object xxx = 'ABX'  ].

2) Compare using DOMAIN MODEL METHODS that are NOT mapped to anything:
session readManyOf: XXX where: [ :object | (object isEffectiveOn: Date today)  ]

In the first case 1) the #xxx method is an accessor for an instVar that is mapped to a field. Hence, Glorp can write the SQL in a way to filter the rows in the DB and just bring to memory the one that satisfies. 

Case 2) would need to instantiate each row of the table, send the message #isEffectiveOn: and check if it's true or not.  So, I have 2 questions here:

a) How can I make such a query work? The same query of the scenario 2 does not work for me and I get a MessageNotUnderstood: BaseExpression>>convertedDbValueOf: (I can attach PharoDebug.log if it helps). 

b) do such type of queries (scenario 2) bring only one object at a time and only keep the ones that satisfy the conditions or it brings (instantiates) all rows/objects at the same time in memory and then filter them?  I think this is important because there are some of my tables that won't fit in memory. 

c) if the answer to b) is that you do one by one (which I don't think so), all (or at least several) plain rows will be in memory right? I don't think you will go to the db for each row..

Thanks in advance, 


--
Mariano
http://marianopeck.wordpress.com

jtuchel

unread,
Aug 19, 2013, 9:19:12 AM8/19/13
to glorp...@googlegroups.com, dbx...@googlegroups.com
Mariano,

the problem here is that what looks like a Block in fact isn't really. You cannot send messages to each of the resulting objects. The "Block" is used to generate an SQL statement, and there is no way to determine what isEffectiveOn: would look like in SQL by simply analyzing the descriptor.

I wish I could call some nice Smalltalk methods on rows as well, but GLORP does not support this, afaik. And I guess it is not really easy to implement. You'd have to decide for each message send in a Block whether it is something that can be expressed in SQL or has to be executed on a materialized object.

So I am not aware of any other possibility than turning such things into a two-pass select. First a readManyOf:where: for everything that's directly mapped, and a subsequent "pure old Smalltalk" select: on the results for everything else.

It would be great to simply forget about the SQL nature and write normal select:/reject: expressions and have Glorp determine how to convert parts of them into SQL and parts as SQL code.

I am afraid this is a very expensive feature, however.

Joachim

jtuchel

unread,
Aug 19, 2013, 9:21:51 AM8/19/13
to glorp...@googlegroups.com, dbx...@googlegroups.com
Mariano,

the problem here is that what looks like a Block in fact isn't really. You cannot send messages to each of the resulting objects. The "Block" is used to generate an SQL statement, and there is no way to determine what isEffectiveOn: would look like in SQL by simply analyzing the descriptor.

I wish I could call some nice Smalltalk methods on rows as well, but GLORP does not support this, afaik. And I guess it is not really easy to implement. You'd have to decide for each message send in a Block whether it is something that can be expressed in SQL or has to be executed on a materialized object.

So I am not aware of any other possibility than turning such things into a two-pass select. First a readManyOf:where: for everything that's directly mapped, and a subsequent "pure old Smalltalk" select: on the results for everything else.

It would be great to simply forget about the SQL nature and write normal select:/reject: expressions and have Glorp determine how to convert parts of them into SQL and parts as Smalltalkcode.


I am afraid this is a very expensive feature, however.

Joachim

Am Dienstag, 23. Juli 2013 17:44:48 UTC+2 schrieb Mariano Martinez Peck:

Mariano Martinez Peck

unread,
Aug 19, 2013, 10:07:31 AM8/19/13
to glorp...@googlegroups.com, dbx...@googlegroups.com



On Mon, Aug 19, 2013 at 10:21 AM, jtuchel <jtu...@objektfabrik.de> wrote:
Mariano,



Hi Joachim, thanks for answering.
 
the problem here is that what looks like a Block in fact isn't really. You cannot send messages to each of the resulting objects. The "Block" is used to generate an SQL statement, and there is no way to determine what isEffectiveOn: would look like in SQL by simply analyzing the descriptor.


Totally agree. 

I wish I could call some nice Smalltalk methods on rows as well, but GLORP does not support this, afaik. And I guess it is not really easy to implement. You'd have to decide for each message send in a Block whether it is something that can be expressed in SQL or has to be executed on a materialized object.

So I am not aware of any other possibility than turning such things into a two-pass select. First a readManyOf:where: for everything that's directly mapped, and a subsequent "pure old Smalltalk" select: on the results for everything else.

It would be great to simply forget about the SQL nature and write normal select:/reject: expressions and have Glorp determine how to convert parts of them into SQL and parts as Smalltalkcode.


I thought Glorp provided these 2 last paragraphs (what I call scenario 2 in my email). I thought Glorp could realized that it was not possible to generate a SQL from the block closure and hence, that it was going to fall back to materialize objects from DB and send them such a message. I am disappointed :(

Anyway, I agree with you that the only possibility is then to do the readManyOf:where: (making sure the SQL will work) and then the #select: in memory. 

 

I am afraid this is a very expensive feature, however.

Joachim

Am Dienstag, 23. Juli 2013 17:44:48 UTC+2 schrieb Mariano Martinez Peck:
Hi.  I know I can have 2 scenarios when writing queries:

1) Compare instance variables that have been mapped to fields. Example:
session readManyOf: XXX where: [ :object | object xxx = 'ABX'  ].

2) Compare using DOMAIN MODEL METHODS that are NOT mapped to anything:
session readManyOf: XXX where: [ :object | (object isEffectiveOn: Date today)  ]

In the first case 1) the #xxx method is an accessor for an instVar that is mapped to a field. Hence, Glorp can write the SQL in a way to filter the rows in the DB and just bring to memory the one that satisfies. 

Case 2) would need to instantiate each row of the table, send the message #isEffectiveOn: and check if it's true or not.  So, I have 2 questions here:

a) How can I make such a query work? The same query of the scenario 2 does not work for me and I get a MessageNotUnderstood: BaseExpression>>convertedDbValueOf: (I can attach PharoDebug.log if it helps). 

b) do such type of queries (scenario 2) bring only one object at a time and only keep the ones that satisfy the conditions or it brings (instantiates) all rows/objects at the same time in memory and then filter them?  I think this is important because there are some of my tables that won't fit in memory. 

c) if the answer to b) is that you do one by one (which I don't think so), all (or at least several) plain rows will be in memory right? I don't think you will go to the db for each row..

Thanks in advance, 


--
Mariano
http://marianopeck.wordpress.com

--
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 glorp...@googlegroups.com.
Visit this group at http://groups.google.com/group/glorp-group.
For more options, visit https://groups.google.com/groups/opt_out.



--
Mariano
http://marianopeck.wordpress.com
Reply all
Reply to author
Forward
Message has been deleted
0 new messages