Dear Glorp Community,
-- this is a little complex to explain, but I'll try. I have a class hierarchy mapped to a single table using the FilteredTypeResolver. In the subclass, there is a composed attribute that consists of the combination of two attributes (in may case a period in time between a start date and an end date). For this period I use an EmbeddedValueToOneMapping. It does its job well in most of the cases, but I found one in which it doesn't. This period istVar is only present in the subclass, not in the superclass. But since both are mapped to the same table, the table has the startDate and endDate column. So we have class Superclass, which has a number of Attributes like id, version, name, whatever. And we have a Subclass with a period attribute which is mapped to the columns startdate and enddate. When I do: Session read: Subclass, the result is fine. When I do: Session read: Superclass, the result is a Debugger (I am using VA Smalltalk 8.6.3, but the Glorp Code looks identical in Pharo 5). The Error I get is: UndefinedObject does not understand instance. And this is the method which doesn't work (I marked the faulty line in red): EmbeddedValueOneToOneMapping>>#mapObject: anObject inElementBuilder: anElementBuilder | myTraceNode myBuilder | "If the object already has a value in my slot, then this it got a cache hit, the embedded value was carried along for the ride, and we don't need to assign anything" (self getValueFrom: anObject) isNil ifFalse: [^self]. "Otherwise, we need to look up the trace node that corresponds to this mapping, and get its instance" myTraceNode := anElementBuilder expression get: self attributeName. myBuilder := anElementBuilder query elementBuilderFor: myTraceNode. self setValueIn: anObject to: myBuilder instance. The problem is that anElementBuilder query elementBuilderFor: myTraceNode returns nil instead of a Builder. And that is because anElementBuilder is the Builder of the Superclass (Base(Superclass)) and myTraceNode is (Base(Superclass).period). anElementBuilder query returns a Query for the superclass, and that Query has no mapping for #period, since that attribute is only mapped in a subclass. So I guess what should really happen is that myBuilder has to be looked up not only in the superclass' query, but also in the query of the Builders of all Subclasses. But I don't know how to find the builders of all subclasses and iterate over these (there is a method named withAllSubbuilders, but that doesn't return what I want/need)... ? Any hints, ideas, bugfixes are welcome 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. |
Hi Niall,
thanks for looking into this. To me it seems like no other mapping really uses the info which Class' instance of it is populating. They just get the value and set it in the instance, only EmbeddedValueToOneMapping wants to use a Query for its job. So I think there are two areas that could help solve this:
The first option would reduce possible side effects by just
changing the EmbeddedValueToOneMapping, but I think the second
sounds like a generally "more correct" solution because you
never know if other mappings could benefit from acting on the
"correct" Builder. However: I couldn't see an obvious way for doing either of these...
Joachim Am 11.03.17 um 19:16 schrieb Niall Ross: Dear Joachim,
-- ----------------------------------------------------------------------- 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. |
In reply to this post by jtuchel
Niall,
I played with this a little more and I almost thought I had the solution. Here is what I tried: mapObject: anObject inElementBuilder: anElementBuilder | myTraceNode myBuilder | "If the object already has a value in my slot, then this it got a cache hit, the embedded value was carried along for the ride, and we don't need to assign anything" (self getValueFrom: anObject) isNil ifFalse: [^self]. "Otherwise, we need to look up the trace node that corresponds to this mapping, and get its instance" myTraceNode := anElementBuilder expression get: self attributeName. myBuilder := ((Query read: anElementBuilder instance class) session: self session) prepare elementBuilderFor: myTraceNode. . self setValueIn: anObject to: myBuilder instance. By building a query for the concrete object's class I was hoping to get a Query object that knows how to map the field. And in fact myBuilder seems to perfectly fit. It contains the mapping for the subclass' embedded field. And in fact what I got was the correct mapping expression as #myBuilder: Base(Subclass).period Unfotunately, this still returns nil in SimpleQuery>>#elementBuilderFor: anExpression ^builders detect: [:each | each expression == anExpression] ifNone: [nil]. because the two expressions (builders) are neither equal(=) nor identical(==). They look exactly the same in the inspector, but obviously they aren't identical, but surprisingly not even equal. There is no implementor of #= in the MappingExpression hierarchy, so at least technically, the unequality of these two equal MappingExpression objects is explicable ;-). Since I don't really know why Glorp assumes these two expressions have to be identical, I am not sure how to continue. So I guess there is some place all the expressions are cached and I just need a way to not create a new Query, but to get the one already existing in the session, or I am probably about 6000 Miles off the right track. Both are very well possible... Joachim Am 11.03.17 um 19:16 schrieb Niall Ross: Dear Joachim,
-- ----------------------------------------------------------------------- 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. |
Niall,
-- since I need to get this fixed pretty soon, I'd like to hear about your ideas on my trial. Do you think this is the right track? Or would you try and start fixing the setup of tracing on the very other end of query processing? My idea was to isolate the fix at the "low end" where negative side effects are minimal. I think if you agree using the Query for the concrete subclass for finding the correct attribute builder, we need one of these two things
Joachim Am Montag, 13. März 2017 16:49:52 UTC+1 schrieb jtuchel:
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. |
Niall,
I can answer my last question now: creating a new query at this point won't help. There is no builder that holds an instance in that case, so the value from the db is not present. The fix has to be established a lot deeper down in the Glorp machinery, analoguous to ObjectBuilder>>#findInstanceForRow:proxyType: Joachim Am 15.03.17 um 08:58 schrieb jtuchel:
-- ----------------------------------------------------------------------- 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. |
I just wanted the list to know that Niall has confirmed the error and provided me with a temporal fix (involving a slightly extended ConditionalMapping for the superclass).
-- He told me he's working on a general fix that is very likely to appear in the next Glorp release. I want to (now also publicly) say a big Thank You to Niall! 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. |
Free forum by Nabble | Edit this page |