1use hawdb_core::Value;
21
22#[derive(Debug, Clone, PartialEq, Eq)]
23pub enum SqlValue {
24 Literal(Value),
25 Parameter(usize),
26}
27
28#[derive(Debug, Clone, PartialEq, Eq)]
30pub struct Expr {
31 pub kind: ExprKind,
32 pub span: SqlSourceSpan,
33}
34
35#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
38pub struct SqlSourceSpan {
39 pub start: SqlSourceLocation,
40 pub end: SqlSourceLocation,
41}
42
43#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
44pub struct SqlSourceLocation {
45 pub line: u64,
46 pub column: u64,
47}
48
49#[derive(Debug, Clone, PartialEq, Eq)]
50pub enum ExprKind {
51 Column(SqlColumnRef),
52 Value(SqlValue),
53 Function {
54 name: String,
55 arguments: Vec<SqlFunctionArgument>,
56 distinct: bool,
57 filter: Option<Box<Expr>>,
58 },
59 And(Box<Expr>, Box<Expr>),
60 Or(Box<Expr>, Box<Expr>),
61 Not(Box<Expr>),
62 Compare {
63 left: Box<Expr>,
64 op: SqlComparisonOp,
65 right: Box<Expr>,
66 },
67 InList {
68 left: Box<Expr>,
69 values: Vec<Expr>,
70 negated: bool,
71 },
72 Like {
73 left: Box<Expr>,
74 pattern: Box<Expr>,
75 case_insensitive: bool,
76 negated: bool,
77 escape: SqlLikeEscape,
78 },
79 IsNull {
80 expression: Box<Expr>,
81 negated: bool,
82 },
83}
84
85pub type SqlExpression = Expr;
87pub type SqlPredicate = Expr;
89
90impl Expr {
91 pub fn unspanned(kind: ExprKind) -> Self {
92 Self {
93 kind,
94 span: SqlSourceSpan::default(),
95 }
96 }
97
98 pub fn column(column: SqlColumnRef) -> Self {
99 Self::unspanned(ExprKind::Column(column))
100 }
101
102 pub fn value(value: SqlValue) -> Self {
103 Self::unspanned(ExprKind::Value(value))
104 }
105
106 pub fn as_column(&self) -> Option<&SqlColumnRef> {
107 match &self.kind {
108 ExprKind::Column(column) => Some(column),
109 _ => None,
110 }
111 }
112
113 pub fn as_value(&self) -> Option<&SqlValue> {
114 match &self.kind {
115 ExprKind::Value(value) => Some(value),
116 _ => None,
117 }
118 }
119
120 pub fn require_column(&self) -> hawdb_core::Result<&SqlColumnRef> {
121 self.as_column().ok_or_else(|| {
122 hawdb_core::HawDBError::Semantic(
123 "this SQL expression position requires a column reference".to_owned(),
124 )
125 })
126 }
127
128 pub fn require_value(&self) -> hawdb_core::Result<&SqlValue> {
129 self.as_value().ok_or_else(|| {
130 hawdb_core::HawDBError::Semantic(
131 "this SQL expression position requires a literal or parameter".to_owned(),
132 )
133 })
134 }
135
136 pub fn try_visit_mut<E>(
139 &mut self,
140 visitor: &mut impl FnMut(&mut Self) -> std::result::Result<(), E>,
141 ) -> std::result::Result<(), E> {
142 match &mut self.kind {
143 ExprKind::Column(_) | ExprKind::Value(_) => {}
144 ExprKind::Function {
145 arguments, filter, ..
146 } => {
147 for argument in arguments {
148 if let SqlFunctionArgument::Expression(expression) = argument {
149 expression.try_visit_mut(visitor)?;
150 }
151 }
152 if let Some(filter) = filter {
153 filter.try_visit_mut(visitor)?;
154 }
155 }
156 ExprKind::And(left, right)
157 | ExprKind::Or(left, right)
158 | ExprKind::Compare { left, right, .. } => {
159 left.try_visit_mut(visitor)?;
160 right.try_visit_mut(visitor)?;
161 }
162 ExprKind::Not(expression) | ExprKind::IsNull { expression, .. } => {
163 expression.try_visit_mut(visitor)?
164 }
165 ExprKind::InList { left, values, .. } => {
166 left.try_visit_mut(visitor)?;
167 for value in values {
168 value.try_visit_mut(visitor)?;
169 }
170 }
171 ExprKind::Like { left, pattern, .. } => {
172 left.try_visit_mut(visitor)?;
173 pattern.try_visit_mut(visitor)?;
174 }
175 }
176 visitor(self)
177 }
178
179 pub fn visit<'a>(&'a self, visitor: &mut impl FnMut(&'a Self)) {
181 visitor(self);
182 match &self.kind {
183 ExprKind::Column(_) | ExprKind::Value(_) => {}
184 ExprKind::Function {
185 arguments, filter, ..
186 } => {
187 for argument in arguments {
188 if let SqlFunctionArgument::Expression(expression) = argument {
189 expression.visit(visitor);
190 }
191 }
192 if let Some(filter) = filter {
193 filter.visit(visitor);
194 }
195 }
196 ExprKind::And(left, right)
197 | ExprKind::Or(left, right)
198 | ExprKind::Compare { left, right, .. } => {
199 left.visit(visitor);
200 right.visit(visitor);
201 }
202 ExprKind::Not(expression) | ExprKind::IsNull { expression, .. } => {
203 expression.visit(visitor)
204 }
205 ExprKind::InList { left, values, .. } => {
206 left.visit(visitor);
207 for value in values {
208 value.visit(visitor);
209 }
210 }
211 ExprKind::Like { left, pattern, .. } => {
212 left.visit(visitor);
213 pattern.visit(visitor);
214 }
215 }
216 }
217}
218
219#[derive(Debug, Clone, PartialEq, Eq)]
220pub enum SqlFunctionArgument {
221 Expression(SqlExpression),
222 Wildcard,
223}
224
225#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
226pub struct SqlColumnRef {
227 pub qualifier: Option<String>,
228 pub name: String,
229}
230
231#[derive(Debug, Clone, PartialEq, Eq)]
232pub struct SqlOrderItem {
233 pub expression: Expr,
234 pub direction: SqlOrderDirection,
235 pub nulls: SqlNullOrder,
236}
237
238#[derive(Debug, Clone, PartialEq, Eq)]
240pub struct SqlIndexColumn {
241 pub column: SqlColumnRef,
242 pub direction: SqlOrderDirection,
243 pub nulls: SqlNullOrder,
244}
245
246#[derive(Debug, Clone, Copy, PartialEq, Eq)]
247pub enum SqlOrderDirection {
248 Asc,
249 Desc,
250}
251
252#[derive(Debug, Clone, Copy, PartialEq, Eq)]
253pub enum SqlNullOrder {
254 DialectDefault,
255 First,
256 Last,
257}
258
259#[derive(Debug, Clone, Copy, PartialEq, Eq)]
260pub enum SqlLikeEscape {
261 Character(char),
262 Disabled,
263}
264
265#[derive(Debug, Clone, Copy, PartialEq, Eq)]
266pub enum SqlComparisonOp {
267 Eq,
268 NotEq,
269 Lt,
270 Lte,
271 Gt,
272 Gte,
273}
274
275impl std::fmt::Display for SqlValue {
276 fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
277 match self {
278 Self::Literal(value) => write!(formatter, "{value}"),
279 Self::Parameter(position) => write!(formatter, "${position}"),
280 }
281 }
282}