@@ -672,6 +672,29 @@ def test_incompatible_partitioned_schema_evolution(
672672 assert table .schema () == Schema (NestedField (2 , "tpep_pickup_datetime" , TimestampType (), False ))
673673
674674
675+ @pytest .mark .integration
676+ @pytest .mark .parametrize ("test_catalog" , CATALOGS )
677+ def test_namespace_with_slash (test_catalog : Catalog ) -> None :
678+ if isinstance (test_catalog , HiveCatalog ):
679+ pytest .skip (f"{ type (test_catalog ).__name__ } does not support slash in namespace" )
680+
681+ namespace = ("new/db" ,)
682+
683+ if test_catalog .namespace_exists (namespace ):
684+ test_catalog .drop_namespace (namespace )
685+
686+ assert not test_catalog .namespace_exists (namespace )
687+
688+ test_catalog .create_namespace (namespace )
689+ assert test_catalog .namespace_exists (namespace )
690+
691+ properties = test_catalog .load_namespace_properties (namespace )
692+ assert properties is not None
693+
694+ test_catalog .drop_namespace (namespace )
695+ assert not test_catalog .namespace_exists (namespace )
696+
697+
675698@pytest .mark .integration
676699@pytest .mark .parametrize ("test_catalog" , CATALOGS )
677700def test_incompatible_sorted_schema_evolution (
@@ -692,3 +715,111 @@ def test_incompatible_sorted_schema_evolution(
692715 assert table .schema () == Schema (
693716 NestedField (1 , "VendorID" , IntegerType (), False ), NestedField (2 , "tpep_pickup_datetime" , TimestampType (), False )
694717 )
718+
719+
720+ @pytest .mark .integration
721+ @pytest .mark .parametrize ("test_catalog" , CATALOGS )
722+ def test_namespace_with_dot (test_catalog : Catalog ) -> None :
723+ if isinstance (test_catalog , (HiveCatalog , SqlCatalog )):
724+ pytest .skip (f"{ type (test_catalog ).__name__ } does not support dot in namespace" )
725+
726+ namespace = ("new.db" ,)
727+
728+ if test_catalog .namespace_exists (namespace ):
729+ test_catalog .drop_namespace (namespace )
730+
731+ assert not test_catalog .namespace_exists (namespace )
732+
733+ test_catalog .create_namespace (namespace )
734+ assert test_catalog .namespace_exists (namespace )
735+
736+ # REST Catalog fixture treats this as a hierarchical namespace.
737+ # Calling list namespaces will get `new`, not `new.db`.
738+ if isinstance (test_catalog , RestCatalog ):
739+ namespaces = test_catalog .list_namespaces ()
740+ assert ("new" ,) in namespaces or ("new.db" ,) in namespaces
741+ else :
742+ assert namespace in test_catalog .list_namespaces ()
743+
744+ properties = test_catalog .load_namespace_properties (namespace )
745+ assert properties is not None
746+
747+ test_catalog .drop_namespace (namespace )
748+ assert not test_catalog .namespace_exists (namespace )
749+
750+
751+ @pytest .mark .integration
752+ @pytest .mark .parametrize ("test_catalog" , CATALOGS )
753+ def test_table_name_with_slash (test_catalog : Catalog , table_schema_simple : Schema ) -> None :
754+ if isinstance (test_catalog , (HiveCatalog , SqlCatalog )):
755+ pytest .skip (f"{ type (test_catalog ).__name__ } does not support slash in table name" )
756+
757+ namespace = ("ns_slash" ,)
758+ table_ident = ("ns_slash" , "tab/le" )
759+
760+ if not test_catalog .namespace_exists (namespace ):
761+ test_catalog .create_namespace (namespace )
762+
763+ if test_catalog .table_exists (table_ident ):
764+ test_catalog .drop_table (table_ident )
765+
766+ assert not test_catalog .table_exists (table_ident )
767+
768+ test_catalog .create_table (table_ident , table_schema_simple )
769+ assert test_catalog .table_exists (table_ident )
770+
771+ table = test_catalog .load_table (table_ident )
772+ assert table .schema ().as_struct () == table_schema_simple .as_struct ()
773+
774+ test_catalog .drop_table (table_ident )
775+ assert not test_catalog .table_exists (table_ident )
776+
777+
778+ @pytest .mark .integration
779+ @pytest .mark .parametrize ("test_catalog" , CATALOGS )
780+ def test_table_name_with_dot (test_catalog : Catalog , table_schema_simple : Schema ) -> None :
781+ if isinstance (test_catalog , (HiveCatalog , SqlCatalog )):
782+ pytest .skip (f"{ type (test_catalog ).__name__ } does not support dot in table name" )
783+
784+ namespace = ("ns_dot" ,)
785+ table_ident = ("ns_dot" , "ta.ble" )
786+
787+ if not test_catalog .namespace_exists (namespace ):
788+ test_catalog .create_namespace (namespace )
789+
790+ if test_catalog .table_exists (table_ident ):
791+ test_catalog .drop_table (table_ident )
792+
793+ assert not test_catalog .table_exists (table_ident )
794+
795+ test_catalog .create_table (table_ident , table_schema_simple )
796+ assert test_catalog .table_exists (table_ident )
797+
798+ assert table_ident in test_catalog .list_tables (namespace )
799+
800+ table = test_catalog .load_table (table_ident )
801+ assert table .schema ().as_struct () == table_schema_simple .as_struct ()
802+
803+ test_catalog .drop_table (table_ident )
804+ assert not test_catalog .table_exists (table_ident )
805+
806+
807+ @pytest .mark .integration
808+ @pytest .mark .parametrize ("test_catalog" , CATALOGS )
809+ def test_drop_missing_table (test_catalog : Catalog , database_name : str ) -> None :
810+ test_catalog .create_namespace_if_not_exists (database_name )
811+ table_ident = (database_name , "missing_table" )
812+ assert not test_catalog .table_exists (table_ident )
813+ with pytest .raises (NoSuchTableError ):
814+ test_catalog .drop_table (table_ident )
815+
816+
817+ @pytest .mark .integration
818+ @pytest .mark .parametrize ("test_catalog" , CATALOGS )
819+ def test_drop_nonexistent_namespace (test_catalog : Catalog ) -> None :
820+ if isinstance (test_catalog , HiveCatalog ):
821+ pytest .skip ("HiveCatalog raises NoSuchObjectException instead of NoSuchNamespaceError" )
822+
823+ namespace = ("non_existent_namespace" ,)
824+ with pytest .raises (NoSuchNamespaceError ):
825+ test_catalog .drop_namespace (namespace )
0 commit comments