]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
Added and + or bitwise operators + simple precedence test
authorGleb Kisenkov <g.kisenkov@gmail.com>
Mon, 9 Jan 2023 18:48:01 +0000 (19:48 +0100)
committerGleb Kisenkov <g.kisenkov@gmail.com>
Mon, 9 Jan 2023 18:48:01 +0000 (19:48 +0100)
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 755a8413740e3a023e5b9aec216025f7e04aae58..8beca2f3c5a4a0cfd871c8a6e10a7f20c9732153 100644 (file)
@@ -281,6 +281,8 @@ OPERATORS = {
     operators.nulls_last_op: " NULLS LAST",
     # bitwise
     operators.bitwise_xor_op: " ^ ",
+    operators.bitwise_or_op: " | ",
+    operators.bitwise_and_op: " & ",
 }
 
 FUNCTIONS: Dict[Type[Function[Any]], str] = {
index ff04c6c940a8a8ebefd47785e9cb365236ff0868..01ca6fb97db7173a4c9bebb145a7678da64ff58e 100644 (file)
@@ -421,6 +421,8 @@ operator_lookup: 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),
     "truediv": (_binary_operate, util.EMPTY_DICT),
     "floordiv": (_binary_operate, util.EMPTY_DICT),
     "custom_op": (_custom_op_operate, util.EMPTY_DICT),
index eb1d9ef8a74aefc80bb48d3bce4be8153957b69f..2bc209eaf6691b681c04a2575113e3356920c75b 100644 (file)
@@ -695,6 +695,16 @@ class ColumnOperators(Operators):
 
         return self.operate(bitwise_xor_op, other)
 
+    def bitwise_or(self, other):
+        """Return bitwise OR operation"""
+
+        return self.operate(bitwise_or_op, other)
+
+    def bitwise_and(self, other):
+        """Return bitwise AND operation"""
+
+        return self.operate(bitwise_and_op, other)
+
     def in_(self, other: Any) -> ColumnOperators:
         """Implement the ``in`` operator.
 
@@ -2125,6 +2135,16 @@ 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)
+
+
 def is_comparison(op: OperatorType) -> bool:
     return op in _comparison or isinstance(op, custom_op) and op.is_comparison
 
@@ -2205,6 +2225,9 @@ _PRECEDENCE: Dict[OperatorType, int] = {
     neg: 8,
     add: 7,
     sub: 7,
+    bitwise_xor_op: 7,
+    bitwise_or_op: 7,
+    bitwise_and_op: 7,
     concat_op: 6,
     filter_op: 6,
     match_op: 5,
@@ -2236,7 +2259,6 @@ _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 9984eb764843a0678e555a5a27f4912fb0c3a872..080cfb767d54c3e19e616c803bd3d5a3abbc6889 100644 (file)
@@ -2424,7 +2424,7 @@ class CompileTest(fixtures.TestBase, AssertsCompiledSQL):
             "WHERE usages.date <@ %(date_1)s::DATERANGE",
         )
 
-    def test_dedicated_bit_xor(self):
+    def test_bitwise_xor(self):
         c1 = column("c1", Integer)
         c2 = column("c2", Integer)
         self.assert_compile(
index 2bf08e6a4bc38802d830a2368cf444fcabd87dd6..ce71eba704bb3ad6a930eba56d500dd0fef2204d 100644 (file)
@@ -1768,6 +1768,14 @@ class OperatorPrecedenceTest(fixtures.TestBase, testing.AssertsCompiledSQL):
         self.assert_compile(op2, "mytable.myid hoho :myid_1 lala :param_1")
         self.assert_compile(op3, "(mytable.myid hoho :myid_1) lala :param_1")
 
+    def test_bitwise_xor_precedence(self):
+        op1 = self.table1.c.myid.bitwise_xor
+        op2 = op1(5).op("lala", precedence=6)(4)
+        op3 = op1(5).op("lala", precedence=8)(4)
+
+        self.assert_compile(op2, "mytable.myid ^ :myid_1 lala :param_1")
+        self.assert_compile(op3, "(mytable.myid ^ :myid_1) lala :param_1")
+
     def test_is_eq_precedence_flat(self):
         self.assert_compile(
             (self.table1.c.name == null())
@@ -4510,18 +4518,26 @@ class AnyAllTest(fixtures.TestBase, testing.AssertsCompiledSQL):
 
 
 class BitOpTest(fixtures.TestBase, testing.AssertsCompiledSQL):
-    def test_generic_bit_xor(self):
+    def test_bitwise_xor(self):
         c1 = column("c1", Integer)
         c2 = column("c2", Integer)
         self.assert_compile(
-            select(c1.op("^")(c2)),
+            select(c1.bitwise_xor(c2)),
             "SELECT c1 ^ c2 AS anon_1",
         )
 
-    def test_dedicated_bit_xor(self):
+    def test_bitwise_or(self):
         c1 = column("c1", Integer)
         c2 = column("c2", Integer)
         self.assert_compile(
-            select(c1.bitwise_xor(c2)),
-            "SELECT c1 ^ c2 AS anon_1",
+            select(c1.bitwise_or(c2)),
+            "SELECT c1 | c2 AS anon_1",
+        )
+
+    def test_bitwise_and(self):
+        c1 = column("c1", Integer)
+        c2 = column("c2", Integer)
+        self.assert_compile(
+            select(c1.bitwise_and(c2)),
+            "SELECT c1 & c2 AS anon_1",
         )