diff --git a/quickwit/quickwit-serve/src/index_api/rest_handler.rs b/quickwit/quickwit-serve/src/index_api/rest_handler.rs index 287c365a3d7..603986d2686 100644 --- a/quickwit/quickwit-serve/src/index_api/rest_handler.rs +++ b/quickwit/quickwit-serve/src/index_api/rest_handler.rs @@ -37,6 +37,7 @@ use quickwit_proto::metastore::{ MetastoreService, MetastoreServiceClient, ResetSourceCheckpointRequest, ToggleSourceRequest, }; use quickwit_proto::types::IndexUid; +use quickwit_query::query_ast::{query_ast_from_user_text, QueryAst}; use serde::de::DeserializeOwned; use serde::{Deserialize, Serialize}; use tracing::info; @@ -88,6 +89,8 @@ pub fn index_management_handlers( .or(delete_source_handler(index_service.metastore())) // Tokenizer handlers. .or(analyze_request_handler()) + // Parse query into query AST handler. + .or(parse_query_request_handler()) } fn json_body( @@ -866,6 +869,50 @@ async fn analyze_request(request: AnalyzeRequest) -> Result>, +} + +fn parse_query_request_filter( +) -> impl Filter + Clone { + warp::path!("parse-query") + .and(warp::post()) + .and(warp::body::json()) +} + +fn parse_query_request_handler( +) -> impl Filter + Clone { + parse_query_request_filter() + .then(parse_query_request) + .and(extract_format_from_qs()) + .map(into_rest_api_response) +} + +/// Analyzes text with given tokenizer config and returns the list of tokens. +#[utoipa::path( + post, + tag = "parse_query", + path = "/parse_query", + request_body = ParseQueryRequest, + responses( + (status = 200, description = "Successfully parsed query into AST.") + ), +)] +async fn parse_query_request(request: ParseQueryRequest) -> Result { + let query_ast = query_ast_from_user_text(&request.query, request.search_fields) + .parse_user_query(&[]) + .map_err(|err| IndexServiceError::Internal(err.to_string()))?; + Ok(query_ast) +} + #[cfg(test)] mod tests { use std::ops::{Bound, RangeInclusive}; @@ -1917,4 +1964,24 @@ mod tests { expected: expected_response_json ); } + + #[tokio::test] + async fn test_parse_query_request() { + let metastore = MetastoreServiceClient::mock(); + let index_service = IndexService::new( + MetastoreServiceClient::from(metastore), + StorageResolver::unconfigured(), + ); + let index_management_handler = + super::index_management_handlers(index_service, Arc::new(NodeConfig::for_test())) + .recover(recover_fn); + let resp = warp::test::request() + .path("/parse-query") + .method("POST") + .json(&true) + .body(r#"{"query": "field:this AND field:that"}"#) + .reply(&index_management_handler) + .await; + assert_eq!(resp.status(), 200); + } }