Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Incongruence possibility between ghosted class and pickled class metadata #72

Open
malthe opened this issue May 9, 2017 · 4 comments
Open

Comments

@malthe
Copy link

malthe commented May 9, 2017

If an object's class attribute is changed, then it won't be correctly unghostified from a retrieval via B-tree since the class is baked into the bucket contents (as an optimization).

Perhaps a solution would be to listen to a commit event for objects loaded through a B-tree and fix-up any buckets if necessary.

@jamadden
Copy link
Member

jamadden commented May 9, 2017

It's not just BTrees, it's any reference to the object. References to persisted objects all include the type so that they can be unghosted:

>>> from ZODB import DB, MappingStorage
>>> from persistent import Persistent
>>> import transaction
>>> db = DB(MappingStorage.MappingStorage())
>>> class X(Persistent): pass
>>> class Y(Persistent): pass
>>> x = X()
>>> conn = db.open()
>>> conn.root()['x'] = x
>>> transaction.commit()
>>> x.__class__ = Y
>>> type(x)
 __main__.Y
>>> x._p_changed = True
>>> transaction.commit()
>>> conn.root()['x']
<__main__.Y at 0x10d3c18c0>
>>> new_conn = db.open()
>>> new_conn.root()['x']
<__main__.X at 0x10d3c9f50>

In general you can't change the __class__ of a persistent object and expect it to be consistently unghosted as the new class unless you can update all the references to it.

This is documented here:

Because the persistent object reference forms include class
information, it is not possible to change the class of a persistent
object for which this form is used. If a transaction changed the
class of an object, a new record with new class metadata would be
written but all the old references would still use the old class.

@malthe
Copy link
Author

malthe commented May 9, 2017

I have tried to devise a "fix" here:

https://github.com/zopefoundation/ZODB/compare/ensure-correct-class-on-ghost-set-state?expand=1

Not sure if it's a good thing.

@davisagli
Copy link
Member

@icemac
Copy link
Member

icemac commented May 16, 2017

We successfully used an approach described in the fourdigits blog.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants