vantage_table/
conditions.rs1use vantage_expressions::{Expression, ExpressiveEnum};
2
3#[derive(Debug, Clone, Copy, PartialEq, Eq)]
5pub struct ConditionHandle(pub(crate) i64);
6
7impl ConditionHandle {
8 pub(crate) fn new(id: i64) -> Self {
9 Self(id)
10 }
11}
12
13pub fn literal_equality<V: Clone>(expr: &Expression<V>) -> Option<(String, V)> {
21 if expr.template.trim() != "{} = {}" || expr.parameters.len() != 2 {
22 return None;
23 }
24 let column = match &expr.parameters[0] {
25 ExpressiveEnum::Nested(lhs) if lhs.parameters.is_empty() => {
26 unquote_identifier(&lhs.template)?
27 }
28 _ => return None,
29 };
30 let value = match &expr.parameters[1] {
31 ExpressiveEnum::Scalar(v) => v.clone(),
32 ExpressiveEnum::Nested(rhs) if rhs.template.trim() == "{}" && rhs.parameters.len() == 1 => {
33 match &rhs.parameters[0] {
34 ExpressiveEnum::Scalar(v) => v.clone(),
35 _ => return None,
36 }
37 }
38 _ => return None,
39 };
40 Some((column, value))
41}
42
43fn unquote_identifier(text: &str) -> Option<String> {
46 let text = text.trim();
47 for q in ['"', '`'] {
48 if let Some(inner) = text.strip_prefix(q).and_then(|t| t.strip_suffix(q)) {
49 let doubled: String = [q, q].iter().collect();
50 if inner.is_empty() || inner.replace(&doubled, "").contains(q) {
51 return None;
52 }
53 return Some(inner.replace(&doubled, &q.to_string()));
54 }
55 }
56 let mut chars = text.chars();
57 let first = chars.next()?;
58 ((first.is_ascii_alphabetic() || first == '_')
59 && chars.all(|c| c.is_ascii_alphanumeric() || c == '_'))
60 .then(|| text.to_string())
61}