Thread: [SQLObject] Hello and Connections (to start)
SQLObject is a Python ORM.
Brought to you by:
ianbicking,
phd
|
From: Luke O. <lu...@me...> - 2003-03-12 07:29:21
|
Ian, et al -
Hello! Well, I've been lurking using SQLObject since a long while ago, but only
really putting it into use in the last week or so. CVS from last week. Things
are mostly going great.
Ian, as you know, I talked about wanting to use our regular global database
connection pooling mechanism (which if you were watching the webware list a few
weeks ago, is a wrapper around a modified MiscUtils.DBPool, which expires unused
connections..). Anyways, I've created an ugly monster stepchild of your DBAPI
class, which takes the standard PostgresConnection and overrides certain parent
class methods. While it's not pretty, it works and is short. Code is below.
Also, I'll look more closely at this in the morning, but we're getting an odd
cache-related error. (which may indeed be due to our connection object? not 100%
sure on how the difference in instanceCaches plays out.)
If we create an object (Object.new(name=....)), it is persisted to the database
and everything works fine except it is not added to Object._SO_instanceCache.
However, if we get another reference (by Object(1), for instance), then it is
added to the cache. This comes into play, because if we ever have one that is
NOT in the cache, objInstance.destroy() raises an exception at line 720, as it
is attempted to be removed from the cache. (At a minimum we just need to check
if it is in cache before that del call, but I'd like to track down why it's not
caching in the first place.) The DELETE SQL works fine, so the object IS gone
regardless...
Also, we've got a problem with Joins (possibly caching as well), where we can
create an object, add it to another as a reference, but the objects are not
equivalent (despite looking identical from repr). So we have (in effect):
>>> p = Person(1)
>>> x = Phones.new(person=p...)
>>> x
<Phone 1 ....>
>>> p.phones
[<Phone 1 ....>]
but "x is p.phones[0]" and "x == p.phones[0]" are both false.
Again, I'll look into these in more depth in the morning, and this is using CVS
from a few days ago, but just curious if other people are seeing these? I
suppose the next thing I'll do is drop in the original PostgresConnection to
rule out my crazy code, but if that's the case I'll need some idea of how to
make mine work. :)
- Luke
--------> local PostgresConnection.py code
from SQLObject import PostgresConnection as PC
import psycopg
from PoolStore import PoolStore
import threading
_store = PoolStore(psycopg, maxPerDSN=10, total=65)
class PostgresConnection(PC):
def __init__(self, dsn, debug=0):
self.dsn = dsn
self.debug = debug
self.instanceCache = {}
self.instanceCacheLock = threading.Lock()
def getConnection(self):
return _store.getConnection(self.dsn)
def releaseConnection(self,conn):
conn.close()
def makeConnection(self):
pass
-------------------------------------------------
This mail sent through IMP: http://horde.org/imp/
|
|
From: Ian B. <ia...@co...> - 2003-03-13 03:42:27
|
On Wed, 2003-03-12 at 01:17, Luke Opperman wrote: > Also, we've got a problem with Joins (possibly caching as well), where we can > create an object, add it to another as a reference, but the objects are not > equivalent (despite looking identical from repr). So we have (in effect): > > >>> p = Person(1) > >>> x = Phones.new(person=p...) > >>> x > <Phone 1 ....> > >>> p.phones > [<Phone 1 ....>] > > but "x is p.phones[0]" and "x == p.phones[0]" are both false. This is probably related to the caching problem that Frank had pointed out before. It should be fixed now in CVS. Ian |
|
From: Ian B. <ia...@co...> - 2003-03-13 03:48:20
|
On Wed, 2003-03-12 at 01:17, Luke Opperman wrote:
> --------> local PostgresConnection.py code
>
> from SQLObject import PostgresConnection as PC
> import psycopg
> from PoolStore import PoolStore
> import threading
>
> _store = PoolStore(psycopg, maxPerDSN=10, total=65)
>
> class PostgresConnection(PC):
>
> def __init__(self, dsn, debug=0):
> self.dsn = dsn
> self.debug = debug
> self.instanceCache = {}
> self.instanceCacheLock = threading.Lock()
>
> def getConnection(self):
> return _store.getConnection(self.dsn)
>
> def releaseConnection(self,conn):
> conn.close()
>
> def makeConnection(self):
> pass
This looks like the right way to go about this. You should call the
parent __init__, though. More like:
def __init__(dsn, debug=0):
PostgresConnection.__init__(dsn, debug=debug)
Though you don't *really* have to override __init__ at all, except if
you want to disallow non-applicable init arguments.
Ian
|
|
From: Luke O. <lu...@me...> - 2003-03-13 03:59:58
|
There was a semi-decent reason conscious decision not to call parent's init: It's in the parent's init that the pooling info is created. But I suppose that's a smaller price to pay than having things break in the future. I guess my only other thing is that if you agree this is about the way to do this sort of override, that DBAPI's __init__ should be careful about creating too much overhead. :) - Luke Quoting Ian Bicking <ia...@co...>: > This looks like the right way to go about this. You should call the > parent __init__, though. More like: > > def __init__(dsn, debug=0): > PostgresConnection.__init__(dsn, debug=debug) > > Though you don't *really* have to override __init__ at all, except if > you want to disallow non-applicable init arguments. > > Ian > > > |
|
From: Ian B. <ia...@co...> - 2003-03-13 04:10:48
|
I'm not going to get too stressed out about a single unused dictionary and threading lock per application :) Per SQLObject instance, that would be a problem. On Wed, 2003-03-12 at 21:47, Luke Opperman wrote: > There was a semi-decent reason conscious decision not to call parent's init: > It's in the parent's init that the pooling info is created. But I suppose that's > a smaller price to pay than having things break in the future. I guess my only > other thing is that if you agree this is about the way to do this sort of > override, that DBAPI's __init__ should be careful about creating too much > overhead. :) > > - Luke > > Quoting Ian Bicking <ia...@co...>: > > > This looks like the right way to go about this. You should call the > > parent __init__, though. More like: > > > > def __init__(dsn, debug=0): > > PostgresConnection.__init__(dsn, debug=debug) > > > > Though you don't *really* have to override __init__ at all, except if > > you want to disallow non-applicable init arguments. > > > > Ian > > > > > > > > > |