From: Mike Bayer Date: Tue, 18 Aug 2015 16:40:18 +0000 (-0400) Subject: - as the Concatenable mixin was changed to support calling down to X-Git-Tag: rel_1_1_0b1~84^2~70^2~138 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=3f8f1f16bd9e284afee910a6036fcb0958a6c0c2;p=thirdparty%2Fsqlalchemy%2Fsqlalchemy.git - as the Concatenable mixin was changed to support calling down to "super" instead of hardcoding to "self.type" for the default return value, the base Comparator was returning other_comparator.type. It's not clear what the rationale for this was, though in theory the base Comparator should possibly even throw an exception if the two types aren't the same (or of the same affinity?) . - mysql.SET was broken on this because the bitwise version adds "0" to the value to force an integer within column_expression, we are doing type_coerces here now in any case so that there is no type ambiguity for this operation --- diff --git a/lib/sqlalchemy/dialects/mysql/base.py b/lib/sqlalchemy/dialects/mysql/base.py index fee05fd2d5..4b3e5bcd16 100644 --- a/lib/sqlalchemy/dialects/mysql/base.py +++ b/lib/sqlalchemy/dialects/mysql/base.py @@ -1584,7 +1584,10 @@ class SET(_EnumeratedValues): def column_expression(self, colexpr): if self.retrieve_as_bitwise: - return colexpr + 0 + return sql.type_coerce( + sql.type_coerce(colexpr, sqltypes.Integer) + 0, + self + ) else: return colexpr diff --git a/lib/sqlalchemy/sql/type_api.py b/lib/sqlalchemy/sql/type_api.py index 701e2a44ad..c4e830b7f3 100644 --- a/lib/sqlalchemy/sql/type_api.py +++ b/lib/sqlalchemy/sql/type_api.py @@ -91,7 +91,7 @@ class TypeEngine(Visitable): boolean comparison or special SQL keywords like MATCH or BETWEEN. """ - return op, other_comparator.type + return op, self.type def __reduce__(self): return _reconstitute_comparator, (self.expr, ) diff --git a/test/sql/test_operators.py b/test/sql/test_operators.py index fbbdd7b623..f3dfd2daf6 100644 --- a/test/sql/test_operators.py +++ b/test/sql/test_operators.py @@ -14,7 +14,7 @@ from sqlalchemy.sql.elements import _literal_as_text from sqlalchemy.schema import Column, Table, MetaData from sqlalchemy.sql import compiler from sqlalchemy.types import TypeEngine, TypeDecorator, UserDefinedType, \ - Boolean, NullType, MatchType, Indexable + Boolean, NullType, MatchType, Indexable, Concatenable from sqlalchemy.dialects import mysql, firebird, postgresql, oracle, \ sqlite, mssql from sqlalchemy import util @@ -210,6 +210,60 @@ class DefaultColumnComparatorTest(fixtures.TestBase): def test_concat(self): self._do_operate_test(operators.concat_op) + def test_default_adapt(self): + class TypeOne(TypeEngine): + pass + + class TypeTwo(TypeEngine): + pass + + expr = column('x', TypeOne()) - column('y', TypeTwo()) + is_( + expr.type._type_affinity, TypeOne + ) + + def test_concatenable_adapt(self): + class TypeOne(Concatenable, TypeEngine): + pass + + class TypeTwo(Concatenable, TypeEngine): + pass + + class TypeThree(TypeEngine): + pass + + expr = column('x', TypeOne()) - column('y', TypeTwo()) + is_( + expr.type._type_affinity, TypeOne + ) + is_( + expr.operator, operator.sub + ) + + expr = column('x', TypeOne()) + column('y', TypeTwo()) + is_( + expr.type._type_affinity, TypeOne + ) + is_( + expr.operator, operators.concat_op + ) + + expr = column('x', TypeOne()) - column('y', TypeThree()) + is_( + expr.type._type_affinity, TypeOne + ) + is_( + expr.operator, operator.sub + ) + + expr = column('x', TypeOne()) + column('y', TypeThree()) + is_( + expr.type._type_affinity, TypeOne + ) + is_( + expr.operator, operator.add + ) + class CustomUnaryOperatorTest(fixtures.TestBase, testing.AssertsCompiledSQL): __dialect__ = 'default'