]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
PoC dedicated default and psql bitwise xor + tests
authorGleb Kisenkov <g.kisenkov@gmail.com>
Mon, 9 Jan 2023 11:47:52 +0000 (12:47 +0100)
committerGleb Kisenkov <g.kisenkov@gmail.com>
Mon, 9 Jan 2023 11:47:52 +0000 (12:47 +0100)
lib/sqlalchemy/dialects/postgresql/base.py
lib/sqlalchemy/sql/compiler.py
lib/sqlalchemy/sql/default_comparator.py
lib/sqlalchemy/sql/operators.py
test/dialect/postgresql/test_compiler.py
test/sql/test_operators.py

index f3e98caa0011d94fbdb50be54c7b18d90ac53341..2636ae6962285d2a18a3fcda5ad2849ae480be32 100644 (file)
@@ -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
     ):
index 2c50081fbf8d199c484d1da05b484e62426e0674..755a8413740e3a023e5b9aec216025f7e04aae58 100644 (file)
@@ -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] = {
index 19b5291c4f2b20a6a37f894011cd9259ad162185..ff04c6c940a8a8ebefd47785e9cb365236ff0868 100644 (file)
@@ -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),
index dc88b3e4968c745363993f02e77c0872cf9841d0..eb1d9ef8a74aefc80bb48d3bce4be8153957b69f 100644 (file)
@@ -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,
index 57b147c90d9f309234c46b7500b4075b7f513a53..9984eb764843a0678e555a5a27f4912fb0c3a872 100644 (file)
@@ -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()
index 103520f1faa98a7007f9c43695e3c3ae778cfc40..2bf08e6a4bc38802d830a2368cf444fcabd87dd6 100644 (file)
@@ -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",
+        )