summaryrefslogtreecommitdiff
path: root/lib/sqlalchemy/sql/default_comparator.py
diff options
context:
space:
mode:
authorMike Bayer <mike_mp@zzzcomputing.com>2014-12-04 18:29:56 -0500
committerMike Bayer <mike_mp@zzzcomputing.com>2014-12-04 18:29:56 -0500
commitf5ff86983f9cc7914a89b96da1fd2638677d345b (patch)
tree39490890539b0b65cf0d3daadd22c99d604bdd15 /lib/sqlalchemy/sql/default_comparator.py
parent87bfcf91e9659893f17adf307090bc0a4a8a8f23 (diff)
downloadsqlalchemy-f5ff86983f9cc7914a89b96da1fd2638677d345b.tar.gz
- The :meth:`.Operators.match` operator is now handled such that the
return type is not strictly assumed to be boolean; it now returns a :class:`.Boolean` subclass called :class:`.MatchType`. The type will still produce boolean behavior when used in Python expressions, however the dialect can override its behavior at result time. In the case of MySQL, while the MATCH operator is typically used in a boolean context within an expression, if one actually queries for the value of a match expression, a floating point value is returned; this value is not compatible with SQLAlchemy's C-based boolean processor, so MySQL's result-set behavior now follows that of the :class:`.Float` type. A new operator object ``notmatch_op`` is also added to better allow dialects to define the negation of a match operation. fixes #3263
Diffstat (limited to 'lib/sqlalchemy/sql/default_comparator.py')
-rw-r--r--lib/sqlalchemy/sql/default_comparator.py21
1 files changed, 16 insertions, 5 deletions
diff --git a/lib/sqlalchemy/sql/default_comparator.py b/lib/sqlalchemy/sql/default_comparator.py
index 4f53e2979..d26fdc455 100644
--- a/lib/sqlalchemy/sql/default_comparator.py
+++ b/lib/sqlalchemy/sql/default_comparator.py
@@ -68,8 +68,12 @@ class _DefaultColumnComparator(operators.ColumnOperators):
def _boolean_compare(self, expr, op, obj, negate=None, reverse=False,
_python_is_types=(util.NoneType, bool),
+ result_type = None,
**kwargs):
+ if result_type is None:
+ result_type = type_api.BOOLEANTYPE
+
if isinstance(obj, _python_is_types + (Null, True_, False_)):
# allow x ==/!= True/False to be treated as a literal.
@@ -80,7 +84,7 @@ class _DefaultColumnComparator(operators.ColumnOperators):
return BinaryExpression(expr,
_literal_as_text(obj),
op,
- type_=type_api.BOOLEANTYPE,
+ type_=result_type,
negate=negate, modifiers=kwargs)
else:
# all other None/True/False uses IS, IS NOT
@@ -103,13 +107,13 @@ class _DefaultColumnComparator(operators.ColumnOperators):
return BinaryExpression(obj,
expr,
op,
- type_=type_api.BOOLEANTYPE,
+ type_=result_type,
negate=negate, modifiers=kwargs)
else:
return BinaryExpression(expr,
obj,
op,
- type_=type_api.BOOLEANTYPE,
+ type_=result_type,
negate=negate, modifiers=kwargs)
def _binary_operate(self, expr, op, obj, reverse=False, result_type=None,
@@ -125,7 +129,8 @@ class _DefaultColumnComparator(operators.ColumnOperators):
op, result_type = left.comparator._adapt_expression(
op, right.comparator)
- return BinaryExpression(left, right, op, type_=result_type)
+ return BinaryExpression(
+ left, right, op, type_=result_type, modifiers=kw)
def _conjunction_operate(self, expr, op, other, **kw):
if op is operators.and_:
@@ -216,11 +221,16 @@ class _DefaultColumnComparator(operators.ColumnOperators):
def _match_impl(self, expr, op, other, **kw):
"""See :meth:`.ColumnOperators.match`."""
+
return self._boolean_compare(
expr, operators.match_op,
self._check_literal(
expr, operators.match_op, other),
- **kw)
+ result_type=type_api.MATCHTYPE,
+ negate=operators.notmatch_op
+ if op is operators.match_op else operators.match_op,
+ **kw
+ )
def _distinct_impl(self, expr, op, **kw):
"""See :meth:`.ColumnOperators.distinct`."""
@@ -282,6 +292,7 @@ class _DefaultColumnComparator(operators.ColumnOperators):
"isnot": (_boolean_compare, operators.isnot),
"collate": (_collate_impl,),
"match_op": (_match_impl,),
+ "notmatch_op": (_match_impl,),
"distinct_op": (_distinct_impl,),
"between_op": (_between_impl, ),
"notbetween_op": (_between_impl, ),