Skip to content

Commit 3228d72

Browse files
yaooqinndongjoon-hyun
authored andcommitted
[SPARK-30603][SQL] Move RESERVED_PROPERTIES from SupportsNamespaces and TableCatalog to CatalogV2Util
### What changes were proposed in this pull request? In this PR, I propose to move the `RESERVED_PROPERTIES `s from `SupportsNamespaces` and `TableCatalog` to `CatalogV2Util`, which can keep `RESERVED_PROPERTIES ` safe for interval usages only. ### Why are the changes needed? the `RESERVED_PROPERTIES` should not be changed by subclasses ### Does this PR introduce any user-facing change? no ### How was this patch tested? existing uts Closes #27318 from yaooqinn/SPARK-30603. Authored-by: Kent Yao <yaooqinn@hotmail.com> Signed-off-by: Dongjoon Hyun <dhyun@apple.com>
1 parent 976946a commit 3228d72

File tree

10 files changed

+56
-52
lines changed

10 files changed

+56
-52
lines changed

sql/catalyst/src/main/java/org/apache/spark/sql/connector/catalog/SupportsNamespaces.java

Lines changed: 3 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,6 @@
2121
import org.apache.spark.sql.catalyst.analysis.NamespaceAlreadyExistsException;
2222
import org.apache.spark.sql.catalyst.analysis.NoSuchNamespaceException;
2323

24-
import java.util.Arrays;
25-
import java.util.List;
2624
import java.util.Map;
2725

2826
/**
@@ -42,33 +40,22 @@
4240
public interface SupportsNamespaces extends CatalogPlugin {
4341

4442
/**
45-
* A property to specify the location of the namespace. If the namespace
43+
* A reserved property to specify the location of the namespace. If the namespace
4644
* needs to store files, it should be under this location.
4745
*/
4846
String PROP_LOCATION = "location";
4947

5048
/**
51-
* A property to specify the description of the namespace. The description
49+
* A reserved property to specify the description of the namespace. The description
5250
* will be returned in the result of "DESCRIBE NAMESPACE" command.
5351
*/
5452
String PROP_COMMENT = "comment";
5553

5654
/**
57-
* A property to specify the owner of the namespace.
55+
* A reserved property to specify the owner of the namespace.
5856
*/
5957
String PROP_OWNER = "owner";
6058

61-
/**
62-
* The list of reserved namespace properties, which can not be removed or changed directly by
63-
* the syntax:
64-
* {{
65-
* ALTER NAMESPACE ... SET PROPERTIES ...
66-
* }}
67-
*
68-
* They need specific syntax to modify
69-
*/
70-
List<String> RESERVED_PROPERTIES = Arrays.asList(PROP_COMMENT, PROP_LOCATION, PROP_OWNER);
71-
7259
/**
7360
* List top-level namespaces from the catalog.
7461
* <p>

sql/catalyst/src/main/java/org/apache/spark/sql/connector/catalog/TableCatalog.java

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,6 @@
2424
import org.apache.spark.sql.catalyst.analysis.TableAlreadyExistsException;
2525
import org.apache.spark.sql.types.StructType;
2626

27-
import java.util.Arrays;
28-
import java.util.List;
2927
import java.util.Map;
3028

3129
/**
@@ -41,32 +39,26 @@
4139
public interface TableCatalog extends CatalogPlugin {
4240

4341
/**
44-
* A property to specify the location of the table. The files of the table
42+
* A reserved property to specify the location of the table. The files of the table
4543
* should be under this location.
4644
*/
4745
String PROP_LOCATION = "location";
4846

4947
/**
50-
* A property to specify the description of the table.
48+
* A reserved property to specify the description of the table.
5149
*/
5250
String PROP_COMMENT = "comment";
5351

5452
/**
55-
* A property to specify the provider of the table.
53+
* A reserved property to specify the provider of the table.
5654
*/
5755
String PROP_PROVIDER = "provider";
5856

5957
/**
60-
* A property to specify the owner of the table.
58+
* A reserved property to specify the owner of the table.
6159
*/
6260
String PROP_OWNER = "owner";
6361

