]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
Include DISTINCT in error message for label reference
authorMike Bayer <mike_mp@zzzcomputing.com>
Fri, 6 Dec 2019 15:24:25 +0000 (10:24 -0500)
committerMike Bayer <mike_mp@zzzcomputing.com>
Fri, 6 Dec 2019 15:57:19 +0000 (10:57 -0500)
Needed to add tests to ensure this label reference is handled
correctly, so also modified the exception message to
be more clear if someone has this error within distinct().

Change-Id: I6e685e46ae336596272d14366445ac224c18d92c

doc/build/changelog/unreleased_13/dist_warn.rst [new file with mode: 0644]
lib/sqlalchemy/sql/compiler.py
test/orm/test_query.py
test/sql/test_compiler.py
test/sql/test_text.py

diff --git a/doc/build/changelog/unreleased_13/dist_warn.rst b/doc/build/changelog/unreleased_13/dist_warn.rst
new file mode 100644 (file)
index 0000000..b70a9f0
--- /dev/null
@@ -0,0 +1,7 @@
+.. change::
+    :tags: bug, sql
+
+    Changed the text of the exception for "Can't resolve label reference" to
+    include other kinds of label coercions, namely that "DISTINCT" is also in
+    this category under the PostgreSQL dialect.
+
index 85c1750b7b0287288dc319ed6af6e67f51a3c57c..a28ce465a911e905902a04e25b45bdb8544f3aeb 100644 (file)
@@ -811,7 +811,10 @@ class SQLCompiler(Compiled):
         except KeyError:
             coercions._no_text_coercion(
                 element.element,
-                extra="Can't resolve label reference for ORDER BY / GROUP BY.",
+                extra=(
+                    "Can't resolve label reference for ORDER BY / "
+                    "GROUP BY / DISTINCT etc."
+                ),
                 exc_cls=exc.CompileError,
             )
         else:
index 2bc0af3c26f8b1977c7a1ba369331c6cd1787957..068a7c8937821dcc83b1fe1d35d305c05b3f1dfd 100644 (file)
@@ -3990,6 +3990,45 @@ class DistinctTest(QueryTest, AssertsCompiledSQL):
             dialect="postgresql",
         )
 
+    def test_columns_augmented_sql_three_using_label_reference(self):
+        User, Address = self.classes.User, self.classes.Address
+
+        sess = create_session()
+
+        q = (
+            sess.query(User.id, User.name.label("foo"), Address.id)
+            .distinct("name")
+            .order_by(User.id, User.name, Address.email_address)
+        )
+
+        # no columns are added when DISTINCT ON is used
+        self.assert_compile(
+            q,
+            "SELECT DISTINCT ON (users.name) users.id AS users_id, "
+            "users.name AS foo, addresses.id AS addresses_id FROM users, "
+            "addresses ORDER BY users.id, users.name, addresses.email_address",
+            dialect="postgresql",
+        )
+
+    def test_columns_augmented_sql_illegal_label_reference(self):
+        User, Address = self.classes.User, self.classes.Address
+
+        sess = create_session()
+
+        q = sess.query(User.id, User.name.label("foo"), Address.id).distinct(
+            "not a label"
+        )
+
+        from sqlalchemy.dialects import postgresql
+
+        assert_raises_message(
+            sa_exc.CompileError,
+            "Can't resolve label reference for ORDER BY / "
+            "GROUP BY / DISTINCT etc.",
+            q.with_labels().statement.compile,
+            dialect=postgresql.dialect(),
+        )
+
     def test_columns_augmented_sql_four(self):
         User, Address = self.classes.User, self.classes.Address
 
index ca73f6c18c1ada7d07d6715bb153f8eaa942f5c9..486b546828024ee0bc3077c1c8c70b70fc729c4f 100644 (file)
@@ -2073,7 +2073,8 @@ class SelectTest(fixtures.TestBase, AssertsCompiledSQL):
         # to check the special thing CompoundSelect does with labels
         assert_raises_message(
             exc.CompileError,
-            "Can't resolve label reference for ORDER BY / GROUP BY. Textual "
+            "Can't resolve label reference for ORDER BY / GROUP BY / "
+            "DISTINCT etc. Textual "
             "SQL expression 'noname'",
             union(
                 select([table1.c.myid, table1.c.name]),
index 3f12d06a90f3f13c9efbe910eddf2fd7157c5772..3386d0aae952610f5bbdd9b595196bb418c75174 100644 (file)
@@ -678,14 +678,16 @@ class TextErrorsTest(fixtures.TestBase, AssertsCompiledSQL):
 class OrderByLabelResolutionTest(fixtures.TestBase, AssertsCompiledSQL):
     __dialect__ = "default"
 
-    def _test_exception(self, stmt, offending_clause):
+    def _test_exception(self, stmt, offending_clause, dialect=None):
         assert_raises_message(
             exc.CompileError,
-            r"Can't resolve label reference for ORDER BY / GROUP BY. "
+            r"Can't resolve label reference for ORDER BY / GROUP BY / "
+            "DISTINCT etc. "
             "Textual SQL "
             "expression %r should be explicitly "
             r"declared as text\(%r\)" % (offending_clause, offending_clause),
             stmt.compile,
+            dialect=dialect,
         )
 
     def test_order_by_label(self):
@@ -736,6 +738,21 @@ class OrderByLabelResolutionTest(fixtures.TestBase, AssertsCompiledSQL):
         stmt = select([table1.c.myid]).order_by("foobar")
         self._test_exception(stmt, "foobar")
 
+    def test_distinct_label(self):
+
+        stmt = select([table1.c.myid.label("foo")]).distinct("foo")
+        self.assert_compile(
+            stmt,
+            "SELECT DISTINCT ON (foo) mytable.myid AS foo FROM mytable",
+            dialect="postgresql",
+        )
+
+    def test_unresolvable_distinct_label(self):
+        from sqlalchemy.dialects import postgresql
+
+        stmt = select([table1.c.myid.label("foo")]).distinct("not a label")
+        self._test_exception(stmt, "not a label", dialect=postgresql.dialect())
+
     def test_group_by_label(self):
         stmt = select([table1.c.myid.label("foo")]).group_by("foo")
         self.assert_compile(
@@ -890,7 +907,8 @@ class OrderByLabelResolutionTest(fixtures.TestBase, AssertsCompiledSQL):
 
         assert_raises_message(
             exc.CompileError,
-            r"Can't resolve label reference for ORDER BY / GROUP BY. "
+            r"Can't resolve label reference for ORDER BY / GROUP BY / "
+            "DISTINCT etc. "
             "Textual SQL "
             "expression 't1name' should be explicitly "
             r"declared as text\('t1name'\)",