From: Mike Bayer Date: Fri, 6 Dec 2019 15:24:25 +0000 (-0500) Subject: Include DISTINCT in error message for label reference X-Git-Tag: rel_1_3_12~4 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=500625103b4c0b7aa2d80a716818fb5e950841a8;p=thirdparty%2Fsqlalchemy%2Fsqlalchemy.git Include DISTINCT in error message for label reference 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 (cherry picked from commit 55f66e430d18b8daa51121cbc18537e2dab1ad9f) --- diff --git a/doc/build/changelog/unreleased_13/dist_warn.rst b/doc/build/changelog/unreleased_13/dist_warn.rst new file mode 100644 index 0000000000..b70a9f08e8 --- /dev/null +++ b/doc/build/changelog/unreleased_13/dist_warn.rst @@ -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. + diff --git a/lib/sqlalchemy/sql/compiler.py b/lib/sqlalchemy/sql/compiler.py index 7a063ab1b5..4dff9b25b2 100644 --- a/lib/sqlalchemy/sql/compiler.py +++ b/lib/sqlalchemy/sql/compiler.py @@ -778,7 +778,8 @@ class SQLCompiler(Compiled): elements._no_text_coercion( element.element, exc.CompileError, - "Can't resolve label reference for ORDER BY / GROUP BY.", + "Can't resolve label reference for ORDER BY / " + "GROUP BY / DISTINCT etc.", ) else: kwargs["render_label_as_label"] = col diff --git a/test/orm/test_query.py b/test/orm/test_query.py index 2791251bdd..2a877015ee 100644 --- a/test/orm/test_query.py +++ b/test/orm/test_query.py @@ -3878,6 +3878,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 diff --git a/test/sql/test_text.py b/test/sql/test_text.py index 4e1013b00f..46493cdc1b 100644 --- a/test/sql/test_text.py +++ b/test/sql/test_text.py @@ -629,14 +629,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): @@ -687,6 +689,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( @@ -840,7 +857,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'\)",