// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License.  You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied.  See the License for the
// specific language governing permissions and limitations
// under the License.

//! See `main.rs` for how to run it.

use arrow::datatypes::{DataType, Field, Schema, SchemaRef};
use datafusion::common::{plan_err, TableReference};
use datafusion::config::ConfigOptions;
use datafusion::error::Result;
use datafusion::logical_expr::{
    AggregateUDF, Expr, LogicalPlan, ScalarUDF, TableProviderFilterPushDown, TableSource,
    WindowUDF,
};
use datafusion::optimizer::{
    Analyzer, AnalyzerRule, Optimizer, OptimizerConfig, OptimizerContext, OptimizerRule,
};
use datafusion::sql::planner::{ContextProvider, SqlToRel};
use datafusion::sql::sqlparser::dialect::PostgreSqlDialect;
use datafusion::sql::sqlparser::parser::Parser;
use std::any::Any;
use std::sync::Arc;

/// This example shows how to use DataFusion's SQL planner to parse SQL text and
/// build `LogicalPlan`s without executing them.
///
/// For example, if you need a SQL planner and optimizer like Apache Calcite,
/// but do not want a Java runtime dependency for some reason, you could use
/// DataFusion as a SQL frontend.
///
/// Normally, users interact with DataFusion via SessionContext. However, using
/// SessionContext requires depending on the full `datafusion` core crate.
///
/// In this example, we demonstrate how to use the lower level APIs directly,
/// which only requires the `datafusion-sql` dependency.
pub fn frontend() -> Result<()> {
    // First, we parse the SQL string. Note that we use the DataFusion
    // Parser, which wraps the `sqlparser-rs` SQL parser and adds DataFusion
    // specific syntax such as `CREATE EXTERNAL TABLE`
    let dialect = PostgreSqlDialect {};
    let sql = "SELECT name FROM person WHERE age BETWEEN 21 AND 32";
    let statements = Parser::parse_sql(&dialect, sql)?;

    // Now, use DataFusion's SQL planner, called `SqlToRel` to create a
    // `LogicalPlan` from the parsed statement
    //
    // To invoke SqlToRel we must provide it schema and function information
    // via an object that implements the `ContextProvider` trait
    let context_provider = MyContextProvider::default();
    let sql_to_rel = SqlToRel::new(&context_provider);
    let logical_plan = sql_to_rel.sql_statement_to_plan(statements[0].clone())?;

    // Here is the logical plan that was generated:
    assert_eq!(
        logical_plan.display_indent().to_string(),
        "Projection: person.name\
        \n  Filter: person.age BETWEEN Int64(21) AND Int64(32)\
        \n    TableScan: person"
    );

    // The initial LogicalPlan is a mechanical translation from the parsed SQL
    // and often can not run without the Analyzer passes.
    //
    // In this example, `person.age` is actually a different data type (Int8)
    // than the values to which it is compared to which are Int64. Most
    // execution engines, including DataFusion's, will fail if you provide such
    // a plan.
    //
    // To prepare it to run, we must apply type coercion to align types, and
    // check for other semantic errors. In DataFusion this is done by a
    // component called the Analyzer.
    let config = OptimizerContext::default().with_skip_failing_rules(false);
    let analyzed_plan = Analyzer::new().execute_and_check(
        logical_plan,
        &config.options(),
        observe_analyzer,
    )?;
    // Note that the Analyzer has added a CAST to the plan to align the types
    assert_eq!(
        analyzed_plan.display_indent().to_string(),
        "Projection: person.name\
        \n  Filter: CAST(person.age AS Int64) BETWEEN Int64(21) AND Int64(32)\
        \n    TableScan: person",
    );

    // As we can see, the Analyzer added a CAST so the types are the same
    // (Int64). However, this plan is not as efficient as it could be, as it
    // will require casting *each row* of the input to UInt64 before comparison
    // to 21 and 32. To optimize this query's performance, it is better to cast
    // the constants once at plan time to UInt8.
    //
    // Query optimization is handled in DataFusion by a component called the
    // Optimizer, which we now invoke
    //
    let optimized_plan =
        Optimizer::new().optimize(analyzed_plan, &config, observe_optimizer)?;

    // Show the fully optimized plan. Note that the optimizer did several things
    // to prepare this plan for execution:
    //
    // 1. Removed casts from person.age as we described above
    // 2. Converted BETWEEN to two single column inequalities (which are typically faster to execute)
    // 3. Pushed the projection of `name` down to the scan (so the scan only returns that column)
    // 4. Pushed the filter into the scan
    // 5. Removed the projection as it was only serving to pass through the name column
    assert_eq!(
        optimized_plan.display_indent().to_string(),
        "TableScan: person projection=[name], full_filters=[person.age >= UInt8(21), person.age <= UInt8(32)]"
    );

    Ok(())
}

// Note that both the optimizer and the analyzer take a callback, called an
// "observer" that is invoked after each pass. We do not do anything with these
// callbacks in this example

fn observe_analyzer(_plan: &LogicalPlan, _rule: &dyn AnalyzerRule) {}
fn observe_optimizer(_plan: &LogicalPlan, _rule: &dyn OptimizerRule) {}

/// Implements the `ContextProvider` trait required to plan SQL
#[derive(Default)]
struct MyContextProvider {
    options: ConfigOptions,
}

impl ContextProvider for MyContextProvider {
    fn get_table_source(&self, name: TableReference) -> Result<Arc<dyn TableSource>> {
        if name.table() == "person" {
            Ok(Arc::new(MyTableSource {
                schema: Arc::new(Schema::new(vec![
                    Field::new("name", DataType::Utf8, false),
                    Field::new("age", DataType::UInt8, false),
                ])),
            }))
        } else {
            plan_err!("Table {} not found", name.table())
        }
    }

    fn get_function_meta(&self, _name: &str) -> Option<Arc<ScalarUDF>> {
        None
    }

    fn get_aggregate_meta(&self, _name: &str) -> Option<Arc<AggregateUDF>> {
        None
    }

    fn get_variable_type(&self, _variable_names: &[String]) -> Option<DataType> {
        None
    }

    fn get_window_meta(&self, _name: &str) -> Option<Arc<WindowUDF>> {
        None
    }

    fn options(&self) -> &ConfigOptions {
        &self.options
    }

    fn udf_names(&self) -> Vec<String> {
        Vec::new()
    }

    fn udaf_names(&self) -> Vec<String> {
        Vec::new()
    }

    fn udwf_names(&self) -> Vec<String> {
        Vec::new()
    }
}

/// TableSource is the part of TableProvider needed for creating a LogicalPlan.
struct MyTableSource {
    schema: SchemaRef,
}

impl TableSource for MyTableSource {
    fn as_any(&self) -> &dyn Any {
        self
    }

    fn schema(&self) -> SchemaRef {
        self.schema.clone()
    }

    // For this example, we report to the DataFusion optimizer that
    // this provider can apply filters during the scan
    fn supports_filters_pushdown(
        &self,
        filters: &[&Expr],
    ) -> Result<Vec<TableProviderFilterPushDown>> {
        Ok(vec![TableProviderFilterPushDown::Exact; filters.len()])
    }
}
