summaryrefslogtreecommitdiff
path: root/lib/sqlalchemy
diff options
context:
space:
mode:
authorMike Bayer <mike_mp@zzzcomputing.com>2008-04-14 18:23:59 +0000
committerMike Bayer <mike_mp@zzzcomputing.com>2008-04-14 18:23:59 +0000
commitf5126ab3a169b6f8a9171868fe32b2bd385f8b8f (patch)
tree35f1ab1254e825ffd8d99ab76da27c28b206c480 /lib/sqlalchemy
parent6a98ffb0598bdf68ff649c9d75fc75ab0c1c1fc0 (diff)
downloadsqlalchemy-f5126ab3a169b6f8a9171868fe32b2bd385f8b8f.tar.gz
- simplified __create_lazy_clause to make better usage of the new local/remote pairs collection
- corrected the direction of local/remote pairs for manytoone - added new tests which demonstrate lazyloading working when the bind param is embedded inside of a SQL function, when _local_remote_pairs argument is used; fixes the viewonly version of [ticket:610] - removed needless kwargs check from visitors.traverse
Diffstat (limited to 'lib/sqlalchemy')
-rw-r--r--lib/sqlalchemy/orm/properties.py16
-rw-r--r--lib/sqlalchemy/orm/strategies.py52
-rw-r--r--lib/sqlalchemy/sql/visitors.py3
3 files changed, 36 insertions, 35 deletions
diff --git a/lib/sqlalchemy/orm/properties.py b/lib/sqlalchemy/orm/properties.py
index 140fffd89..55f6c9875 100644
--- a/lib/sqlalchemy/orm/properties.py
+++ b/lib/sqlalchemy/orm/properties.py
@@ -621,9 +621,10 @@ class PropertyLoader(StrategizedProperty):
if self.direction is MANYTOONE:
self.remote_side, self.local_side = [util.OrderedSet(s) for s in zip(*eq_pairs)]
+ self.local_remote_pairs = [(r, l) for l, r in eq_pairs]
else:
self.local_side, self.remote_side = [util.OrderedSet(s) for s in zip(*eq_pairs)]
- self.local_remote_pairs = zip(self.local_side, self.remote_side)
+ self.local_remote_pairs = eq_pairs
if self.direction is ONETOMANY:
for l in self.local_side:
@@ -651,12 +652,15 @@ class PropertyLoader(StrategizedProperty):
self.direction = ONETOMANY
else:
self.direction = MANYTOONE
-
+ elif self._arg_local_remote_pairs:
+ remote = util.Set([r for l, r in self._arg_local_remote_pairs])
+ if self.foreign_keys.intersection(remote):
+ self.direction = ONETOMANY
+ else:
+ self.direction = MANYTOONE
elif self.remote_side:
- for f in self.foreign_keys:
- if f in self.remote_side:
- self.direction = ONETOMANY
- return
+ if self.foreign_keys.intersection(self.remote_side):
+ self.direction = ONETOMANY
else:
self.direction = MANYTOONE
else:
diff --git a/lib/sqlalchemy/orm/strategies.py b/lib/sqlalchemy/orm/strategies.py
index 3bbb380d1..e758ac08b 100644
--- a/lib/sqlalchemy/orm/strategies.py
+++ b/lib/sqlalchemy/orm/strategies.py
@@ -351,41 +351,39 @@ class LazyLoader(AbstractRelationLoader):
def __create_lazy_clause(cls, prop, reverse_direction=False):
binds = {}
+ lookup = {}
equated_columns = {}
- secondaryjoin = prop.secondaryjoin
- local = prop.local_side
-
- def should_bind(targetcol, othercol):
- if reverse_direction and not secondaryjoin:
- return othercol in local
- else:
- return targetcol in local
-
- def visit_binary(binary):
- leftcol = binary.left
- rightcol = binary.right
-
- equated_columns[rightcol] = leftcol
- equated_columns[leftcol] = rightcol
-
- if should_bind(leftcol, rightcol):
- if leftcol not in binds:
- binds[leftcol] = sql.bindparam(None, None, type_=binary.right.type)
- binary.left = binds[leftcol]
- elif should_bind(rightcol, leftcol):
- if rightcol not in binds:
- binds[rightcol] = sql.bindparam(None, None, type_=binary.left.type)
- binary.right = binds[rightcol]
-
+ if reverse_direction and not prop.secondaryjoin:
+ for l, r in prop.local_remote_pairs:
+ _list = lookup.setdefault(r, [])
+ _list.append((r, l))
+ equated_columns[l] = r
+ else:
+ for l, r in prop.local_remote_pairs:
+ _list = lookup.setdefault(l, [])
+ _list.append((l, r))
+ equated_columns[r] = l
+
+ def col_to_bind(col):
+ if col in lookup:
+ for tobind, equated in lookup[col]:
+ if equated in binds:
+ return None
+ if col not in binds:
+ binds[col] = sql.bindparam(None, None, type_=col.type)
+ return binds[col]
+ return None
+
lazywhere = prop.primaryjoin
if not prop.secondaryjoin or not reverse_direction:
- lazywhere = visitors.traverse(lazywhere, clone=True, visit_binary=visit_binary)
+ lazywhere = visitors.traverse(lazywhere, before_clone=col_to_bind, clone=True)
if prop.secondaryjoin is not None:
+ secondaryjoin = prop.secondaryjoin
if reverse_direction:
- secondaryjoin = visitors.traverse(secondaryjoin, clone=True, visit_binary=visit_binary)
+ secondaryjoin = visitors.traverse(secondaryjoin, before_clone=col_to_bind, clone=True)
lazywhere = sql.and_(lazywhere, secondaryjoin)
bind_to_col = dict([(binds[col].key, col) for col in binds])
diff --git a/lib/sqlalchemy/sql/visitors.py b/lib/sqlalchemy/sql/visitors.py
index 792391929..9888a228a 100644
--- a/lib/sqlalchemy/sql/visitors.py
+++ b/lib/sqlalchemy/sql/visitors.py
@@ -177,7 +177,6 @@ def traverse(clause, **kwargs):
__traverse_options__ = kwargs.pop('traverse_options', {})
vis = Vis()
for key in kwargs:
- if key.startswith('visit_'):
- setattr(vis, key, kwargs[key])
+ setattr(vis, key, kwargs[key])
return vis.traverse(clause, clone=clone)