sdd commented on code in PR #534:
URL: https://github.com/apache/iceberg-rust/pull/534#discussion_r1725609116


##########
crates/catalog/sql/src/catalog.rs:
##########
@@ -276,4 +579,385 @@ mod tests {
         new_sql_catalog(warehouse_loc.clone()).await;
         new_sql_catalog(warehouse_loc.clone()).await;
     }
+
+    #[tokio::test]
+    async fn test_list_namespaces_returns_empty_vector() {
+        let warehouse_loc = temp_path();
+        let catalog = new_sql_catalog(warehouse_loc).await;
+
+        assert_eq!(catalog.list_namespaces(None).await.unwrap(), vec![]);
+    }
+
+    #[tokio::test]
+    async fn test_list_namespaces_returns_multiple_namespaces() {
+        let warehouse_loc = temp_path();
+        let catalog = new_sql_catalog(warehouse_loc).await;
+        let namespace_ident_1 = NamespaceIdent::new("a".into());
+        let namespace_ident_2 = NamespaceIdent::new("b".into());
+        create_namespaces(&catalog, &vec![&namespace_ident_1, 
&namespace_ident_2]).await;
+
+        assert_eq!(
+            to_set(catalog.list_namespaces(None).await.unwrap()),
+            to_set(vec![namespace_ident_1, namespace_ident_2])
+        );
+    }
+
+    #[tokio::test]
+    async fn test_list_namespaces_returns_only_top_level_namespaces() {
+        let warehouse_loc = temp_path();
+        let catalog = new_sql_catalog(warehouse_loc).await;
+        let namespace_ident_1 = NamespaceIdent::new("a".into());
+        let namespace_ident_2 = NamespaceIdent::from_strs(vec!["a", 
"b"]).unwrap();
+        let namespace_ident_3 = NamespaceIdent::new("b".into());
+        create_namespaces(&catalog, &vec![
+            &namespace_ident_1,
+            &namespace_ident_2,
+            &namespace_ident_3,
+        ])
+        .await;
+
+        assert_eq!(
+            to_set(catalog.list_namespaces(None).await.unwrap()),
+            to_set(vec![namespace_ident_1, namespace_ident_3])
+        );
+    }
+
+    #[tokio::test]
+    async fn test_list_namespaces_returns_no_namespaces_under_parent() {
+        let warehouse_loc = temp_path();
+        let catalog = new_sql_catalog(warehouse_loc).await;
+        let namespace_ident_1 = NamespaceIdent::new("a".into());
+        let namespace_ident_2 = NamespaceIdent::new("b".into());
+        create_namespaces(&catalog, &vec![&namespace_ident_1, 
&namespace_ident_2]).await;
+
+        assert_eq!(
+            catalog
+                .list_namespaces(Some(&namespace_ident_1))
+                .await
+                .unwrap(),
+            vec![]
+        );
+    }
+
+    #[tokio::test]
+    async fn test_list_namespaces_returns_namespace_under_parent() {
+        let warehouse_loc = temp_path();
+        let catalog = new_sql_catalog(warehouse_loc).await;
+        let namespace_ident_1 = NamespaceIdent::new("a".into());
+        let namespace_ident_2 = NamespaceIdent::from_strs(vec!["a", 
"b"]).unwrap();
+        let namespace_ident_3 = NamespaceIdent::new("c".into());
+        create_namespaces(&catalog, &vec![
+            &namespace_ident_1,
+            &namespace_ident_2,
+            &namespace_ident_3,
+        ])
+        .await;
+
+        assert_eq!(
+            to_set(catalog.list_namespaces(None).await.unwrap()),
+            to_set(vec![namespace_ident_1.clone(), namespace_ident_3])
+        );
+
+        assert_eq!(
+            catalog
+                .list_namespaces(Some(&namespace_ident_1))
+                .await
+                .unwrap(),
+            vec![NamespaceIdent::from_strs(vec!["a", "b"]).unwrap()]
+        );
+    }
+
+    #[tokio::test]
+    async fn test_list_namespaces_returns_multiple_namespaces_under_parent() {
+        let warehouse_loc = temp_path();
+        let catalog = new_sql_catalog(warehouse_loc).await;
+        let namespace_ident_1 = NamespaceIdent::new("a".to_string());
+        let namespace_ident_2 = NamespaceIdent::from_strs(vec!["a", 
"a"]).unwrap();
+        let namespace_ident_3 = NamespaceIdent::from_strs(vec!["a", 
"b"]).unwrap();
+        let namespace_ident_4 = NamespaceIdent::from_strs(vec!["a", 
"c"]).unwrap();
+        let namespace_ident_5 = NamespaceIdent::new("b".into());
+        create_namespaces(&catalog, &vec![
+            &namespace_ident_1,
+            &namespace_ident_2,
+            &namespace_ident_3,
+            &namespace_ident_4,
+            &namespace_ident_5,
+        ])
+        .await;
+
+        assert_eq!(
+            to_set(
+                catalog
+                    .list_namespaces(Some(&namespace_ident_1))
+                    .await
+                    .unwrap()
+            ),
+            to_set(vec![
+                NamespaceIdent::from_strs(vec!["a", "a"]).unwrap(),
+                NamespaceIdent::from_strs(vec!["a", "b"]).unwrap(),
+                NamespaceIdent::from_strs(vec!["a", "c"]).unwrap(),
+            ])
+        );
+    }
+
+    #[tokio::test]
+    async fn test_namespace_exists_returns_false() {
+        let warehouse_loc = temp_path();
+        let catalog = new_sql_catalog(warehouse_loc).await;
+        let namespace_ident = NamespaceIdent::new("a".into());
+        create_namespace(&catalog, &namespace_ident).await;
+
+        assert!(!catalog
+            .namespace_exists(&NamespaceIdent::new("b".into()))
+            .await
+            .unwrap());
+    }
+
+    #[tokio::test]
+    async fn test_namespace_exists_returns_true() {
+        let warehouse_loc = temp_path();
+        let catalog = new_sql_catalog(warehouse_loc).await;
+        let namespace_ident = NamespaceIdent::new("a".into());
+        create_namespace(&catalog, &namespace_ident).await;
+
+        assert!(catalog.namespace_exists(&namespace_ident).await.unwrap());
+    }
+
+    #[tokio::test]
+    async fn test_create_namespace_with_properties() {
+        let warehouse_loc = temp_path();
+        let catalog = new_sql_catalog(warehouse_loc).await;
+        let namespace_ident = NamespaceIdent::new("abc".into());
+
+        let mut properties: HashMap<String, String> = HashMap::new();
+        properties.insert("k".into(), "v".into());
+
+        assert_eq!(
+            catalog
+                .create_namespace(&namespace_ident, properties.clone())
+                .await
+                .unwrap(),
+            Namespace::with_properties(namespace_ident.clone(), 
properties.clone())
+        );
+
+        assert_eq!(
+            catalog.get_namespace(&namespace_ident).await.unwrap(),
+            Namespace::with_properties(namespace_ident, properties)
+        );
+    }
+
+    #[tokio::test]
+    async fn test_create_namespace_throws_error_if_namespace_already_exists() {
+        let warehouse_loc = temp_path();
+        let catalog = new_sql_catalog(warehouse_loc).await;
+        let namespace_ident = NamespaceIdent::new("a".into());
+        create_namespace(&catalog, &namespace_ident).await;
+
+        assert_eq!(
+            catalog
+                .create_namespace(&namespace_ident, HashMap::new())
+                .await
+                .unwrap_err()
+                .to_string(),
+            format!(
+                "Unexpected => Namespace {:?} already exists",
+                &namespace_ident
+            )
+        );
+
+        assert_eq!(
+            catalog.get_namespace(&namespace_ident).await.unwrap(),
+            Namespace::with_properties(namespace_ident, default_properties())
+        );
+    }
+
+    #[tokio::test]
+    async fn test_create_nested_namespace() {
+        let warehouse_loc = temp_path();
+        let catalog = new_sql_catalog(warehouse_loc).await;
+        let parent_namespace_ident = NamespaceIdent::new("a".into());
+        create_namespace(&catalog, &parent_namespace_ident).await;
+
+        let child_namespace_ident = NamespaceIdent::from_strs(vec!["a", 
"b"]).unwrap();
+
+        assert_eq!(
+            catalog
+                .create_namespace(&child_namespace_ident, HashMap::new())
+                .await
+                .unwrap(),
+            Namespace::new(child_namespace_ident.clone())
+        );
+
+        assert_eq!(
+            catalog.get_namespace(&child_namespace_ident).await.unwrap(),
+            Namespace::with_properties(child_namespace_ident, 
default_properties())
+        );
+    }
+
+    #[tokio::test]
+    async fn test_create_deeply_nested_namespace() {
+        let warehouse_loc = temp_path();
+        let catalog = new_sql_catalog(warehouse_loc).await;
+        let namespace_ident_a = NamespaceIdent::new("a".into());
+        let namespace_ident_a_b = NamespaceIdent::from_strs(vec!["a", 
"b"]).unwrap();
+        create_namespaces(&catalog, &vec![&namespace_ident_a, 
&namespace_ident_a_b]).await;
+
+        let namespace_ident_a_b_c = NamespaceIdent::from_strs(vec!["a", "b", 
"c"]).unwrap();
+
+        assert_eq!(
+            catalog
+                .create_namespace(&namespace_ident_a_b_c, HashMap::new())
+                .await
+                .unwrap(),
+            Namespace::new(namespace_ident_a_b_c.clone())
+        );
+
+        assert_eq!(
+            catalog.get_namespace(&namespace_ident_a_b_c).await.unwrap(),
+            Namespace::with_properties(namespace_ident_a_b_c, 
default_properties())
+        );
+    }
+
+    #[tokio::test]
+    async fn 
test_create_nested_namespace_throws_error_if_top_level_namespace_doesnt_exist() 
{
+        let warehouse_loc = temp_path();
+        let catalog = new_sql_catalog(warehouse_loc).await;
+
+        let nested_namespace_ident = NamespaceIdent::from_strs(vec!["a", 
"b"]).unwrap();
+
+        assert_eq!(
+            catalog
+                .create_namespace(&nested_namespace_ident, HashMap::new())
+                .await
+                .unwrap_err()
+                .to_string(),
+            format!(
+                "Unexpected => No such namespace: {:?}",
+                NamespaceIdent::new("a".into())
+            )
+        );
+
+        assert_eq!(catalog.list_namespaces(None).await.unwrap(), vec![]);
+    }
+
+    #[tokio::test]
+    async fn test_drop_namespace() {
+        let warehouse_loc = temp_path();
+        let catalog = new_sql_catalog(warehouse_loc).await;
+        let namespace_ident = NamespaceIdent::new("abc".into());
+        create_namespace(&catalog, &namespace_ident).await;
+
+        catalog.drop_namespace(&namespace_ident).await.unwrap();
+
+        assert!(!catalog.namespace_exists(&namespace_ident).await.unwrap())
+    }
+
+    #[tokio::test]
+    async fn test_drop_nested_namespace() {
+        let warehouse_loc = temp_path();
+        let catalog = new_sql_catalog(warehouse_loc).await;
+        let namespace_ident_a = NamespaceIdent::new("a".into());
+        let namespace_ident_a_b = NamespaceIdent::from_strs(vec!["a", 
"b"]).unwrap();
+        create_namespaces(&catalog, &vec![&namespace_ident_a, 
&namespace_ident_a_b]).await;
+
+        catalog.drop_namespace(&namespace_ident_a_b).await.unwrap();
+
+        assert!(!catalog
+            .namespace_exists(&namespace_ident_a_b)
+            .await
+            .unwrap());
+
+        assert!(catalog.namespace_exists(&namespace_ident_a).await.unwrap());
+    }
+
+    #[tokio::test]
+    async fn test_drop_deeply_nested_namespace() {
+        let warehouse_loc = temp_path();
+        let catalog = new_sql_catalog(warehouse_loc).await;
+        let namespace_ident_a = NamespaceIdent::new("a".into());
+        let namespace_ident_a_b = NamespaceIdent::from_strs(vec!["a", 
"b"]).unwrap();
+        let namespace_ident_a_b_c = NamespaceIdent::from_strs(vec!["a", "b", 
"c"]).unwrap();
+        create_namespaces(&catalog, &vec![
+            &namespace_ident_a,
+            &namespace_ident_a_b,
+            &namespace_ident_a_b_c,
+        ])
+        .await;
+
+        catalog
+            .drop_namespace(&namespace_ident_a_b_c)
+            .await
+            .unwrap();
+
+        assert!(!catalog
+            .namespace_exists(&namespace_ident_a_b_c)
+            .await
+            .unwrap());
+
+        assert!(catalog
+            .namespace_exists(&namespace_ident_a_b)
+            .await
+            .unwrap());
+
+        assert!(catalog.namespace_exists(&namespace_ident_a).await.unwrap());
+    }
+
+    #[tokio::test]
+    async fn test_drop_namespace_throws_error_if_namespace_doesnt_exist() {
+        let warehouse_loc = temp_path();
+        let catalog = new_sql_catalog(warehouse_loc).await;
+
+        let non_existent_namespace_ident = NamespaceIdent::new("abc".into());
+        assert_eq!(
+            catalog
+                .drop_namespace(&non_existent_namespace_ident)
+                .await
+                .unwrap_err()
+                .to_string(),
+            format!(
+                "Unexpected => No such namespace: {:?}",
+                non_existent_namespace_ident
+            )
+        )
+    }
+
+    #[tokio::test]
+    async fn 
test_drop_namespace_throws_error_if_nested_namespace_doesnt_exist() {
+        let warehouse_loc = temp_path();
+        let catalog = new_sql_catalog(warehouse_loc).await;
+        create_namespace(&catalog, &NamespaceIdent::new("a".into())).await;
+
+        let non_existent_namespace_ident =
+            NamespaceIdent::from_vec(vec!["a".into(), "b".into()]).unwrap();
+        assert_eq!(
+            catalog
+                .drop_namespace(&non_existent_namespace_ident)
+                .await
+                .unwrap_err()
+                .to_string(),
+            format!(
+                "Unexpected => No such namespace: {:?}",
+                non_existent_namespace_ident
+            )
+        )
+    }
+
+    #[tokio::test]
+    #[ignore = "Java/Python do not drop nested namespaces?"]
+    async fn 
test_dropping_a_namespace_also_drops_namespaces_nested_under_that_one() {

Review Comment:
   I think your second suggestion, only allowing dropping a namespace when it 
is empty, makes sense. Or how about adding a boolean flag, `drop_children`? If 
true, drop any children present in the namespace as well as the namespace. If 
false, only drop the namespace if it is empty, and return an `Err` otherwise.
   
   All of these approaches seem more sensible than the Python / Java approach 
of dropping a namespace but leaving any tables that were within it with a 
missing parent. That feels buggy.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscr...@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
us...@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscr...@iceberg.apache.org
For additional commands, e-mail: issues-h...@iceberg.apache.org

Reply via email to