diff options
author | Mike Bayer <mike_mp@zzzcomputing.com> | 2012-07-28 17:12:09 -0400 |
---|---|---|
committer | Mike Bayer <mike_mp@zzzcomputing.com> | 2012-07-28 17:12:09 -0400 |
commit | f839b8927099b64b2d120ffd93d5f444b8951e59 (patch) | |
tree | c4e6c15d586f0ddd4d76753f0427285e1a3ceb4d /lib/sqlalchemy/sql/util.py | |
parent | 22ba1c43b792953ae6f791512d276739c8c09eae (diff) | |
download | sqlalchemy-f839b8927099b64b2d120ffd93d5f444b8951e59.tar.gz |
- [feature] Added reduce_columns() method
to select() construct, replaces columns inline
using the util.reduce_columns utility function
to remove equivalent columns. reduce_columns()
also adds "with_only_synonyms" to limit the
reduction just to those columns which have the same
name. The deprecated fold_equivalents() feature is
removed [ticket:1729].
- [feature] Added with_labels and
reduce_columns keyword arguments to
Query.subquery(), to provide two alternate
strategies for producing queries with uniquely-
named columns. [ticket:1729].
Diffstat (limited to 'lib/sqlalchemy/sql/util.py')
-rw-r--r-- | lib/sqlalchemy/sql/util.py | 59 |
1 files changed, 12 insertions, 47 deletions
diff --git a/lib/sqlalchemy/sql/util.py b/lib/sqlalchemy/sql/util.py index 0727f0537..6bfaf4b8c 100644 --- a/lib/sqlalchemy/sql/util.py +++ b/lib/sqlalchemy/sql/util.py @@ -585,6 +585,7 @@ def reduce_columns(columns, *clauses, **kw): """ ignore_nonexistent_tables = kw.pop('ignore_nonexistent_tables', False) + only_synonyms = kw.pop('only_synonyms', False) columns = util.ordered_column_set(columns) @@ -610,21 +611,27 @@ def reduce_columns(columns, *clauses, **kw): continue else: raise - if fk_col.shares_lineage(c): + if fk_col.shares_lineage(c) and \ + (not only_synonyms or \ + c.name == col.name): omit.add(col) break if clauses: def visit_binary(binary): if binary.operator == operators.eq: - cols = util.column_set(chain(*[c.proxy_set for c in columns.difference(omit)])) + cols = util.column_set(chain(*[c.proxy_set + for c in columns.difference(omit)])) if binary.left in cols and binary.right in cols: - for c in columns: - if c.shares_lineage(binary.right): + for c in reversed(columns): + if c.shares_lineage(binary.right) and \ + (not only_synonyms or \ + c.name == binary.left.name): omit.add(c) break for clause in clauses: - visitors.traverse(clause, {}, {'binary':visit_binary}) + if clause is not None: + visitors.traverse(clause, {}, {'binary': visit_binary}) return expression.ColumnSet(columns.difference(omit)) @@ -677,48 +684,6 @@ def criterion_as_pairs(expression, consider_as_foreign_keys=None, visitors.traverse(expression, {}, {'binary':visit_binary}) return pairs -def folded_equivalents(join, equivs=None): - """Return a list of uniquely named columns. - - The column list of the given Join will be narrowed - down to a list of all equivalently-named, - equated columns folded into one column, where 'equated' means they are - equated to each other in the ON clause of this join. - - This function is used by Join.select(fold_equivalents=True). - - Deprecated. This function is used for a certain kind of - "polymorphic_union" which is designed to achieve joined - table inheritance where the base table has no "discriminator" - column; [ticket:1131] will provide a better way to - achieve this. - - """ - if equivs is None: - equivs = set() - def visit_binary(binary): - if binary.operator == operators.eq and binary.left.name == binary.right.name: - equivs.add(binary.right) - equivs.add(binary.left) - visitors.traverse(join.onclause, {}, {'binary':visit_binary}) - collist = [] - if isinstance(join.left, expression.Join): - left = folded_equivalents(join.left, equivs) - else: - left = list(join.left.columns) - if isinstance(join.right, expression.Join): - right = folded_equivalents(join.right, equivs) - else: - right = list(join.right.columns) - used = set() - for c in left + right: - if c in equivs: - if c.name not in used: - collist.append(c) - used.add(c.name) - else: - collist.append(c) - return collist class AliasedRow(object): """Wrap a RowProxy with a translation map. |