Re: [Pharo-users] Glorp: #includesKey:

2017-10-25 Thread Herby Vojčík

Niall Ross wrote:

Dear Herby,
adding #includesKey: is certainly doable. If you look at callers above
and subcallers below #anySatisfyDefault: you will see the issues
involved. Your includesKey: needs the same degree of platform-awareness
that Glorp's #anySatisfy: and #allSatisfy: implementations use. But
since #anySatisfy: is there, you have a ready template to follow.


I don't feel competent enough, from what I looked, Glorp innards are a 
bit complex.



Alternatively, I may well add #includesKey: - though not as my most
urgent task. :-) I did a fair amount of work to extend the usability of
DictionaryMappings in Glorp three years ago (part of demonstrating the
ObjectStudio business-mapping/Glorp-generating tools - see my ESUG 2014
presentation for details) but I did not then think of providing
#includesKey:. Thanks for suggesting the idea.


My pleasure. :-)

As I wrote elsewhere, also #keys is something (probably the most 
general) one that could be added as a matter of allowing to work with 
the key field - as far as I was able to find out, there is no way to 
actually get to the key, for which I found workaround since I mapped 
object, but would be out of luck if I mapped single primitive value.


For the moment, it is not pressing, but yes, it would be nice to be able 
to have #keys mapping to key field and #includesKey: as an idiomatic way 
to do keys includes:.


Thanks again, Herby


If you were to work on this, be aware:

- always reinitialise FunctionExpression class after adding/changing any
Glorp function (or just close and reopen your image, of course)

- If (and only if) you construct Query whereClauses in stages (e.g. you
have code like

myQuery AND: [:customer | customer orders includesKey: #onlineOrders]

or similar) then, using its callers in GlorpTest as a guide, know when
you might need to send #setUpBaseFromSession: to your query while doing
so. (N.B. that method is a Glorp version 8.2.1 addition; you will not
have it in older Glorp.) The point is that stage-constructed where
clauses must convert from block to expression before execution, to
combine the stages. Any that use #anySatisfy:/#allSatisfy: need
platform-specific information to do this; I would expect any
#includesKey: implementation to be the same.

HTH
Niall Ross


Tom Robinson wrote:

Hi Herby,

In my opinion, the way you found to make it work is the way it should
be. The reason is that the first way doesn't translate into SQL and the
second one does. It might be possible to add includesKey: functionality
but resolving that to SQL would be more complex. I would not call this a
bug. I would call it a limitation of the implementation. I don't know of
anyone planning to add this feature to Glorp right now.

Regards,

Tom

On 10/24/2017 12:27 PM, Herby Vojčík wrote:


Hello!

I am using a DictionaryMapping in my code, and I wanted to use
#includesKey: in #where: clause (something akin

each tools includesKey: aToolId

) to select only rows for which DictionaryMapping uses certain key. It
failed with the error in the lines of "#tools does not resolve to
field". I had to come up with

each tools anySatisfy: [ :tool | tool id = aToolId ]

Is it the bug / feature / problem in my approach? If bug, is it
planned to add #includesKey: translation to DictionaryMapping?

Thanks, Herby







Re: [Pharo-users] Glorp: #includesKey:

2017-10-25 Thread Herby Vojčík

jtuc...@objektfabrik.de wrote:

Herby,

I must admit I've never used Dictionary Mappings with Glorp, so I don't
have an answer.
But I am a bit confused by your code examples. See below


Am 24.10.17 um 20:27 schrieb Herby Vojčík:

Hello!

I am using a DictionaryMapping in my code, and I wanted to use
#includesKey: in #where: clause (something akin

  each tools includesKey: aToolId


What SQL expression would you expect here?


SELECT * FROM AGENT a WHERE a.tool_id = :aToolId

AFAICT, DISTINCT is not needed as  are fks to other table's 
compound primary key , so they are known to be unique.



