summaryrefslogtreecommitdiff
path: root/lib/sqlalchemy/sql.py
diff options
context:
space:
mode:
authorMike Bayer <mike_mp@zzzcomputing.com>2007-03-02 21:22:14 +0000
committerMike Bayer <mike_mp@zzzcomputing.com>2007-03-02 21:22:14 +0000
commit2a77850707db1dc71bd069be04b049cc52af8983 (patch)
treeda3aebcd2d59de3c025b785f2c703b513255953f /lib/sqlalchemy/sql.py
parent7e2ae824a56c760286e33adce03324b8e696472a (diff)
downloadsqlalchemy-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.py53
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