diff options
Diffstat (limited to 'lib/sqlalchemy/sql')
-rw-r--r-- | lib/sqlalchemy/sql/_elements_constructors.py | 17 | ||||
-rw-r--r-- | lib/sqlalchemy/sql/compiler.py | 7 | ||||
-rw-r--r-- | lib/sqlalchemy/sql/default_comparator.py | 16 | ||||
-rw-r--r-- | lib/sqlalchemy/sql/elements.py | 15 | ||||
-rw-r--r-- | lib/sqlalchemy/sql/expression.py | 1 | ||||
-rw-r--r-- | lib/sqlalchemy/sql/operators.py | 120 |
6 files changed, 176 insertions, 0 deletions
diff --git a/lib/sqlalchemy/sql/_elements_constructors.py b/lib/sqlalchemy/sql/_elements_constructors.py index 9b9632273..98f5a1cc6 100644 --- a/lib/sqlalchemy/sql/_elements_constructors.py +++ b/lib/sqlalchemy/sql/_elements_constructors.py @@ -1030,6 +1030,23 @@ def distinct(expr: _ColumnExpressionArgument[_T]) -> UnaryExpression[_T]: return UnaryExpression._create_distinct(expr) +def bitwise_not(expr: _ColumnExpressionArgument[_T]) -> UnaryExpression[_T]: + """Produce a unary bitwise NOT clause, typically via the ``~`` operator. + + Not to be confused with boolean negation :func:`_sql.not_`. + + .. versionadded:: 2.0.2 + + .. seealso:: + + :ref:`operators_bitwise` + + + """ + + return UnaryExpression._create_bitwise_not(expr) + + def extract(field: str, expr: _ColumnExpressionArgument[Any]) -> Extract: """Return a :class:`.Extract` construct. diff --git a/lib/sqlalchemy/sql/compiler.py b/lib/sqlalchemy/sql/compiler.py index d4ddc2e5d..bc463f9a1 100644 --- a/lib/sqlalchemy/sql/compiler.py +++ b/lib/sqlalchemy/sql/compiler.py @@ -279,6 +279,13 @@ OPERATORS = { operators.asc_op: " ASC", operators.nulls_first_op: " NULLS FIRST", operators.nulls_last_op: " NULLS LAST", + # bitwise + operators.bitwise_xor_op: " ^ ", + operators.bitwise_or_op: " | ", + operators.bitwise_and_op: " & ", + operators.bitwise_not_op: "~", + operators.bitwise_lshift_op: " << ", + operators.bitwise_rshift_op: " >> ", } FUNCTIONS: Dict[Type[Function[Any]], str] = { diff --git a/lib/sqlalchemy/sql/default_comparator.py b/lib/sqlalchemy/sql/default_comparator.py index 19b5291c4..57460b036 100644 --- a/lib/sqlalchemy/sql/default_comparator.py +++ b/lib/sqlalchemy/sql/default_comparator.py @@ -273,6 +273,16 @@ def _neg_impl( return UnaryExpression(expr, operator=operators.neg, type_=expr.type) +def _bitwise_not_impl( + expr: ColumnElement[Any], op: OperatorType, **kw: Any +) -> ColumnElement[Any]: + """See :meth:`.ColumnOperators.bitwise_not`.""" + + return UnaryExpression( + expr, operator=operators.bitwise_not_op, type_=expr.type + ) + + def _match_impl( expr: ColumnElement[Any], op: OperatorType, other: Any, **kw: Any ) -> ColumnElement[Any]: @@ -420,6 +430,12 @@ operator_lookup: Dict[ "sub": (_binary_operate, util.EMPTY_DICT), "div": (_binary_operate, util.EMPTY_DICT), "mod": (_binary_operate, util.EMPTY_DICT), + "bitwise_xor_op": (_binary_operate, util.EMPTY_DICT), + "bitwise_or_op": (_binary_operate, util.EMPTY_DICT), + "bitwise_and_op": (_binary_operate, util.EMPTY_DICT), + "bitwise_not_op": (_bitwise_not_impl, util.EMPTY_DICT), + "bitwise_lshift_op": (_binary_operate, util.EMPTY_DICT), + "bitwise_rshift_op": (_binary_operate, util.EMPTY_DICT), "truediv": (_binary_operate, util.EMPTY_DICT), "floordiv": (_binary_operate, util.EMPTY_DICT), "custom_op": (_custom_op_operate, util.EMPTY_DICT), diff --git a/lib/sqlalchemy/sql/elements.py b/lib/sqlalchemy/sql/elements.py index c3f7b884c..70c65b5a1 100644 --- a/lib/sqlalchemy/sql/elements.py +++ b/lib/sqlalchemy/sql/elements.py @@ -3587,6 +3587,21 @@ class UnaryExpression(ColumnElement[_T]): wraps_column_expression=False, ) + @classmethod + def _create_bitwise_not( + cls, + expr: _ColumnExpressionArgument[_T], + ) -> UnaryExpression[_T]: + col_expr: ColumnElement[_T] = coercions.expect( + roles.ExpressionElementRole, expr + ) + return UnaryExpression( + col_expr, + operator=operators.bitwise_not_op, + type_=col_expr.type, + wraps_column_expression=False, + ) + @property def _order_by_label_element(self) -> Optional[Label[Any]]: if self.modifier in (operators.desc_op, operators.asc_op): diff --git a/lib/sqlalchemy/sql/expression.py b/lib/sqlalchemy/sql/expression.py index 3f5c76a50..7076cd10d 100644 --- a/lib/sqlalchemy/sql/expression.py +++ b/lib/sqlalchemy/sql/expression.py @@ -22,6 +22,7 @@ from ._elements_constructors import any_ as any_ from ._elements_constructors import asc as asc from ._elements_constructors import between as between from ._elements_constructors import bindparam as bindparam +from ._elements_constructors import bitwise_not as bitwise_not from ._elements_constructors import case as case from ._elements_constructors import cast as cast from ._elements_constructors import collate as collate diff --git a/lib/sqlalchemy/sql/operators.py b/lib/sqlalchemy/sql/operators.py index 567802916..c973126ca 100644 --- a/lib/sqlalchemy/sql/operators.py +++ b/lib/sqlalchemy/sql/operators.py @@ -697,6 +697,90 @@ class ColumnOperators(Operators): """ return self.operate(ilike_op, other, escape=escape) + def bitwise_xor(self, other: Any) -> ColumnOperators: + """Produce a bitwise XOR operation, typically via the ``^`` + operator, or ``#`` for PostgreSQL. + + .. versionadded:: 2.0.2 + + .. seealso:: + + :ref:`operators_bitwise` + + """ + + return self.operate(bitwise_xor_op, other) + + def bitwise_or(self, other: Any) -> ColumnOperators: + """Produce a bitwise OR operation, typically via the ``|`` + operator. + + .. versionadded:: 2.0.2 + + .. seealso:: + + :ref:`operators_bitwise` + + """ + + return self.operate(bitwise_or_op, other) + + def bitwise_and(self, other: Any) -> ColumnOperators: + """Produce a bitwise AND operation, typically via the ``&`` + operator. + + .. versionadded:: 2.0.2 + + .. seealso:: + + :ref:`operators_bitwise` + + """ + + return self.operate(bitwise_and_op, other) + + def bitwise_not(self) -> ColumnOperators: + """Produce a bitwise NOT operation, typically via the ``~`` + operator. + + .. versionadded:: 2.0.2 + + .. seealso:: + + :ref:`operators_bitwise` + + """ + + return self.operate(bitwise_not_op) + + def bitwise_lshift(self, other: Any) -> ColumnOperators: + """Produce a bitwise LSHIFT operation, typically via the ``<<`` + operator. + + .. versionadded:: 2.0.2 + + .. seealso:: + + :ref:`operators_bitwise` + + """ + + return self.operate(bitwise_lshift_op, other) + + def bitwise_rshift(self, other: Any) -> ColumnOperators: + """Produce a bitwise RSHIFT operation, typically via the ``>>`` + operator. + + .. versionadded:: 2.0.2 + + .. seealso:: + + :ref:`operators_bitwise` + + """ + + return self.operate(bitwise_rshift_op, other) + def in_(self, other: Any) -> ColumnOperators: """Implement the ``in`` operator. @@ -2266,6 +2350,36 @@ def json_path_getitem_op(a: Any, b: Any) -> Any: raise NotImplementedError() +@_operator_fn +def bitwise_xor_op(a: Any, b: Any) -> Any: + return a.bitwise_xor(b) + + +@_operator_fn +def bitwise_or_op(a: Any, b: Any) -> Any: + return a.bitwise_or(b) + + +@_operator_fn +def bitwise_and_op(a: Any, b: Any) -> Any: + return a.bitwise_and(b) + + +@_operator_fn +def bitwise_not_op(a: Any) -> Any: + return a.bitwise_not() + + +@_operator_fn +def bitwise_lshift_op(a: Any, b: Any) -> Any: + return a.bitwise_lshift(b) + + +@_operator_fn +def bitwise_rshift_op(a: Any, b: Any) -> Any: + return a.bitwise_rshift(b) + + def is_comparison(op: OperatorType) -> bool: return op in _comparison or isinstance(op, custom_op) and op.is_comparison @@ -2344,8 +2458,14 @@ _PRECEDENCE: Dict[OperatorType, int] = { floordiv: 8, mod: 8, neg: 8, + bitwise_not_op: 8, add: 7, sub: 7, + bitwise_xor_op: 7, + bitwise_or_op: 7, + bitwise_and_op: 7, + bitwise_lshift_op: 7, + bitwise_rshift_op: 7, concat_op: 6, filter_op: 6, match_op: 5, |