diff options
author | Mike Bayer <mike_mp@zzzcomputing.com> | 2008-03-29 00:00:49 +0000 |
---|---|---|
committer | Mike Bayer <mike_mp@zzzcomputing.com> | 2008-03-29 00:00:49 +0000 |
commit | c4955c05a3ab40d53c83982da612e746c662640d (patch) | |
tree | c979c566711917679c9fa5d31b6dbcdb1c76eb34 /lib/sqlalchemy/sql/util.py | |
parent | 30020880d90ee2f983b8e6bfb1624349209dd8b0 (diff) | |
download | sqlalchemy-c4955c05a3ab40d53c83982da612e746c662640d.tar.gz |
- merged with_polymorphic branch, which was merged with query_columns branch
- removes everything to do with select_table, which remains as a keyword argument synonymous with
with_polymorphic=('*', select_table).
- all "polymorphic" selectables find their way to Query by way of _set_select_from() now, so that
all joins/aliasing/eager loads/etc. is handled consistently. Mapper has methods for producing
polymorphic selectables so that Query and eagerloaders alike can get to them.
- row aliasing simplified, so that they don't need to nest. they only need the source selectable
and adapt to whatever incoming columns they get.
- Query is more egalitarian about mappers/columns now. Still has a strong sense of "entity zero",
but also introduces new unpublished/experimental _values() method which sets up a columns-only query.
- Query.order_by() and Query.group_by() take *args now (also still take a list, will likely deprecate
in 0.5). May want to do this for select() as well.
- the existing "check for False discriminiator" "fix" was not working completely, added coverage
- orphan detection was broken when the target object was a subclass of the mapper with the orphaned
relation, fixed that too.
Diffstat (limited to 'lib/sqlalchemy/sql/util.py')
-rw-r--r-- | lib/sqlalchemy/sql/util.py | 83 |
1 files changed, 44 insertions, 39 deletions
diff --git a/lib/sqlalchemy/sql/util.py b/lib/sqlalchemy/sql/util.py index d4163b73b..8ed561e5f 100644 --- a/lib/sqlalchemy/sql/util.py +++ b/lib/sqlalchemy/sql/util.py @@ -93,46 +93,51 @@ def reduce_columns(columns, *clauses): return expression.ColumnSet(columns.difference(omit)) -def row_adapter(from_, to, equivalent_columns=None): - """create a row adapter between two selectables. +class AliasedRow(object): + + def __init__(self, row, map): + # AliasedRow objects don't nest, so un-nest + # if another AliasedRow was passed + if isinstance(row, AliasedRow): + self.row = row.row + else: + self.row = row + self.map = map + + def __contains__(self, key): + return self.map[key] in self.row - The returned adapter is a class that can be instantiated repeatedly for any number - of rows; this is an inexpensive process. However, the creation of the row - adapter class itself *is* fairly expensive so caching should be used to prevent - repeated calls to this function. - """ + def has_key(self, key): + return key in self - map = {} - for c in to.c: - corr = from_.corresponding_column(c) - if corr: - map[c] = corr - elif equivalent_columns: - if c in equivalent_columns: - for c2 in equivalent_columns[c]: - corr = from_.corresponding_column(c2) - if corr: - map[c] = corr - break - - class AliasedRow(object): - def __init__(self, row): - self.row = row - def __contains__(self, key): - if key in map: - return map[key] in self.row - else: - return key in self.row - def has_key(self, key): - return key in self - def __getitem__(self, key): - if key in map: - key = map[key] - return self.row[key] - def keys(self): - return map.keys() - AliasedRow.map = map - return AliasedRow + def __getitem__(self, key): + return self.row[self.map[key]] + + def keys(self): + return self.row.keys() + +def row_adapter(from_, equivalent_columns=None): + """create a row adapter against a selectable.""" + + if equivalent_columns is None: + equivalent_columns = {} + + def locate_col(col): + c = from_.corresponding_column(col) + if c: + return c + elif col in equivalent_columns: + for c2 in equivalent_columns[col]: + corr = from_.corresponding_column(c2) + if corr: + return corr + return col + + map = util.PopulateDict(locate_col) + + def adapt(row): + return AliasedRow(row, map) + return adapt class ColumnsInClause(visitors.ClauseVisitor): """Given a selectable, visit clauses and determine if any columns @@ -189,7 +194,7 @@ class ClauseAdapter(visitors.ClauseVisitor): if not clone: raise exceptions.ArgumentError("ClauseAdapter 'clone' argument must be True") return visitors.ClauseVisitor.traverse(self, obj, clone=True) - + def copy_and_chain(self, adapter): """create a copy of this adapter and chain to the given adapter. |