diff options
author | Ilja Everilä <saarni@gmail.com> | 2014-09-10 11:34:33 +0300 |
---|---|---|
committer | Ilja Everilä <saarni@gmail.com> | 2014-09-10 11:34:33 +0300 |
commit | ad82849bbe4ef329129204d02781f737c0c79fcb (patch) | |
tree | 58bb07abaada3c96277933520fefd973c365a103 /lib/sqlalchemy/sql/elements.py | |
parent | a23264e1dc43b1250b9b5de541ff27bd49a2b2c1 (diff) | |
download | sqlalchemy-ad82849bbe4ef329129204d02781f737c0c79fcb.tar.gz |
implementation for <aggregate_fun> FILTER (WHERE ...)
Diffstat (limited to 'lib/sqlalchemy/sql/elements.py')
-rw-r--r-- | lib/sqlalchemy/sql/elements.py | 65 |
1 files changed, 65 insertions, 0 deletions
diff --git a/lib/sqlalchemy/sql/elements.py b/lib/sqlalchemy/sql/elements.py index 8ec0aa700..5562e80d7 100644 --- a/lib/sqlalchemy/sql/elements.py +++ b/lib/sqlalchemy/sql/elements.py @@ -2888,6 +2888,71 @@ class Over(ColumnElement): )) +class AggregateFilter(ColumnElement): + """Represent an aggregate FILTER clause. + + This is a special operator against aggregate functions, + which controls which rows are passed to it. + It's supported only by certain database backends. + + """ + __visit_name__ = 'aggregatefilter' + + criterion = None + + def __init__(self, func, *criterion): + """Produce an :class:`.AggregateFilter` object against a function. + + Used against aggregate functions, + for database backends that support aggregate "FILTER" clause. + + E.g.:: + + from sqlalchemy import aggregatefilter + aggregatefilter(func.count(1), MyClass.name == 'some name') + + Would produce "COUNT(1) FILTER (WHERE myclass.name = 'some name')". + + This function is also available from the :data:`~.expression.func` + construct itself via the :meth:`.FunctionElement.filter` method. + + """ + self.func = func + self.filter(*criterion) + + def filter(self, *criterion): + for criterion in list(criterion): + criterion = _expression_literal_as_text(criterion) + + if self.criterion is not None: + self.criterion = self.criterion & criterion + else: + self.criterion = criterion + + return self + + @util.memoized_property + def type(self): + return self.func.type + + def get_children(self, **kwargs): + return [c for c in + (self.func, self.criterion) + if c is not None] + + def _copy_internals(self, clone=_clone, **kw): + self.func = clone(self.func, **kw) + if self.criterion is not None: + self.criterion = clone(self.criterion, **kw) + + @property + def _from_objects(self): + return list(itertools.chain( + *[c._from_objects for c in (self.func, self.criterion) + if c is not None] + )) + + class Label(ColumnElement): """Represents a column label (AS). |