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