summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Bayer <mike_mp@zzzcomputing.com>2006-02-07 02:54:26 +0000
committerMike Bayer <mike_mp@zzzcomputing.com>2006-02-07 02:54:26 +0000
commite5262ceeebee885c52e849a2693fa73c6057f0cb (patch)
tree1792f2d0517d5eea211bcddd1403db5e11b9edb2
parent63472a96e2f118ebe19fe56bdf62a1297ec84991 (diff)
downloadsqlalchemy-e5262ceeebee885c52e849a2693fa73c6057f0cb.tar.gz
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
-rw-r--r--lib/sqlalchemy/engine.py1
-rw-r--r--lib/sqlalchemy/mapping/__init__.py2
-rw-r--r--lib/sqlalchemy/mapping/mapper.py8
-rw-r--r--lib/sqlalchemy/mapping/properties.py14
-rw-r--r--lib/sqlalchemy/util.py9
5 files changed, 27 insertions, 7 deletions
diff --git a/lib/sqlalchemy/engine.py b/lib/sqlalchemy/engine.py
index 8bb4767d9..dfc4a7337 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 ce693b2fb..f208a932e 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 eb54e0301..597214220 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 a58db251f..72cb44749 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 9e93e995a..665ab4f53 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):