I would guess that you want to build a subquery like exists, because the
way I understand the query, you want to find all instances of (whatever
each is) that hold an Association in their tools dictionary where the
key is aToolId.


Yes.

Maybe it needs EXISTS, I don't know. Semantics is clear, though.



) to select only rows for which DictionaryMapping uses certain key. It
failed with the error in the lines of "#tools does not resolve to
field". I had to come up with




each tools anySatisfy: [ :tool | tool id = aToolId ]

Hmm. This makes me wonder. Is #tools really a Dictionary? Inside the
Block, I'd expect the :tool parameter to be an Association, and that
doesn't understand #id,does it? I guess @each is the parameter within an
Block like in

self session read: MyClass where: [:each| each tools ...]

If so, I have a hard time believing that anySatisfy: would work (never
tried)...


Yes, it works. Dictionary enumerates values, as I have written in reply 
to Tom's post.



Is it the bug / feature / problem in my approach? If bug, is it
planned to add #includesKey: translation to DictionaryMapping?


I don't know, but would guess it is not currently on the Todo-list.

My first tip would be to try and find some slides (most likely made by
Niall and presented at an ESUG) including the words "subquery", "glorp"
and "exists". You won't find much, but that may be a starting point.


I actually managed to get there, but
  a) using ugly workaround IMO, #includesKey: is part of dictionary's 
protocol, should be known;
  b) as I wrote in Tom's reply, the workaround only worked because 
mapping was to object. If the mapping was to primitive value (number, 
string), I would not have any 'tool id' ready to use and I would be left 
 without option. There is no way to construct such query atm in 
Glorp, afaict, if I cannot use #keys not #includesKey: in where clause. 
Is that not a bug?



Not sure this helps, ;-)


Joachim


Thanks, Herby



Re: [Pharo-users] Glorp: #includesKey:

2017-10-25 Thread Herby Vojčík

Tom Robinson wrote:

Hi Herby,

In my opinion, the way you found to make it work is the way it should
be. The reason is that the first way doesn't translate into SQL and the
second one does. It might be possible to add includesKey: functionality
but resolving that to SQL would be more complex. I would not call this a


I think I disagree with this, but correct me if I am wrong.

With DictionaryMapping, you map a set of (key, value) pairs into 
appropriate fields in a table. In essence, it does not differ at all to 
mapping any other collection containing objects with fields (actually, 
from what I understood, it does internal tricks to do just that - create 
internal "class mapping" for an association of that particular 
dictionary mapping).


In case of primitive value dictionaries, it even _is_ the same: key is 
mapped to one field, value is mapped to different field. If I want to 
create subquery using value, I can freely use things like #anySatisfy: 
to filter on that value (which I did in my case, but I come to that 
later). Since Dictionary enumerates values in do:, select:, collect: 
(and anySatisfy:), writing


  each tools anySatisfy: [...]

is the same as writing

  each tools values anySatisfy: [...]

but what if I wanted to write

  each tools keys anySatisfy: [...]

? I cannot, Glorp fails on 'keys' (I tried to use `keys includes:` 
instead of `includesKey:`, to no avail).


So what I want to point here is, that in DictionaryMapping I map keys 
and values to different fields in table (values can be complex, in which 
keys they are mapped to more fields, but that is not important 
distinction here), but Glorp only allows me to use values (and only 
implicitly) in where clauses; I have no way to use keys at all there.


So I assert here that "resolving that to SQL would be more complex" is 
not true. Key is mapped the same way value is; if I can use where clause 
that uses value in certain way, I should be able to use key as well - 
SQL generating from one or the other have same level of difficulty (in 
fact, I think key is easier, as you do not actually need to join the 
foreign table); the generated SQL could be something like


  SELECT * FROM AGENT a
WHERE a.tool_id = 

The fact that I found a

  each tools anySatisfy: [ :tool | tool id = aToolId ]

