From 2bd59cd6ecca15cc0be4f7acf00b06f9320b4244 Mon Sep 17 00:00:00 2001 From: Diretnan Domnan Date: Wed, 25 Sep 2024 23:25:40 +0200 Subject: [PATCH] NONLINEARALGORITHMINDEX command inclusions --- ahnlich/dsl/src/db.rs | 110 ++++++++++++++++++++++++++++++++- ahnlich/dsl/src/syntax/db.pest | 17 ++++- 2 files changed, 125 insertions(+), 2 deletions(-) diff --git a/ahnlich/dsl/src/db.rs b/ahnlich/dsl/src/db.rs index f78439b1..9d0d2bd1 100644 --- a/ahnlich/dsl/src/db.rs +++ b/ahnlich/dsl/src/db.rs @@ -1,4 +1,6 @@ -use ahnlich_types::{db::DBQuery, keyval::StoreName, metadata::MetadataKey}; +use ahnlich_types::{ + db::DBQuery, keyval::StoreName, metadata::MetadataKey, similarity::NonLinearAlgorithm, +}; use pest::Parser; use pest_derive::Parser; @@ -8,6 +10,13 @@ use crate::error::DslError; #[grammar = "syntax/db.pest"] struct DBQueryParser; +fn to_non_linear(input: &str) -> Option { + match input.to_lowercase().trim() { + "kdtree" => Some(NonLinearAlgorithm::KDTree), + _ => None, + } +} + // Parse raw strings separated by ; into a Vec. Examples include but are not restricted // to // @@ -17,6 +26,17 @@ struct DBQueryParser; // INFOSERVER // DROPSTORE store_name IF EXISTS // CREATEPREDINDEX (key_1, key_2) in store_name +// DROPPREDINDEX IF EXISTS (key1, key2) in store_name +// CREATENONLINEARALGORITHMINDEX (kdtree) in store_name +// DROPNONLINEARALGORITHMINDEX IF EXISTS (kdtree) in store_name +// +// #TODO +// SET +// DELKEY +// CREATESTORE +// GETKEY +// GETPRED +// GETSIMN pub fn parse_db_query(input: &str) -> Result, DslError> { let pairs = DBQueryParser::parse(Rule::query, input).map_err(Box::new)?; let statements = pairs.into_iter().collect::>(); @@ -29,6 +49,24 @@ pub fn parse_db_query(input: &str) -> Result, DslError> { Rule::list_clients => DBQuery::ListClients, Rule::list_stores => DBQuery::ListStores, Rule::info_server => DBQuery::InfoServer, + Rule::create_non_linear_algorithm_index => { + let mut inner_pairs = statement.into_inner(); + let index_name_pairs = inner_pairs + .next() + .ok_or(DslError::UnexpectedSpan((start_pos, end_pos)))?; + let non_linear_indices = index_name_pairs + .into_inner() + .flat_map(|index_pair| to_non_linear(index_pair.as_str())) + .collect(); + let store = inner_pairs + .next() + .ok_or(DslError::UnexpectedSpan((start_pos, end_pos)))? + .as_str(); + DBQuery::CreateNonLinearAlgorithmIndex { + store: StoreName(store.to_string()), + non_linear_indices, + } + } Rule::create_pred_index => { let mut inner_pairs = statement.into_inner(); let index_name_pairs = inner_pairs @@ -47,6 +85,32 @@ pub fn parse_db_query(input: &str) -> Result, DslError> { predicates, } } + Rule::drop_non_linear_algorithm_index => { + let mut inner_pairs = statement.into_inner().peekable(); + let mut if_exists = false; + if let Some(next_pair) = inner_pairs.peek() { + if next_pair.as_rule() == Rule::if_exists { + inner_pairs.next(); // Consume it if needed + if_exists = true; + } + }; + let index_names_pair = inner_pairs + .next() + .ok_or(DslError::UnexpectedSpan((start_pos, end_pos)))?; + let store = inner_pairs + .next() + .ok_or(DslError::UnexpectedSpan((start_pos, end_pos)))? + .as_str(); + let non_linear_indices = index_names_pair + .into_inner() + .flat_map(|index_pair| to_non_linear(index_pair.as_str())) + .collect(); + DBQuery::DropNonLinearAlgorithmIndex { + store: StoreName(store.to_string()), + non_linear_indices, + error_if_not_exists: !if_exists, + } + } Rule::drop_pred_index => { let mut inner_pairs = statement.into_inner().peekable(); let mut if_exists = false; @@ -216,4 +280,48 @@ mod tests { }] ); } + + #[test] + fn test_create_non_linear_algorithm_parse() { + let input = r#"createnonlinearalgorithmindex (fake) in store2"#; + let DslError::UnexpectedSpan((start, end)) = parse_db_query(input).unwrap_err() else { + panic!("Unexpected error pattern found") + }; + assert_eq!((start, end), (0, 46)); + let input = r#"createnonlinearalgorithmindex (kdtree) in store2"#; + assert_eq!( + parse_db_query(input).expect("Could not parse query input"), + vec![DBQuery::CreateNonLinearAlgorithmIndex { + store: StoreName("store2".to_string()), + non_linear_indices: HashSet::from_iter([NonLinearAlgorithm::KDTree]), + }] + ); + } + + #[test] + fn test_drop_non_linear_algorithm_parse() { + let input = r#"DROPNONLINEARALGORITHMINDEX (fake) in 1234"#; + let DslError::UnexpectedSpan((start, end)) = parse_db_query(input).unwrap_err() else { + panic!("Unexpected error pattern found") + }; + assert_eq!((start, end), (0, 42)); + let input = r#"DROPNONLINEARALGORITHMINDEX (kdtree) in 1234"#; + assert_eq!( + parse_db_query(input).expect("Could not parse query input"), + vec![DBQuery::DropNonLinearAlgorithmIndex { + store: StoreName("1234".to_string()), + non_linear_indices: HashSet::from_iter([NonLinearAlgorithm::KDTree]), + error_if_not_exists: true, + }] + ); + let input = r#"DROPNONLINEARALGORITHMINDEX IF EXISTS (kdtree) in 1234"#; + assert_eq!( + parse_db_query(input).expect("Could not parse query input"), + vec![DBQuery::DropNonLinearAlgorithmIndex { + store: StoreName("1234".to_string()), + non_linear_indices: HashSet::from_iter([NonLinearAlgorithm::KDTree]), + error_if_not_exists: false, + }] + ); + } } diff --git a/ahnlich/dsl/src/syntax/db.pest b/ahnlich/dsl/src/syntax/db.pest index 84ae45ad..fd1f2c5f 100644 --- a/ahnlich/dsl/src/syntax/db.pest +++ b/ahnlich/dsl/src/syntax/db.pest @@ -2,7 +2,18 @@ whitespace = _{ " " | "\t" } query = _{ statement ~ (";" ~ statement) * } // Matches multiple statements separated by ; -statement = _{ ping | info_server | list_stores | list_clients | drop_store | create_pred_index | drop_pred_index | invalid_statement } +statement = _{ + ping | + info_server | + list_stores | + list_clients | + drop_store | + create_pred_index | + drop_pred_index | + create_non_linear_algorithm_index | + drop_non_linear_algorithm_index | + invalid_statement +} ping = { whitespace* ~ ^"ping" ~ whitespace* } info_server = { whitespace* ~ ^"infoserver" ~ whitespace* } @@ -10,13 +21,17 @@ list_stores = { whitespace* ~ ^"liststores" ~ whitespace* } list_clients = { whitespace* ~ ^"listclients" ~ whitespace* } drop_store = { whitespace* ~ ^"dropstore" ~ whitespace* ~ store_name ~ (if_exists | invalid_statement)? } create_pred_index = { whitespace* ~ ^"createpredindex" ~ whitespace* ~ "(" ~ index_names ~ ")" ~ whitespace* ~ ^"in" ~ whitespace* ~ store_name } +create_non_linear_algorithm_index = { whitespace* ~ ^"createnonlinearalgorithmindex" ~ whitespace* ~ "(" ~ non_linear_algorithms ~ ")" ~ whitespace* ~ ^"in" ~ whitespace* ~ store_name} drop_pred_index = { whitespace* ~ ^"droppredindex" ~ whitespace* ~ (if_exists)? ~ "(" ~ index_names ~ ")" ~ whitespace* ~ ^"in" ~whitespace* ~ store_name } +drop_non_linear_algorithm_index = { whitespace* ~ ^"dropnonlinearalgorithmindex" ~ whitespace* ~ (if_exists)? ~ "(" ~ non_linear_algorithms ~ ")" ~ whitespace* ~ ^"in" ~whitespace* ~ store_name } if_exists = { whitespace* ~ ^"if" ~ whitespace* ~ ^"exists" ~ whitespace* } // stores and predicates can be alphanumeric store_name = { (ASCII_ALPHANUMERIC | "_" | "-")+ } index_name = { (ASCII_ALPHANUMERIC | "_" | "-")+ } +non_linear_algorithm = { ^"kdtree" } +non_linear_algorithms = { non_linear_algorithm ~ (whitespace* ~ "," ~ whitespace* ~ non_linear_algorithm)* } index_names = { index_name ~ (whitespace* ~ "," ~ whitespace* ~ index_name)* } // Catch-all rule for invalid statements