@@ -3,7 +3,7 @@ use crate::compile::{
33 StatusFlags ,
44} ;
55use sqlparser:: ast;
6- use std:: { collections:: HashMap , future :: Future , pin :: Pin , sync:: Arc , time:: SystemTime } ;
6+ use std:: { collections:: HashMap , sync:: Arc , time:: SystemTime } ;
77
88use crate :: {
99 compile:: {
@@ -30,7 +30,7 @@ use datafusion::{
3030 scalar:: ScalarValue ,
3131} ;
3232use itertools:: Itertools ;
33- use sqlparser:: ast:: { escape_single_quote_string, ObjectName } ;
33+ use sqlparser:: ast:: { escape_single_quote_string} ;
3434
3535#[ derive( Clone ) ]
3636pub struct QueryRouter {
@@ -108,6 +108,22 @@ impl QueryRouter {
108108 }
109109
110110 pub async fn plan (
111+ & self ,
112+ stmt : ast:: Statement ,
113+ qtrace : & mut Option < Qtrace > ,
114+ span_id : Option < Arc < SpanId > > ,
115+ ) -> CompilationResult < QueryPlan > {
116+ match stmt {
117+ ast:: Statement :: Explain { analyze, statement, verbose, .. } => self . explain_to_plan (
118+ statement,
119+ verbose,
120+ analyze
121+ ) . await ,
122+ other => self . plan_query ( & other, qtrace, span_id) . await ,
123+ }
124+ }
125+
126+ async fn plan_query (
111127 & self ,
112128 stmt : & ast:: Statement ,
113129 qtrace : & mut Option < Qtrace > ,
@@ -134,15 +150,6 @@ impl QueryRouter {
134150 ( ast:: Statement :: ShowVariable { variable } , _) => {
135151 self . show_variable_to_plan ( variable, span_id. clone ( ) ) . await
136152 }
137- (
138- ast:: Statement :: Explain {
139- statement,
140- verbose,
141- analyze,
142- ..
143- } ,
144- _,
145- ) => self . explain_to_plan ( & statement, * verbose, * analyze) . await ,
146153 ( ast:: Statement :: StartTransaction { .. } , DatabaseProtocol :: PostgreSQL ) => {
147154 // TODO: Real support
148155 Ok ( QueryPlan :: MetaOk (
@@ -260,68 +267,62 @@ impl QueryRouter {
260267 . await
261268 }
262269
263- fn explain_to_plan (
270+ async fn explain_to_plan (
264271 & self ,
265- statement : & Box < ast:: Statement > ,
272+ statement : Box < ast:: Statement > ,
266273 verbose : bool ,
267274 analyze : bool ,
268- ) -> Pin < Box < dyn Future < Output = Result < QueryPlan , CompilationError > > + Send > > {
269- let self_cloned = self . clone ( ) ;
270-
271- let statement = statement. clone ( ) ;
272- // This Boxing construct here because of recursive call to self.plan()
273- Box :: pin ( async move {
274- // TODO span_id ?
275- let plan = self_cloned. plan ( & statement, & mut None , None ) . await ?;
275+ ) -> Result < QueryPlan , CompilationError > {
276+ // TODO span_id ?
277+ let plan = self . plan_query ( & statement, & mut None , None ) . await ?;
276278
277- match plan {
278- QueryPlan :: MetaOk ( _, _) | QueryPlan :: MetaTabular ( _, _) => Ok ( QueryPlan :: MetaTabular (
279- StatusFlags :: empty ( ) ,
280- Box :: new ( dataframe:: DataFrame :: new (
281- vec ! [ dataframe:: Column :: new(
282- "Execution Plan" . to_string( ) ,
283- ColumnType :: String ,
284- ColumnFlags :: empty( ) ,
285- ) ] ,
286- vec ! [ dataframe:: Row :: new( vec![ dataframe:: TableValue :: String (
287- "This query doesnt have a plan, because it already has values for response"
288- . to_string( ) ,
289- ) ] ) ] ,
290- ) ) ,
279+ match plan {
280+ QueryPlan :: MetaOk ( _, _) | QueryPlan :: MetaTabular ( _, _) => Ok ( QueryPlan :: MetaTabular (
281+ StatusFlags :: empty ( ) ,
282+ Box :: new ( dataframe:: DataFrame :: new (
283+ vec ! [ dataframe:: Column :: new(
284+ "Execution Plan" . to_string( ) ,
285+ ColumnType :: String ,
286+ ColumnFlags :: empty( ) ,
287+ ) ] ,
288+ vec ! [ dataframe:: Row :: new( vec![ dataframe:: TableValue :: String (
289+ "This query doesnt have a plan, because it already has values for response"
290+ . to_string( ) ,
291+ ) ] ) ] ,
291292 ) ) ,
292- QueryPlan :: DataFusionSelect ( plan, context)
293- | QueryPlan :: CreateTempTable ( plan, context, _, _) => {
294- // EXPLAIN over CREATE TABLE AS shows the SELECT query plan
295- let plan = Arc :: new ( plan) ;
296- let schema = LogicalPlan :: explain_schema ( ) ;
297- let schema = schema. to_dfschema_ref ( ) . map_err ( |err| {
298- CompilationError :: internal ( format ! (
299- "Unable to get DF schema for explain plan: {}" ,
300- err
301- ) )
302- } ) ?;
303-
304- let explain_plan = if analyze {
305- LogicalPlan :: Analyze ( Analyze {
306- verbose,
307- input : plan,
308- schema,
309- } )
310- } else {
311- let stringified_plans = vec ! [ plan. to_stringified( PlanType :: InitialLogicalPlan ) ] ;
312-
313- LogicalPlan :: Explain ( Explain {
314- verbose,
315- plan,
316- stringified_plans,
317- schema,
318- } )
319- } ;
293+ ) ) ,
294+ QueryPlan :: DataFusionSelect ( plan, context)
295+ | QueryPlan :: CreateTempTable ( plan, context, _, _) => {
296+ // EXPLAIN over CREATE TABLE AS shows the SELECT query plan
297+ let plan = Arc :: new ( plan) ;
298+ let schema = LogicalPlan :: explain_schema ( ) ;
299+ let schema = schema. to_dfschema_ref ( ) . map_err ( |err| {
300+ CompilationError :: internal ( format ! (
301+ "Unable to get DF schema for explain plan: {}" ,
302+ err
303+ ) )
304+ } ) ?;
320305
321- Ok ( QueryPlan :: DataFusionSelect ( explain_plan, context) )
322- }
306+ let explain_plan = if analyze {
307+ LogicalPlan :: Analyze ( Analyze {
308+ verbose,
309+ input : plan,
310+ schema,
311+ } )
312+ } else {
313+ let stringified_plans = vec ! [ plan. to_stringified( PlanType :: InitialLogicalPlan ) ] ;
314+
315+ LogicalPlan :: Explain ( Explain {
316+ verbose,
317+ plan,
318+ stringified_plans,
319+ schema,
320+ } )
321+ } ;
322+
323+ Ok ( QueryPlan :: DataFusionSelect ( explain_plan, context) )
323324 }
324- } )
325+ }
325326 }
326327
327328 fn set_role_to_plan (
@@ -535,7 +536,7 @@ impl QueryRouter {
535536 ) ) ;
536537 } ;
537538
538- let ObjectName ( ident_parts) = name;
539+ let ast :: ObjectName ( ident_parts) = name;
539540 let Some ( table_name) = ident_parts. last ( ) else {
540541 return Err ( CompilationError :: internal (
541542 "table name contains no ident parts" . to_string ( ) ,
@@ -585,7 +586,7 @@ impl QueryRouter {
585586 "DROP TABLE supports dropping only one table at a time" . to_string ( ) ,
586587 ) ) ;
587588 }
588- let ObjectName ( ident_parts) = names. first ( ) . unwrap ( ) ;
589+ let ast :: ObjectName ( ident_parts) = names. first ( ) . unwrap ( ) ;
589590 let Some ( table_name) = ident_parts. last ( ) else {
590591 return Err ( CompilationError :: internal (
591592 "table name contains no ident parts" . to_string ( ) ,
@@ -674,7 +675,7 @@ pub async fn convert_statement_to_cube_query(
674675 }
675676
676677 let planner = QueryRouter :: new ( session. state . clone ( ) , meta, session. session_manager . clone ( ) ) ;
677- planner. plan ( & stmt, qtrace, span_id) . await
678+ planner. plan ( stmt, qtrace, span_id) . await
678679}
679680
680681pub async fn convert_sql_to_cube_query (
0 commit comments