Skip to main content

tank_core/expression/
visitor.rs

1use crate::{
2    BinaryOp, BinaryOpType, ColumnRef, Context, DynQuery, Expression, Operand, Order, Ordered,
3    SqlWriter, UnaryOp, Value,
4};
5
6pub trait ExpressionVisitor {
7    fn visit_column(
8        &mut self,
9        _writer: &dyn SqlWriter,
10        _context: &mut Context,
11        _out: &mut DynQuery,
12        _value: &ColumnRef,
13    ) -> bool {
14        false
15    }
16    fn visit_operand(
17        &mut self,
18        _writer: &dyn SqlWriter,
19        _context: &mut Context,
20        _out: &mut DynQuery,
21        _value: &Operand,
22    ) -> bool {
23        false
24    }
25    fn visit_unary_op(
26        &mut self,
27        _writer: &dyn SqlWriter,
28        _context: &mut Context,
29        _out: &mut DynQuery,
30        _value: &UnaryOp<&dyn Expression>,
31    ) -> bool {
32        false
33    }
34    fn visit_binary_op(
35        &mut self,
36        _writer: &dyn SqlWriter,
37        _context: &mut Context,
38        _out: &mut DynQuery,
39        _value: &BinaryOp<&dyn Expression, &dyn Expression>,
40    ) -> bool {
41        false
42    }
43    fn visit_ordered(
44        &mut self,
45        _writer: &dyn SqlWriter,
46        _context: &mut Context,
47        _out: &mut DynQuery,
48        _value: &Ordered<&dyn Expression>,
49    ) -> bool {
50        false
51    }
52}
53
54#[derive(Default, Debug, Copy, Clone)]
55pub struct FindOrder {
56    pub order: Order,
57}
58impl ExpressionVisitor for FindOrder {
59    fn visit_column(
60        &mut self,
61        _writer: &dyn SqlWriter,
62        _context: &mut Context,
63        _out: &mut DynQuery,
64        _value: &ColumnRef,
65    ) -> bool {
66        true
67    }
68    fn visit_operand(
69        &mut self,
70        _writer: &dyn SqlWriter,
71        _context: &mut Context,
72        _out: &mut DynQuery,
73        _value: &Operand,
74    ) -> bool {
75        true
76    }
77    fn visit_unary_op(
78        &mut self,
79        _writer: &dyn SqlWriter,
80        _context: &mut Context,
81        _out: &mut DynQuery,
82        _value: &UnaryOp<&dyn Expression>,
83    ) -> bool {
84        true
85    }
86    fn visit_binary_op(
87        &mut self,
88        _writer: &dyn SqlWriter,
89        _context: &mut Context,
90        _out: &mut DynQuery,
91        _value: &BinaryOp<&dyn Expression, &dyn Expression>,
92    ) -> bool {
93        true
94    }
95    fn visit_ordered(
96        &mut self,
97        _writer: &dyn SqlWriter,
98        _context: &mut Context,
99        _out: &mut DynQuery,
100        value: &Ordered<&dyn Expression>,
101    ) -> bool {
102        self.order = value.order;
103        true
104    }
105}
106
107#[derive(Default, Debug, Copy, Clone)]
108pub struct IsTrue;
109impl ExpressionVisitor for IsTrue {
110    fn visit_operand(
111        &mut self,
112        _writer: &dyn SqlWriter,
113        _context: &mut Context,
114        _out: &mut DynQuery,
115        value: &Operand,
116    ) -> bool {
117        match value {
118            Operand::LitBool(true)
119            | Operand::Variable(Value::Boolean(Some(true), ..))
120            | Operand::Value(Value::Boolean(Some(true), ..)) => true,
121            _ => false,
122        }
123    }
124}
125
126#[derive(Default, Debug, Copy, Clone)]
127pub struct IsFalse;
128impl ExpressionVisitor for IsFalse {
129    fn visit_operand(
130        &mut self,
131        _writer: &dyn SqlWriter,
132        _context: &mut Context,
133        _out: &mut DynQuery,
134        value: &Operand,
135    ) -> bool {
136        match value {
137            Operand::LitBool(false)
138            | Operand::Variable(Value::Boolean(Some(false), ..))
139            | Operand::Value(Value::Boolean(Some(false), ..)) => true,
140            _ => false,
141        }
142    }
143}
144
145#[derive(Default, Debug)]
146pub struct IsAggregateFunction;
147impl ExpressionVisitor for IsAggregateFunction {
148    fn visit_operand(
149        &mut self,
150        _writer: &dyn SqlWriter,
151        _context: &mut Context,
152        _out: &mut DynQuery,
153        value: &Operand,
154    ) -> bool {
155        match value {
156            Operand::Call(function, ..) => match function {
157                s if s.eq_ignore_ascii_case("abs") => true,
158                s if s.eq_ignore_ascii_case("avg") => true,
159                s if s.eq_ignore_ascii_case("count") => true,
160                s if s.eq_ignore_ascii_case("max") => true,
161                s if s.eq_ignore_ascii_case("min") => true,
162                s if s.eq_ignore_ascii_case("sum") => true,
163                _ => false,
164            },
165            _ => false,
166        }
167    }
168    fn visit_binary_op(
169        &mut self,
170        writer: &dyn SqlWriter,
171        context: &mut Context,
172        out: &mut DynQuery,
173        value: &BinaryOp<&dyn Expression, &dyn Expression>,
174    ) -> bool {
175        if value.op == BinaryOpType::Alias {
176            value.lhs.accept_visitor(self, writer, context, out)
177        } else {
178            false
179        }
180    }
181}
182
183#[derive(Default, Debug)]
184pub struct IsAsterisk;
185impl ExpressionVisitor for IsAsterisk {
186    fn visit_operand(
187        &mut self,
188        _writer: &dyn SqlWriter,
189        _context: &mut Context,
190        _out: &mut DynQuery,
191        value: &Operand,
192    ) -> bool {
193        matches!(value, Operand::Asterisk)
194    }
195}
196
197#[derive(Default, Debug)]
198pub struct IsQuestionMark;
199impl ExpressionVisitor for IsQuestionMark {
200    fn visit_operand(
201        &mut self,
202        _writer: &dyn SqlWriter,
203        _context: &mut Context,
204        _out: &mut DynQuery,
205        value: &Operand,
206    ) -> bool {
207        matches!(value, Operand::QuestionMark)
208    }
209}
210
211#[derive(Default, Debug)]
212pub struct IsAlias {
213    pub name: String,
214}
215impl ExpressionVisitor for IsAlias {
216    fn visit_binary_op(
217        &mut self,
218        _writer: &dyn SqlWriter,
219        context: &mut Context,
220        _out: &mut DynQuery,
221        value: &BinaryOp<&dyn Expression, &dyn Expression>,
222    ) -> bool {
223        if value.op != BinaryOpType::Alias {
224            return false;
225        }
226        self.name = value.rhs.as_identifier(context);
227        true
228    }
229}