summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/sqlalchemy/dialects/firebird/base.py3
-rw-r--r--lib/sqlalchemy/dialects/mssql/base.py12
-rw-r--r--lib/sqlalchemy/dialects/mysql/base.py21
-rw-r--r--lib/sqlalchemy/dialects/postgresql/base.py2
-rw-r--r--lib/sqlalchemy/orm/query.py3
-rw-r--r--lib/sqlalchemy/sql/compiler.py11
-rw-r--r--lib/sqlalchemy/sql/selectable.py3
-rw-r--r--lib/sqlalchemy/testing/assertions.py1
-rw-r--r--lib/sqlalchemy/testing/requirements.py5
-rw-r--r--lib/sqlalchemy/testing/suite/test_select.py15
10 files changed, 54 insertions, 22 deletions
diff --git a/lib/sqlalchemy/dialects/firebird/base.py b/lib/sqlalchemy/dialects/firebird/base.py
index a43413780..5779ac885 100644
--- a/lib/sqlalchemy/dialects/firebird/base.py
+++ b/lib/sqlalchemy/dialects/firebird/base.py
@@ -525,8 +525,7 @@ class FBCompiler(sql.compiler.SQLCompiler):
result += "FIRST %s " % self.process(select._limit_clause, **kw)
if select._offset_clause is not None:
result += "SKIP %s " % self.process(select._offset_clause, **kw)
- if select._distinct:
- result += "DISTINCT "
+ result += super(FBCompiler, self).get_select_precolumns(select, **kw)
return result
def limit_clause(self, select, **kw):
diff --git a/lib/sqlalchemy/dialects/mssql/base.py b/lib/sqlalchemy/dialects/mssql/base.py
index df6196bae..0dd2ac11b 100644
--- a/lib/sqlalchemy/dialects/mssql/base.py
+++ b/lib/sqlalchemy/dialects/mssql/base.py
@@ -1636,9 +1636,7 @@ class MSSQLCompiler(compiler.SQLCompiler):
def get_select_precolumns(self, select, **kw):
""" MS-SQL puts TOP, it's version of LIMIT here """
- s = ""
- if select._distinct:
- s += "DISTINCT "
+ s = super(MSSQLCompiler, self).get_select_precolumns(select, **kw)
if select._simple_int_limit and (
select._offset_clause is None
@@ -1649,12 +1647,8 @@ class MSSQLCompiler(compiler.SQLCompiler):
# so have to use literal here.
kw["literal_execute"] = True
s += "TOP %s " % self.process(select._limit_clause, **kw)
- if s:
- return s
- else:
- return compiler.SQLCompiler.get_select_precolumns(
- self, select, **kw
- )
+
+ return s
def get_from_hint_text(self, table, text):
return text
diff --git a/lib/sqlalchemy/dialects/mysql/base.py b/lib/sqlalchemy/dialects/mysql/base.py
index 53c916304..38f3fa611 100644
--- a/lib/sqlalchemy/dialects/mysql/base.py
+++ b/lib/sqlalchemy/dialects/mysql/base.py
@@ -1450,19 +1450,22 @@ class MySQLCompiler(compiler.SQLCompiler):
def get_select_precolumns(self, select, **kw):
"""Add special MySQL keywords in place of DISTINCT.
- .. note::
-
- this usage is deprecated. :meth:`_expression.Select.prefix_with`
- should be used for special keywords at the start
- of a SELECT.
+ .. deprecated 1.4:: this usage is deprecated.
+ :meth:`_expression.Select.prefix_with` should be used for special
+ keywords at the start of a SELECT.
"""
if isinstance(select._distinct, util.string_types):
+ util.warn_deprecated(
+ "Sending string values for 'distinct' is deprecated in the "
+ "MySQL dialect and will be removed in a future release. "
+ "Please use :meth:`.Select.prefix_with` for special keywords "
+ "at the start of a SELECT statement",
+ version="1.4",
+ )
return select._distinct.upper() + " "
- elif select._distinct:
- return "DISTINCT "
- else:
- return ""
+
+ return super(MySQLCompiler, self).get_select_precolumns(select, **kw)
def visit_join(self, join, asfrom=False, from_linter=None, **kwargs):
if from_linter:
diff --git a/lib/sqlalchemy/dialects/postgresql/base.py b/lib/sqlalchemy/dialects/postgresql/base.py
index 20540ac02..ca2f6a8a4 100644
--- a/lib/sqlalchemy/dialects/postgresql/base.py
+++ b/lib/sqlalchemy/dialects/postgresql/base.py
@@ -1693,6 +1693,8 @@ class PGCompiler(compiler.SQLCompiler):
return "ONLY " + sqltext
def get_select_precolumns(self, select, **kw):
+ # Do not call super().get_select_precolumns because
+ # it will warn/raise when distinct on is present
if select._distinct or select._distinct_on:
if select._distinct_on:
return (
diff --git a/lib/sqlalchemy/orm/query.py b/lib/sqlalchemy/orm/query.py
index 4d7eee9ba..ab49a4dcc 100644
--- a/lib/sqlalchemy/orm/query.py
+++ b/lib/sqlalchemy/orm/query.py
@@ -3156,6 +3156,9 @@ class Query(Generative):
the PostgreSQL dialect will render a ``DISTINCT ON (<expressions>)``
construct.
+ .. deprecated:: 1.4 Using \*expr in other dialects is deprecated
+ and will raise :class:`_exc.CompileError` in a future version.
+
"""
if not expr:
self._distinct = True
diff --git a/lib/sqlalchemy/sql/compiler.py b/lib/sqlalchemy/sql/compiler.py
index bc16b1429..23eff773c 100644
--- a/lib/sqlalchemy/sql/compiler.py
+++ b/lib/sqlalchemy/sql/compiler.py
@@ -2868,7 +2868,16 @@ class SQLCompiler(Compiled):
before column list.
"""
- return select._distinct and "DISTINCT " or ""
+ if select._distinct_on:
+ util.warn_deprecated(
+ "DISTINCT ON is currently supported only by the PostgreSQL "
+ "dialect. Use of DISTINCT ON for other backends is currently "
+ "silently ignored, however this usage is deprecated, and will "
+ "raise CompileError in a future release for all backends "
+ "that do not support this syntax.",
+ version="1.4",
+ )
+ return "DISTINCT " if select._distinct else ""
def group_by_clause(self, select, **kw):
"""allow dialects to customize how GROUP BY is rendered."""
diff --git a/lib/sqlalchemy/sql/selectable.py b/lib/sqlalchemy/sql/selectable.py
index 89ee7e28f..c8df637ba 100644
--- a/lib/sqlalchemy/sql/selectable.py
+++ b/lib/sqlalchemy/sql/selectable.py
@@ -4138,6 +4138,9 @@ class Select(
the PostgreSQL dialect will render a ``DISTINCT ON (<expressions>>)``
construct.
+ .. deprecated:: 1.4 Using \*expr in other dialects is deprecated
+ and will raise :class:`_exc.CompileError` in a future version.
+
"""
if expr:
self._distinct = True
diff --git a/lib/sqlalchemy/testing/assertions.py b/lib/sqlalchemy/testing/assertions.py
index 61d272160..05dcf230b 100644
--- a/lib/sqlalchemy/testing/assertions.py
+++ b/lib/sqlalchemy/testing/assertions.py
@@ -412,7 +412,6 @@ class AssertsCompiledSQL(object):
c = clause.compile(dialect=dialect, **kw)
param_str = repr(getattr(c, "params", {}))
-
if util.py3k:
param_str = param_str.encode("utf-8").decode("ascii", "ignore")
print(
diff --git a/lib/sqlalchemy/testing/requirements.py b/lib/sqlalchemy/testing/requirements.py
index 644483b79..31011a970 100644
--- a/lib/sqlalchemy/testing/requirements.py
+++ b/lib/sqlalchemy/testing/requirements.py
@@ -1170,6 +1170,11 @@ class SuiteRequirements(Requirements):
return exclusions.closed()
@property
+ def supports_distinct_on(self):
+ """If a backend supports the DISTINCT ON in a select"""
+ return exclusions.closed()
+
+ @property
def supports_is_distinct_from(self):
"""Supports some form of "x IS [NOT] DISTINCT FROM y" construct.
Different dialects will implement their own flavour, e.g.,
diff --git a/lib/sqlalchemy/testing/suite/test_select.py b/lib/sqlalchemy/testing/suite/test_select.py
index c1f77a7c1..ad17ebb4a 100644
--- a/lib/sqlalchemy/testing/suite/test_select.py
+++ b/lib/sqlalchemy/testing/suite/test_select.py
@@ -12,6 +12,7 @@ from ..schema import Column
from ..schema import Table
from ... import bindparam
from ... import case
+from ... import column
from ... import Computed
from ... import false
from ... import func
@@ -20,6 +21,7 @@ from ... import literal_column
from ... import null
from ... import select
from ... import String
+from ... import table
from ... import testing
from ... import text
from ... import true
@@ -1016,6 +1018,19 @@ class ComputedColumnTest(fixtures.TablesTest):
eq_(res, [(100, 40), (1764, 168)])
+class DistinctOnTest(AssertsCompiledSQL, fixtures.TablesTest):
+ __backend__ = True
+ __requires__ = ("standard_cursor_sql",)
+
+ @testing.fails_if(testing.requires.supports_distinct_on)
+ def test_distinct_on(self):
+ stm = select(["*"]).distinct(column("q")).select_from(table("foo"))
+ with testing.expect_deprecated(
+ "DISTINCT ON is currently supported only by the PostgreSQL "
+ ):
+ self.assert_compile(stm, "SELECT DISTINCT * FROM foo")
+
+
class IsOrIsNotDistinctFromTest(fixtures.TablesTest):
__backend__ = True
__requires__ = ("supports_is_distinct_from",)