is in fact only because non-primitive mappings are processed differently 
in DictionaryMapping, a non-primitive values are _required_ to have a 
field defined (not in table, that is understandable, I need to be able 
to make a join, but in descriptor) a mapping that contains the key. So 
in essence, that could be represented as


  SELECT * FROM AGENT a
WHERE a.tool_id IN
 (SELECT * FROM TOOL t
   WHERE t.agent_id = a.id
 AND t.id = a.tool_id
 AND t.id = )

which is basically same as above, as actually, "a.tool_id = asDbValue>" is executed here as well (plus checking that such dictionary 
actually exists at all; maybe that should be present in previous case as 
well, but Glorp can generate the join, that's not the question here).


It is actually interesting question what SQL Glorp actually generated 
for "TgAgent readOneOf: [:a|a tools anySatisfy: [:t|t id = toolId]]".


Point here is:

  1. Why do I need to work it around via [:tool | tool id = aToolId] 
when I am only interested on "which tools the agent uses" (in fact, give 
me all agents using this tool).
  2. Should this be key -> primitive value mapping, I have simple _no 
way_ to ask the equivalent of #includesKey: at all (as the value is, for 
example, a String or an Integer, so no `tool id` is available).



bug. I would call it a limitation of the implementation. I don't know of
anyone planning to add this feature to Glorp right now.


That's why I would say #keys (and, ideally, #includesKey:) are actually 
needed addition to Glorp's set of known-and-translated selectors in case 
of DictionaryMapping.



Regards,

Tom


Thanks, Herby




Re: [Pharo-users] Glorp: #includesKey:

2017-10-24 Thread jtuc...@objektfabrik.de

Herby,

I must admit I've never used Dictionary Mappings with Glorp, so I don't 
have an answer.

But I am a bit confused by your code examples. See below


Am 24.10.17 um 20:27 schrieb Herby Vojčík:

Hello!

I am using a DictionaryMapping in my code, and I wanted to use 
#includesKey: in #where: clause (something akin


  each tools includesKey: aToolId


What SQL expression would you expect here?

I would guess that you want to build a subquery like exists, because the 
way I understand the query, you want to find all instances of (whatever 
each is) that hold an Association in their tools dictionary where the 
key is aToolId.


) to select only rows for which DictionaryMapping uses certain key. It 
failed with the error in the lines of "#tools does not resolve to 
field". I had to come up with





each tools anySatisfy: [ :tool | tool id = aToolId ]
Hmm. This makes me wonder. Is #tools really a Dictionary? Inside the 
Block, I'd expect the :tool parameter to be an Association, and that 
doesn't understand #id,does it? I guess @each is the parameter within an 
Block like in


self session read: MyClass where: [:each| each tools ...]

If so, I have a hard time believing that anySatisfy: would work (never 
tried)...






Is it the bug / feature / problem in my approach? If bug, is it 
planned to add #includesKey: translation to DictionaryMapping?



I don't know, but would guess it is not currently on the Todo-list.

My first tip would be to try and find some slides (most likely made by 
Niall and presented at an ESUG) including the words "subquery", "glorp" 
and "exists". You won't find much, but that may be a starting point.


Not sure this helps, ;-)


Joachim


--
---
Objektfabrik Joachim Tuchel  mailto:jtuc...@objektfabrik.de
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




[Pharo-users] Glorp: #includesKey:

2017-10-24 Thread Herby Vojčík

Hello!

I am using a DictionaryMapping in my code, and I wanted to use 
#includesKey: in #where: clause (something akin


  each tools includesKey: aToolId

) to select only rows for which DictionaryMapping uses certain key. It 
failed with the error in the lines of "#tools does not resolve to 
field". I had to come up with


  each tools anySatisfy: [ :tool | tool id = aToolId ]

Is it the bug / feature / problem in my approach? If bug, is it planned 
to add #includesKey: translation to DictionaryMapping?


Thanks, Herby