pub fn select_to_plan(
        &self,
        stmt: &ast::Statement,
        q: &Box<ast::Query>,
        connection_state: Arc<ConnectionState>,
    ) -> CompilationResult<QueryPlan> {
        let select = match &q.body {
            sqlparser::ast::SetExpr::Select(select) => select,
            _ => {
                return Err(CompilationError::Unsupported(
                    "Unsupported Query".to_string(),
                ));
            }
        };

        let from_table = if select.from.len() == 1 {
            &select.from[0]
        } else {
            return self.create_df_logical_plan(stmt.clone(), connection_state);
        };

        let (schema_name, table_name) = match &from_table.relation {
            ast::TableFactor::Table { name, .. } => match name {
                ast::ObjectName(identifiers) => {
                    if identifiers.len() == 2 {
                        // db.`KibanaSampleDataEcommerce`
                        (identifiers[0].value.clone(), identifiers[1].value.clone())
                    } else if identifiers.len() == 1 {
                        // `KibanaSampleDataEcommerce`
                        ("db".to_string(), identifiers[0].value.clone())
                    } else {
                        return Err(CompilationError::Unsupported(
                            "Query with multiple tables in from".to_string(),
                        ));
                    }
                }
            },
            factor => {
                return Err(CompilationError::Unsupported(format!(
                    "table factor: {:?}",
                    factor
                )));
            }
        };

        if schema_name.to_lowercase() == "information_schema"
            || schema_name.to_lowercase() == "performance_schema"
        {
            return self.create_df_logical_plan(stmt.clone(), connection_state);
        }

        if !select.from[0].joins.is_empty() {
            return Err(CompilationError::Unsupported(
                "Query with JOIN instruction(s)".to_string(),
            ));
        }

        if q.with.is_some() {
            return Err(CompilationError::Unsupported(
                "Query with CTE instruction(s)".to_string(),
            ));
        }

        if !select.cluster_by.is_empty() {
            return Err(CompilationError::Unsupported(
                "Query with CLUSTER BY instruction(s)".to_string(),
            ));
        }

        if !select.distribute_by.is_empty() {
            return Err(CompilationError::Unsupported(
                "Query with DISTRIBUTE BY instruction(s)".to_string(),
            ));
        }

        if select.having.is_some() {
            return Err(CompilationError::Unsupported(
                "Query with HAVING instruction(s)".to_string(),
            ));
        }

        if schema_name.to_lowercase() != "db" {
            return Err(CompilationError::Unsupported(format!(
                "Unable to access schema {}",
                schema_name
            )));
        }

        // @todo Better solution?
        // Metabase
        if q.to_string()
            == format!(
                "SELECT true AS `_` FROM `{}` WHERE 1 <> 1 LIMIT 0",
                table_name
            )
        {
            return Ok(QueryPlan::MetaTabular(
                StatusFlags::empty(),
                Arc::new(dataframe::DataFrame::new(
                    vec![dataframe::Column::new(
                        "_".to_string(),
                        ColumnType::MYSQL_TYPE_TINY,
                        ColumnFlags::empty(),
                    )],
                    vec![],
                )),
            ));
        };

        if let Some(cube) = self.context.find_cube_with_name(table_name.clone()) {
            let mut ctx = QueryContext::new(&cube);
            let mut builder = compile_select(select, &mut ctx)?;

            if let Some(limit_expr) = &q.limit {
                let limit = limit_expr.to_string().parse::<i32>().map_err(|e| {
                    CompilationError::Unsupported(format!(
                        "Unable to parse limit: {}",
                        e.to_string()
                    ))
                })?;

                builder.with_limit(limit);
            }

            if let Some(offset_expr) = &q.offset {
                let offset = offset_expr.value.to_string().parse::<i32>().map_err(|e| {
                    CompilationError::Unsupported(format!(
                        "Unable to parse offset: {}",
                        e.to_string()
                    ))
                })?;

                builder.with_offset(offset);
            }

            compile_group(&select.group_by, &ctx, &mut builder)?;
            compile_order(&q.order_by, &ctx, &mut builder)?;

            if let Some(selection) = &select.selection {
                compile_where(selection, &ctx, &mut builder)?;
            }

            Ok(QueryPlan::CubeSelect(StatusFlags::empty(), builder.build()))
        } else {
            Err(CompilationError::Unknown(format!(
                "Unknown cube '{}'. Please ensure your schema files are valid.",
                table_name,
            )))
        }
    }
