diff options
| author | mike bayer <mike_mp@zzzcomputing.com> | 2021-01-14 18:55:59 +0000 |
|---|---|---|
| committer | Gerrit Code Review <gerrit@bbpush.zzzcomputing.com> | 2021-01-14 18:55:59 +0000 |
| commit | 41ca37734aa4f293ac5fb63c239d78185c8ec983 (patch) | |
| tree | 372f172e38ba565df1a6b3acb9c70c843eed3735 | |
| parent | 4d20df14846e644b88fbe8a288116422bf5e343e (diff) | |
| parent | b4c6cfc2fde6c652e79ca157f8023a3f8941bc3c (diff) | |
| download | sqlalchemy-41ca37734aa4f293ac5fb63c239d78185c8ec983.tar.gz | |
Merge "Use UnsupportedCompilationError for no default compiler"
| -rw-r--r-- | doc/build/changelog/unreleased_13/5836.rst | 13 | ||||
| -rw-r--r-- | lib/sqlalchemy/exc.py | 6 | ||||
| -rw-r--r-- | lib/sqlalchemy/ext/compiler.py | 16 | ||||
| -rw-r--r-- | test/ext/test_compiler.py | 25 |
4 files changed, 49 insertions, 11 deletions
diff --git a/doc/build/changelog/unreleased_13/5836.rst b/doc/build/changelog/unreleased_13/5836.rst new file mode 100644 index 000000000..0ddfb9a8d --- /dev/null +++ b/doc/build/changelog/unreleased_13/5836.rst @@ -0,0 +1,13 @@ +.. change:: + :tags: bug, ext + :tickets: 5836 + + Fixed issue where the stringification that is sometimes called when + attempting to generate the "key" for the ``.c`` collection on a selectable + would fail if the column were an unlabeled custom SQL construct using the + ``sqlalchemy.ext.compiler`` extension, and did not provide a default + compilation form; while this seems like an unusual case, it can get invoked + for some ORM scenarios such as when the expression is used in an "order by" + in combination with joined eager loading. The issue is that the lack of a + default compiler function was raising :class:`.CompileError` and not + :class:`.UnsupportedCompilationError`. diff --git a/lib/sqlalchemy/exc.py b/lib/sqlalchemy/exc.py index b031c1610..08b1bb060 100644 --- a/lib/sqlalchemy/exc.py +++ b/lib/sqlalchemy/exc.py @@ -179,10 +179,10 @@ class UnsupportedCompilationError(CompileError): code = "l7de" - def __init__(self, compiler, element_type): + def __init__(self, compiler, element_type, message=None): super(UnsupportedCompilationError, self).__init__( - "Compiler %r can't render element of type %s" - % (compiler, element_type) + "Compiler %r can't render element of type %s%s" + % (compiler, element_type, ": %s" % message if message else "") ) diff --git a/lib/sqlalchemy/ext/compiler.py b/lib/sqlalchemy/ext/compiler.py index 5a31173ec..47fb6720b 100644 --- a/lib/sqlalchemy/ext/compiler.py +++ b/lib/sqlalchemy/ext/compiler.py @@ -425,9 +425,11 @@ def compiles(class_, *specs): return existing_dispatch(element, compiler, **kw) except exc.UnsupportedCompilationError as uce: util.raise_( - exc.CompileError( - "%s construct has no default " - "compilation handler." % type(element) + exc.UnsupportedCompilationError( + compiler, + type(element), + message="%s construct has no default " + "compilation handler." % type(element), ), from_=uce, ) @@ -476,9 +478,11 @@ class _dispatcher(object): fn = self.specs["default"] except KeyError as ke: util.raise_( - exc.CompileError( - "%s construct has no default " - "compilation handler." % type(element) + exc.UnsupportedCompilationError( + compiler, + type(element), + message="%s construct has no default " + "compilation handler." % type(element), ), replace_context=ke, ) diff --git a/test/ext/test_compiler.py b/test/ext/test_compiler.py index d011417d7..c10e27180 100644 --- a/test/ext/test_compiler.py +++ b/test/ext/test_compiler.py @@ -151,13 +151,33 @@ class UserDefinedTest(fixtures.TestBase, AssertsCompiledSQL): return "mythingy" assert_raises_message( - exc.CompileError, + exc.UnsupportedCompilationError, "<class 'test.ext.test_compiler..*MyThingy'> " "construct has no default compilation handler.", str, MyThingy(), ) + def test_no_default_proxy_generation(self): + class my_function(FunctionElement): + name = "my_function" + type = Numeric() + + @compiles(my_function, "sqlite") + def sqlite_my_function(element, compiler, **kw): + return "my_function(%s)" % compiler.process(element.clauses, **kw) + + t1 = table("t1", column("q")) + stmt = select(my_function(t1.c.q)) + + self.assert_compile( + stmt, + "SELECT my_function(t1.q) AS my_function_1 FROM t1", + dialect="sqlite", + ) + + eq_(stmt.selected_columns.keys(), [stmt._raw_columns[0].anon_label]) + def test_no_default_message(self): class MyThingy(ClauseElement): pass @@ -167,7 +187,8 @@ class UserDefinedTest(fixtures.TestBase, AssertsCompiledSQL): return "mythingy" assert_raises_message( - exc.CompileError, + exc.UnsupportedCompilationError, + "Compiler .*StrSQLCompiler.* can't .* " "<class 'test.ext.test_compiler..*MyThingy'> " "construct has no default compilation handler.", str, |
