diff options
author | Mike Bayer <mike_mp@zzzcomputing.com> | 2006-02-01 23:23:37 +0000 |
---|---|---|
committer | Mike Bayer <mike_mp@zzzcomputing.com> | 2006-02-01 23:23:37 +0000 |
commit | fd9c860700186de4b9aae97c7a3f67fe6ef18f84 (patch) | |
tree | fc7df3c770fb57de7779c55da9ac435432dcaa8b /lib/sqlalchemy/ext/proxy.py | |
parent | e0d2cc3fdb3d1547e16f92093fa8c5c82127681e (diff) | |
download | sqlalchemy-fd9c860700186de4b9aae97c7a3f67fe6ef18f84.tar.gz |
new ProxyEngine dispatches to multiple engines; contributed by jason pellerin
Diffstat (limited to 'lib/sqlalchemy/ext/proxy.py')
-rw-r--r-- | lib/sqlalchemy/ext/proxy.py | 146 |
1 files changed, 146 insertions, 0 deletions
diff --git a/lib/sqlalchemy/ext/proxy.py b/lib/sqlalchemy/ext/proxy.py new file mode 100644 index 000000000..ae5f40cfa --- /dev/null +++ b/lib/sqlalchemy/ext/proxy.py @@ -0,0 +1,146 @@ +try: + from threading import local +except ImportError: + from sqlalchemy.util import ThreadLocal as local + +from sqlalchemy import sql +from sqlalchemy.engine import create_engine +from sqlalchemy.types import TypeEngine + +import thread + +class ProxyEngine(object): + """ + SQLEngine proxy. Supports lazy and late initialization by + delegating to a real engine (set with connect()), and using proxy + classes for TableImpl, ColumnImpl and TypeEngine. + """ + + def __init__(self): + # create the local storage for uri->engine map and current engine + self.storage = local() + self.storage.connection = {} + self.storage.engine = None + self.tables = {} + + def connect(self, uri, opts=None, **kwargs): + """Establish connection to a real engine. + """ + key = "%s(%s,%s)" % (uri, repr(opts), repr(kwargs)) + try: + map = self.storage.connection + except AttributeError: + self.storage.connection = {} + self.storage.engine = None + map = self.storage.connection + try: + self.engine = map[key] + except KeyError: + map[key] = create_engine(uri, opts, **kwargs) + self.storage.engine = map[key] + + def get_engine(self): + if self.storage.engine is None: + raise AttributeError('No connection established') + return self.storage.engine + + def set_engine(self, engine): + self.storage.engine = engine + + engine = property(get_engine, set_engine) + + def hash_key(self): + return "%s(%s)" % (self.__class__.__name__, id(self)) + + def oid_column_name(self): + # NOTE: setting up mappers fails unless the proxy engine returns + # something for oid column name, and the call happens too early + # to proxy, so effecticely no oids are allowed when using + # proxy engine + return None + + def columnimpl(self, column): + """Proxy point: return a ProxyColumnImpl + """ + return ProxyColumnImpl(self, column) + + def tableimpl(self, table): + """Proxy point: return a ProxyTableImpl + """ + return ProxyTableImpl(self, table) + + def type_descriptor(self, typeobj): + """Proxy point: return a ProxyTypeEngine + """ + return ProxyTypeEngine(self, typeobj) + + def __getattr__(self, attr): + # call get_engine() to give subclasses a chance to change + # connection establishment behavior + if self.get_engine() is not None: + return getattr(self.engine, attr) + raise AttributeError('No connection established in ProxyEngine: ' + ' no access to %s' % attr) + +class ProxyColumnImpl(sql.ColumnImpl): + """Proxy column; defers engine access to ProxyEngine + """ + def __init__(self, engine, column): + sql.ColumnImpl.__init__(self, column) + self._engine = engine + + engine = property(lambda self: self._engine.engine) + +class ProxyTableImpl(sql.TableImpl): + """Proxy table; defers engine access to ProxyEngine + """ + def __init__(self, engine, table): + sql.TableImpl.__init__(self, table) + self._engine = engine + + engine = property(lambda self: self._engine.engine) + +class ProxyTypeEngine(object): + """Proxy type engine; defers engine access to ProxyEngine + """ + def __init__(self, engine, typeobj): + self._engine = engine + self.typeobj = typeobj + + engine = property(lambda self: self._engine.engine) + + def __getattr__(self, attr): + # NOTE: + # profiling so far indicates that caching the type_descriptor + # results is more trouble than it's worth + return getattr(self.engine.type_descriptor(self.typeobj), attr) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + |