@@ -23,7 +23,7 @@ import java.util.Collections
2323import scala .collection .JavaConverters ._
2424
2525import org .apache .spark .SparkFunSuite
26- import org .apache .spark .sql .catalyst .analysis .{NoSuchTableException , TableAlreadyExistsException }
26+ import org .apache .spark .sql .catalyst .analysis .{NamespaceAlreadyExistsException , NoSuchNamespaceException , NoSuchTableException , TableAlreadyExistsException }
2727import org .apache .spark .sql .catalyst .parser .CatalystSqlParser
2828import org .apache .spark .sql .internal .SQLConf
2929import org .apache .spark .sql .types .{DoubleType , IntegerType , LongType , StringType , StructField , StructType , TimestampType }
@@ -37,13 +37,14 @@ class TableCatalogSuite extends SparkFunSuite {
3737 .add(" id" , IntegerType )
3838 .add(" data" , StringType )
3939
40- private def newCatalog (): TableCatalog = {
40+ private def newCatalog (): TableCatalog with SupportsNamespaces = {
4141 val newCatalog = new TestTableCatalog
4242 newCatalog.initialize(" test" , CaseInsensitiveStringMap .empty())
4343 newCatalog
4444 }
4545
46- private val testIdent = Identifier .of(Array (" `" , " ." ), " test_table" )
46+ private val testNs = Array (" `" , " ." )
47+ private val testIdent = Identifier .of(testNs, " test_table" )
4748
4849 test(" Catalogs can load the catalog" ) {
4950 val catalog = newCatalog()
@@ -654,4 +655,198 @@ class TableCatalogSuite extends SparkFunSuite {
654655 assert(! wasDropped)
655656 assert(! catalog.tableExists(testIdent))
656657 }
658+
659+ test(" listNamespaces: list namespaces from metadata" ) {
660+ val catalog = newCatalog()
661+ catalog.createNamespaceMetadata(Array (" ns1" ), Map (" property" -> " value" ).asJava)
662+
663+ assert(catalog.listNamespaces === Array (Array (" ns1" )))
664+ assert(catalog.listNamespaces(Array ()) === Array (Array (" ns1" )))
665+ assert(catalog.listNamespaces(Array (" ns1" )) === Array ())
666+ }
667+
668+ test(" listNamespaces: list namespaces from tables" ) {
669+ val catalog = newCatalog()
670+ val ident1 = Identifier .of(Array (" ns1" , " ns2" ), " test_table_1" )
671+ val ident2 = Identifier .of(Array (" ns1" , " ns2" ), " test_table_2" )
672+
673+ catalog.createTable(ident1, schema, Array .empty, emptyProps)
674+ catalog.createTable(ident2, schema, Array .empty, emptyProps)
675+
676+ assert(catalog.listNamespaces === Array (Array (" ns1" )))
677+ assert(catalog.listNamespaces(Array ()) === Array (Array (" ns1" )))
678+ assert(catalog.listNamespaces(Array (" ns1" )) === Array (Array (" ns1" , " ns2" )))
679+ assert(catalog.listNamespaces(Array (" ns1" , " ns2" )) === Array ())
680+ }
681+
682+ test(" listNamespaces: list namespaces from metadata and tables" ) {
683+ val catalog = newCatalog()
684+ val ident1 = Identifier .of(Array (" ns1" , " ns2" ), " test_table_1" )
685+ val ident2 = Identifier .of(Array (" ns1" , " ns2" ), " test_table_2" )
686+
687+ catalog.createNamespaceMetadata(Array (" ns1" ), Map (" property" -> " value" ).asJava)
688+ catalog.createTable(ident1, schema, Array .empty, emptyProps)
689+ catalog.createTable(ident2, schema, Array .empty, emptyProps)
690+
691+ assert(catalog.listNamespaces === Array (Array (" ns1" )))
692+ assert(catalog.listNamespaces(Array ()) === Array (Array (" ns1" )))
693+ assert(catalog.listNamespaces(Array (" ns1" )) === Array (Array (" ns1" , " ns2" )))
694+ assert(catalog.listNamespaces(Array (" ns1" , " ns2" )) === Array ())
695+ }
696+
697+ test(" loadNamespaceMetadata: fail if no metadata or tables exist" ) {
698+ val catalog = newCatalog()
699+
700+ val exc = intercept[NoSuchNamespaceException ] {
701+ catalog.loadNamespaceMetadata(testNs)
702+ }
703+
704+ assert(exc.getMessage.contains(testNs.quoted))
705+ }
706+
707+ test(" loadNamespaceMetadata: no metadata, table exists" ) {
708+ val catalog = newCatalog()
709+
710+ catalog.createTable(testIdent, schema, Array .empty, emptyProps)
711+
712+ val metadata = catalog.loadNamespaceMetadata(testNs)
713+
714+ assert(metadata.asScala === Map .empty)
715+ }
716+
717+ test(" loadNamespaceMetadata: metadata exists, no tables" ) {
718+ val catalog = newCatalog()
719+
720+ catalog.createNamespaceMetadata(testNs, Map (" property" -> " value" ).asJava)
721+
722+ val metadata = catalog.loadNamespaceMetadata(testNs)
723+
724+ assert(metadata.asScala === Map (" property" -> " value" ))
725+ }
726+
727+ test(" loadNamespaceMetadata: metadata and table exist" ) {
728+ val catalog = newCatalog()
729+
730+ catalog.createTable(testIdent, schema, Array .empty, emptyProps)
731+ catalog.createNamespaceMetadata(testNs, Map (" property" -> " value" ).asJava)
732+
733+ val metadata = catalog.loadNamespaceMetadata(testNs)
734+
735+ assert(metadata.asScala === Map (" property" -> " value" ))
736+ }
737+
738+ test(" createNamespaceMetadata: basic behavior" ) {
739+ val catalog = newCatalog()
740+
741+ catalog.createNamespaceMetadata(testNs, Map (" property" -> " value" ).asJava)
742+
743+ assert(catalog.namespaceExists(testNs) === true )
744+ assert(catalog.loadNamespaceMetadata(testNs).asScala === Map (" property" -> " value" ))
745+ }
746+
747+ test(" createNamespaceMetadata: fail if metadata already exists" ) {
748+ val catalog = newCatalog()
749+
750+ catalog.createNamespaceMetadata(testNs, Map (" property" -> " value" ).asJava)
751+
752+ val exc = intercept[NamespaceAlreadyExistsException ] {
753+ catalog.createNamespaceMetadata(testNs, Map (" property" -> " value" ).asJava)
754+ }
755+
756+ assert(exc.getMessage.contains(testNs.quoted))
757+ assert(catalog.namespaceExists(testNs) === true )
758+ assert(catalog.loadNamespaceMetadata(testNs).asScala === Map (" property" -> " value" ))
759+ }
760+
761+ test(" createNamespaceMetadata: table exists" ) {
762+ val catalog = newCatalog()
763+
764+ catalog.createTable(testIdent, schema, Array .empty, emptyProps)
765+
766+ assert(catalog.namespaceExists(testNs) === true )
767+ assert(catalog.loadNamespaceMetadata(testNs).asScala === Map .empty)
768+
769+ catalog.createNamespaceMetadata(testNs, Map (" property" -> " value" ).asJava)
770+
771+ assert(catalog.namespaceExists(testNs) === true )
772+ assert(catalog.loadNamespaceMetadata(testNs).asScala === Map (" property" -> " value" ))
773+ }
774+
775+ test(" dropNamespace: drop missing namespace" ) {
776+ val catalog = newCatalog()
777+
778+ assert(catalog.namespaceExists(testNs) === false )
779+
780+ val ret = catalog.dropNamespace(testNs)
781+
782+ assert(ret === false )
783+ }
784+
785+ test(" dropNamespace: drop empty namespace" ) {
786+ val catalog = newCatalog()
787+
788+ catalog.createNamespaceMetadata(testNs, Map (" property" -> " value" ).asJava)
789+
790+ assert(catalog.namespaceExists(testNs) === true )
791+ assert(catalog.loadNamespaceMetadata(testNs).asScala === Map (" property" -> " value" ))
792+
793+ val ret = catalog.dropNamespace(testNs)
794+
795+ assert(ret === true )
796+ assert(catalog.namespaceExists(testNs) === false )
797+ }
798+
799+ test(" dropNamespace: fail if not empty" ) {
800+ val catalog = newCatalog()
801+
802+ catalog.createTable(testIdent, schema, Array .empty, emptyProps)
803+ catalog.createNamespaceMetadata(testNs, Map (" property" -> " value" ).asJava)
804+
805+ val exc = intercept[IllegalStateException ] {
806+ catalog.dropNamespace(testNs)
807+ }
808+
809+ assert(exc.getMessage.contains(testNs.quoted))
810+ assert(catalog.namespaceExists(testNs) === true )
811+ assert(catalog.loadNamespaceMetadata(testNs).asScala === Map (" property" -> " value" ))
812+ }
813+
814+ test(" alterNamespace: basic behavior" ) {
815+ val catalog = newCatalog()
816+
817+ catalog.createNamespaceMetadata(testNs, Map (" property" -> " value" ).asJava)
818+
819+ catalog.alterNamespace(testNs, NamespaceChange .setProperty(" property2" , " value2" ))
820+ assert(catalog.loadNamespaceMetadata(testNs).asScala === Map (
821+ " property" -> " value" , " property2" -> " value2" ))
822+
823+ catalog.alterNamespace(testNs,
824+ NamespaceChange .removeProperty(" property2" ),
825+ NamespaceChange .setProperty(" property3" , " value3" ))
826+ assert(catalog.loadNamespaceMetadata(testNs).asScala === Map (
827+ " property" -> " value" , " property3" -> " value3" ))
828+
829+ catalog.alterNamespace(testNs, NamespaceChange .removeProperty(" property3" ))
830+ assert(catalog.loadNamespaceMetadata(testNs).asScala === Map (" property" -> " value" ))
831+ }
832+
833+ test(" alterNamespace: create metadata if missing and table exists" ) {
834+ val catalog = newCatalog()
835+
836+ catalog.createTable(testIdent, schema, Array .empty, emptyProps)
837+
838+ catalog.alterNamespace(testNs, NamespaceChange .setProperty(" property" , " value" ))
839+
840+ assert(catalog.loadNamespaceMetadata(testNs).asScala === Map (" property" -> " value" ))
841+ }
842+
843+ test(" alterNamespace: fail if no metadata or table exists" ) {
844+ val catalog = newCatalog()
845+
846+ val exc = intercept[NoSuchNamespaceException ] {
847+ catalog.alterNamespace(testNs, NamespaceChange .setProperty(" property" , " value" ))
848+ }
849+
850+ assert(exc.getMessage.contains(testNs.quoted))
851+ }
657852}
0 commit comments