diff options
| author | Mike Bayer <mike_mp@zzzcomputing.com> | 2008-04-14 18:23:59 +0000 |
|---|---|---|
| committer | Mike Bayer <mike_mp@zzzcomputing.com> | 2008-04-14 18:23:59 +0000 |
| commit | f5126ab3a169b6f8a9171868fe32b2bd385f8b8f (patch) | |
| tree | 35f1ab1254e825ffd8d99ab76da27c28b206c480 /lib/sqlalchemy | |
| parent | 6a98ffb0598bdf68ff649c9d75fc75ab0c1c1fc0 (diff) | |
| download | sqlalchemy-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.py | 16 | ||||
| -rw-r--r-- | lib/sqlalchemy/orm/strategies.py | 52 | ||||
| -rw-r--r-- | lib/sqlalchemy/sql/visitors.py | 3 |
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) |