64-
/**
65-
* The list of reserved table properties.
66-
*/
67-
List<String> RESERVED_PROPERTIES =
68-
Arrays.asList(PROP_COMMENT, PROP_LOCATION, PROP_PROVIDER, PROP_OWNER);
69-
7062
/**
7163
* List the tables in a namespace from the catalog.
7264
* <p>

sql/catalyst/src/main/scala/org/apache/spark/sql/connector/catalog/CatalogV2Util.scala

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,35 @@ import org.apache.spark.util.Utils
3333
private[sql] object CatalogV2Util {
3434
import org.apache.spark.sql.connector.catalog.CatalogV2Implicits._
3535

36+
/**
37+
* The list of reserved table properties, which can not be removed or changed directly by
38+
* the syntax:
39+
* {{
40+
* ALTER TABLE ... SET TBLPROPERTIES ...
41+
* }}
42+
*
43+
* They need specific syntax to modify
44+
*/
45+
val TABLE_RESERVED_PROPERTIES =
46+
Seq(TableCatalog.PROP_COMMENT,
47+
TableCatalog.PROP_LOCATION,
48+
TableCatalog.PROP_PROVIDER,
49+
TableCatalog.PROP_OWNER)
50+
51+
/**
52+
* The list of reserved namespace properties, which can not be removed or changed directly by
53+
* the syntax:
54+
* {{
55+
* ALTER NAMESPACE ... SET PROPERTIES ...
56+
* }}
57+
*
58+
* They need specific syntax to modify
59+
*/
60+
val NAMESPACE_RESERVED_PROPERTIES =
61+
Seq(SupportsNamespaces.PROP_COMMENT,
62+
SupportsNamespaces.PROP_LOCATION,
63+
SupportsNamespaces.PROP_OWNER)
64+
3665
/**
3766
* Apply properties changes to a map and return the result.
3867
*/

sql/core/src/main/scala/org/apache/spark/sql/catalyst/analysis/ResolveSessionCatalog.scala

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,14 +17,12 @@
1717

1818
package org.apache.spark.sql.catalyst.analysis
1919

