Forcing save when #register: doesn't work

11 views
Skip to first unread message

Esteban Maringolo

unread,
Nov 1, 2020, 8:20:46 PM11/1/20
to GLORP Mailing List
Hi,

I have a weird situation where I can't find an easy way to debug (as usual).

Within a unit of work I read some object A from the DB, explicitly
#register: it in the session, modify some of its attributes, and then
commit the unit of work and the changes are not saved to the table.

Following the #register: message sends it ends up being registered as
an existing object (which is true), but I don't understand why the
changes are not applied afterwards since there are changes between the
read object (and hence its rowmap) and the new one.

Is there an easy way to debug this? This happens somehow deep in a ETL
and I can't find a way to reproduce it outside of the actual execution
of the ETL, so I want to identify the issue and then write the unit
test once the fix is done.

Thanks!

Esteban A. Maringolo

Alan Knight

unread,
Nov 5, 2020, 8:55:15 AM11/5/20
to glorp...@googlegroups.com
There is a debugRead/debugWrite type of variable on mappings that you can set, and you will get a halt when it reads or writes. That's probably the most useful hidden trick. But that will show you when it's being written to the RowMap. Do you know that the RowMaps are different? I guess you could halt/log on the various steps. Is the object different from the registered copy. Does the mapping write the new value into the generated RowMap. Is the generated RowMap for the new version of this object different from the old one? Does the differencing produce a RowMap that contains the modified value? Does that modified value get written from the RowMap to the DB? RowMaps are not trivial to inspect, but should have all the information.

I'm a little bit suspicious of the explicit register, though it ought to be harmless. When you read within a unit of work things are automatically registered.

And actually thinking of the last couple of steps I wrote up there, is this a funny VA-specific object, where registration/lookup of the original object might not be working? Registration has to have special cases for the different ways that collections are implemented in different dialects. There could be others. Although if that was the reason I'd expect it to be easy to reproduce in isolation.


--
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 view this discussion on the web visit https://groups.google.com/d/msgid/glorp-group/CAJMgPCJ8%3DuUWYFVH%3DaKVyCSqYd_wCmBVH4g2u0RNDaq63CgJrQ%40mail.gmail.com.

Esteban Maringolo

unread,
Nov 8, 2020, 8:11:07 PM11/8/20
to GLORP Mailing List
Hi Alan,

Thanks for responding, I'm currently doing #forceSaveOf: and it is working.

forceSaveOf: anObject
"This is the same as registering an object, but it tells us to disregard whether/how the object has changed and to save all of its fields. This is useful if we need to register an object after changes have occurred, and can be used to implement something more like an object by object save facility. Still somewhat experimental."
  | realObject |
  realObject := self realObjectFor: anObject ifNone: [^self].
  self inUnitOfWorkDo: [currentUnitOfWork registerAsNew: realObject]

What I don't understand is why registering it as new still generates an UPDATE instead of an INSERT.

I know that objects read from the database are automatically registered, but since I do a lot of "read and if it doesn't exist then create it", and I treat both cases the same, so I do something like:

myPlayer := self readPlayerWithId: id ifNone: [self createNewPlayerWithId: id].
db register: myPlayer.

It is a simplified version of the code, but more or less it does the same for several objects that are sync'ed from an API.


Regards!

Esteban A. Maringolo


jtuchel

unread,
Nov 10, 2020, 1:17:06 PM11/10/20
to glorp-group
Esteban,

I am not sure I understand this line of code:

self inUnitOfWorkDo: [currentUnitOfWork registerAsNew: realObject]

doesn't currentUnitOfWork refernence the currentUnitOfWork of this context? And when you put it in the inUnitOfWorkDo: Block, that other unitOfWork is going to be the active unitOfWork, but not the one you thing it is? A stupid explanation, I know, let's try with a code example: I think your code is equivalent to this:

a:= self currentUnitOfWork.
self inUnitOfWorkDo: [a registerAsNew: realObject].

Or am I wrong? I would guess that the result looks different if you change your code to:

self inUnitOfWorkDo: [self privateGetCurrentUnitOfWork registerAsNew: realObject].


I've had a long day of debugging and not understanding a lot of what I observe, so please bear with me if this is total nonsense...

Joachim

Esteban Maringolo

unread,
Nov 10, 2020, 8:11:46 PM11/10/20
to GLORP Mailing List
Hi Joachim,

There is no support for nested units of work, so the currentUnitOfWork in the inUnitOfWorkDo: block is going to be the same for what you call "a context" (which is the session).

Unless there is something else going on, which might also be the case :-)

Esteban A. Maringolo


Reply all
Reply to author
Forward
0 new messages