/// Common case for both planners: meta & olap
/// This method tries to detect what planner to use as earlier as possible
/// and forward context to correct planner
Common case for both planners: meta & olap
This method tries to detect what planner to use as earlier as possible
and forward context to correct planner
Common case for both planners : meta & olap This method tries to detect what planner to use as earlier as possible and forward context to correct planner
pub fn select_to_plan(
        &self,
        stmt: &ast::Statement,
        q: &Box<ast::Query>,
        connection_state: Arc<ConnectionState>,
    ) -> CompilationResult<QueryPlan> {
        let select = match &q.body {
            sqlparser::ast::SetExpr::Select(select) => select,
            _ => {
                return Err(CompilationError::Unsupported(
                    "Unsupported Query".to_string(),
                ));
            }
        };
        let from_table = if select.from.len() == 1 {
            &select.from[0]
        } else {
            return self.create_df_logical_plan(stmt.clone(), connection_state);
        };
        let (schema_name, table_name) = match &from_table.relation {
            ast::TableFactor::Table { name, .. } => match name {
                ast::ObjectName(identifiers) => {
                    if identifiers.len() == 2 {
                        // db.`KibanaSampleDataEcommerce`
                        (identifiers[0].value.clone(), identifiers[1].value.clone())
                    } else if identifiers.len() == 1 {
                        // `KibanaSampleDataEcommerce`
                        ("db".to_string(), identifiers[0].value.clone())
                    } else {
                        return Err(CompilationError::Unsupported(
                            "Query with multiple tables in from".to_string(),
                        ));
                    }
                }
            },
            factor => {
                return Err(CompilationError::Unsupported(format!(
                    "table factor: {:?}",
                    factor
                )));
            }
        };
        if schema_name.to_lowercase() == "information_schema"
            || schema_name.to_lowercase() == "performance_schema"
        {
            return self.create_df_logical_plan(stmt.clone(), connection_state);
        }
        if !select.from[0].joins.is_empty() {
            return Err(CompilationError::Unsupported(
                "Query with JOIN instruction(s)".to_string(),
            ));
        }
        if q.with.is_some() {
            return Err(CompilationError::Unsupported(
                "Query with CTE instruction(s)".to_string(),
            ));
        }
        if !select.cluster_by.is_empty() {
            return Err(CompilationError::Unsupported(
                "Query with CLUSTER BY instruction(s)".to_string(),
            ));
        }
        if !select.distribute_by.is_empty() {
            return Err(CompilationError::Unsupported(
                "Query with DISTRIBUTE BY instruction(s)".to_string(),
            ));
        }
        if select.having.is_some() {
            return Err(CompilationError::Unsupported(
                "Query with HAVING instruction(s)".to_string(),
            ));
        }
        if schema_name.to_lowercase() != "db" {
            return Err(CompilationError::Unsupported(format!(
                "Unable to access schema {}",
                schema_name
            )));
        }
        // @todo Better solution?
        // Metabase
        if q.to_string()
            == format!(
                "SELECT true AS `_` FROM `{}` WHERE 1 <> 1 LIMIT 0",
                table_name
            )
        {
            return Ok(QueryPlan::MetaTabular(
                StatusFlags::empty(),
                Arc::new(dataframe::DataFrame::new(
                    vec![dataframe::Column::new(
                        "_".to_string(),
                        ColumnType::MYSQL_TYPE_TINY,
                        ColumnFlags::empty(),
                    )],
                    vec![],
                )),
            ));
        };
        if let Some(cube) = self.context.find_cube_with_name(table_name.clone()) {
            let mut ctx = QueryContext::new(&cube);
            let mut builder = compile_select(select, &mut ctx)?;
            if let Some(limit_expr) = &q.limit {
                let limit = limit_expr.to_string().parse::<i32>().map_err(|e| {
                    CompilationError::Unsupported(format!(
                        "Unable to parse limit: {}",
                        e.to_string()
                    ))
                })?;
                builder.with_limit(limit);
            }
            if let Some(offset_expr) = &q.offset {
                let offset = offset_expr.value.to_string().parse::<i32>().map_err(|e| {
                    CompilationError::Unsupported(format!(
                        "Unable to parse offset: {}",
                        e.to_string()
                    ))
                })?;
                builder.with_offset(offset);
            }
            compile_group(&select.group_by, &ctx, &mut builder)?;
            compile_order(&q.order_by, &ctx, &mut builder)?;
            if let Some(selection) = &select.selection {
                compile_where(selection, &ctx, &mut builder)?;
            }
            Ok(QueryPlan::CubeSelect(StatusFlags::empty(), builder.build()))
        } else {
            Err(CompilationError::Unknown(format!(
                "Unknown cube '{}'. Please ensure your schema files are valid.",
                table_name,
            )))
        }
    }
