4242from pyiceberg .table .metadata import INITIAL_SPEC_ID
4343from pyiceberg .table .sorting import INITIAL_SORT_ORDER_ID , SortField , SortOrder
4444from pyiceberg .transforms import BucketTransform , DayTransform , IdentityTransform
45+ from pyiceberg .typedef import Identifier
4546from pyiceberg .types import IntegerType , LongType , NestedField , TimestampType , UUIDType
4647from tests .conftest import clean_up
4748
@@ -640,7 +641,6 @@ def test_rest_custom_namespace_separator(rest_catalog: RestCatalog, table_schema
640641 loaded_table = rest_catalog .load_table (identifier = full_table_identifier_tuple )
641642 assert loaded_table .name () == full_table_identifier_tuple
642643
643-
644644@pytest .mark .integration
645645@pytest .mark .parametrize ("test_catalog" , CATALOGS )
646646def test_incompatible_partitioned_schema_evolution (
@@ -671,6 +671,28 @@ def test_incompatible_partitioned_schema_evolution(
671671 assert table .spec () == PartitionSpec (PartitionField (2 , 1001 , DayTransform (), "tpep_pickup_day" ), spec_id = 1 )
672672 assert table .schema () == Schema (NestedField (2 , "tpep_pickup_datetime" , TimestampType (), False ))
673673
674+ @pytest .mark .integration
675+ @pytest .mark .parametrize ("test_catalog" , CATALOGS )
676+ def test_namespace_with_slash (test_catalog : Catalog ) -> None :
677+ if isinstance (test_catalog , (HiveCatalog , SqlCatalog , RestCatalog )):
678+ pytest .skip (f"{ type (test_catalog ).__name__ } does not support slash in namespace" )
679+
680+ namespace = ("new/db" ,)
681+
682+ if test_catalog .namespace_exists (namespace ):
683+ test_catalog .drop_namespace (namespace )
684+
685+ assert not test_catalog .namespace_exists (namespace )
686+
687+ test_catalog .create_namespace (namespace )
688+ assert test_catalog .namespace_exists (namespace )
689+
690+ properties = test_catalog .load_namespace_properties (namespace )
691+ assert properties is not None
692+
693+ test_catalog .drop_namespace (namespace )
694+ assert not test_catalog .namespace_exists (namespace )
695+
674696
675697@pytest .mark .integration
676698@pytest .mark .parametrize ("test_catalog" , CATALOGS )
@@ -692,3 +714,103 @@ def test_incompatible_sorted_schema_evolution(
692714 assert table .schema () == Schema (
693715 NestedField (1 , "VendorID" , IntegerType (), False ), NestedField (2 , "tpep_pickup_datetime" , TimestampType (), False )
694716 )
717+
718+ def test_namespace_with_dot (test_catalog : Catalog ) -> None :
719+ if isinstance (test_catalog , (HiveCatalog , SqlCatalog , RestCatalog )):
720+ pytest .skip (f"{ type (test_catalog ).__name__ } does not support dot in namespace" )
721+
722+ namespace = ("new.db" ,)
723+
724+ if test_catalog .namespace_exists (namespace ):
725+ test_catalog .drop_namespace (namespace )
726+
727+ assert not test_catalog .namespace_exists (namespace )
728+
729+ test_catalog .create_namespace (namespace )
730+ assert test_catalog .namespace_exists (namespace )
731+
732+ # list_namespaces returns a list of tuples
733+ assert namespace in test_catalog .list_namespaces ()
734+
735+ properties = test_catalog .load_namespace_properties (namespace )
736+ assert properties is not None
737+
738+ test_catalog .drop_namespace (namespace )
739+ assert not test_catalog .namespace_exists (namespace )
740+
741+
742+ @pytest .mark .integration
743+ @pytest .mark .parametrize ("test_catalog" , CATALOGS )
744+ def test_table_name_with_slash (test_catalog : Catalog , table_schema_simple : Schema ) -> None :
745+ if isinstance (test_catalog , (HiveCatalog , SqlCatalog , RestCatalog )):
746+ pytest .skip (f"{ type (test_catalog ).__name__ } does not support slash in table name" )
747+
748+ namespace = ("ns_slash" ,)
749+ table_ident = ("ns_slash" , "tab/le" )
750+
751+ if not test_catalog .namespace_exists (namespace ):
752+ test_catalog .create_namespace (namespace )
753+
754+ if test_catalog .table_exists (table_ident ):
755+ test_catalog .drop_table (table_ident )
756+
757+ assert not test_catalog .table_exists (table_ident )
758+
759+ test_catalog .create_table (table_ident , table_schema_simple )
760+ assert test_catalog .table_exists (table_ident )
761+
762+ table = test_catalog .load_table (table_ident )
763+ assert table .schema ().as_struct () == table_schema_simple .as_struct ()
764+
765+ test_catalog .drop_table (table_ident )
766+ assert not test_catalog .table_exists (table_ident )
767+
768+
769+ @pytest .mark .integration
770+ @pytest .mark .parametrize ("test_catalog" , CATALOGS )
771+ def test_table_name_with_dot (test_catalog : Catalog , table_schema_simple : Schema ) -> None :
772+ if isinstance (test_catalog , (HiveCatalog , SqlCatalog , RestCatalog )):
773+ pytest .skip (f"{ type (test_catalog ).__name__ } does not support dot in table name" )
774+
775+ namespace = ("ns_dot" ,)
776+ table_ident = ("ns_dot" , "ta.ble" )
777+
778+ if not test_catalog .namespace_exists (namespace ):
779+ test_catalog .create_namespace (namespace )
780+
781+ if test_catalog .table_exists (table_ident ):
782+ test_catalog .drop_table (table_ident )
783+
784+ assert not test_catalog .table_exists (table_ident )
785+
786+ test_catalog .create_table (table_ident , table_schema_simple )
787+ assert test_catalog .table_exists (table_ident )
788+
789+ assert table_ident in test_catalog .list_tables (namespace )
790+
791+ table = test_catalog .load_table (table_ident )
792+ assert table .schema ().as_struct () == table_schema_simple .as_struct ()
793+
794+ test_catalog .drop_table (table_ident )
795+ assert not test_catalog .table_exists (table_ident )
796+
797+
798+ @pytest .mark .integration
799+ @pytest .mark .parametrize ("test_catalog" , CATALOGS )
800+ def test_drop_missing_table (test_catalog : Catalog , database_name : str ) -> None :
801+ test_catalog .create_namespace_if_not_exists (database_name )
802+ table_ident = (database_name , "missing_table" )
803+ assert not test_catalog .table_exists (table_ident )
804+ with pytest .raises (NoSuchTableError ):
805+ test_catalog .drop_table (table_ident )
806+
807+
808+ @pytest .mark .integration
809+ @pytest .mark .parametrize ("test_catalog" , CATALOGS )
810+ def test_drop_nonexistent_namespace (test_catalog : Catalog ) -> None :
811+ if isinstance (test_catalog , HiveCatalog ):
812+ pytest .skip ("HiveCatalog raises NoSuchObjectException instead of NoSuchNamespaceError" )
813+
814+ namespace = ("non_existent_namespace" ,)
815+ with pytest .raises (NoSuchNamespaceError ):
816+ test_catalog .drop_namespace (namespace )
0 commit comments