Skip to content
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -1193,15 +1193,6 @@ class DDLParserSuite extends AnalysisTest {
"DESC TABLE COLUMN for a specific partition is not supported"))
}

test("describe database") {
val sql1 = "DESCRIBE DATABASE EXTENDED a.b"
val sql2 = "DESCRIBE DATABASE a.b"
comparePlans(parsePlan(sql1),
DescribeNamespace(UnresolvedNamespace(Seq("a", "b")), extended = true))
comparePlans(parsePlan(sql2),
DescribeNamespace(UnresolvedNamespace(Seq("a", "b")), extended = false))
}

test("SPARK-17328 Fix NPE with EXPLAIN DESCRIBE TABLE") {
comparePlans(parsePlan("describe t"),
DescribeRelation(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1233,26 +1233,6 @@ class DataSourceV2SQLSuite
assert(exception.getMessage.contains("Namespace 'ns1' not found"))
}

test("DescribeNamespace using v2 catalog") {
withNamespace("testcat.ns1.ns2") {
sql("CREATE NAMESPACE IF NOT EXISTS testcat.ns1.ns2 COMMENT " +
"'test namespace' LOCATION '/tmp/ns_test'")
val descriptionDf = sql("DESCRIBE NAMESPACE testcat.ns1.ns2")
assert(descriptionDf.schema.map(field => (field.name, field.dataType)) ===
Seq(
("info_name", StringType),
("info_value", StringType)
))
val description = descriptionDf.collect()
assert(description === Seq(
Row("Namespace Name", "ns2"),
Row(SupportsNamespaces.PROP_COMMENT.capitalize, "test namespace"),
Row(SupportsNamespaces.PROP_LOCATION.capitalize, "/tmp/ns_test"),
Row(SupportsNamespaces.PROP_OWNER.capitalize, defaultUser))
)
}
}

test("ALTER NAMESPACE .. SET PROPERTIES using v2 catalog") {
withNamespace("testcat.ns1.ns2") {
sql("CREATE NAMESPACE IF NOT EXISTS testcat.ns1.ns2 COMMENT " +
Expand Down Expand Up @@ -2810,25 +2790,6 @@ class DataSourceV2SQLSuite
}
}

test("SPARK-34577: drop/add columns to a dataset of `DESCRIBE NAMESPACE`") {
withNamespace("ns") {
sql("CREATE NAMESPACE ns")
val description = sql(s"DESCRIBE NAMESPACE ns")
val noCommentDataset = description.drop("info_name")
val expectedSchema = new StructType()
.add(
name = "info_value",
dataType = StringType,
nullable = true,
metadata = new MetadataBuilder()
.putString("comment", "value of the namespace info").build())
assert(noCommentDataset.schema === expectedSchema)
val isNullDataset = noCommentDataset
.withColumn("is_null", noCommentDataset("info_value").isNull)
assert(isNullDataset.schema === expectedSchema.add("is_null", BooleanType, false))
}
}

test("SPARK-34923: do not propagate metadata columns through Project") {
val t1 = s"${catalogAndNamespace}table"
withTable(t1) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -225,7 +225,29 @@ class InMemoryCatalogedDDLSuite extends DDLSuite with SharedSparkSession {
}
}

abstract class DDLSuite extends QueryTest with SQLTestUtils {
trait CommandTestUtils extends SQLTestUtils {
private val escapedIdentifier = "`(.+)`".r

/**
* Strip backticks, if any, from the string.
*/
protected def cleanIdentifier(ident: String): String = {
ident match {
case escapedIdentifier(i) => i
case plainIdent => plainIdent
}
}

/**
* Returns the path to the database of the given name.
*/
protected def getDBPath(dbName: String): URI = {
val warehousePath = makeQualifiedPath(spark.sessionState.conf.warehousePath)
new Path(CatalogUtils.URIToString(warehousePath), s"$dbName.db").toUri
}
}

abstract class DDLSuite extends QueryTest with CommandTestUtils {

protected val reversedProperties = Seq(PROP_OWNER)

Expand All @@ -239,8 +261,6 @@ abstract class DDLSuite extends QueryTest with SQLTestUtils {
isDataSource: Boolean = true,
partitionCols: Seq[String] = Seq("a", "b")): CatalogTable

private val escapedIdentifier = "`(.+)`".r

private def dataSource: String = {
if (isUsingHiveMetastore) {
"HIVE"
Expand All @@ -258,16 +278,6 @@ abstract class DDLSuite extends QueryTest with SQLTestUtils {
assert(normalizeCatalogTable(actual) == normalizeCatalogTable(expected))
}

/**
* Strip backticks, if any, from the string.
*/
private def cleanIdentifier(ident: String): String = {
ident match {
case escapedIdentifier(i) => i
case plainIdent => plainIdent
}
}

private def assertUnsupported(query: String): Unit = {
val e = intercept[AnalysisException] {
sql(query)
Expand Down Expand Up @@ -304,11 +314,6 @@ abstract class DDLSuite extends QueryTest with SQLTestUtils {
catalog.createPartitions(tableName, Seq(part), ignoreIfExists = false)
}

private def getDBPath(dbName: String): URI = {
val warehousePath = makeQualifiedPath(spark.sessionState.conf.warehousePath)
new Path(CatalogUtils.URIToString(warehousePath), s"$dbName.db").toUri
}

test("alter table: set location (datasource table)") {
testSetLocation(isDatasourceTable = true)
}
Expand Down Expand Up @@ -757,14 +762,6 @@ abstract class DDLSuite extends QueryTest with SQLTestUtils {

sql(s"CREATE DATABASE $dbName")

checkAnswer(
sql(s"DESCRIBE DATABASE EXTENDED $dbName").toDF("key", "value")
.where("key not like 'Owner%'"), // filter for consistency with in-memory catalog
Row("Database Name", dbNameWithoutBackTicks) ::
Row("Comment", "") ::
Row("Location", CatalogUtils.URIToString(location)) ::
Row("Properties", "") :: Nil)

sql(s"ALTER DATABASE $dbName SET DBPROPERTIES ('a'='a', 'b'='b', 'c'='c')")

checkAnswer(
Expand Down Expand Up @@ -813,7 +810,7 @@ abstract class DDLSuite extends QueryTest with SQLTestUtils {
}
}

test("Drop/Alter/Describe Database - database does not exists") {
test("Drop/Alter Database - database does not exists") {
val databaseNames = Seq("db1", "`database`")

databaseNames.foreach { dbName =>
Expand All @@ -829,13 +826,6 @@ abstract class DDLSuite extends QueryTest with SQLTestUtils {
sql(s"ALTER DATABASE $dbName SET DBPROPERTIES ('d'='d')")
}.getMessage
assert(message.contains(s"Database '$dbNameWithoutBackTicks' not found"))

message = intercept[AnalysisException] {
sql(s"DESCRIBE DATABASE EXTENDED $dbName")
}.getMessage
assert(message.contains(s"Database '$dbNameWithoutBackTicks' not found"))

sql(s"DROP DATABASE IF EXISTS $dbName")
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/*
* 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.
*/

package org.apache.spark.sql.execution.command

import org.apache.spark.sql.catalyst.analysis.{AnalysisTest, UnresolvedNamespace}
import org.apache.spark.sql.catalyst.parser.CatalystSqlParser.parsePlan
import org.apache.spark.sql.catalyst.plans.logical.DescribeNamespace

class DescribeNamespaceParserSuite extends AnalysisTest {
test("describe namespace") {
val sql1 = "DESCRIBE NAMESPACE EXTENDED a.b"
val sql2 = "DESCRIBE NAMESPACE a.b"
comparePlans(parsePlan(sql1),
DescribeNamespace(UnresolvedNamespace(Seq("a", "b")), extended = true))
comparePlans(parsePlan(sql2),
DescribeNamespace(UnresolvedNamespace(Seq("a", "b")), extended = false))
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
/*
* 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.
*/

package org.apache.spark.sql.execution.command

import org.apache.spark.sql.{AnalysisException, QueryTest}

/**
* This base suite contains unified tests for the `DESCRIBE NAMESPACE` command that check V1 and V2
* table catalogs. The tests that cannot run for all supported catalogs are located in more
* specific test suites:
*
* - V2 table catalog tests: `org.apache.spark.sql.execution.command.v2.DescribeNamespaceSuite`
* - V1 table catalog tests:
* `org.apache.spark.sql.execution.command.v1.DescribeNamespaceSuiteBase`
* - V1 In-Memory catalog: `org.apache.spark.sql.execution.command.v1.DescribeNamespaceSuite`
* - V1 Hive External catalog:
* `org.apache.spark.sql.hive.execution.command.DescribeNamespaceSuite`
*/
trait DescribeNamespaceSuiteBase extends QueryTest with DDLCommandTestUtils with CommandTestUtils {
override val command = "DESCRIBE NAMESPACE"

test("namespace does not exists") {
val databaseNames = Seq("db1", "`database`")
databaseNames.foreach { dbName =>
val dbNameWithoutBackTicks = cleanIdentifier(dbName)
val message = intercept[AnalysisException] {
sql(s"DESCRIBE NAMESPACE EXTENDED $catalog.$dbName")
}.getMessage

val prefix = if (catalogVersion == "V2") "Namespace" else "Database"
assert(message.contains(s"$prefix '$dbNameWithoutBackTicks' not found"))

sql(s"DROP NAMESPACE IF EXISTS $catalog.$dbName")
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
/*
* 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.
*/

package org.apache.spark.sql.execution.command.v1

import org.apache.spark.sql.Row
import org.apache.spark.sql.catalyst.catalog.CatalogUtils
import org.apache.spark.sql.execution.command

/**
* This base suite contains unified tests for the `DESCRIBE NAMESPACE` command that checks V1
* table catalogs. The tests that cannot run for all V1 catalogs are located in more
* specific test suites:
*
* - V1 In-Memory catalog: `org.apache.spark.sql.execution.command.v1.DescribeNamespaceSuite`
* - V1 Hive External catalog:
* `org.apache.spark.sql.hive.execution.command.DescribeNamespaceSuite`
*/
trait DescribeNamespaceSuiteBase extends command.DescribeNamespaceSuiteBase {
test("basic") {
val namespaceNames = Seq("db1", "`database`")
withNamespace(namespaceNames: _*) {
namespaceNames.foreach { ns =>
val dbNameWithoutBackTicks = cleanIdentifier(ns)
val location = getDBPath(dbNameWithoutBackTicks)

sql(s"CREATE NAMESPACE $ns")

checkAnswer(
sql(s"DESCRIBE NAMESPACE EXTENDED $ns")
.toDF("key", "value")
.where("key not like 'Owner%'"), // filter for consistency with in-memory catalog
Row("Database Name", dbNameWithoutBackTicks) ::
Row("Comment", "") ::
Row("Location", CatalogUtils.URIToString(location)) ::
Row("Properties", "") :: Nil)
}
}
}
}

/**
* The class contains tests for the `DESCRIBE NAMESPACE` command to check V1 In-Memory
* table catalog.
*/
class DescribeNamespaceSuite extends DescribeNamespaceSuiteBase with CommandSuiteBase
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
/*
* 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.
*/

package org.apache.spark.sql.execution.command.v2

import org.apache.spark.sql.Row
import org.apache.spark.sql.connector.catalog.SupportsNamespaces
import org.apache.spark.sql.execution.command
import org.apache.spark.sql.types.{BooleanType, MetadataBuilder, StringType, StructType}
import org.apache.spark.util.Utils

/**
* The class contains tests for the `DESCRIBE NAMESPACE` command to check V2 table catalogs.
*/
class DescribeNamespaceSuite extends command.DescribeNamespaceSuiteBase with CommandSuiteBase {
test("DescribeNamespace using v2 catalog") {
withNamespace("test_catalog.ns1.ns2") {
sql("CREATE NAMESPACE IF NOT EXISTS test_catalog.ns1.ns2 COMMENT " +
"'test namespace' LOCATION '/tmp/ns_test'")
val descriptionDf = sql("DESCRIBE NAMESPACE test_catalog.ns1.ns2")
assert(descriptionDf.schema.map(field => (field.name, field.dataType)) ===
Seq(
("info_name", StringType),
("info_value", StringType)
))
val description = descriptionDf.collect()
assert(description === Seq(
Row("Namespace Name", "ns2"),
Row(SupportsNamespaces.PROP_COMMENT.capitalize, "test namespace"),
Row(SupportsNamespaces.PROP_LOCATION.capitalize, "/tmp/ns_test"),
Row(SupportsNamespaces.PROP_OWNER.capitalize, Utils.getCurrentUserName()))
)
}
}

test("SPARK-34577: drop/add columns to a dataset of `DESCRIBE NAMESPACE`") {
withNamespace("ns") {
sql("CREATE NAMESPACE ns")
val description = sql(s"DESCRIBE NAMESPACE ns")
val noCommentDataset = description.drop("info_name")
val expectedSchema = new StructType()
.add(
name = "info_value",
dataType = StringType,
nullable = true,
metadata = new MetadataBuilder()
.putString("comment", "value of the namespace info").build())
assert(noCommentDataset.schema === expectedSchema)
val isNullDataset = noCommentDataset
.withColumn("is_null", noCommentDataset("info_value").isNull)
assert(isNullDataset.schema === expectedSchema.add("is_null", BooleanType, false))
}
}
}
Loading