This is an automated email from the ASF dual-hosted git repository.

alamb pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/datafusion.git


The following commit(s) were added to refs/heads/main by this push:
     new a4796fa078 Minor: Move MemoryCatalog*Provider into a module, improve 
comments (#11183)
a4796fa078 is described below

commit a4796fa07893cc4db6b6c0f92dab85d2720a52c4
Author: Andrew Lamb <[email protected]>
AuthorDate: Tue Jul 2 12:39:05 2024 -0400

    Minor: Move MemoryCatalog*Provider into a module, improve comments (#11183)
    
    * Minor: Move MemoryCatalog*Provider into a module, improve comments
    
    * fix docs
---
 datafusion/core/src/catalog/information_schema.rs |   2 +-
 datafusion/core/src/catalog/listing_schema.rs     |   2 +-
 datafusion/core/src/catalog/memory.rs             | 352 ++++++++++++++++++++++
 datafusion/core/src/catalog/mod.rs                | 193 ++----------
 datafusion/core/src/catalog/schema.rs             | 155 +---------
 datafusion/core/src/lib.rs                        |   2 +-
 6 files changed, 375 insertions(+), 331 deletions(-)

diff --git a/datafusion/core/src/catalog/information_schema.rs 
b/datafusion/core/src/catalog/information_schema.rs
index a9d4590a5e..c953de6d16 100644
--- a/datafusion/core/src/catalog/information_schema.rs
+++ b/datafusion/core/src/catalog/information_schema.rs
@@ -15,7 +15,7 @@
 // specific language governing permissions and limitations
 // under the License.
 
-//! Implements the SQL [Information Schema] for DataFusion.
+//! [`InformationSchemaProvider`] that implements the SQL [Information Schema] 
for DataFusion.
 //!
 //! [Information Schema]: https://en.wikipedia.org/wiki/Information_schema
 
diff --git a/datafusion/core/src/catalog/listing_schema.rs 
b/datafusion/core/src/catalog/listing_schema.rs
index 29f3e4ad81..373fe788c7 100644
--- a/datafusion/core/src/catalog/listing_schema.rs
+++ b/datafusion/core/src/catalog/listing_schema.rs
@@ -15,7 +15,7 @@
 // specific language governing permissions and limitations
 // under the License.
 
-//! listing_schema contains a SchemaProvider that scans ObjectStores for 
tables automatically
+//! [`ListingSchemaProvider`]: [`SchemaProvider`] that scans ObjectStores for 
tables automatically
 
 use std::any::Any;
 use std::collections::{HashMap, HashSet};
diff --git a/datafusion/core/src/catalog/memory.rs 
b/datafusion/core/src/catalog/memory.rs
new file mode 100644
index 0000000000..3af823913a
--- /dev/null
+++ b/datafusion/core/src/catalog/memory.rs
@@ -0,0 +1,352 @@
+// 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.
+
+//! [`MemoryCatalogProvider`], [`MemoryCatalogProviderList`]: In-memory
+//! implementations of [`CatalogProviderList`] and [`CatalogProvider`].
+
+use crate::catalog::schema::SchemaProvider;
+use crate::catalog::{CatalogProvider, CatalogProviderList};
+use crate::datasource::TableProvider;
+use async_trait::async_trait;
+use dashmap::DashMap;
+use datafusion_common::{exec_err, DataFusionError};
+use std::any::Any;
+use std::sync::Arc;
+
+/// Simple in-memory list of catalogs
+pub struct MemoryCatalogProviderList {
+    /// Collection of catalogs containing schemas and ultimately TableProviders
+    pub catalogs: DashMap<String, Arc<dyn CatalogProvider>>,
+}
+
+impl MemoryCatalogProviderList {
+    /// Instantiates a new `MemoryCatalogProviderList` with an empty 
collection of catalogs
+    pub fn new() -> Self {
+        Self {
+            catalogs: DashMap::new(),
+        }
+    }
+}
+
+impl Default for MemoryCatalogProviderList {
+    fn default() -> Self {
+        Self::new()
+    }
+}
+
+impl CatalogProviderList for MemoryCatalogProviderList {
+    fn as_any(&self) -> &dyn Any {
+        self
+    }
+
+    fn register_catalog(
+        &self,
+        name: String,
+        catalog: Arc<dyn CatalogProvider>,
+    ) -> Option<Arc<dyn CatalogProvider>> {
+        self.catalogs.insert(name, catalog)
+    }
+
+    fn catalog_names(&self) -> Vec<String> {
+        self.catalogs.iter().map(|c| c.key().clone()).collect()
+    }
+
+    fn catalog(&self, name: &str) -> Option<Arc<dyn CatalogProvider>> {
+        self.catalogs.get(name).map(|c| c.value().clone())
+    }
+}
+
+/// Simple in-memory implementation of a catalog.
+pub struct MemoryCatalogProvider {
+    schemas: DashMap<String, Arc<dyn SchemaProvider>>,
+}
+
+impl MemoryCatalogProvider {
+    /// Instantiates a new MemoryCatalogProvider with an empty collection of 
schemas.
+    pub fn new() -> Self {
+        Self {
+            schemas: DashMap::new(),
+        }
+    }
+}
+
+impl Default for MemoryCatalogProvider {
+    fn default() -> Self {
+        Self::new()
+    }
+}
+
+impl CatalogProvider for MemoryCatalogProvider {
+    fn as_any(&self) -> &dyn Any {
+        self
+    }
+
+    fn schema_names(&self) -> Vec<String> {
+        self.schemas.iter().map(|s| s.key().clone()).collect()
+    }
+
+    fn schema(&self, name: &str) -> Option<Arc<dyn SchemaProvider>> {
+        self.schemas.get(name).map(|s| s.value().clone())
+    }
+
+    fn register_schema(
+        &self,
+        name: &str,
+        schema: Arc<dyn SchemaProvider>,
+    ) -> datafusion_common::Result<Option<Arc<dyn SchemaProvider>>> {
+        Ok(self.schemas.insert(name.into(), schema))
+    }
+
+    fn deregister_schema(
+        &self,
+        name: &str,
+        cascade: bool,
+    ) -> datafusion_common::Result<Option<Arc<dyn SchemaProvider>>> {
+        if let Some(schema) = self.schema(name) {
+            let table_names = schema.table_names();
+            match (table_names.is_empty(), cascade) {
+                (true, _) | (false, true) => {
+                    let (_, removed) = self.schemas.remove(name).unwrap();
+                    Ok(Some(removed))
+                }
+                (false, false) => exec_err!(
+                    "Cannot drop schema {} because other tables depend on it: 
{}",
+                    name,
+                    itertools::join(table_names.iter(), ", ")
+                ),
+            }
+        } else {
+            Ok(None)
+        }
+    }
+}
+
+/// Simple in-memory implementation of a schema.
+pub struct MemorySchemaProvider {
+    tables: DashMap<String, Arc<dyn TableProvider>>,
+}
+
+impl MemorySchemaProvider {
+    /// Instantiates a new MemorySchemaProvider with an empty collection of 
tables.
+    pub fn new() -> Self {
+        Self {
+            tables: DashMap::new(),
+        }
+    }
+}
+
+impl Default for MemorySchemaProvider {
+    fn default() -> Self {
+        Self::new()
+    }
+}
+
+#[async_trait]
+impl SchemaProvider for MemorySchemaProvider {
+    fn as_any(&self) -> &dyn Any {
+        self
+    }
+
+    fn table_names(&self) -> Vec<String> {
+        self.tables
+            .iter()
+            .map(|table| table.key().clone())
+            .collect()
+    }
+
+    async fn table(
+        &self,
+        name: &str,
+    ) -> datafusion_common::Result<Option<Arc<dyn TableProvider>>, 
DataFusionError> {
+        Ok(self.tables.get(name).map(|table| table.value().clone()))
+    }
+
+    fn register_table(
+        &self,
+        name: String,
+        table: Arc<dyn TableProvider>,
+    ) -> datafusion_common::Result<Option<Arc<dyn TableProvider>>> {
+        if self.table_exist(name.as_str()) {
+            return exec_err!("The table {name} already exists");
+        }
+        Ok(self.tables.insert(name, table))
+    }
+
+    fn deregister_table(
+        &self,
+        name: &str,
+    ) -> datafusion_common::Result<Option<Arc<dyn TableProvider>>> {
+        Ok(self.tables.remove(name).map(|(_, table)| table))
+    }
+
+    fn table_exist(&self, name: &str) -> bool {
+        self.tables.contains_key(name)
+    }
+}
+
+#[cfg(test)]
+mod test {
+    use super::*;
+    use crate::catalog::schema::{MemorySchemaProvider, SchemaProvider};
+    use crate::catalog::CatalogProvider;
+    use crate::datasource::empty::EmptyTable;
+    use crate::datasource::listing::{ListingTable, ListingTableConfig, 
ListingTableUrl};
+    use crate::datasource::TableProvider;
+    use crate::prelude::SessionContext;
+    use arrow_schema::Schema;
+    use datafusion_common::assert_batches_eq;
+    use std::any::Any;
+    use std::sync::Arc;
+
+    #[test]
+    fn memory_catalog_dereg_nonempty_schema() {
+        let cat = Arc::new(MemoryCatalogProvider::new()) as Arc<dyn 
CatalogProvider>;
+
+        let schema = Arc::new(MemorySchemaProvider::new()) as Arc<dyn 
SchemaProvider>;
+        let test_table = Arc::new(EmptyTable::new(Arc::new(Schema::empty())))
+            as Arc<dyn TableProvider>;
+        schema.register_table("t".into(), test_table).unwrap();
+
+        cat.register_schema("foo", schema.clone()).unwrap();
+
+        assert!(
+            cat.deregister_schema("foo", false).is_err(),
+            "dropping empty schema without cascade should error"
+        );
+        assert!(cat.deregister_schema("foo", true).unwrap().is_some());
+    }
+
+    #[test]
+    fn memory_catalog_dereg_empty_schema() {
+        let cat = Arc::new(MemoryCatalogProvider::new()) as Arc<dyn 
CatalogProvider>;
+
+        let schema = Arc::new(MemorySchemaProvider::new()) as Arc<dyn 
SchemaProvider>;
+        cat.register_schema("foo", schema).unwrap();
+
+        assert!(cat.deregister_schema("foo", false).unwrap().is_some());
+    }
+
+    #[test]
+    fn memory_catalog_dereg_missing() {
+        let cat = Arc::new(MemoryCatalogProvider::new()) as Arc<dyn 
CatalogProvider>;
+        assert!(cat.deregister_schema("foo", false).unwrap().is_none());
+    }
+
+    #[test]
+    fn default_register_schema_not_supported() {
+        // mimic a new CatalogProvider and ensure it does not support 
registering schemas
+        struct TestProvider {}
+        impl CatalogProvider for TestProvider {
+            fn as_any(&self) -> &dyn Any {
+                self
+            }
+
+            fn schema_names(&self) -> Vec<String> {
+                unimplemented!()
+            }
+
+            fn schema(&self, _name: &str) -> Option<Arc<dyn SchemaProvider>> {
+                unimplemented!()
+            }
+        }
+
+        let schema = Arc::new(MemorySchemaProvider::new()) as Arc<dyn 
SchemaProvider>;
+        let catalog = Arc::new(TestProvider {});
+
+        match catalog.register_schema("foo", schema) {
+            Ok(_) => panic!("unexpected OK"),
+            Err(e) => assert_eq!(e.strip_backtrace(), "This feature is not 
implemented: Registering new schemas is not supported"),
+        };
+    }
+
+    #[tokio::test]
+    async fn test_mem_provider() {
+        let provider = MemorySchemaProvider::new();
+        let table_name = "test_table_exist";
+        assert!(!provider.table_exist(table_name));
+        assert!(provider.deregister_table(table_name).unwrap().is_none());
+        let test_table = EmptyTable::new(Arc::new(Schema::empty()));
+        // register table successfully
+        assert!(provider
+            .register_table(table_name.to_string(), Arc::new(test_table))
+            .unwrap()
+            .is_none());
+        assert!(provider.table_exist(table_name));
+        let other_table = EmptyTable::new(Arc::new(Schema::empty()));
+        let result =
+            provider.register_table(table_name.to_string(), 
Arc::new(other_table));
+        assert!(result.is_err());
+    }
+
+    #[tokio::test]
+    async fn test_schema_register_listing_table() {
+        let testdata = crate::test_util::parquet_test_data();
+        let testdir = if testdata.starts_with('/') {
+            format!("file://{testdata}")
+        } else {
+            format!("file:///{testdata}")
+        };
+        let filename = if testdir.ends_with('/') {
+            format!("{}{}", testdir, "alltypes_plain.parquet")
+        } else {
+            format!("{}/{}", testdir, "alltypes_plain.parquet")
+        };
+
+        let table_path = ListingTableUrl::parse(filename).unwrap();
+
+        let catalog = MemoryCatalogProvider::new();
+        let schema = MemorySchemaProvider::new();
+
+        let ctx = SessionContext::new();
+
+        let config = ListingTableConfig::new(table_path)
+            .infer(&ctx.state())
+            .await
+            .unwrap();
+        let table = ListingTable::try_new(config).unwrap();
+
+        schema
+            .register_table("alltypes_plain".to_string(), Arc::new(table))
+            .unwrap();
+
+        catalog.register_schema("active", Arc::new(schema)).unwrap();
+        ctx.register_catalog("cat", Arc::new(catalog));
+
+        let df = ctx
+            .sql("SELECT id, bool_col FROM cat.active.alltypes_plain")
+            .await
+            .unwrap();
+
+        let actual = df.collect().await.unwrap();
+
+        let expected = [
+            "+----+----------+",
+            "| id | bool_col |",
+            "+----+----------+",
+            "| 4  | true     |",
+            "| 5  | false    |",
+            "| 6  | true     |",
+            "| 7  | false    |",
+            "| 2  | true     |",
+            "| 3  | false    |",
+            "| 0  | true     |",
+            "| 1  | false    |",
+            "+----+----------+",
+        ];
+        assert_batches_eq!(expected, &actual);
+    }
+}
diff --git a/datafusion/core/src/catalog/mod.rs 
b/datafusion/core/src/catalog/mod.rs
index 53b1333399..531adc4b21 100644
--- a/datafusion/core/src/catalog/mod.rs
+++ b/datafusion/core/src/catalog/mod.rs
@@ -16,16 +16,30 @@
 // under the License.
 
 //! Interfaces and default implementations of catalogs and schemas.
+//!
+//! Traits:
+//! * [`CatalogProviderList`]: a collection of `CatalogProvider`s
+//! * [`CatalogProvider`]: a collection of [`SchemaProvider`]s (sometimes 
called a "database" in other systems)
+//! * [`SchemaProvider`]:  a collection of `TableProvider`s (often called a 
"schema" in other systems)
+//!
+//! Implementations
+//! * Simple memory based catalog: [`MemoryCatalogProviderList`], 
[`MemoryCatalogProvider`], [`MemorySchemaProvider`]
+//! * Information schema: [`information_schema`]
+//! * Listing schema: [`listing_schema`]
 
 pub mod information_schema;
 pub mod listing_schema;
+mod memory;
 pub mod schema;
 
+pub use memory::{
+    MemoryCatalogProvider, MemoryCatalogProviderList, MemorySchemaProvider,
+};
+pub use schema::SchemaProvider;
+
 pub use datafusion_sql::{ResolvedTableReference, TableReference};
 
-use crate::catalog::schema::SchemaProvider;
-use dashmap::DashMap;
-use datafusion_common::{exec_err, not_impl_err, Result};
+use datafusion_common::{not_impl_err, Result};
 use std::any::Any;
 use std::collections::BTreeSet;
 use std::ops::ControlFlow;
@@ -59,49 +73,6 @@ pub trait CatalogProviderList: Sync + Send {
 #[deprecated(since = "35.0.0", note = "use [`CatalogProviderList`] instead")]
 pub trait CatalogList: CatalogProviderList {}
 
-/// Simple in-memory list of catalogs
-pub struct MemoryCatalogProviderList {
-    /// Collection of catalogs containing schemas and ultimately TableProviders
-    pub catalogs: DashMap<String, Arc<dyn CatalogProvider>>,
-}
-
-impl MemoryCatalogProviderList {
-    /// Instantiates a new `MemoryCatalogProviderList` with an empty 
collection of catalogs
-    pub fn new() -> Self {
-        Self {
-            catalogs: DashMap::new(),
-        }
-    }
-}
-
-impl Default for MemoryCatalogProviderList {
-    fn default() -> Self {
-        Self::new()
-    }
-}
-
-impl CatalogProviderList for MemoryCatalogProviderList {
-    fn as_any(&self) -> &dyn Any {
-        self
-    }
-
-    fn register_catalog(
-        &self,
-        name: String,
-        catalog: Arc<dyn CatalogProvider>,
-    ) -> Option<Arc<dyn CatalogProvider>> {
-        self.catalogs.insert(name, catalog)
-    }
-
-    fn catalog_names(&self) -> Vec<String> {
-        self.catalogs.iter().map(|c| c.key().clone()).collect()
-    }
-
-    fn catalog(&self, name: &str) -> Option<Arc<dyn CatalogProvider>> {
-        self.catalogs.get(name).map(|c| c.value().clone())
-    }
-}
-
 /// Represents a catalog, comprising a number of named schemas.
 ///
 /// # Catalog Overview
@@ -232,71 +203,6 @@ pub trait CatalogProvider: Sync + Send {
     }
 }
 
-/// Simple in-memory implementation of a catalog.
-pub struct MemoryCatalogProvider {
-    schemas: DashMap<String, Arc<dyn SchemaProvider>>,
-}
-
-impl MemoryCatalogProvider {
-    /// Instantiates a new MemoryCatalogProvider with an empty collection of 
schemas.
-    pub fn new() -> Self {
-        Self {
-            schemas: DashMap::new(),
-        }
-    }
-}
-
-impl Default for MemoryCatalogProvider {
-    fn default() -> Self {
-        Self::new()
-    }
-}
-
-impl CatalogProvider for MemoryCatalogProvider {
-    fn as_any(&self) -> &dyn Any {
-        self
-    }
-
-    fn schema_names(&self) -> Vec<String> {
-        self.schemas.iter().map(|s| s.key().clone()).collect()
-    }
-
-    fn schema(&self, name: &str) -> Option<Arc<dyn SchemaProvider>> {
-        self.schemas.get(name).map(|s| s.value().clone())
-    }
-
-    fn register_schema(
-        &self,
-        name: &str,
-        schema: Arc<dyn SchemaProvider>,
-    ) -> Result<Option<Arc<dyn SchemaProvider>>> {
-        Ok(self.schemas.insert(name.into(), schema))
-    }
-
-    fn deregister_schema(
-        &self,
-        name: &str,
-        cascade: bool,
-    ) -> Result<Option<Arc<dyn SchemaProvider>>> {
-        if let Some(schema) = self.schema(name) {
-            let table_names = schema.table_names();
-            match (table_names.is_empty(), cascade) {
-                (true, _) | (false, true) => {
-                    let (_, removed) = self.schemas.remove(name).unwrap();
-                    Ok(Some(removed))
-                }
-                (false, false) => exec_err!(
-                    "Cannot drop schema {} because other tables depend on it: 
{}",
-                    name,
-                    itertools::join(table_names.iter(), ", ")
-                ),
-            }
-        } else {
-            Ok(None)
-        }
-    }
-}
-
 /// Collects all tables and views referenced in the SQL statement. CTEs are 
collected separately.
 /// This can be used to determine which tables need to be in the catalog for a 
query to be planned.
 ///
@@ -476,71 +382,6 @@ pub fn resolve_table_references(
 #[cfg(test)]
 mod tests {
     use super::*;
-    use crate::catalog::schema::MemorySchemaProvider;
-    use crate::datasource::empty::EmptyTable;
-    use crate::datasource::TableProvider;
-    use arrow::datatypes::Schema;
-
-    #[test]
-    fn default_register_schema_not_supported() {
-        // mimic a new CatalogProvider and ensure it does not support 
registering schemas
-        struct TestProvider {}
-        impl CatalogProvider for TestProvider {
-            fn as_any(&self) -> &dyn Any {
-                self
-            }
-
-            fn schema_names(&self) -> Vec<String> {
-                unimplemented!()
-            }
-
-            fn schema(&self, _name: &str) -> Option<Arc<dyn SchemaProvider>> {
-                unimplemented!()
-            }
-        }
-
-        let schema = Arc::new(MemorySchemaProvider::new()) as Arc<dyn 
SchemaProvider>;
-        let catalog = Arc::new(TestProvider {});
-
-        match catalog.register_schema("foo", schema) {
-            Ok(_) => panic!("unexpected OK"),
-            Err(e) => assert_eq!(e.strip_backtrace(), "This feature is not 
implemented: Registering new schemas is not supported"),
-        };
-    }
-
-    #[test]
-    fn memory_catalog_dereg_nonempty_schema() {
-        let cat = Arc::new(MemoryCatalogProvider::new()) as Arc<dyn 
CatalogProvider>;
-
-        let schema = Arc::new(MemorySchemaProvider::new()) as Arc<dyn 
SchemaProvider>;
-        let test_table = Arc::new(EmptyTable::new(Arc::new(Schema::empty())))
-            as Arc<dyn TableProvider>;
-        schema.register_table("t".into(), test_table).unwrap();
-
-        cat.register_schema("foo", schema.clone()).unwrap();
-
-        assert!(
-            cat.deregister_schema("foo", false).is_err(),
-            "dropping empty schema without cascade should error"
-        );
-        assert!(cat.deregister_schema("foo", true).unwrap().is_some());
-    }
-
-    #[test]
-    fn memory_catalog_dereg_empty_schema() {
-        let cat = Arc::new(MemoryCatalogProvider::new()) as Arc<dyn 
CatalogProvider>;
-
-        let schema = Arc::new(MemorySchemaProvider::new()) as Arc<dyn 
SchemaProvider>;
-        cat.register_schema("foo", schema).unwrap();
-
-        assert!(cat.deregister_schema("foo", false).unwrap().is_some());
-    }
-
-    #[test]
-    fn memory_catalog_dereg_missing() {
-        let cat = Arc::new(MemoryCatalogProvider::new()) as Arc<dyn 
CatalogProvider>;
-        assert!(cat.deregister_schema("foo", false).unwrap().is_none());
-    }
 
     #[test]
     fn resolve_table_references_shadowed_cte() {
diff --git a/datafusion/core/src/catalog/schema.rs 
b/datafusion/core/src/catalog/schema.rs
index 8249c3a533..7d76b3fa4f 100644
--- a/datafusion/core/src/catalog/schema.rs
+++ b/datafusion/core/src/catalog/schema.rs
@@ -19,7 +19,6 @@
 //! representing collections of named tables.
 
 use async_trait::async_trait;
-use dashmap::DashMap;
 use datafusion_common::{exec_err, DataFusionError};
 use std::any::Any;
 use std::sync::Arc;
@@ -27,6 +26,9 @@ use std::sync::Arc;
 use crate::datasource::TableProvider;
 use crate::error::Result;
 
+// backwards compatibility
+pub use super::MemorySchemaProvider;
+
 /// Represents a schema, comprising a number of named tables.
 ///
 /// Please see [`CatalogProvider`] for details of implementing a custom 
catalog.
@@ -80,154 +82,3 @@ pub trait SchemaProvider: Sync + Send {
     /// Returns true if table exist in the schema provider, false otherwise.
     fn table_exist(&self, name: &str) -> bool;
 }
-
-/// Simple in-memory implementation of a schema.
-pub struct MemorySchemaProvider {
-    tables: DashMap<String, Arc<dyn TableProvider>>,
-}
-
-impl MemorySchemaProvider {
-    /// Instantiates a new MemorySchemaProvider with an empty collection of 
tables.
-    pub fn new() -> Self {
-        Self {
-            tables: DashMap::new(),
-        }
-    }
-}
-
-impl Default for MemorySchemaProvider {
-    fn default() -> Self {
-        Self::new()
-    }
-}
-
-#[async_trait]
-impl SchemaProvider for MemorySchemaProvider {
-    fn as_any(&self) -> &dyn Any {
-        self
-    }
-
-    fn table_names(&self) -> Vec<String> {
-        self.tables
-            .iter()
-            .map(|table| table.key().clone())
-            .collect()
-    }
-
-    async fn table(
-        &self,
-        name: &str,
-    ) -> Result<Option<Arc<dyn TableProvider>>, DataFusionError> {
-        Ok(self.tables.get(name).map(|table| table.value().clone()))
-    }
-
-    fn register_table(
-        &self,
-        name: String,
-        table: Arc<dyn TableProvider>,
-    ) -> Result<Option<Arc<dyn TableProvider>>> {
-        if self.table_exist(name.as_str()) {
-            return exec_err!("The table {name} already exists");
-        }
-        Ok(self.tables.insert(name, table))
-    }
-
-    fn deregister_table(&self, name: &str) -> Result<Option<Arc<dyn 
TableProvider>>> {
-        Ok(self.tables.remove(name).map(|(_, table)| table))
-    }
-
-    fn table_exist(&self, name: &str) -> bool {
-        self.tables.contains_key(name)
-    }
-}
-
-#[cfg(test)]
-mod tests {
-    use std::sync::Arc;
-
-    use arrow::datatypes::Schema;
-
-    use crate::assert_batches_eq;
-    use crate::catalog::schema::{MemorySchemaProvider, SchemaProvider};
-    use crate::catalog::{CatalogProvider, MemoryCatalogProvider};
-    use crate::datasource::empty::EmptyTable;
-    use crate::datasource::listing::{ListingTable, ListingTableConfig, 
ListingTableUrl};
-    use crate::prelude::SessionContext;
-
-    #[tokio::test]
-    async fn test_mem_provider() {
-        let provider = MemorySchemaProvider::new();
-        let table_name = "test_table_exist";
-        assert!(!provider.table_exist(table_name));
-        assert!(provider.deregister_table(table_name).unwrap().is_none());
-        let test_table = EmptyTable::new(Arc::new(Schema::empty()));
-        // register table successfully
-        assert!(provider
-            .register_table(table_name.to_string(), Arc::new(test_table))
-            .unwrap()
-            .is_none());
-        assert!(provider.table_exist(table_name));
-        let other_table = EmptyTable::new(Arc::new(Schema::empty()));
-        let result =
-            provider.register_table(table_name.to_string(), 
Arc::new(other_table));
-        assert!(result.is_err());
-    }
-
-    #[tokio::test]
-    async fn test_schema_register_listing_table() {
-        let testdata = crate::test_util::parquet_test_data();
-        let testdir = if testdata.starts_with('/') {
-            format!("file://{testdata}")
-        } else {
-            format!("file:///{testdata}")
-        };
-        let filename = if testdir.ends_with('/') {
-            format!("{}{}", testdir, "alltypes_plain.parquet")
-        } else {
-            format!("{}/{}", testdir, "alltypes_plain.parquet")
-        };
-
-        let table_path = ListingTableUrl::parse(filename).unwrap();
-
-        let catalog = MemoryCatalogProvider::new();
-        let schema = MemorySchemaProvider::new();
-
-        let ctx = SessionContext::new();
-
-        let config = ListingTableConfig::new(table_path)
-            .infer(&ctx.state())
-            .await
-            .unwrap();
-        let table = ListingTable::try_new(config).unwrap();
-
-        schema
-            .register_table("alltypes_plain".to_string(), Arc::new(table))
-            .unwrap();
-
-        catalog.register_schema("active", Arc::new(schema)).unwrap();
-        ctx.register_catalog("cat", Arc::new(catalog));
-
-        let df = ctx
-            .sql("SELECT id, bool_col FROM cat.active.alltypes_plain")
-            .await
-            .unwrap();
-
-        let actual = df.collect().await.unwrap();
-
-        let expected = [
-            "+----+----------+",
-            "| id | bool_col |",
-            "+----+----------+",
-            "| 4  | true     |",
-            "| 5  | false    |",
-            "| 6  | true     |",
-            "| 7  | false    |",
-            "| 2  | true     |",
-            "| 3  | false    |",
-            "| 0  | true     |",
-            "| 1  | false    |",
-            "+----+----------+",
-        ];
-        assert_batches_eq!(expected, &actual);
-    }
-}
diff --git a/datafusion/core/src/lib.rs b/datafusion/core/src/lib.rs
index 5f0af2d0ad..2810dca463 100644
--- a/datafusion/core/src/lib.rs
+++ b/datafusion/core/src/lib.rs
@@ -182,7 +182,7 @@
 //! In order to achieve this, DataFusion supports extension at many points:
 //!
 //! * read from any datasource ([`TableProvider`])
-//! * define your own catalogs, schemas, and table lists ([`CatalogProvider`])
+//! * define your own catalogs, schemas, and table lists ([`catalog`] and 
[`CatalogProvider`])
 //! * build your own query language or plans ([`LogicalPlanBuilder`])
 //! * declare and use user-defined functions ([`ScalarUDF`], and 
[`AggregateUDF`], [`WindowUDF`])
 //! * add custom plan rewrite passes ([`AnalyzerRule`], [`OptimizerRule`]  and 
[`PhysicalOptimizerRule`])


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to