Daniel Hernández
Daniel Hernández

Reputation: 1317

What is the ZODB data model?

Suppose that I define a new persistent class Account as is described in in the ZODB tutorial.

import persistent, ZODB, ZODB.FileStorage, import transaction

class Account(persistent.Persistent):

    def __init__(self):
        self.balance = 0.0

    def deposit(self, amount):
    self.balance += amount

    def cash(self, amount):
        assert amount < self.balance
        self.balance -= amount

storage = ZODB.FileStorage.FileStorage('mydata.fs')
db = ZODB.DB(storage)
connection = db.open()
root = connection.root

root.accounts = BTrees.OOBTree.BTree()
root.accounts['account-1'] = Account()

transaction.commit()

After running this script I wrote another script to access the object that I have created.

import persistent, ZODB, ZODB.FileStorage

class Account(persistent.Persistent):
     ...

storage = ZODB.FileStorage.FileStorage('mydata.fs')
db = ZODB.DB(storage)
connection = db.open()
root = connection.root

print(root.accounts['account-1'])
print(root.accounts['account-1'].balance)

The output of this second script is:

<__main__.Account object at 0x95fbaac>
0.0

But if I comment lines where class Account is defined the output is:

<persistent broken __main__.Account instance '\x00\x00\x00\x00\x00\x00\x00\x02'>
Traceback (most recent call last):
  File "test.py", line 24, in <module>
    print(root.accounts['account-1'].balance)
AttributeError: 'Account' object has no attribute 'balance'

I guest that object declarations is not attached to the database, so we can't execute or methods that I previously defined in Account. But it is not clear to me if I have some access to attributes in objects where no class definition is found. So my question is: Is there a base data model that can be used to access objects without class definitions in ZODB?

My question is also motivated by the following concerns:

I'm habituated to applications where databases have data models that are separated from application logic. Suppose I incorporate a new module X (defining classes) in a application and then I discovered that X is creating problems in my application. In the classic approach, I always can stop the application and inspect the database without the logic layer to analyze and try to fix the data. And then, start the application again without the module X. But in ZODB I don't found documentation about a data layer that can be used without class definitions.

Upvotes: 0

Views: 515

Answers (1)

Martijn Pieters
Martijn Pieters

Reputation: 1121266

The ZODB is built on top of the pickle module; persistence merely serves to detect changes and to create boundaries between records (so changes to one persistent object do not require writing away the whole object tree).

The data model then is your Python code; pickle merely stores refences to the class locations, like your Account, to restore instances from.

When you removed the Account class definition, all persistent could give you is a placeholder object for the data. It tells you that pickle was looking for a class named Account in the module __main__, and that the ZODB object id is 2.

You can still inspect the attributes your Account instance had in the __Broken_state__ attribute of the 'broken' object, if you wanted to introspect that data.

Upvotes: 4

Related Questions