Skip to content

Commit 472392f

Browse files
committed
Update ElasticSQL handlers
1 parent 83ab884 commit 472392f

4 files changed

Lines changed: 76 additions & 49 deletions

File tree

asap-query-engine/src/data_model/streaming_config.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ impl StreamingConfig {
7272
SchemaConfig::PromQL(_) => QueryLanguage::promql,
7373
SchemaConfig::SQL(_) => QueryLanguage::sql,
7474
SchemaConfig::ElasticQueryDSL => QueryLanguage::elastic_querydsl,
75-
SchemaConfig::ElasticSQL => QueryLanguage::elastic_sql,
75+
SchemaConfig::ElasticSQL(_) => QueryLanguage::elastic_sql,
7676
})
7777
.unwrap_or(QueryLanguage::promql); // Default to promql if no inference_config
7878

asap-query-engine/src/drivers/query/adapters/elastic_http.rs

Lines changed: 53 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use super::config::AdapterConfig;
22
use super::traits::*;
3+
use crate::QueryResult;
34
use crate::data_model::QueryLanguage;
45
use async_trait::async_trait;
56
use axum::{
@@ -11,7 +12,7 @@ use axum::{
1112
use serde_json::{json, Value};
1213
use std::collections::HashMap;
1314
use std::sync::Arc;
14-
use tracing::{debug, error};
15+
use tracing::{debug, error, info};
1516

1617
/// Elasticsearch HTTP protocol adapter
1718
pub struct ElasticHttpAdapter {
@@ -26,34 +27,30 @@ impl ElasticHttpAdapter {
2627

2728
/// Parse Elasticsearch query from JSON body
2829
fn parse_elasticsearch_query(&self, body: &Bytes) -> Result<ParsedQueryRequest, AdapterError> {
29-
debug!(
30-
"Elasticsearch adapter: parsing query for language {:?}",
31-
self.config.language
32-
);
33-
34-
// Parse the JSON body
3530
let json_body: Value = serde_json::from_slice(body)
3631
.map_err(|e| AdapterError::ParseError(format!("Invalid JSON: {}", e)))?;
3732

38-
// Store the entire query as a JSON string
39-
let query = serde_json::to_string(&json_body)
40-
.map_err(|e| AdapterError::ParseError(format!("Failed to serialize query: {}", e)))?;
33+
// Extract the SQL string from the "query" field
34+
let query = match &self.config.language {
35+
QueryLanguage::elastic_sql => {
36+
json_body
37+
.get("query")
38+
.and_then(|v| v.as_str())
39+
.ok_or_else(|| AdapterError::MissingParameter("query".to_string()))?
40+
.to_string()
41+
}
42+
_ => {
43+
// For QueryDSL, keep the full JSON as before
44+
serde_json::to_string(&json_body)
45+
.map_err(|e| AdapterError::ParseError(format!("Failed to serialize query: {}", e)))?
46+
}
47+
};
4148

4249
let time = std::time::SystemTime::now()
4350
.duration_since(std::time::UNIX_EPOCH)
4451
.unwrap_or_default()
4552
.as_secs_f64();
4653

47-
debug!(
48-
"Elasticsearch adapter: parsed {} query with time={}",
49-
if matches!(self.config.language, QueryLanguage::elastic_sql) {
50-
"SQL"
51-
} else {
52-
"Query DSL"
53-
},
54-
time
55-
);
56-
5754
Ok(ParsedQueryRequest { query, time })
5855
}
5956
}
@@ -125,35 +122,53 @@ impl QueryRequestAdapter for ElasticHttpAdapter {
125122
#[async_trait]
126123
impl QueryResponseAdapter for ElasticHttpAdapter {
127124
async fn format_success_response(
128-
&self,
129-
_result: &QueryExecutionResult,
130-
) -> Result<Response, StatusCode> {
131-
debug!("Elasticsearch adapter: formatting success response");
132-
133-
// For now, since we're falling back for every query,
134-
// the result from the fallback will be passed through
135-
// In the future, this could transform local execution results
136-
// to Elasticsearch format
125+
&self,
126+
result: &QueryExecutionResult,
127+
) -> Result<Response, StatusCode> {
128+
info!("SKETCH HIT: serving {} rows from precomputed sketches",
129+
match &result.query_result {
130+
QueryResult::Vector(v) => v.values.len(),
131+
QueryResult::Matrix(_) => 0,
132+
});
133+
134+
let label_names = &result.query_output_labels.labels;
135+
136+
let hits: Vec<Value> = match &result.query_result {
137+
QueryResult::Vector(instant_vector) => {
138+
instant_vector
139+
.values
140+
.iter()
141+
.map(|element| {
142+
let mut source = serde_json::Map::new();
143+
for (i, label_name) in label_names.iter().enumerate() {
144+
let label_value =
145+
element.labels.get(i).map(|s| s.as_str()).unwrap_or("");
146+
source.insert(label_name.clone(), json!(label_value));
147+
}
148+
source.insert("value".to_string(), json!(element.value));
149+
json!({
150+
"_source": source
151+
})
152+
})
153+
.collect()
154+
}
155+
QueryResult::Matrix(_) => {
156+
return Err(StatusCode::NOT_IMPLEMENTED);
157+
}
158+
};
137159

138-
// Return a stub Elasticsearch-style response for now.
139160
let response = json!({
140161
"took": 0,
141162
"timed_out": false,
142163
"hits": {
143164
"total": {
144-
"value": 0,
165+
"value": hits.len(),
145166
"relation": "eq"
146167
},
147-
"hits": []
168+
"hits": hits
148169
}
149170
});
150171

151-
debug!(
152-
"Elasticsearch adapter: returning stub response: {}",
153-
serde_json::to_string_pretty(&response)
154-
.unwrap_or_else(|_| "Unable to format".to_string())
155-
);
156-
157172
Ok(Json(response).into_response())
158173
}
159174

asap-query-engine/src/drivers/query/fallback/elastic.rs

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -80,11 +80,23 @@ impl FallbackClient for ElasticHttpFallback {
8080

8181
debug!("Full forwarding URL: {}", full_url);
8282

83-
let query_body: Value = match serde_json::from_str(&request.query) {
84-
Ok(json) => json,
85-
Err(e) => {
86-
error!("Failed to parse query as JSON: {}", e);
87-
return Err(StatusCode::INTERNAL_SERVER_ERROR);
83+
let query_body: Value = match self.language {
84+
QueryLanguage::elastic_sql => {
85+
// query is a raw SQL string, need to wrap it for the ES SQL endpoint
86+
serde_json::json!({
87+
"query": request.query.trim().trim_end_matches(';'),
88+
"fetch_size": 1000,
89+
})
90+
}
91+
_ => {
92+
// query is already a JSON string (Query DSL)
93+
match serde_json::from_str(&request.query) {
94+
Ok(json) => json,
95+
Err(e) => {
96+
error!("Failed to parse query as JSON: {}", e);
97+
return Err(StatusCode::INTERNAL_SERVER_ERROR);
98+
}
99+
}
88100
}
89101
};
90102

asap-query-engine/src/engines/simple_engine.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1132,7 +1132,7 @@ impl SimpleEngine {
11321132
return None;
11331133
}
11341134
&SchemaConfig::ElasticQueryDSL => todo!(),
1135-
&SchemaConfig::ElasticSQL => todo!(),
1135+
SchemaConfig::ElasticSQL(sql_schema) => sql_schema.clone(),
11361136
};
11371137

11381138
let statements = parser::parse_sql(&GenericDialect {}, query.as_str()).unwrap();
@@ -1345,7 +1345,7 @@ impl SimpleEngine {
13451345
.streaming_config
13461346
.get_aggregation_config(agg_info.aggregation_id_for_key)
13471347
.map(|config| config.aggregated_labels.clone())
1348-
.unwrap_or_else(KeyByLabelNames::empty);
1348+
.unwrap_or_else(KeyByLabelNames::empty);
13491349

13501350
Some(QueryExecutionContext {
13511351
metric: metric.to_string(),
@@ -1473,14 +1473,14 @@ impl SimpleEngine {
14731473
QueryLanguage::promql => self.handle_query_promql(query, time),
14741474
QueryLanguage::sql => self.handle_query_sql(query, time),
14751475
QueryLanguage::elastic_querydsl => self.handle_query_elastic(),
1476-
QueryLanguage::elastic_sql => self.handle_query_elastic(),
1476+
QueryLanguage::elastic_sql => self.handle_query_sql(query, time),
14771477
}
14781478
}
14791479

14801480
pub fn handle_query_elastic(&self) -> Option<(KeyByLabelNames, QueryResult)> {
14811481
None
14821482
}
1483-
1483+
14841484
// /// Try to extract sketch query components from a PromQL query string.
14851485
// ///
14861486
// /// Attempts the standard AST parser first. If that fails (e.g. for custom
@@ -1919,7 +1919,7 @@ impl SimpleEngine {
19191919
warn!("PromQL query requested but config has ElasticQueryDSL schema");
19201920
return None;
19211921
}
1922-
&SchemaConfig::ElasticSQL => {
1922+
SchemaConfig::ElasticSQL(_) => {
19231923
warn!("PromQL query requested but config has ElasticSQL schema");
19241924
return None;
19251925
}

0 commit comments

Comments
 (0)