From: Mike Bayer Date: Tue, 7 Feb 2006 02:54:26 +0000 (+0000) Subject: trying to get mappers to support having versions against different tables for the... X-Git-Tag: rel_0_1_0~42 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=e5262ceeebee885c52e849a2693fa73c6057f0cb;p=thirdparty%2Fsqlalchemy%2Fsqlalchemy.git trying to get mappers to support having versions against different tables for the same class, that dont affect the original class mapper and create objects with the correct identity key support in EagerLoader to better handle "selectalias" when the eager mapper hits another eager mapper, etc --- diff --git a/lib/sqlalchemy/engine.py b/lib/sqlalchemy/engine.py index 8bb4767d95..dfc4a7337b 100644 --- a/lib/sqlalchemy/engine.py +++ b/lib/sqlalchemy/engine.py @@ -725,6 +725,7 @@ class RowProxy: except: raise AttributeError def keys(self): + print "KEYS", self.__parent.keys return self.__parent.keys def values(self): return list(self) diff --git a/lib/sqlalchemy/mapping/__init__.py b/lib/sqlalchemy/mapping/__init__.py index ce693b2fb8..f208a932ec 100644 --- a/lib/sqlalchemy/mapping/__init__.py +++ b/lib/sqlalchemy/mapping/__init__.py @@ -117,6 +117,8 @@ def class_mapper(class_): pass raise "Class '%s' has no mapper associated with it" % class_.__name__ +mapperlib.class_mapper = class_mapper + def assign_mapper(class_, *args, **params): params.setdefault("is_primary", True) if not isinstance(getattr(class_, '__init__'), types.MethodType): diff --git a/lib/sqlalchemy/mapping/mapper.py b/lib/sqlalchemy/mapping/mapper.py index eb54e0301d..597214220d 100644 --- a/lib/sqlalchemy/mapping/mapper.py +++ b/lib/sqlalchemy/mapping/mapper.py @@ -174,7 +174,10 @@ class Mapper(object): ): objectstore.global_attributes.reset_class_managed(self.class_) self._init_class() - + self.identitytable = self.primarytable + else: + self.identitytable = class_mapper(self.class_).table + if inherits is not None: for key, prop in inherits.props.iteritems(): if not self.props.has_key(key): @@ -678,10 +681,9 @@ class Mapper(object): for key, value in self.props.iteritems(): value.setup(key, statement, **kwargs) return statement - def _identity_key(self, row): - return objectstore.get_row_key(row, self.class_, self.primarytable, self.pks_by_table[self.table]) + return objectstore.get_row_key(row, self.class_, self.identitytable, self.pks_by_table[self.table]) def _instance(self, row, imap, result = None, populate_existing = False): """pulls an object instance from the given row and appends it to the given result diff --git a/lib/sqlalchemy/mapping/properties.py b/lib/sqlalchemy/mapping/properties.py index a58db251f0..72cb447496 100644 --- a/lib/sqlalchemy/mapping/properties.py +++ b/lib/sqlalchemy/mapping/properties.py @@ -706,7 +706,7 @@ class EagerLoader(PropertyLoader): self.eagersecondary = self.secondaryjoin self.eager_order_by = self.order_by - def setup(self, key, statement, recursion_stack = None, **options): + def setup(self, key, statement, recursion_stack = None, eagertable=None, **options): """add a left outer join to the statement thats being constructed""" if recursion_stack is None: @@ -726,12 +726,19 @@ class EagerLoader(PropertyLoader): else: towrap = self.parent.table + if eagertable is not None: + eagerprimary = self.eagerprimary.copy_container() + aliasizer = Aliasizer(self.parent.table, aliases={self.parent.table:eagertable}) + eagerprimary.accept_visitor(aliasizer) + else: + eagerprimary = self.eagerprimary + if self.secondaryjoin is not None: - statement._outerjoin = sql.outerjoin(towrap, self.secondary, self.eagerprimary).outerjoin(self.eagertarget, self.eagersecondary) + statement._outerjoin = sql.outerjoin(towrap, self.secondary, eagerprimary).outerjoin(self.eagertarget, self.eagersecondary) if self.order_by is False and self.secondary.default_order_by() is not None: statement.order_by(*self.secondary.default_order_by()) else: - statement._outerjoin = towrap.outerjoin(self.eagertarget, self.eagerprimary) + statement._outerjoin = towrap.outerjoin(self.eagertarget, eagerprimary) if self.order_by is False and self.eagertarget.default_order_by() is not None: statement.order_by(*self.eagertarget.default_order_by()) @@ -777,6 +784,7 @@ class EagerLoader(PropertyLoader): # the values against the columns of the mapper's original non-aliased table. if self.selectalias is not None: fakerow = {} + fakerow = util.DictDecorator(row) for c in self.eagertarget.c: fakerow[c.original] = row[c] row = fakerow diff --git a/lib/sqlalchemy/util.py b/lib/sqlalchemy/util.py index 9e93e995a5..665ab4f537 100644 --- a/lib/sqlalchemy/util.py +++ b/lib/sqlalchemy/util.py @@ -161,7 +161,14 @@ class ThreadLocal(object): def __setattr__(self, key, value): self._tdict["%d_%s" % (thread.get_ident(), key)] = value - +class DictDecorator(dict): + def __init__(self, decorate): + self.decorate = decorate + def __getitem__(self, key): + try: + return dict.__getitem__(self, key) + except KeyError: + return self.decorate[key] class HashSet(object): """implements a Set.""" def __init__(self, iter = None, ordered = False):