diff options
| author | Mike Bayer <mike_mp@zzzcomputing.com> | 2007-03-05 23:08:52 +0000 |
|---|---|---|
| committer | Mike Bayer <mike_mp@zzzcomputing.com> | 2007-03-05 23:08:52 +0000 |
| commit | 9154e1eff1da41c41b31e2a24a6128ff457c7716 (patch) | |
| tree | 743bb691fc6e06e5b3d43c29a96568f1ac81a66e /lib/sqlalchemy/sql.py | |
| parent | 7693a680edf9776d3037283f3d63e3aeeb06649e (diff) | |
| download | sqlalchemy-9154e1eff1da41c41b31e2a24a6128ff457c7716.tar.gz | |
- added concept of 'require_embedded' to corresponding_column.
requires that the target column be present in a sub-element of the
target selectable.
- embedded logic above more appropriate for ClauseAdapter functionality
since its trying to "pull up" clauses that represent columns within
a larger union up to the level of the union itself.
- the "direction" test against the "foreign_keys" collection apparently
works for an exact "column 'x' is present in the collection", no proxy
relationships needed. fixes the case of relating a selectable/alias
to one of its underlying tables, probably fixes other scenarios
Diffstat (limited to 'lib/sqlalchemy/sql.py')
| -rw-r--r-- | lib/sqlalchemy/sql.py | 36 |
1 files changed, 28 insertions, 8 deletions
diff --git a/lib/sqlalchemy/sql.py b/lib/sqlalchemy/sql.py index da1afe799..073277d57 100644 --- a/lib/sqlalchemy/sql.py +++ b/lib/sqlalchemy/sql.py @@ -506,6 +506,21 @@ class ClauseVisitor(object): def visit_label(self, label):pass def visit_typeclause(self, typeclause):pass +class VisitColumnMixin(object): + """a mixin that adds Column traversal to a ClauseVisitor""" + def visit_table(self, table): + for c in table.c: + c.accept_visitor(self) + def visit_select(self, select): + for c in select.c: + c.accept_visitor(self) + def visit_compound_select(self, select): + for c in select.c: + c.accept_visitor(self) + def visit_alias(self, alias): + for c in alias.c: + c.accept_visitor(self) + class Executor(object): """Represent a *thing that can produce Compiled objects and execute them*.""" @@ -1041,20 +1056,25 @@ class FromClause(Selectable): self._oid_column = self._locate_oid_column() return self._oid_column - def corresponding_column(self, column, raiseerr=True, keys_ok=False, require_exact=False): + def _get_all_embedded_columns(self): + ret = [] + class FindCols(VisitColumnMixin, ClauseVisitor): + def visit_column(self, col): + ret.append(col) + self.accept_visitor(FindCols()) + return ret + + def corresponding_column(self, column, raiseerr=True, keys_ok=False, require_embedded=False): """Given a ``ColumnElement``, return the ``ColumnElement`` object from this ``Selectable`` which corresponds to that original ``Column`` via a proxy relationship. """ - if require_exact: - if self.columns.get(column.name) is column: - return column + if require_embedded and column not in util.Set(self._get_all_embedded_columns()): + if not raiseerr: + return None else: - if not raiseerr: - return None - else: - raise exceptions.InvalidRequestError("Column instance '%s' is not directly present in table '%s'" % (str(column), str(column.table))) + raise exceptions.InvalidRequestError("Column instance '%s' is not directly present within selectable '%s'" % (str(column), column.table)) for c in column.orig_set: try: return self.original_columns[c] |
