diff --git a/pypika/terms.py b/pypika/terms.py index a277e1a5..0d523d10 100644 --- a/pypika/terms.py +++ b/pypika/terms.py @@ -147,6 +147,9 @@ def isnotnull(self) -> 'NotNullCriterion': def bitwiseand(self, value: int) -> "BitwiseAndCriterion": return BitwiseAndCriterion(self, self.wrap_constant(value)) + def bitwiseor(self, value: int) -> "BitwiseOrCriterion": + return BitwiseOrCriterion(self, self.wrap_constant(value)) + def gt(self, other: Any) -> "BasicCriterion": return self > other @@ -1045,6 +1048,39 @@ def get_sql(self, **kwargs: Any) -> str: return format_alias_sql(sql, self.alias, **kwargs) +class BitwiseOrCriterion(Criterion): + def __init__(self, term: Term, value: Any, alias: Optional[str] = None) -> None: + super().__init__(alias) + self.term = term + self.value = value + + def nodes_(self) -> Iterator[NodeT]: + yield self + yield from self.term.nodes_() + yield from self.value.nodes_() + + @builder + def replace_table(self, current_table: Optional["Table"], new_table: Optional["Table"]) -> "BitwiseOrCriterion": + """ + Replaces all occurrences of the specified table with the new table. Useful when reusing fields across queries. + + :param current_table: + The table to be replaced. + :param new_table: + The table to replace with. + :return: + A copy of the criterion with the tables replaced. + """ + self.term = self.term.replace_table(current_table, new_table) + + def get_sql(self, **kwargs: Any) -> str: + sql = "({term} | {value})".format( + term=self.term.get_sql(**kwargs), + value=self.value, + ) + return format_alias_sql(sql, self.alias, **kwargs) + + class NullCriterion(Criterion): def __init__(self, term: Term, alias: Optional[str] = None) -> None: super().__init__(alias) diff --git a/pypika/tests/test_criterions.py b/pypika/tests/test_criterions.py index fca2ceee..a0893edd 100644 --- a/pypika/tests/test_criterions.py +++ b/pypika/tests/test_criterions.py @@ -270,6 +270,23 @@ def test__bitwise_and_in_where_clause(self): self.assertEqual('SELECT "abc" FROM "items" WHERE ("foo" & 1)=1', str(q)) + def test__criterion_bitwise_or(self): + c1 = Field("foo").bitwiseor(2) + c2 = Field("foo", table=self.t).bitwiseor(10) == 2 + + self.assertEqual('("foo" | 2)', str(c1)) + self.assertEqual('("crit"."foo" | 10)=2', str(c2)) + + def test__criterion_bitwise_or_with_alias(self): + c1 = Field("foo").bitwiseor(2).as_('alias') + + self.assertEqual('("foo" | 2) "alias"', str(c1)) + + def test__bitwise_or_in_where_clause(self): + q = QueryBuilder().from_('items').select('abc').where(Field("foo").bitwiseor(1) == 1) + + self.assertEqual('SELECT "abc" FROM "items" WHERE ("foo" | 1)=1', str(q)) + class NotTests(unittest.TestCase): table_abc, table_efg = Table("abc", alias="cx0"), Table("efg", alias="cx1")