From c50681e7b622cfccc6ca6105a22a5b5f59ce99cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Ml=C3=A1dek?= Date: Sat, 21 Oct 2023 22:55:20 +0200 Subject: [PATCH] feat(db): :construction: #key expressions in lang --- base/src/lang.rs | 11 +++++++++++ db/src/engine.rs | 9 +++++++++ db/src/lib.rs | 13 +++++++++++-- 3 files changed, 31 insertions(+), 2 deletions(-) diff --git a/base/src/lang.rs b/base/src/lang.rs index 3218df8..735485a 100644 --- a/base/src/lang.rs +++ b/base/src/lang.rs @@ -24,6 +24,7 @@ where In(Vec), Contains(String), Variable(Option), + Key(String), } #[derive(Debug, Clone, PartialEq)] @@ -180,6 +181,16 @@ impl TryFrom<&lexpr::Value> for Query { Some(var_name.into()) })) } + lexpr::Value::Symbol(symbol) if symbol.starts_with('#') => { + let var_name = symbol.strip_prefix('#').unwrap(); + if var_name.is_empty() { + return Err(UpEndError::QueryParseError( + "Malformed expression: Key cannot be empty.".into(), + )); + } else { + return Ok(QueryComponent::Key(var_name.into())); + } + } _ => Ok(QueryComponent::Exact(T::try_from(value.clone())?)), } } diff --git a/db/src/engine.rs b/db/src/engine.rs index fbcfd92..ad38ef0 100644 --- a/db/src/engine.rs +++ b/db/src/engine.rs @@ -262,12 +262,18 @@ fn to_sqlite_predicates(query: Query) -> Result data::entity_searchable.like(format!("%{}%", q_entity)), )), QueryComponent::Variable(_) => {} + QueryComponent::Key(_) => { + subqueries.push(Box::new) + } }; match &eq.attribute { QueryComponent::Exact(q_attribute) => { subqueries.push(Box::new(data::attribute.eq(q_attribute.0.clone()))) } + QueryComponent::Key(q_attribute) => { + subqueries.push(Box::new(data::attribute.eq(q_attribute.clone()))) + } QueryComponent::In(q_attributes) => subqueries.push(Box::new( data::attribute.eq_any(q_attributes.iter().map(|a| &a.0).cloned()), )), @@ -337,6 +343,9 @@ fn to_sqlite_predicates(query: Query) -> Result subqueries.push(Box::new(data::value_str.like(format!("S%{}%", q_value)))) } QueryComponent::Variable(_) => {} + QueryComponent::Key(key) => { + subqueries.push(Box::new(data::value_str.like(format!("K%{}%", key)))) + } }; match subqueries.len() { diff --git a/db/src/lib.rs b/db/src/lib.rs index 07b2d2f..6b64d0d 100644 --- a/db/src/lib.rs +++ b/db/src/lib.rs @@ -432,7 +432,7 @@ impl UpEndConnection { #[cfg(test)] mod test { - use upend_base::constants::{ATTR_LABEL, ATTR_IN}; + use upend_base::constants::{ATTR_IN, ATTR_KEY, ATTR_LABEL}; use super::*; use tempfile::TempDir; @@ -542,6 +542,15 @@ mod test { let result = connection.query(query).unwrap(); assert_eq!(result.len(), 1); assert_eq!(result[0].entity, edge_entity); - assert_eq!(result[0].value, EntryValue::Address(random_entity)); + assert_eq!(result[0].value, EntryValue::Address(random_entity.clone())); + + upend_insert_val!(connection, random_entity, ATTR_KEY, "FOO").unwrap(); + let query = format!(r#"(matches #FOO "{ATTR_LABEL}" ?)"#) + .parse() + .unwrap(); + let result = connection.query(query).unwrap(); + assert_eq!(result.len(), 1); + assert_eq!(result[0].entity, random_entity); + assert_eq!(result[0].value, EntryValue::String("FOOBAR".to_string())); } }