On Sun, Jul 20, 2003 at 04:21:47PM +0100, Matt Goodall wrote:
> I just found an interesting problem due to programmer (i.e. me) error
> but it leaves the SQLObject caches damaged so I wondered if SQLObject
> should cope better.
>
> The problem is probably best demonstrated by (untested) example with a
> description of what happens inside SQLObject's caches:
>
> id = Obj.new(col1='a', col2='b')
> # added to cache with key == int(1)
>
> o = Obj(id)
> # found in cache with key == int(1)
>
> o = Obj(str(id)) # note the cast to a string
> # reads from database, adds to cache with key == str(1)
> # Eek, two objects now in cache!
>
> o.col1, o.col2 = o.col2, o.col1
> # writes change to db, only object str(id) in cache matches
>
> o = Obj(str(id))
> # found in cache with key == str(1)
>
> o = Obj(id)
> # found in cache with key == int(1) but bad data
>
> Lovely isn't it, and all because I stored the object's id in a hidden
> form field ;-). I won't tell you how long it took to work out what was
> happening!
>
> My app is working again now but should SQLObject have let this happen?
No. :)
> The obvious thing to do is to force the id to int() inside the Obj
> constructor but that would break any attempt to allow alphanumeric ids.
> So, perhaps a better solution is to always use a string as the cache
> keys?
Hmmm...I think there is a need here for a "primarykeygeddon" (to
borrow a Zope 3ism). The way in which SQLObject lets you define PK's
is inevitably overlapping with keys to use for caching.
Ideally, like Python dictionaries, any immutable type should be able
to be used as a key for a table, IMHO. So, there are use cases for all
of the following (and many more, but just to list a few different
examples to be mindful of...) to be primary keys:
* dates
* ints
* strings
* a tuple of columns (each of which may be different types)
It seems that the right thing to do here would be to use the same type
in the cache key as that being used for the PK of the SQLObject. It
may be useful to force the correct type to be passed into the
constructor when retrieving objects as well (I see little benefit in
implicit type conversion for this).
So, perhaps we should address composites at the same time as deciding
which keys to use in the cache.
So:
What do you think about forcing the correct type to be passed into the
constructor? (I think it's reasonable; 1 and "1" are two different
keys in a dictionary)
How do you want to be able to define composite keys in SQLObjects?
--
Brad Bollenbach
BBnet.ca
|