use std::sync::Arc;
use std::{any::Any, borrow::Cow};
use crate::TableProvider;
use arrow::datatypes::SchemaRef;
use datafusion_common::{internal_err, Constraints};
use datafusion_expr::{Expr, TableProviderFilterPushDown, TableSource, TableType};
pub struct DefaultTableSource {
pub table_provider: Arc<dyn TableProvider>,
}
impl DefaultTableSource {
pub fn new(table_provider: Arc<dyn TableProvider>) -> Self {
Self { table_provider }
}
}
impl TableSource for DefaultTableSource {
fn as_any(&self) -> &dyn Any {
self
}
fn schema(&self) -> SchemaRef {
self.table_provider.schema()
}
fn constraints(&self) -> Option<&Constraints> {
self.table_provider.constraints()
}
fn table_type(&self) -> TableType {
self.table_provider.table_type()
}
fn supports_filters_pushdown(
&self,
filter: &[&Expr],
) -> datafusion_common::Result<Vec<TableProviderFilterPushDown>> {
self.table_provider.supports_filters_pushdown(filter)
}
fn get_logical_plan(&self) -> Option<Cow<datafusion_expr::LogicalPlan>> {
self.table_provider.get_logical_plan()
}
fn get_column_default(&self, column: &str) -> Option<&Expr> {
self.table_provider.get_column_default(column)
}
}
pub fn provider_as_source(
table_provider: Arc<dyn TableProvider>,
) -> Arc<dyn TableSource> {
Arc::new(DefaultTableSource::new(table_provider))
}
pub fn source_as_provider(
source: &Arc<dyn TableSource>,
) -> datafusion_common::Result<Arc<dyn TableProvider>> {
match source
.as_ref()
.as_any()
.downcast_ref::<DefaultTableSource>()
{
Some(source) => Ok(Arc::clone(&source.table_provider)),
_ => internal_err!("TableSource was not DefaultTableSource"),
}
}
#[test]
fn preserves_table_type() {
use async_trait::async_trait;
use datafusion_common::DataFusionError;
#[derive(Debug)]
struct TestTempTable;
#[async_trait]
impl TableProvider for TestTempTable {
fn as_any(&self) -> &dyn Any {
self
}
fn table_type(&self) -> TableType {
TableType::Temporary
}
fn schema(&self) -> SchemaRef {
unimplemented!()
}
async fn scan(
&self,
_: &dyn crate::Session,
_: Option<&Vec<usize>>,
_: &[Expr],
_: Option<usize>,
) -> Result<Arc<dyn datafusion_physical_plan::ExecutionPlan>, DataFusionError>
{
unimplemented!()
}
}
let table_source = DefaultTableSource::new(Arc::new(TestTempTable));
assert_eq!(table_source.table_type(), TableType::Temporary);
}