From: Gleb Kisenkov Date: Mon, 9 Jan 2023 11:47:52 +0000 (+0100) Subject: PoC dedicated default and psql bitwise xor + tests X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=38c80578dbd9c1db86b06cab424fbc4cacaacbe9;p=thirdparty%2Fsqlalchemy%2Fsqlalchemy.git PoC dedicated default and psql bitwise xor + tests --- diff --git a/lib/sqlalchemy/dialects/postgresql/base.py b/lib/sqlalchemy/dialects/postgresql/base.py index f3e98caa00..2636ae6962 100644 --- a/lib/sqlalchemy/dialects/postgresql/base.py +++ b/lib/sqlalchemy/dialects/postgresql/base.py @@ -1713,6 +1713,9 @@ class PGCompiler(compiler.SQLCompiler): self.process(element.stop, **kw), ) + def visit_bitwise_xor_op_binary(self, binary, operator, **kw): + return self._generate_generic_binary(binary, " # ", **kw) + def visit_json_getitem_op_binary( self, binary, operator, _cast_applied=False, **kw ): diff --git a/lib/sqlalchemy/sql/compiler.py b/lib/sqlalchemy/sql/compiler.py index 2c50081fbf..755a841374 100644 --- a/lib/sqlalchemy/sql/compiler.py +++ b/lib/sqlalchemy/sql/compiler.py @@ -279,6 +279,8 @@ OPERATORS = { operators.asc_op: " ASC", operators.nulls_first_op: " NULLS FIRST", operators.nulls_last_op: " NULLS LAST", + # bitwise + operators.bitwise_xor_op: " ^ ", } FUNCTIONS: Dict[Type[Function[Any]], str] = { diff --git a/lib/sqlalchemy/sql/default_comparator.py b/lib/sqlalchemy/sql/default_comparator.py index 19b5291c4f..ff04c6c940 100644 --- a/lib/sqlalchemy/sql/default_comparator.py +++ b/lib/sqlalchemy/sql/default_comparator.py @@ -420,6 +420,7 @@ 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), "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/operators.py b/lib/sqlalchemy/sql/operators.py index dc88b3e496..eb1d9ef8a7 100644 --- a/lib/sqlalchemy/sql/operators.py +++ b/lib/sqlalchemy/sql/operators.py @@ -690,6 +690,11 @@ class ColumnOperators(Operators): """ return self.operate(ilike_op, other, escape=escape) + def bitwise_xor(self, other): + """Return bitwise XOR operation""" + + return self.operate(bitwise_xor_op, other) + def in_(self, other: Any) -> ColumnOperators: """Implement the ``in`` operator. @@ -2115,6 +2120,11 @@ 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) + + def is_comparison(op: OperatorType) -> bool: return op in _comparison or isinstance(op, custom_op) and op.is_comparison @@ -2226,6 +2236,7 @@ _PRECEDENCE: Dict[OperatorType, int] = { is_false: 5, and_: 3, or_: 2, + bitwise_xor_op: 1, # just guessing comma_op: -1, desc_op: 3, asc_op: 3, diff --git a/test/dialect/postgresql/test_compiler.py b/test/dialect/postgresql/test_compiler.py index 57b147c90d..9984eb7648 100644 --- a/test/dialect/postgresql/test_compiler.py +++ b/test/dialect/postgresql/test_compiler.py @@ -2424,6 +2424,14 @@ class CompileTest(fixtures.TestBase, AssertsCompiledSQL): "WHERE usages.date <@ %(date_1)s::DATERANGE", ) + def test_dedicated_bit_xor(self): + c1 = column("c1", Integer) + c2 = column("c2", Integer) + self.assert_compile( + select(c1.bitwise_xor(c2)), + "SELECT c1 # c2 AS anon_1", + ) + class InsertOnConflictTest(fixtures.TablesTest, AssertsCompiledSQL): __dialect__ = postgresql.dialect() diff --git a/test/sql/test_operators.py b/test/sql/test_operators.py index 103520f1fa..2bf08e6a4b 100644 --- a/test/sql/test_operators.py +++ b/test/sql/test_operators.py @@ -4507,3 +4507,21 @@ class AnyAllTest(fixtures.TestBase, testing.AssertsCompiledSQL): r"use the .scalar_values\(\) method.", ): fn(values(t.c.data).data([(1,), (42,)])) + + +class BitOpTest(fixtures.TestBase, testing.AssertsCompiledSQL): + def test_generic_bit_xor(self): + c1 = column("c1", Integer) + c2 = column("c2", Integer) + self.assert_compile( + select(c1.op("^")(c2)), + "SELECT c1 ^ c2 AS anon_1", + ) + + def test_dedicated_bit_xor(self): + c1 = column("c1", Integer) + c2 = column("c2", Integer) + self.assert_compile( + select(c1.bitwise_xor(c2)), + "SELECT c1 ^ c2 AS anon_1", + )