pub fn select_to_plan ( & self , stmt : & ast :: Statement , q : & Box < ast :: Query > , connection_state : Arc < ConnectionState > , ) -> CompilationResult < QueryPlan > { let select = match & q . body { sqlparser :: ast :: SetExpr :: Select ( select ) => select , _ => { return Err ( CompilationError :: Unsupported ( " " . to_string ( ) , ) ) ; } } ; let from_table = if select . from . len ( ) == 1 { & select . from [ 0 ] } else { return self . create_df_logical_plan ( stmt . clone ( ) , connection_state ) ; } ; let ( schema_name , table_name ) = match & from_table . relation { ast :: TableFactor :: Table { name , .. } => match name { ast :: ObjectName ( identifiers ) => { if identifiers . len ( ) == 2 { // db.`KibanaSampleDataEcommerce` ( identifiers [ 0 ] . value . clone ( ) , identifiers [ 1 ] . value . clone ( ) ) } else if identifiers . len ( ) == 1 { // `KibanaSampleDataEcommerce` ( " " . to_string ( ) , identifiers [ 0 ] . value . clone ( ) ) } else { return Err ( CompilationError :: Unsupported ( " " . to_string ( ) , ) ) ; } } } , factor => { return Err ( CompilationError :: Unsupported ( format ! ( " " factor ) ) ) ; } } ; if schema_name . to_lowercase ( ) == " " || schema_name . to_lowercase ( ) == " " { return self . create_df_logical_plan ( stmt . clone ( ) , connection_state ) ; } if ! select . from [ 0 ] . joins . is_empty ( ) { return Err ( CompilationError :: Unsupported ( " " . to_string ( ) , ) ) ; } if q . with . is_some ( ) { return Err ( CompilationError :: Unsupported ( " " . to_string ( ) , ) ) ; } if ! select . cluster_by . is_empty ( ) { return Err ( CompilationError :: Unsupported ( " " . to_string ( ) , ) ) ; } if ! select . distribute_by . is_empty ( ) { return Err ( CompilationError :: Unsupported ( " " . to_string ( ) , ) ) ; } if select . having . is_some ( ) { return Err ( CompilationError :: Unsupported ( " " . to_string ( ) , ) ) ; } if schema_name . to_lowercase ( ) != " " { return Err ( CompilationError :: Unsupported ( format ! ( " " schema_name ) ) ) ; } // @todo Better solution? // Metabase if q . to_string ( ) == format ! ( " " table_name ) { return Ok ( QueryPlan :: MetaTabular ( StatusFlags :: empty ( ) , Arc :: new ( dataframe :: DataFrame :: new ( vec ! [ dataframe Column new ( " " to_string ( ) ColumnType MYSQL_TYPE_TINY ColumnFlags empty ( ) ) ] , vec ! [ ] , ) ) , ) ) ; } ; if let Some ( cube ) = self . context . find_cube_with_name ( table_name . clone ( ) ) { let mut ctx = QueryContext :: new ( & cube ) ; let mut builder = compile_select ( select , & mut ctx ) ? ; if let Some ( limit_expr ) = & q . limit { let limit = limit_expr . to_string ( ) . parse :: < i32 > ( ) . map_err ( | e | { CompilationError :: Unsupported ( format ! ( " " e to_string ( ) ) ) } ) ? ; builder . with_limit ( limit ) ; } if let Some ( offset_expr ) = & q . offset { let offset = offset_expr . value . to_string ( ) . parse :: < i32 > ( ) . map_err ( | e | { CompilationError :: Unsupported ( format ! ( " " e to_string ( ) ) ) } ) ? ; builder . with_offset ( offset ) ; } compile_group ( & select . group_by , & ctx , & mut builder ) ? ; compile_order ( & q . order_by , & ctx , & mut builder ) ? ; if let Some ( selection ) = & select . selection { compile_where ( selection , & ctx , & mut builder ) ? ; } Ok ( QueryPlan :: CubeSelect ( StatusFlags :: empty ( ) , builder . build ( ) ) ) } else { Err ( CompilationError :: Unknown ( format ! ( " " table_name ) ) ) } }
Common case for both planners: meta & olap
This method tries to detect what planner to use as earlier as possible
and forward context to correct planner
Common case for both planners : meta & olap This method tries to detect what planner to use as earlier as possible and forward context to correct planner
&self
stmt
&ast::Statement
q
&Box<ast::Query>
connection_state
Arc<ConnectionState>
&self
stmt
&ast::Statement
q
&Box<ast::Query>
connection_state
Arc<ConnectionState>