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}