diff options
author | Mike Bayer <mike_mp@zzzcomputing.com> | 2007-01-23 04:05:07 +0000 |
---|---|---|
committer | Mike Bayer <mike_mp@zzzcomputing.com> | 2007-01-23 04:05:07 +0000 |
commit | 30f75c2157478480c54ca65d2a00ec1ed6a8820e (patch) | |
tree | c94aa42baccc2d5bef90bd2e3084aa2a930f4b90 /lib/sqlalchemy/sql_util.py | |
parent | caabadf86666256d1626b84e512fd66bad52fb50 (diff) | |
download | sqlalchemy-30f75c2157478480c54ca65d2a00ec1ed6a8820e.tar.gz |
relationships no longer compile against the "selectable" mapper (i.e. the polymorphic mapper). join conditions, foreign keys etc. are configured against the actual mappers used in the relationship in all cases. the lazy and eager loaders in turn "adapt" their lazy/eager clauses to that of the "selectable" mapper if one is present. this is because the join conditions between the mapper's base tables are *far* easier to work with and detect direction etc. compared to an enormous polymorphic union; dealing with the polymorphic union is pushed further out into select query construction.
Diffstat (limited to 'lib/sqlalchemy/sql_util.py')
-rw-r--r-- | lib/sqlalchemy/sql_util.py | 48 |
1 files changed, 48 insertions, 0 deletions
diff --git a/lib/sqlalchemy/sql_util.py b/lib/sqlalchemy/sql_util.py index bfbcff554..4c6cd4d07 100644 --- a/lib/sqlalchemy/sql_util.py +++ b/lib/sqlalchemy/sql_util.py @@ -107,3 +107,51 @@ class Aliasizer(sql.ClauseVisitor): binary.left = self.get_alias(binary.left.table).corresponding_column(binary.left) if isinstance(binary.right, schema.Column) and self.tables.has_key(binary.right.table): binary.right = self.get_alias(binary.right.table).corresponding_column(binary.right) + + +class ClauseAdapter(sql.ClauseVisitor): + """given a clause (like as in a WHERE criterion), locates columns which 'correspond' to a given selectable, + and changes those columns to be that of the selectable. + + such as: + + table1 = Table('sometable', metadata, + Column('col1', Integer), + Column('col2', Integer) + ) + table2 = Table('someothertable', metadata, + Column('col1', Integer), + Column('col2', Integer) + ) + + condition = table1.c.col1 == table2.c.col1 + + and make an alias of table1: + + s = table1.alias('foo') + + calling condition.accept_visitor(ClauseAdapter(s)) converts condition to read: + + s.c.col1 == table2.c.col1 + + """ + def __init__(self, selectable): + self.selectable = selectable + def visit_binary(self, binary): + if isinstance(binary.left, sql.ColumnElement): + col = self.selectable.corresponding_column(binary.left, raiseerr=False, keys_ok=False) + if col is not None: + binary.left = col + if isinstance(binary.right, sql.ColumnElement): + col = self.selectable.corresponding_column(binary.right, raiseerr=False, keys_ok=False) + if col is not None: + binary.right = col + +class ColumnsInClause(sql.ClauseVisitor): + """given a selectable, visits clauses and determines if any columns from the clause are in the selectable""" + def __init__(self, selectable): + self.selectable = selectable + self.result = False + def visit_column(self, column): + if self.selectable.c.get(column.key) is column: + self.result = True |