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

liurenjie1024 pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/iceberg-rust.git


The following commit(s) were added to refs/heads/main by this push:
     new 05651e205 feat(datafusion): Add support for DROP TABLE (#2033)
05651e205 is described below

commit 05651e2052723cc80f117f6f26afa20f677b1968
Author: Shawn Chang <[email protected]>
AuthorDate: Wed Jan 21 17:16:19 2026 -0800

    feat(datafusion): Add support for DROP TABLE (#2033)
    
    ## Which issue does this PR close?
    
    - Closes #2060
    
    ## What changes are included in this PR?
    - Support DROP TABLE syntax by implementing
    `SchemaProvider::deregister_table`
    
    
    ## Are these changes tested?
    Added sqllogictests
---
 crates/integrations/datafusion/src/schema.rs       | 76 +++++++++++++++++++++-
 .../sqllogictest/testdata/schedules/df_test.toml   |  4 ++
 .../testdata/slts/df_test/drop_table.slt           | 63 ++++++++++++++++++
 3 files changed, 142 insertions(+), 1 deletion(-)

diff --git a/crates/integrations/datafusion/src/schema.rs 
b/crates/integrations/datafusion/src/schema.rs
index 022964ba6..508aeb303 100644
--- a/crates/integrations/datafusion/src/schema.rs
+++ b/crates/integrations/datafusion/src/schema.rs
@@ -29,7 +29,7 @@ use futures::StreamExt;
 use futures::future::try_join_all;
 use iceberg::arrow::arrow_schema_to_schema_auto_assign_ids;
 use iceberg::inspect::MetadataTableType;
-use iceberg::{Catalog, Error, ErrorKind, NamespaceIdent, Result, 
TableCreation};
+use iceberg::{Catalog, Error, ErrorKind, NamespaceIdent, Result, 
TableCreation, TableIdent};
 
 use crate::table::IcebergTableProvider;
 use crate::to_datafusion_error;
@@ -211,6 +211,42 @@ impl SchemaProvider for IcebergSchemaProvider {
             DataFusionError::Execution(format!("Failed to create Iceberg 
table: {e}"))
         })?
     }
+
+    fn deregister_table(&self, name: &str) -> DFResult<Option<Arc<dyn 
TableProvider>>> {
+        // Check if table exists
+        if !self.table_exist(name) {
+            return Ok(None);
+        }
+
+        let catalog = self.catalog.clone();
+        let namespace = self.namespace.clone();
+        let tables = self.tables.clone();
+        let table_name = name.to_string();
+
+        // Use tokio's spawn_blocking to handle the async work on a blocking 
thread pool
+        let result = tokio::task::spawn_blocking(move || {
+            let rt = tokio::runtime::Handle::current();
+            rt.block_on(async move {
+                let table_ident = TableIdent::new(namespace, 
table_name.clone());
+
+                // Drop the table from the Iceberg catalog
+                catalog
+                    .drop_table(&table_ident)
+                    .await
+                    .map_err(to_datafusion_error)?;
+
+                // Remove from local cache and return the removed provider
+                let removed = tables
+                    .remove(&table_name)
+                    .map(|(_, table)| table as Arc<dyn TableProvider>);
+
+                Ok(removed)
+            })
+        });
+
+        futures::executor::block_on(result)
+            .map_err(|e| DataFusionError::Execution(format!("Failed to drop 
Iceberg table: {e}")))?
+    }
 }
 
 /// Verifies that a table provider contains no data by scanning with LIMIT 1.
@@ -368,4 +404,42 @@ mod tests {
             "Expected error about table already existing, got: {err}",
         );
     }
+
+    #[tokio::test]
+    async fn test_deregister_table_succeeds() {
+        let (schema_provider, _temp_dir) = create_test_schema_provider().await;
+
+        // Create and register an empty table
+        let arrow_schema = Arc::new(ArrowSchema::new(vec![Field::new(
+            "id",
+            DataType::Int32,
+            false,
+        )]));
+
+        let empty_batch = RecordBatch::new_empty(arrow_schema.clone());
+        let mem_table = MemTable::try_new(arrow_schema, 
vec![vec![empty_batch]]).unwrap();
+
+        // Register the table
+        let result = schema_provider.register_table("drop_me".to_string(), 
Arc::new(mem_table));
+        assert!(result.is_ok());
+        assert!(schema_provider.table_exist("drop_me"));
+
+        // Deregister the table
+        let result = schema_provider.deregister_table("drop_me");
+        assert!(result.is_ok());
+        assert!(result.unwrap().is_some());
+
+        // Verify the table no longer exists
+        assert!(!schema_provider.table_exist("drop_me"));
+    }
+
+    #[tokio::test]
+    async fn test_deregister_nonexistent_table_returns_none() {
+        let (schema_provider, _temp_dir) = create_test_schema_provider().await;
+
+        // Attempt to deregister a table that doesn't exist
+        let result = schema_provider.deregister_table("nonexistent");
+        assert!(result.is_ok());
+        assert!(result.unwrap().is_none());
+    }
 }
diff --git a/crates/sqllogictest/testdata/schedules/df_test.toml 
b/crates/sqllogictest/testdata/schedules/df_test.toml
index 6fdd08054..1a1a0ad33 100644
--- a/crates/sqllogictest/testdata/schedules/df_test.toml
+++ b/crates/sqllogictest/testdata/schedules/df_test.toml
@@ -33,3 +33,7 @@ slt = "df_test/insert_into.slt"
 [[steps]]
 engine = "df"
 slt = "df_test/binary_predicate_pushdown.slt"
+
+[[steps]]
+engine = "df"
+slt = "df_test/drop_table.slt"
diff --git a/crates/sqllogictest/testdata/slts/df_test/drop_table.slt 
b/crates/sqllogictest/testdata/slts/df_test/drop_table.slt
new file mode 100644
index 000000000..c721c84e1
--- /dev/null
+++ b/crates/sqllogictest/testdata/slts/df_test/drop_table.slt
@@ -0,0 +1,63 @@
+# 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.
+
+# Test DROP TABLE functionality
+
+# Create a table to drop
+statement ok
+CREATE TABLE default.default.table_to_drop (id INT NOT NULL, name STRING)
+
+# Verify the table exists
+query IT rowsort
+SELECT * FROM default.default.table_to_drop
+----
+
+# Insert some data
+query I
+INSERT INTO default.default.table_to_drop VALUES (1, 'Test')
+----
+1
+
+# Verify data exists
+query IT rowsort
+SELECT * FROM default.default.table_to_drop
+----
+1 Test
+
+# Drop the table
+statement ok
+DROP TABLE default.default.table_to_drop
+
+# Verify the table no longer exists (should error)
+statement error
+SELECT * FROM default.default.table_to_drop
+
+# Test DROP TABLE IF EXISTS on non-existent table (should not error)
+statement ok
+DROP TABLE IF EXISTS default.default.nonexistent_table
+
+# Create another table for IF EXISTS test
+statement ok
+CREATE TABLE default.default.another_table (id INT NOT NULL)
+
+# Drop with IF EXISTS
+statement ok
+DROP TABLE IF EXISTS default.default.another_table
+
+# Verify it's gone
+statement error
+SELECT * FROM default.default.another_table

Reply via email to