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 = <toolId asDbValue> 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 = <aToolId asDbValue>) which is basically same as above, as actually, "a.tool_id = <aToolId 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