Skip to content

Commit 053bb71

Browse files
committed
Move explain functions to explain.rs
1 parent 537476f commit 053bb71

File tree

2 files changed

+50
-42
lines changed

2 files changed

+50
-42
lines changed

src/explain.rs

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,3 +180,50 @@ impl ExecutionPlan for DistributedExplainExec {
180180
self.schema.clone()
181181
}
182182
}
183+
184+
/// Check if this is an EXPLAIN query (but not EXPLAIN ANALYZE)
185+
///
186+
/// This function distinguishes between:
187+
/// - EXPLAIN queries (returns true) - show plan information only
188+
/// - EXPLAIN ANALYZE queries (returns false) - execute and show runtime stats
189+
/// - Regular queries (returns false) - normal query execution
190+
pub fn is_explain_query(query: &str) -> bool {
191+
let query_upper = query.trim().to_uppercase();
192+
// Must start with "EXPLAIN" followed by whitespace or end of string
193+
let is_explain = query_upper.starts_with("EXPLAIN") &&
194+
(query_upper.len() == 7 || query_upper.chars().nth(7).is_some_and(|c| c.is_whitespace()));
195+
let is_explain_analyze = query_upper.starts_with("EXPLAIN ANALYZE");
196+
is_explain && !is_explain_analyze
197+
}
198+
199+
#[cfg(test)]
200+
mod tests {
201+
use super::*;
202+
203+
#[test]
204+
fn test_is_explain_query() {
205+
// Test EXPLAIN queries (should return true)
206+
assert!(is_explain_query("EXPLAIN SELECT * FROM table"));
207+
assert!(is_explain_query("explain select * from table"));
208+
assert!(is_explain_query(" EXPLAIN SELECT 1"));
209+
assert!(is_explain_query("EXPLAIN\nSELECT * FROM test"));
210+
211+
// Test EXPLAIN ANALYZE queries (should return false)
212+
assert!(!is_explain_query("EXPLAIN ANALYZE SELECT * FROM table"));
213+
assert!(!is_explain_query("explain analyze SELECT * FROM table"));
214+
assert!(!is_explain_query(" EXPLAIN ANALYZE SELECT 1"));
215+
216+
// Test regular queries (should return false)
217+
assert!(!is_explain_query("SELECT * FROM table"));
218+
assert!(!is_explain_query("INSERT INTO table VALUES (1)"));
219+
assert!(!is_explain_query("UPDATE table SET col = 1"));
220+
assert!(!is_explain_query("DELETE FROM table"));
221+
assert!(!is_explain_query("CREATE TABLE test (id INT)"));
222+
223+
// Test edge cases
224+
assert!(!is_explain_query(""));
225+
assert!(!is_explain_query(" "));
226+
assert!(!is_explain_query("EXPLAINSELECT")); // No space
227+
assert!(is_explain_query("EXPLAIN")); // Just EXPLAIN
228+
}
229+
}

src/proxy_service.rs

Lines changed: 3 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ use tokio::{
4646
use tonic::{Request, Response, Status, async_trait, transport::Server};
4747

4848
use crate::{
49-
explain::DistributedExplainExec,
49+
explain::{DistributedExplainExec, is_explain_query},
5050
protobuf::DistributedExplainExecNode,
5151
flight::{FlightSqlHandler, FlightSqlServ},
5252
k8s::get_worker_addresses,
@@ -169,7 +169,7 @@ impl DfRayProxyHandler {
169169
/// This method only handles EXPLAIN queries (plan only). EXPLAIN ANALYZE queries are handled as regular queries because they need to be executed.
170170
pub async fn prepare_explain(&self, sql: &str) -> Result<QueryPlan> {
171171
// Validate that this is actually an EXPLAIN query (not EXPLAIN ANALYZE)
172-
if !self.is_explain_query(sql) {
172+
if !is_explain_query(sql) {
173173
return Err(anyhow!("prepare_explain called with non-EXPLAIN query or EXPLAIN ANALYZE query: {}", sql).into());
174174
}
175175

@@ -219,16 +219,6 @@ impl DfRayProxyHandler {
219219
})
220220
}
221221

222-
/// Check if this is an EXPLAIN query (but not EXPLAIN ANALYZE)
223-
fn is_explain_query(&self, query: &str) -> bool {
224-
let query_upper = query.trim().to_uppercase();
225-
// Must start with "EXPLAIN" followed by whitespace or end of string
226-
let is_explain = query_upper.starts_with("EXPLAIN") &&
227-
(query_upper.len() == 7 || query_upper.chars().nth(7).is_some_and(|c| c.is_whitespace()));
228-
let is_explain_analyze = query_upper.starts_with("EXPLAIN ANALYZE");
229-
is_explain && !is_explain_analyze
230-
}
231-
232222
/// Create a FlightInfo response with the given ticket data
233223
fn create_flight_info_response(
234224
&self,
@@ -480,7 +470,7 @@ impl FlightSqlHandler for DfRayProxyHandler {
480470
query: arrow_flight::sql::CommandStatementQuery,
481471
_request: Request<FlightDescriptor>,
482472
) -> Result<Response<FlightInfo>, Status> {
483-
let is_explain = self.is_explain_query(&query.query);
473+
let is_explain = is_explain_query(&query.query);
484474

485475
if is_explain {
486476
self.handle_explain_request(&query.query).await
@@ -662,35 +652,6 @@ mod tests {
662652
// Unit tests for helper functions
663653
// //////////////////////////////////////////////////////////////
664654

665-
#[test]
666-
fn test_is_explain_query() {
667-
let handler = create_test_handler();
668-
669-
// Test EXPLAIN queries (should return true)
670-
assert!(handler.is_explain_query("EXPLAIN SELECT * FROM table"));
671-
assert!(handler.is_explain_query("explain select * from table"));
672-
assert!(handler.is_explain_query(" EXPLAIN SELECT 1"));
673-
assert!(handler.is_explain_query("EXPLAIN\nSELECT * FROM test"));
674-
675-
// Test EXPLAIN ANALYZE queries (should return false)
676-
assert!(!handler.is_explain_query("EXPLAIN ANALYZE SELECT * FROM table"));
677-
assert!(!handler.is_explain_query("explain analyze SELECT * FROM table"));
678-
assert!(!handler.is_explain_query(" EXPLAIN ANALYZE SELECT 1"));
679-
680-
// Test regular queries (should return false)
681-
assert!(!handler.is_explain_query("SELECT * FROM table"));
682-
assert!(!handler.is_explain_query("INSERT INTO table VALUES (1)"));
683-
assert!(!handler.is_explain_query("UPDATE table SET col = 1"));
684-
assert!(!handler.is_explain_query("DELETE FROM table"));
685-
assert!(!handler.is_explain_query("CREATE TABLE test (id INT)"));
686-
687-
// Test edge cases
688-
assert!(!handler.is_explain_query(""));
689-
assert!(!handler.is_explain_query(" "));
690-
assert!(!handler.is_explain_query("EXPLAINSELECT")); // No space
691-
assert!(handler.is_explain_query("EXPLAIN")); // Just EXPLAIN
692-
}
693-
694655
#[test]
695656
fn test_validate_single_stage_addrs_success() {
696657
let handler = create_test_handler();

0 commit comments

Comments
 (0)