Skip to main content

tank_core/expression/
binary_op.rs

1use crate::{
2    DynQuery, Expression, ExpressionVisitor, GenericSqlWriter, OpPrecedence,
3    writer::{Context, SqlWriter},
4};
5use proc_macro2::TokenStream;
6use quote::{ToTokens, TokenStreamExt, quote};
7use std::mem;
8
9#[derive(Clone, Copy, PartialEq, Eq, Debug)]
10pub enum BinaryOpType {
11    Indexing,
12    Cast,
13    Multiplication,
14    Division,
15    Remainder,
16    Addition,
17    Subtraction,
18    ShiftLeft,
19    ShiftRight,
20    BitwiseAnd,
21    BitwiseOr,
22    In,
23    NotIn,
24    Is,
25    IsNot,
26    Like,
27    NotLike,
28    Regexp,
29    NotRegexp,
30    Glob,
31    NotGlob,
32    Equal,
33    NotEqual,
34    Less,
35    Greater,
36    LessEqual,
37    GreaterEqual,
38    And,
39    Or,
40    Alias,
41}
42
43impl OpPrecedence for BinaryOpType {
44    fn precedence(&self, writer: &dyn SqlWriter) -> i32 {
45        writer.expression_binary_op_precedence(self)
46    }
47}
48
49#[derive(Debug)]
50pub struct BinaryOp<L: Expression, R: Expression> {
51    pub op: BinaryOpType,
52    pub lhs: L,
53    pub rhs: R,
54}
55
56impl<L: Expression, R: Expression> OpPrecedence for BinaryOp<L, R> {
57    fn precedence(&self, writer: &dyn SqlWriter) -> i32 {
58        writer.expression_binary_op_precedence(&self.op)
59    }
60}
61
62impl<L: Expression, R: Expression> Expression for BinaryOp<L, R> {
63    fn write_query(&self, writer: &dyn SqlWriter, context: &mut Context, out: &mut DynQuery) {
64        writer.write_expression_binary_op(
65            context,
66            out,
67            &BinaryOp {
68                op: self.op,
69                lhs: &self.lhs,
70                rhs: &self.rhs,
71            },
72        )
73    }
74    fn accept_visitor(
75        &self,
76        matcher: &mut dyn ExpressionVisitor,
77        writer: &dyn SqlWriter,
78        context: &mut Context,
79        out: &mut DynQuery,
80    ) -> bool {
81        matcher.visit_binary_op(
82            writer,
83            context,
84            out,
85            &BinaryOp {
86                op: self.op,
87                lhs: &self.lhs,
88                rhs: &self.rhs,
89            },
90        )
91    }
92    fn as_identifier(&self, context: &mut Context) -> String {
93        if self.op == BinaryOpType::Alias {
94            self.rhs.as_identifier(context)
95        } else {
96            let mut out = DynQuery::new(String::new());
97            let writer = GenericSqlWriter::new();
98            self.write_query(&writer, context, &mut out);
99            mem::take(out.buffer())
100        }
101    }
102}
103
104impl ToTokens for BinaryOpType {
105    fn to_tokens(&self, tokens: &mut TokenStream) {
106        let v = format!("{self:?}");
107        tokens.append_all(quote!(::tank::BinaryOpType::#v));
108    }
109}