summaryrefslogtreecommitdiff
path: root/lib/sqlalchemy/sql/expression.py
diff options
context:
space:
mode:
authorMike Bayer <mike_mp@zzzcomputing.com>2011-02-10 14:17:08 -0500
committerMike Bayer <mike_mp@zzzcomputing.com>2011-02-10 14:17:08 -0500
commit3f9a343d725eea883aba2145de4cbb7b84f9d08c (patch)
treef55e890195c76543e689c3b939b84df15cd80a3e /lib/sqlalchemy/sql/expression.py
parenta6d54d18c1ddac30940affaa940edaad59e5d63f (diff)
downloadsqlalchemy-3f9a343d725eea883aba2145de4cbb7b84f9d08c.tar.gz
- Query.distinct() now accepts column expressions
as *args, interpreted by the Postgresql dialect as DISTINCT ON (<expr>). [ticket:1069] - select.distinct() now accepts column expressions as *args, interpreted by the Postgresql dialect as DISTINCT ON (<expr>). Note this was already available via passing a list to the `distinct` keyword argument to select(). [ticket:1069] - select.prefix_with() accepts multiple expressions (i.e. *expr), 'prefix' keyword argument to select() accepts a list or tuple. - Passing a string to the `distinct` keyword argument of `select()` for the purpose of emitting special MySQL keywords (DISTINCTROW etc.) is deprecated - use `prefix_with()` for this. - put kw arguments to select() in order - restore docs for _SelectBase, renamed from _SelectBaseMixin
Diffstat (limited to 'lib/sqlalchemy/sql/expression.py')
-rw-r--r--lib/sqlalchemy/sql/expression.py141
1 files changed, 100 insertions, 41 deletions
diff --git a/lib/sqlalchemy/sql/expression.py b/lib/sqlalchemy/sql/expression.py
index 04ca147bb..4287216a4 100644
--- a/lib/sqlalchemy/sql/expression.py
+++ b/lib/sqlalchemy/sql/expression.py
@@ -187,23 +187,38 @@ def select(columns=None, whereclause=None, from_obj=[], **kwargs):
Deprecated. Use .execution_options(autocommit=<True|False>)
to set the autocommit option.
- :param prefixes:
- a list of strings or :class:`ClauseElement` objects to include
- directly after the SELECT keyword in the generated statement,
- for dialect-specific query features.
+ :param bind=None:
+ an :class:`~.base.Engine` or :class:`~.base.Connection` instance
+ to which the
+ resulting :class:`.Select` object will be bound. The :class:`.Select`
+ object will otherwise automatically bind to whatever
+ :class:`~.base.Connectable` instances can be located within its contained
+ :class:`.ClauseElement` members.
+
+ :param correlate=True:
+ indicates that this :class:`Select` object should have its
+ contained :class:`FromClause` elements "correlated" to an enclosing
+ :class:`Select` object. This means that any :class:`ClauseElement`
+ instance within the "froms" collection of this :class:`Select`
+ which is also present in the "froms" collection of an
+ enclosing select will not be rendered in the ``FROM`` clause
+ of this select statement.
:param distinct=False:
when ``True``, applies a ``DISTINCT`` qualifier to the columns
clause of the resulting statement.
-
- :param use_labels=False:
- when ``True``, the statement will be generated using labels
- for each column in the columns clause, which qualify each
- column with its parent table's (or aliases) name so that name
- conflicts between columns in different tables don't occur.
- The format of the label is <tablename>_<column>. The "c"
- collection of the resulting :class:`Select` object will use these
- names as well for targeting column members.
+
+ The boolean argument may also be a column expression or list
+ of column expressions - this is a special calling form which
+ is understood by the Postgresql dialect to render the
+ ``DISTINCT ON (<columns>)`` syntax.
+
+ ``distinct`` is also available via the :meth:`~.Select.distinct`
+ generative method.
+
+ .. note:: The ``distinct`` keyword's acceptance of a string
+ argument for usage with MySQL is deprecated. Use
+ the ``prefixes`` argument or :meth:`~.Select.prefix_with`.
:param for_update=False:
when ``True``, applies ``FOR UPDATE`` to the end of the
@@ -213,15 +228,6 @@ def select(columns=None, whereclause=None, from_obj=[], **kwargs):
and oracle supports "nowait" which translates to ``FOR UPDATE
NOWAIT``.
- :param correlate=True:
- indicates that this :class:`Select` object should have its
- contained :class:`FromClause` elements "correlated" to an enclosing
- :class:`Select` object. This means that any :class:`ClauseElement`
- instance within the "froms" collection of this :class:`Select`
- which is also present in the "froms" collection of an
- enclosing select will not be rendered in the ``FROM`` clause
- of this select statement.
-
:param group_by:
a list of :class:`ClauseElement` objects which will comprise the
``GROUP BY`` clause of the resulting select.
@@ -230,10 +236,6 @@ def select(columns=None, whereclause=None, from_obj=[], **kwargs):
a :class:`ClauseElement` that will comprise the ``HAVING`` clause
of the resulting select when ``GROUP BY`` is used.
- :param order_by:
- a scalar or list of :class:`ClauseElement` objects which will
- comprise the ``ORDER BY`` clause of the resulting select.
-
:param limit=None:
a numerical value which usually compiles to a ``LIMIT``
expression in the resulting select. Databases that don't
@@ -246,13 +248,29 @@ def select(columns=None, whereclause=None, from_obj=[], **kwargs):
support ``OFFSET`` will attempt to provide similar
functionality.
- :param bind=None:
- an ``Engine`` or ``Connection`` instance to which the
- resulting ``Select ` object will be bound. The ``Select``
- object will otherwise automatically bind to whatever
- ``Connectable`` instances can be located within its contained
- :class:`ClauseElement` members.
+ :param order_by:
+ a scalar or list of :class:`ClauseElement` objects which will
+ comprise the ``ORDER BY`` clause of the resulting select.
+ :param prefixes:
+ a list of strings or :class:`ClauseElement` objects to include
+ directly after the SELECT keyword in the generated statement,
+ for dialect-specific query features. ``prefixes`` is
+ also available via the :meth:`~.Select.prefix_with`
+ generative method.
+
+ :param use_labels=False:
+ when ``True``, the statement will be generated using labels
+ for each column in the columns clause, which qualify each
+ column with its parent table's (or aliases) name so that name
+ conflicts between columns in different tables don't occur.
+ The format of the label is <tablename>_<column>. The "c"
+ collection of the resulting :class:`Select` object will use these
+ names as well for targeting column members.
+
+ use_labels is also available via the :meth:`~._SelectBase.apply_labels`
+ generative method.
+
"""
return Select(columns, whereclause=whereclause, from_obj=from_obj,
**kwargs)
@@ -4085,6 +4103,7 @@ class Select(_SelectBase):
_prefixes = ()
_hints = util.immutabledict()
+ _distinct = False
def __init__(self,
columns,
@@ -4106,7 +4125,24 @@ class Select(_SelectBase):
"""
self._should_correlate = correlate
- self._distinct = distinct
+ if distinct is not False:
+ if isinstance(distinct, basestring):
+ util.warn_deprecated(
+ "A string argument passed to the 'distinct' "
+ "keyword argument of 'select()' is deprecated "
+ "- please use 'prefixes' or 'prefix_with()' "
+ "to specify additional prefixes")
+ if prefixes:
+ prefixes = util.to_list(prefixes) + [distinct]
+ else:
+ prefixes = [distinct]
+ elif distinct is True:
+ self._distinct = True
+ else:
+ self._distinct = [
+ _literal_as_text(e)
+ for e in util.to_list(distinct)
+ ]
self._correlate = set()
self._froms = util.OrderedSet()
@@ -4329,21 +4365,44 @@ class Select(_SelectBase):
self.append_having(having)
@_generative
- def distinct(self):
- """return a new select() construct which will apply DISTINCT to its
+ def distinct(self, *expr):
+ """Return a new select() construct which will apply DISTINCT to its
columns clause.
- """
- self._distinct = True
+ :param \*expr: optional column expressions. When present,
+ the Postgresql dialect will render a ``DISTINCT ON (<expressions>>)``
+ construct.
+
+ """
+ if expr:
+ expr = [_literal_as_text(e) for e in expr]
+ if isinstance(self._distinct, list):
+ self._distinct = self._distinct + expr
+ else:
+ self._distinct = expr
+ else:
+ self._distinct = True
@_generative
- def prefix_with(self, clause):
+ def prefix_with(self, *expr):
"""return a new select() construct which will apply the given
- expression to the start of its columns clause, not using any commas.
+ expressions, typically strings, to the start of its columns clause,
+ not using any commas. In particular is useful for MySQL
+ keywords.
+
+ e.g.::
+
+ select(['a', 'b']).prefix_with('HIGH_PRIORITY',
+ 'SQL_SMALL_RESULT',
+ 'ALL')
+
+ Would render::
+
+ SELECT HIGH_PRIORITY SQL_SMALL_RESULT ALL a, b
"""
- clause = _literal_as_text(clause)
- self._prefixes = self._prefixes + (clause,)
+ expr = tuple(_literal_as_text(e) for e in expr)
+ self._prefixes = self._prefixes + expr
@_generative
def select_from(self, fromclause):