]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
- Fixed potential issue where a custom subclass
authorMike Bayer <mike_mp@zzzcomputing.com>
Sun, 19 Jul 2015 14:00:13 +0000 (10:00 -0400)
committerMike Bayer <mike_mp@zzzcomputing.com>
Sun, 19 Jul 2015 14:00:13 +0000 (10:00 -0400)
of :class:`.FunctionElement` or other column element that incorrectly
states 'None' or any other invalid object as the ``.type``
attribute will report this exception instead of recursion overflow.
fixes #3485

doc/build/changelog/changelog_10.rst
lib/sqlalchemy/sql/elements.py
test/sql/test_functions.py

index 48626a52535ea7869fbe023bcd6ed5f6d7bd3300..c4d9ab44807a06e7a5567c3bd86f11a97f9137bb 100644 (file)
 .. changelog::
     :version: 1.0.7
 
+    .. change::
+        :tags: bug, sql
+        :tickets: 3485
+
+        Fixed potential issue where a custom subclass
+        of :class:`.FunctionElement` or other column element that incorrectly
+        states 'None' or any other invalid object as the ``.type``
+        attribute will report this exception instead of recursion overflow.
+
     .. change::
         :tags: bug, sql
         :pullreq: github:188
index 27ecce2b0b39bd44297463180586057890367b94..41dfcf147891ee124f7f0e8cf664f1041b5b5f4e 100644 (file)
@@ -715,7 +715,14 @@ class ColumnElement(operators.ColumnOperators, ClauseElement):
 
     @util.memoized_property
     def comparator(self):
-        return self.type.comparator_factory(self)
+        try:
+            comparator_factory = self.type.comparator_factory
+        except AttributeError:
+            raise TypeError(
+                "Object %r associated with '.type' attribute "
+                "is not a TypeEngine class or object" % self.type)
+        else:
+            return comparator_factory(self)
 
     def __getattr__(self, key):
         try:
index ec8d9b5c0d4f77cf930b6c63284bdec346139816..ccc9b2dcdb2d6eba854c4df41365402410cf713e 100644 (file)
@@ -9,12 +9,12 @@ from sqlalchemy.sql.compiler import BIND_TEMPLATES
 from sqlalchemy.testing.engines import all_dialects
 from sqlalchemy import types as sqltypes
 from sqlalchemy.sql import functions
-from sqlalchemy.sql.functions import GenericFunction
+from sqlalchemy.sql.functions import GenericFunction, FunctionElement
 import decimal
 from sqlalchemy import testing
 from sqlalchemy.testing import fixtures, AssertsCompiledSQL, engines
 from sqlalchemy.dialects import sqlite, postgresql, mysql, oracle
-
+from sqlalchemy.testing import assert_raises_message
 
 table1 = table('mytable',
                column('myid', Integer),
@@ -477,6 +477,18 @@ class CompileTest(fixtures.TestBase, AssertsCompiledSQL):
             "AS anon_1 FROM mytable"
         )
 
+    def test_incorrect_none_type(self):
+        class MissingType(FunctionElement):
+            name = 'mt'
+            type = None
+
+        assert_raises_message(
+            TypeError,
+            "Object None associated with '.type' attribute is "
+            "not a TypeEngine class or object",
+            MissingType().compile
+        )
+
 
 class ExecuteTest(fixtures.TestBase):