summaryrefslogtreecommitdiff
path: root/lib/sqlalchemy/sql/default_comparator.py
diff options
context:
space:
mode:
Diffstat (limited to 'lib/sqlalchemy/sql/default_comparator.py')
-rw-r--r--lib/sqlalchemy/sql/default_comparator.py234
1 files changed, 135 insertions, 99 deletions
diff --git a/lib/sqlalchemy/sql/default_comparator.py b/lib/sqlalchemy/sql/default_comparator.py
index 8149f9731..fa0052198 100644
--- a/lib/sqlalchemy/sql/default_comparator.py
+++ b/lib/sqlalchemy/sql/default_comparator.py
@@ -11,19 +11,43 @@
from .. import exc, util
from . import type_api
from . import operators
-from .elements import BindParameter, True_, False_, BinaryExpression, \
- Null, _const_expr, _clause_element_as_expr, \
- ClauseList, ColumnElement, TextClause, UnaryExpression, \
- collate, _is_literal, _literal_as_text, ClauseElement, and_, or_, \
- Slice, Visitable, _literal_as_binds, CollectionAggregate, \
- Tuple
+from .elements import (
+ BindParameter,
+ True_,
+ False_,
+ BinaryExpression,
+ Null,
+ _const_expr,
+ _clause_element_as_expr,
+ ClauseList,
+ ColumnElement,
+ TextClause,
+ UnaryExpression,
+ collate,
+ _is_literal,
+ _literal_as_text,
+ ClauseElement,
+ and_,
+ or_,
+ Slice,
+ Visitable,
+ _literal_as_binds,
+ CollectionAggregate,
+ Tuple,
+)
from .selectable import SelectBase, Alias, Selectable, ScalarSelect
-def _boolean_compare(expr, op, obj, negate=None, reverse=False,
- _python_is_types=(util.NoneType, bool),
- result_type = None,
- **kwargs):
+def _boolean_compare(
+ 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
@@ -33,57 +57,64 @@ def _boolean_compare(expr, op, obj, negate=None, reverse=False,
# allow x ==/!= True/False to be treated as a literal.
# this comes out to "== / != true/false" or "1/0" if those
# constants aren't supported and works on all platforms
- if op in (operators.eq, operators.ne) and \
- isinstance(obj, (bool, True_, False_)):
- return BinaryExpression(expr,
- _literal_as_text(obj),
- op,
- type_=result_type,
- negate=negate, modifiers=kwargs)
+ if op in (operators.eq, operators.ne) and isinstance(
+ obj, (bool, True_, False_)
+ ):
+ return BinaryExpression(
+ expr,
+ _literal_as_text(obj),
+ op,
+ type_=result_type,
+ negate=negate,
+ modifiers=kwargs,
+ )
elif op in (operators.is_distinct_from, operators.isnot_distinct_from):
- return BinaryExpression(expr,
- _literal_as_text(obj),
- op,
- type_=result_type,
- negate=negate, modifiers=kwargs)
+ return BinaryExpression(
+ expr,
+ _literal_as_text(obj),
+ op,
+ type_=result_type,
+ negate=negate,
+ modifiers=kwargs,
+ )
else:
# all other None/True/False uses IS, IS NOT
if op in (operators.eq, operators.is_):
- return BinaryExpression(expr, _const_expr(obj),
- operators.is_,
- negate=operators.isnot,
- type_=result_type
- )
+ return BinaryExpression(
+ expr,
+ _const_expr(obj),
+ operators.is_,
+ negate=operators.isnot,
+ type_=result_type,
+ )
elif op in (operators.ne, operators.isnot):
- return BinaryExpression(expr, _const_expr(obj),
- operators.isnot,
- negate=operators.is_,
- type_=result_type
- )
+ return BinaryExpression(
+ expr,
+ _const_expr(obj),
+ operators.isnot,
+ negate=operators.is_,
+ type_=result_type,
+ )
else:
raise exc.ArgumentError(
"Only '=', '!=', 'is_()', 'isnot()', "
"'is_distinct_from()', 'isnot_distinct_from()' "
- "operators can be used with None/True/False")
+ "operators can be used with None/True/False"
+ )
else:
obj = _check_literal(expr, op, obj)
if reverse:
- return BinaryExpression(obj,
- expr,
- op,
- type_=result_type,
- negate=negate, modifiers=kwargs)
+ return BinaryExpression(
+ obj, expr, op, type_=result_type, negate=negate, modifiers=kwargs
+ )
else:
- return BinaryExpression(expr,
- obj,
- op,
- type_=result_type,
- negate=negate, modifiers=kwargs)
+ return BinaryExpression(
+ expr, obj, op, type_=result_type, negate=negate, modifiers=kwargs
+ )
-def _custom_op_operate(expr, op, obj, reverse=False, result_type=None,
- **kw):
+def _custom_op_operate(expr, op, obj, reverse=False, result_type=None, **kw):
if result_type is None:
if op.return_type:
result_type = op.return_type
@@ -91,11 +122,11 @@ def _custom_op_operate(expr, op, obj, reverse=False, result_type=None,
result_type = type_api.BOOLEANTYPE
return _binary_operate(
- expr, op, obj, reverse=reverse, result_type=result_type, **kw)
+ expr, op, obj, reverse=reverse, result_type=result_type, **kw
+ )
-def _binary_operate(expr, op, obj, reverse=False, result_type=None,
- **kw):
+def _binary_operate(expr, op, obj, reverse=False, result_type=None, **kw):
obj = _check_literal(expr, op, obj)
if reverse:
@@ -105,10 +136,10 @@ def _binary_operate(expr, op, obj, reverse=False, result_type=None,
if result_type is None:
op, result_type = left.comparator._adapt_expression(
- op, right.comparator)
+ op, right.comparator
+ )
- return BinaryExpression(
- left, right, op, type_=result_type, modifiers=kw)
+ return BinaryExpression(left, right, op, type_=result_type, modifiers=kw)
def _conjunction_operate(expr, op, other, **kw):
@@ -128,8 +159,7 @@ def _in_impl(expr, op, seq_or_selectable, negate_op, **kw):
seq_or_selectable = _clause_element_as_expr(seq_or_selectable)
if isinstance(seq_or_selectable, ScalarSelect):
- return _boolean_compare(expr, op, seq_or_selectable,
- negate=negate_op)
+ return _boolean_compare(expr, op, seq_or_selectable, negate=negate_op)
elif isinstance(seq_or_selectable, SelectBase):
# TODO: if we ever want to support (x, y, z) IN (select x,
@@ -138,32 +168,33 @@ def _in_impl(expr, op, seq_or_selectable, negate_op, **kw):
# does not export itself as a FROM clause
return _boolean_compare(
- expr, op, seq_or_selectable.as_scalar(),
- negate=negate_op, **kw)
+ expr, op, seq_or_selectable.as_scalar(), negate=negate_op, **kw
+ )
elif isinstance(seq_or_selectable, (Selectable, TextClause)):
- return _boolean_compare(expr, op, seq_or_selectable,
- negate=negate_op, **kw)
+ return _boolean_compare(
+ expr, op, seq_or_selectable, negate=negate_op, **kw
+ )
elif isinstance(seq_or_selectable, ClauseElement):
- if isinstance(seq_or_selectable, BindParameter) and \
- seq_or_selectable.expanding:
+ if (
+ isinstance(seq_or_selectable, BindParameter)
+ and seq_or_selectable.expanding
+ ):
if isinstance(expr, Tuple):
- seq_or_selectable = (
- seq_or_selectable._with_expanding_in_types(
- [elem.type for elem in expr]
- )
+ seq_or_selectable = seq_or_selectable._with_expanding_in_types(
+ [elem.type for elem in expr]
)
return _boolean_compare(
- expr, op,
- seq_or_selectable,
- negate=negate_op)
+ expr, op, seq_or_selectable, negate=negate_op
+ )
else:
raise exc.InvalidRequestError(
- 'in_() accepts'
- ' either a list of expressions, '
+ "in_() accepts"
+ " either a list of expressions, "
'a selectable, or an "expanding" bound parameter: %r'
- % seq_or_selectable)
+ % seq_or_selectable
+ )
# Handle non selectable arguments as sequences
args = []
@@ -171,9 +202,10 @@ def _in_impl(expr, op, seq_or_selectable, negate_op, **kw):
if not _is_literal(o):
if not isinstance(o, operators.ColumnOperators):
raise exc.InvalidRequestError(
- 'in_() accepts'
- ' either a list of expressions, '
- 'a selectable, or an "expanding" bound parameter: %r' % o)
+ "in_() accepts"
+ " either a list of expressions, "
+ 'a selectable, or an "expanding" bound parameter: %r' % o
+ )
elif o is None:
o = Null()
else:
@@ -182,15 +214,14 @@ def _in_impl(expr, op, seq_or_selectable, negate_op, **kw):
if len(args) == 0:
op, negate_op = (
- operators.empty_in_op,
- operators.empty_notin_op) if op is operators.in_op \
- else (
- operators.empty_notin_op,
- operators.empty_in_op)
+ (operators.empty_in_op, operators.empty_notin_op)
+ if op is operators.in_op
+ else (operators.empty_notin_op, operators.empty_in_op)
+ )
- return _boolean_compare(expr, op,
- ClauseList(*args).self_group(against=op),
- negate=negate_op)
+ return _boolean_compare(
+ expr, op, ClauseList(*args).self_group(against=op), negate=negate_op
+ )
def _getitem_impl(expr, op, other, **kw):
@@ -202,13 +233,14 @@ def _getitem_impl(expr, op, other, **kw):
def _unsupported_impl(expr, op, *arg, **kw):
- raise NotImplementedError("Operator '%s' is not supported on "
- "this expression" % op.__name__)
+ raise NotImplementedError(
+ "Operator '%s' is not supported on " "this expression" % op.__name__
+ )
def _inv_impl(expr, op, **kw):
"""See :meth:`.ColumnOperators.__inv__`."""
- if hasattr(expr, 'negation_clause'):
+ if hasattr(expr, "negation_clause"):
return expr.negation_clause
else:
return expr._negate()
@@ -223,20 +255,22 @@ def _match_impl(expr, op, other, **kw):
"""See :meth:`.ColumnOperators.match`."""
return _boolean_compare(
- expr, operators.match_op,
- _check_literal(
- expr, operators.match_op, other),
+ expr,
+ operators.match_op,
+ _check_literal(expr, operators.match_op, other),
result_type=type_api.MATCHTYPE,
negate=operators.notmatch_op
- if op is operators.match_op else operators.match_op,
+ if op is operators.match_op
+ else operators.match_op,
**kw
)
def _distinct_impl(expr, op, **kw):
"""See :meth:`.ColumnOperators.distinct`."""
- return UnaryExpression(expr, operator=operators.distinct_op,
- type_=expr.type)
+ return UnaryExpression(
+ expr, operator=operators.distinct_op, type_=expr.type
+ )
def _between_impl(expr, op, cleft, cright, **kw):
@@ -247,17 +281,21 @@ def _between_impl(expr, op, cleft, cright, **kw):
_check_literal(expr, operators.and_, cleft),
_check_literal(expr, operators.and_, cright),
operator=operators.and_,
- group=False, group_contents=False),
+ group=False,
+ group_contents=False,
+ ),
op,
negate=operators.notbetween_op
if op is operators.between_op
else operators.between_op,
- modifiers=kw)
+ modifiers=kw,
+ )
def _collate_impl(expr, op, other, **kw):
return collate(expr, other)
+
# a mapping of operators with the method they use, along with
# their negated operator for comparison operators
operator_lookup = {
@@ -271,8 +309,8 @@ operator_lookup = {
"mod": (_binary_operate,),
"truediv": (_binary_operate,),
"custom_op": (_custom_op_operate,),
- "json_path_getitem_op": (_binary_operate, ),
- "json_getitem_op": (_binary_operate, ),
+ "json_path_getitem_op": (_binary_operate,),
+ "json_getitem_op": (_binary_operate,),
"concat_op": (_binary_operate,),
"any_op": (_scalar, CollectionAggregate._create_any),
"all_op": (_scalar, CollectionAggregate._create_all),
@@ -303,8 +341,8 @@ operator_lookup = {
"match_op": (_match_impl,),
"notmatch_op": (_match_impl,),
"distinct_op": (_distinct_impl,),
- "between_op": (_between_impl, ),
- "notbetween_op": (_between_impl, ),
+ "between_op": (_between_impl,),
+ "notbetween_op": (_between_impl,),
"neg": (_neg_impl,),
"getitem": (_getitem_impl,),
"lshift": (_unsupported_impl,),
@@ -315,12 +353,11 @@ operator_lookup = {
def _check_literal(expr, operator, other, bindparam_type=None):
if isinstance(other, (ColumnElement, TextClause)):
- if isinstance(other, BindParameter) and \
- other.type._isnull:
+ if isinstance(other, BindParameter) and other.type._isnull:
other = other._clone()
other.type = expr.type
return other
- elif hasattr(other, '__clause_element__'):
+ elif hasattr(other, "__clause_element__"):
other = other.__clause_element__()
elif isinstance(other, type_api.TypeEngine.Comparator):
other = other.expr
@@ -331,4 +368,3 @@ def _check_literal(expr, operator, other, bindparam_type=None):
return expr._bind_param(operator, other, type_=bindparam_type)
else:
return other
-