// 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.

//! Table source

use crate::{Expr, LogicalPlan};

use arrow::datatypes::SchemaRef;
use datafusion_common::{Constraints, Result};

use std::{any::Any, borrow::Cow};

/// Indicates how a filter expression is handled by
/// [`TableProvider::scan`].
///
/// Filter expressions are boolean expressions used to reduce the number of
/// rows that are read from a table. Only rows that evaluate to `true` ("pass
/// the filter") are returned. Rows that evaluate to `false` or `NULL` are
/// omitted.
///
/// [`TableProvider::scan`]: https://docs.rs/datafusion/latest/datafusion/datasource/trait.TableProvider.html#tymethod.scan
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum TableProviderFilterPushDown {
    /// The filter cannot be used by the provider and will not be pushed down.
    Unsupported,
    /// The filter can be used, but the provider might still return some tuples
    /// that do not pass the filter.
    ///
    /// In this case, DataFusion applies an additional `Filter` operation
    /// after the scan to ensure all rows are filtered correctly.
    Inexact,
    /// The provider **guarantees** that it will omit **only** tuples which
    /// pass the filter.
    ///
    /// In this case, DataFusion will not apply additional filtering.
    Exact,
}

/// Indicates the type of this table for metadata/catalog purposes.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum TableType {
    /// An ordinary physical table.
    Base,
    /// A non-materialized table that itself uses a query internally to provide data.
    View,
    /// A transient table.
    Temporary,
}

impl std::fmt::Display for TableType {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        match self {
            TableType::Base => write!(f, "Base"),
            TableType::View => write!(f, "View"),
            TableType::Temporary => write!(f, "Temporary"),
        }
    }
}

/// Planning time information about a table.
///
/// This trait is used during logical query planning and optimizations, and
/// provides a subset of the [`TableProvider`] trait, such as schema information
/// and filter push-down capabilities. The [`TableProvider`] trait provides
/// additional information needed for physical query execution, such as the
/// ability to perform a scan or insert data.
///
/// # See Also:
///
/// [`DefaultTableSource`]  to go from [`TableProvider`], to `TableSource`
///
/// # Rationale
///
/// The reason for having two separate traits is to avoid having the logical
/// plan code be dependent on the DataFusion execution engine. Some projects use
/// DataFusion's logical plans and have their own execution engine.
///
/// [`TableProvider`]: https://docs.rs/datafusion/latest/datafusion/datasource/trait.TableProvider.html
/// [`DefaultTableSource`]: https://docs.rs/datafusion/latest/datafusion/datasource/default_table_source/struct.DefaultTableSource.html
pub trait TableSource: Sync + Send {
    fn as_any(&self) -> &dyn Any;

    /// Get a reference to the schema for this table
    fn schema(&self) -> SchemaRef;

    /// Get primary key indices, if any
    fn constraints(&self) -> Option<&Constraints> {
        None
    }

    /// Get the type of this table for metadata/catalog purposes.
    fn table_type(&self) -> TableType {
        TableType::Base
    }

    /// Tests whether the table provider can make use of any or all filter expressions
    /// to optimize data retrieval. Only non-volatile expressions are passed to this function.
    fn supports_filters_pushdown(
        &self,
        filters: &[&Expr],
    ) -> Result<Vec<TableProviderFilterPushDown>> {
        Ok((0..filters.len())
            .map(|_| TableProviderFilterPushDown::Unsupported)
            .collect())
    }

    /// Get the Logical plan of this table provider, if available.
    ///
    /// For example, a view may have a logical plan, but a CSV file does not.
    fn get_logical_plan(&'_ self) -> Option<Cow<'_, LogicalPlan>> {
        None
    }

    /// Get the default value for a column, if available.
    fn get_column_default(&self, _column: &str) -> Option<&Expr> {
        None
    }
}
