diff options
| author | Mike Bayer <mike_mp@zzzcomputing.com> | 2008-02-09 01:48:19 +0000 |
|---|---|---|
| committer | Mike Bayer <mike_mp@zzzcomputing.com> | 2008-02-09 01:48:19 +0000 |
| commit | 1a3dc519930712d2e6de095a07d76da9a9062210 (patch) | |
| tree | 2587b92dde7ddba71b369ad1b88c7e0e296470cc /lib/sqlalchemy | |
| parent | 0b890e1ccde7da937a25107d9287d4dc4e5b7775 (diff) | |
| download | sqlalchemy-1a3dc519930712d2e6de095a07d76da9a9062210.tar.gz | |
- lazy loader can now handle a join condition where the "bound"
column (i.e. the one that gets the parent id sent as a bind
parameter) appears more than once in the join condition.
Specifically this allows the common task of a relation()
which contains a parent-correlated subquery, such as "select
only the most recent child item". [ticket:946]
- col_is_part_of_mappings made more strict, seems to be OK
with tests
- memusage will dump out the size list in an assertion fail
Diffstat (limited to 'lib/sqlalchemy')
| -rw-r--r-- | lib/sqlalchemy/orm/properties.py | 20 | ||||
| -rw-r--r-- | lib/sqlalchemy/orm/strategies.py | 16 |
2 files changed, 23 insertions, 13 deletions
diff --git a/lib/sqlalchemy/orm/properties.py b/lib/sqlalchemy/orm/properties.py index a7932bfc5..d08dd7124 100644 --- a/lib/sqlalchemy/orm/properties.py +++ b/lib/sqlalchemy/orm/properties.py @@ -494,19 +494,19 @@ class PropertyLoader(StrategizedProperty): if vis.result: raise exceptions.ArgumentError("In relationship '%s', primary and secondary join conditions must not include columns from the polymorphic 'select_table' argument as of SA release 0.3.4. Construct join conditions using the base tables of the related mappers." % (str(self))) + def _col_is_part_of_mappings(self, column): + if self.secondary is None: + return self.parent.mapped_table.c.contains_column(column) or \ + self.target.c.contains_column(column) + else: + return self.parent.mapped_table.c.contains_column(column) or \ + self.target.c.contains_column(column) or \ + self.secondary.c.contains_column(column) is not None + def _determine_fks(self): if self._legacy_foreignkey and not self._is_self_referential(): self.foreign_keys = self._legacy_foreignkey - def col_is_part_of_mappings(col): - if self.secondary is None: - return self.parent.mapped_table.corresponding_column(col) is not None or \ - self.target.corresponding_column(col) is not None - else: - return self.parent.mapped_table.corresponding_column(col) is not None or \ - self.target.corresponding_column(col) is not None or \ - self.secondary.corresponding_column(col) is not None - if self.foreign_keys: self._opposite_side = util.Set() def visit_binary(binary): @@ -529,7 +529,7 @@ class PropertyLoader(StrategizedProperty): # this check is for when the user put the "view_only" flag on and has tables that have nothing # to do with the relationship's parent/child mappings in the join conditions. we dont want cols # or clauses related to those external tables dealt with. see orm.relationships.ViewOnlyTest - if not col_is_part_of_mappings(binary.left) or not col_is_part_of_mappings(binary.right): + if not self._col_is_part_of_mappings(binary.left) or not self._col_is_part_of_mappings(binary.right): return for f in binary.left.foreign_keys: diff --git a/lib/sqlalchemy/orm/strategies.py b/lib/sqlalchemy/orm/strategies.py index 3b3c86d1a..bdc8ab9a9 100644 --- a/lib/sqlalchemy/orm/strategies.py +++ b/lib/sqlalchemy/orm/strategies.py @@ -265,7 +265,7 @@ NoLoader.logger = logging.class_logger(NoLoader) class LazyLoader(AbstractRelationLoader): def init(self): super(LazyLoader, self).init() - (self.lazywhere, self.lazybinds, self.equated_columns) = self._create_lazy_clause(self) + (self.lazywhere, self.lazybinds, self.equated_columns) = self._create_lazy_clause(self.parent_property) self.logger.info(str(self.parent_property) + " lazy loading clause " + str(self.lazywhere)) @@ -366,6 +366,9 @@ class LazyLoader(AbstractRelationLoader): equated_columns = {} def should_bind(targetcol, othercol): + if not prop._col_is_part_of_mappings(targetcol): + return False + if reverse_direction and not secondaryjoin: return targetcol in remote_side else: @@ -381,13 +384,20 @@ class LazyLoader(AbstractRelationLoader): equated_columns[leftcol] = rightcol if should_bind(leftcol, rightcol): - binary.left = binds[leftcol] = sql.bindparam(None, None, type_=binary.right.type) + if leftcol in binds: + binary.left = binds[leftcol] + else: + binary.left = binds[leftcol] = sql.bindparam(None, None, type_=binary.right.type) # the "left is not right" compare is to handle part of a join clause that is "table.c.col1==table.c.col1", # which can happen in rare cases (test/orm/relationships.py RelationTest2) if leftcol is not rightcol and should_bind(rightcol, leftcol): - binary.right = binds[rightcol] = sql.bindparam(None, None, type_=binary.left.type) + if rightcol in binds: + binary.right = binds[rightcol] + else: + binary.right = binds[rightcol] = sql.bindparam(None, None, type_=binary.left.type) + lazywhere = primaryjoin if not secondaryjoin or not reverse_direction: |
