From 5e8396a60ed69341b1e73ac415c7cd6dceec0c8a Mon Sep 17 00:00:00 2001 From: Mike Bayer Date: Wed, 6 Dec 2017 14:12:42 -0500 Subject: [PATCH] Change visit name for ColumnElement No SQLA built-in subclasses ColumnElement without specifying an alternate visit_name, and user defined ColumnElement subclasses should avoid being treated like ColumnClause, e.g. where a Table is present. Fixes: #4142 Change-Id: I15ed09ba8bdebae4cb0c7e5e5df3f59351477577 --- doc/build/changelog/unreleased_12/4142.rst | 9 +++++++++ lib/sqlalchemy/sql/elements.py | 2 +- test/sql/test_utils.py | 16 ++++++++++++++-- 3 files changed, 24 insertions(+), 3 deletions(-) create mode 100644 doc/build/changelog/unreleased_12/4142.rst diff --git a/doc/build/changelog/unreleased_12/4142.rst b/doc/build/changelog/unreleased_12/4142.rst new file mode 100644 index 0000000000..be5ac2fb75 --- /dev/null +++ b/doc/build/changelog/unreleased_12/4142.rst @@ -0,0 +1,9 @@ +.. change:: + :tags: bug, sql + :tickets: 4142 + + Changed the "visit name" of :class:`.ColumnElement` from "column" to + "column_element", so that when this element is used as the basis for a + user-defined SQL element, it is not assumed to behave like a table-bound + :class:`.ColumnClause` when processed by various SQL traversal utilities, + as are commonly used by the ORM. diff --git a/lib/sqlalchemy/sql/elements.py b/lib/sqlalchemy/sql/elements.py index 3b2bcb4ff1..2cc1d9c423 100644 --- a/lib/sqlalchemy/sql/elements.py +++ b/lib/sqlalchemy/sql/elements.py @@ -571,7 +571,7 @@ class ColumnElement(operators.ColumnOperators, ClauseElement): """ - __visit_name__ = 'column' + __visit_name__ = 'column_element' primary_key = False foreign_keys = [] diff --git a/test/sql/test_utils.py b/test/sql/test_utils.py index 84e7ad7328..bd8368cd25 100644 --- a/test/sql/test_utils.py +++ b/test/sql/test_utils.py @@ -1,8 +1,9 @@ -from sqlalchemy.testing import fixtures, is_true, is_false +from sqlalchemy.testing import fixtures, is_true, is_false, eq_ from sqlalchemy import MetaData, Table, Column, Integer, String from sqlalchemy import and_, or_, bindparam -from sqlalchemy.sql.elements import ClauseList +from sqlalchemy.sql.elements import ClauseList, ColumnElement from sqlalchemy.sql import operators +from sqlalchemy.sql import util as sql_util class CompareClausesTest(fixtures.TestBase): @@ -106,3 +107,14 @@ class CompareClausesTest(fixtures.TestBase): is_false(b1.compare(b8)) is_false(b8.compare(b9)) is_true(b8.compare(b8)) + + +class MiscTest(fixtures.TestBase): + def test_column_element_no_visit(self): + class MyElement(ColumnElement): + pass + + eq_( + sql_util.find_tables(MyElement(), check_columns=True), + [] + ) -- 2.47.3