20-
import scala.collection.JavaConverters._
21-
2220
import org.apache.spark.sql.{AnalysisException, SaveMode}
2321
import org.apache.spark.sql.catalyst.{FunctionIdentifier, TableIdentifier}
2422
import org.apache.spark.sql.catalyst.catalog.{BucketSpec, CatalogStorageFormat, CatalogTable, CatalogTableType, CatalogUtils}
2523
import org.apache.spark.sql.catalyst.plans.logical._
2624
import org.apache.spark.sql.catalyst.rules.Rule
27-
import org.apache.spark.sql.connector.catalog.{CatalogManager, CatalogPlugin, Identifier, LookupCatalog, SupportsNamespaces, TableCatalog, TableChange, V1Table}
25+
import org.apache.spark.sql.connector.catalog.{CatalogManager, CatalogPlugin, CatalogV2Util, Identifier, LookupCatalog, SupportsNamespaces, TableCatalog, TableChange, V1Table}
2826
import org.apache.spark.sql.connector.expressions.Transform
2927
import org.apache.spark.sql.execution.command._
3028
import org.apache.spark.sql.execution.datasources.{CreateTable, DataSource, RefreshTable}
@@ -326,7 +324,7 @@ class ResolveSessionCatalog(
326324

327325
val comment = c.properties.get(SupportsNamespaces.PROP_COMMENT)
328326
val location = c.properties.get(SupportsNamespaces.PROP_LOCATION)
329-
val newProperties = c.properties -- SupportsNamespaces.RESERVED_PROPERTIES.asScala
327+
val newProperties = c.properties -- CatalogV2Util.NAMESPACE_RESERVED_PROPERTIES
330328
CreateDatabaseCommand(ns.head, c.ifNotExists, location, comment, newProperties)
331329

332330
case d @ DropNamespace(SessionCatalogAndNamespace(_, ns), _, _) =>

sql/core/src/main/scala/org/apache/spark/sql/execution/command/ddl.scala

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ import java.util.Locale
2121
import java.util.concurrent.TimeUnit._
2222

2323
import scala.collection.{GenMap, GenSeq}
24-
import scala.collection.JavaConverters._
2524
import scala.collection.parallel.ForkJoinTaskSupport
2625
import scala.collection.parallel.immutable.ParVector
2726
import scala.util.control.NonFatal
@@ -38,8 +37,8 @@ import org.apache.spark.sql.catalyst.catalog._
3837
import org.apache.spark.sql.catalyst.catalog.CatalogTypes.TablePartitionSpec
3938
import org.apache.spark.sql.catalyst.expressions.{Attribute, AttributeReference}
4039
import org.apache.spark.sql.catalyst.plans.logical.LogicalPlan
40+
import org.apache.spark.sql.connector.catalog.{CatalogV2Util, TableCatalog}
4141
import org.apache.spark.sql.connector.catalog.SupportsNamespaces._
42-
import org.apache.spark.sql.connector.catalog.TableCatalog
4342
import org.apache.spark.sql.execution.datasources.{HadoopFsRelation, LogicalRelation, PartitioningUtils}
4443
import org.apache.spark.sql.execution.datasources.orc.OrcFileFormat
4544
import org.apache.spark.sql.execution.datasources.parquet.ParquetSchemaConverter
@@ -183,7 +182,7 @@ case class DescribeDatabaseCommand(
183182
Row("Owner", allDbProperties.getOrElse(PROP_OWNER, "")) :: Nil
184183

185184
if (extended) {
186-
val properties = allDbProperties -- RESERVED_PROPERTIES.asScala
185+
val properties = allDbProperties -- CatalogV2Util.NAMESPACE_RESERVED_PROPERTIES
187186
val propertiesStr =
188187
if (properties.isEmpty) {
189188
""

sql/core/src/main/scala/org/apache/spark/sql/execution/datasources/v2/DescribeNamespaceExec.scala

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ import scala.collection.mutable.ArrayBuffer
2323
import org.apache.spark.sql.catalyst.InternalRow
2424
import org.apache.spark.sql.catalyst.encoders.RowEncoder
2525
import org.apache.spark.sql.catalyst.expressions.{Attribute, GenericRowWithSchema}
26-
import org.apache.spark.sql.connector.catalog.SupportsNamespaces
26+
import org.apache.spark.sql.connector.catalog.{CatalogV2Util, SupportsNamespaces}
2727
import org.apache.spark.sql.types.StructType
2828

2929
/**
@@ -35,7 +35,6 @@ case class DescribeNamespaceExec(
3535
namespace: Seq[String],
3636
isExtended: Boolean) extends V2CommandExec {
3737
private val encoder = RowEncoder(StructType.fromAttributes(output)).resolveAndBind()
38-
import SupportsNamespaces._
3938

4039
override protected def run(): Seq[InternalRow] = {
4140
val rows = new ArrayBuffer[InternalRow]()
@@ -44,12 +43,12 @@ case class DescribeNamespaceExec(
4443

4544
rows += toCatalystRow("Namespace Name", ns.last)
4645

47-
SupportsNamespaces.RESERVED_PROPERTIES.asScala.foreach { p =>
46+
CatalogV2Util.NAMESPACE_RESERVED_PROPERTIES.foreach { p =>
4847
rows ++= Option(metadata.get(p)).map(toCatalystRow(p.capitalize, _))
4948
}
5049

5150
if (isExtended) {
52-
val properties = metadata.asScala -- RESERVED_PROPERTIES.asScala
51+
val properties = metadata.asScala -- CatalogV2Util.NAMESPACE_RESERVED_PROPERTIES
5352
if (properties.nonEmpty) {
5453
rows += toCatalystRow("Properties", properties.toSeq.mkString("(", ",", ")"))
5554
}

sql/core/src/main/scala/org/apache/spark/sql/execution/datasources/v2/DescribeTableExec.scala

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ import scala.collection.mutable.ArrayBuffer
2323
import org.apache.spark.sql.catalyst.InternalRow
2424
import org.apache.spark.sql.catalyst.encoders.RowEncoder
2525
import org.apache.spark.sql.catalyst.expressions.{Attribute, GenericRowWithSchema}
26-
import org.apache.spark.sql.connector.catalog.{Table, TableCatalog}
26+
import org.apache.spark.sql.connector.catalog.{CatalogV2Util, Table, TableCatalog}
2727
import org.apache.spark.sql.types.StructType
2828

2929
case class DescribeTableExec(
@@ -49,14 +49,14 @@ case class DescribeTableExec(
4949
rows += toCatalystRow("# Detailed Table Information", "", "")
5050
rows += toCatalystRow("Name", table.name(), "")
5151

52-
TableCatalog.RESERVED_PROPERTIES.asScala.toList.foreach(propKey => {
52+
CatalogV2Util.TABLE_RESERVED_PROPERTIES.foreach(propKey => {
5353
if (table.properties.containsKey(propKey)) {
5454
rows += toCatalystRow(propKey.capitalize, table.properties.get(propKey), "")
5555
}
5656
})
5757
val properties =
5858
table.properties.asScala.toList
59-
.filter(kv => !TableCatalog.RESERVED_PROPERTIES.contains(kv._1))
59+
.filter(kv => !CatalogV2Util.TABLE_RESERVED_PROPERTIES.contains(kv._1))
6060
.sortBy(_._1).map {
6161
case (key, value) => key + "=" + value
6262
}.mkString("[", ",", "]")

sql/core/src/main/scala/org/apache/spark/sql/execution/datasources/v2/V2SessionCatalog.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -232,7 +232,7 @@ class V2SessionCatalog(catalog: SessionCatalog, conf: SQLConf)
232232
// validate that this catalog's reserved properties are not removed
233233
changes.foreach {
234234
case remove: RemoveProperty
235-
if SupportsNamespaces.RESERVED_PROPERTIES.contains(remove.property) =>
235+
if CatalogV2Util.NAMESPACE_RESERVED_PROPERTIES.contains(remove.property) =>
236236
throw new UnsupportedOperationException(
237237
s"Cannot remove reserved property: ${remove.property}")
238238
case _ =>

sql/core/src/test/scala/org/apache/spark/sql/connector/DataSourceV2SQLSuite.scala

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -901,15 +901,15 @@ class DataSourceV2SQLSuite
901901
test("CreateNameSpace: reserved properties") {
902902
import SupportsNamespaces._
903903
withSQLConf((SQLConf.LEGACY_PROPERTY_NON_RESERVED.key, "false")) {
904-
RESERVED_PROPERTIES.asScala.filterNot(_ == PROP_COMMENT).foreach { key =>
904+
CatalogV2Util.NAMESPACE_RESERVED_PROPERTIES.filterNot(_ == PROP_COMMENT).foreach { key =>
905905
val exception = intercept[ParseException] {
906906
sql(s"CREATE NAMESPACE testcat.reservedTest WITH DBPROPERTIES('$key'='dummyVal')")
907907
}
908908
assert(exception.getMessage.contains(s"$key is a reserved namespace property"))
909909
}
910910
}
911911
withSQLConf((SQLConf.LEGACY_PROPERTY_NON_RESERVED.key, "true")) {
912-
RESERVED_PROPERTIES.asScala.filterNot(_ == PROP_COMMENT).foreach { key =>
912+
CatalogV2Util.NAMESPACE_RESERVED_PROPERTIES.filterNot(_ == PROP_COMMENT).foreach { key =>
913913
withNamespace("testcat.reservedTest") {
914914
sql(s"CREATE NAMESPACE testcat.reservedTest WITH DBPROPERTIES('$key'='foo')")
915915
assert(sql("DESC NAMESPACE EXTENDED testcat.reservedTest")
@@ -928,7 +928,7 @@ class DataSourceV2SQLSuite
928928
test("create/replace/alter table - reserved properties") {
929929
import TableCatalog._
930930
withSQLConf((SQLConf.LEGACY_PROPERTY_NON_RESERVED.key, "false")) {
931-
RESERVED_PROPERTIES.asScala.filterNot(_ == PROP_COMMENT).foreach { key =>
931+
CatalogV2Util.TABLE_RESERVED_PROPERTIES.filterNot(_ == PROP_COMMENT).foreach { key =>
932932
Seq("OPTIONS", "TBLPROPERTIES").foreach { clause =>
933933
Seq("CREATE", "REPLACE").foreach { action =>
934934
val e = intercept[ParseException] {
@@ -950,7 +950,7 @@ class DataSourceV2SQLSuite
950950
}
951951
}
952952
withSQLConf((SQLConf.LEGACY_PROPERTY_NON_RESERVED.key, "true")) {
953-
RESERVED_PROPERTIES.asScala.filterNot(_ == PROP_COMMENT).foreach { key =>
953+
CatalogV2Util.TABLE_RESERVED_PROPERTIES.filterNot(_ == PROP_COMMENT).foreach { key =>
954954
Seq("OPTIONS", "TBLPROPERTIES").foreach { clause =>
955955
withTable("testcat.reservedTest") {
956956
Seq("CREATE", "REPLACE").foreach { action =>
@@ -1108,7 +1108,7 @@ class DataSourceV2SQLSuite
11081108
test("AlterNamespaceSetProperties: reserved properties") {
11091109
import SupportsNamespaces._
11101110
withSQLConf((SQLConf.LEGACY_PROPERTY_NON_RESERVED.key, "false")) {
1111-
RESERVED_PROPERTIES.asScala.filterNot(_ == PROP_COMMENT).foreach { key =>
1111+
CatalogV2Util.NAMESPACE_RESERVED_PROPERTIES.filterNot(_ == PROP_COMMENT).foreach { key =>
11121112
withNamespace("testcat.reservedTest") {
11131113
sql("CREATE NAMESPACE testcat.reservedTest")
11141114
val exception = intercept[ParseException] {
@@ -1119,7 +1119,7 @@ class DataSourceV2SQLSuite
11191119
}
11201120
}
11211121
withSQLConf((SQLConf.LEGACY_PROPERTY_NON_RESERVED.key, "true")) {
1122-
RESERVED_PROPERTIES.asScala.filterNot(_ == PROP_COMMENT).foreach { key =>
1122+
CatalogV2Util.NAMESPACE_RESERVED_PROPERTIES.filterNot(_ == PROP_COMMENT).foreach { key =>
11231123
withNamespace("testcat.reservedTest") {
11241124
sql(s"CREATE NAMESPACE testcat.reservedTest")
11251125
sql(s"ALTER NAMESPACE testcat.reservedTest SET PROPERTIES ('$key'='foo')")

sql/core/src/test/scala/org/apache/spark/sql/execution/datasources/v2/V2SessionCatalogSuite.scala

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ import org.scalatest.BeforeAndAfter
2727
import org.apache.spark.sql.AnalysisException
2828
import org.apache.spark.sql.catalyst.analysis.{NamespaceAlreadyExistsException, NoSuchNamespaceException, NoSuchTableException, TableAlreadyExistsException}
2929
import org.apache.spark.sql.catalyst.parser.CatalystSqlParser
30-
import org.apache.spark.sql.connector.catalog.{Identifier, NamespaceChange, SupportsNamespaces, TableChange}
30+
import org.apache.spark.sql.connector.catalog.{CatalogV2Util, Identifier, NamespaceChange, SupportsNamespaces, TableChange}
3131
import org.apache.spark.sql.test.SharedSparkSession
3232
import org.apache.spark.sql.types.{DoubleType, IntegerType, LongType, StringType, StructField, StructType, TimestampType}
3333
import org.apache.spark.sql.util.CaseInsensitiveStringMap
@@ -742,7 +742,7 @@ class V2SessionCatalogNamespaceSuite extends V2SessionCatalogBaseSuite {
742742
actual: scala.collection.Map[String, String]): Unit = {
743743
// remove location and comment that are automatically added by HMS unless they are expected
744744
val toRemove =
745-
SupportsNamespaces.RESERVED_PROPERTIES.asScala.filter(expected.contains)
745+
CatalogV2Util.NAMESPACE_RESERVED_PROPERTIES.filter(expected.contains)
746746
assert(expected -- toRemove === actual)
747747
}
748748

@@ -1000,7 +1000,7 @@ class V2SessionCatalogNamespaceSuite extends V2SessionCatalogBaseSuite {
10001000

10011001
catalog.createNamespace(testNs, emptyProps)
10021002

1003-
SupportsNamespaces.RESERVED_PROPERTIES.asScala.foreach { p =>
1003+
CatalogV2Util.NAMESPACE_RESERVED_PROPERTIES.foreach { p =>
10041004
val exc = intercept[UnsupportedOperationException] {
10051005
catalog.alterNamespace(testNs, NamespaceChange.removeProperty(p))
10061006
}

0 commit comments

Comments
 (0)