diff options
author | Mike Bayer <mike_mp@zzzcomputing.com> | 2007-03-02 21:22:14 +0000 |
---|---|---|
committer | Mike Bayer <mike_mp@zzzcomputing.com> | 2007-03-02 21:22:14 +0000 |
commit | 2a77850707db1dc71bd069be04b049cc52af8983 (patch) | |
tree | da3aebcd2d59de3c025b785f2c703b513255953f /lib/sqlalchemy/sql.py | |
parent | 7e2ae824a56c760286e33adce03324b8e696472a (diff) | |
download | sqlalchemy-2a77850707db1dc71bd069be04b049cc52af8983.tar.gz |
- added "fold_equivalents" argument to Join.select(), which removes
'duplicate' columns from the resulting column clause that are known to be
equivalent based on the join condition. this is of great usage when
constructing subqueries of joins which Postgres complains about if
duplicate column names are present.
- added support to polymorphic stuff for more than one "equivalent column",
when trying to target columns in the polymorphic union; this applies
to multi-leveled inheritance
- put above-two concepts together to get the abc_inheritance tests to work
with postgres
Diffstat (limited to 'lib/sqlalchemy/sql.py')
-rw-r--r-- | lib/sqlalchemy/sql.py | 53 |
1 files changed, 50 insertions, 3 deletions
diff --git a/lib/sqlalchemy/sql.py b/lib/sqlalchemy/sql.py index 273af5415..9c8d5db08 100644 --- a/lib/sqlalchemy/sql.py +++ b/lib/sqlalchemy/sql.py @@ -1549,8 +1549,55 @@ class Join(FromClause): def _group_parenthesized(self): return True - def select(self, whereclauses = None, **params): - return select([self.left, self.right], whereclauses, from_obj=[self], **params) + def _get_folded_equivalents(self, equivs=None): + if equivs is None: + equivs = util.Set() + class LocateEquivs(ClauseVisitor): + def visit_binary(self, binary): + if binary.operator == '=' and binary.left.name == binary.right.name: + equivs.add(binary.right) + equivs.add(binary.left) + self.onclause.accept_visitor(LocateEquivs()) + collist = [] + if isinstance(self.left, Join): + left = self.left._get_folded_equivalents(equivs) + else: + left = list(self.left.columns) + if isinstance(self.right, Join): + right = self.right._get_folded_equivalents(equivs) + else: + right = list(self.right.columns) + used = util.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 + + def select(self, whereclause = None, fold_equivalents=False, **kwargs): + """Create a ``Select`` from this ``Join``. + + whereclause + the WHERE criterion that will be sent to the ``select()`` function + + fold_equivalents + based on the join criterion of this ``Join``, do not include equivalent + columns in the column list of the resulting select. this will recursively + apply to any joins directly nested by this one as well. + + **kwargs + all other kwargs are sent to the underlying ``select()`` function + + """ + if fold_equivalents: + collist = self._get_folded_equivalents() + else: + collist = [self.left, self.right] + + return select(collist, whereclause, from_obj=[self], **kwargs) def accept_visitor(self, visitor): self.left.accept_visitor(visitor) @@ -1912,7 +1959,7 @@ class Select(_SelectBaseMixin, FromClause): self.offset = offset self.for_update = for_update self.is_compound = False - + # indicates that this select statement should not expand its columns # into the column clause of an enclosing select, and should instead # act like a single scalar column |