From c08d569a0d0b423415be1e25218508256a0d32a5 Mon Sep 17 00:00:00 2001 From: panbingkun Date: Mon, 16 May 2022 16:21:26 +0800 Subject: [PATCH 1/4] [SPARK-37939][SQL] Use error classes in the parsing errors of properties --- .../main/resources/error/error-classes.json | 15 ++++ .../spark/sql/errors/QueryParsingErrors.scala | 26 ++++-- .../sql/errors/QueryParsingErrorsSuite.scala | 88 +++++++++++++++++++ 3 files changed, 122 insertions(+), 7 deletions(-) diff --git a/core/src/main/resources/error/error-classes.json b/core/src/main/resources/error/error-classes.json index 3a7bc757f739b..2a9905eb59bc2 100644 --- a/core/src/main/resources/error/error-classes.json +++ b/core/src/main/resources/error/error-classes.json @@ -129,6 +129,12 @@ "message" : [ "The value of parameter(s) '' in is invalid: " ], "sqlState" : "22023" }, + "INVALID_PROPERTY_KEY" : { + "message" : [ "'' is an invalid property key, please use quotes, e.g. SET ``=``" ] + }, + "INVALID_PROPERTY_VALUE" : { + "message" : [ "'' is an invalid property value, please use quotes, e.g. SET ``=``" ] + }, "INVALID_SQL_SYNTAX" : { "message" : [ "Invalid SQL syntax: " ], "sqlState" : "42000" @@ -209,6 +215,12 @@ "DESC_TABLE_COLUMN_PARTITION" : { "message" : [ "DESC TABLE COLUMN for a specific partition." ] }, + "CLEAN_RESERVED_NAMESPACE_PROPERTY" : { + "message" : [ " is a reserved namespace property, ." ] + }, + "CLEAN_RESERVED_TABLE_PROPERTY" : { + "message" : [ " is a reserved table property, ." ] + }, "DISTRIBUTE_BY" : { "message" : [ "DISTRIBUTE BY clause." ] }, @@ -245,6 +257,9 @@ "PIVOT_TYPE" : { "message" : [ "Pivoting by the value '' of the column data type ." ] }, + "PROPERTIES_AND_DBPROPERTIES_BOTH_SPECIFIED_CONFLICT" : { + "message" : [ "Either PROPERTIES or DBPROPERTIES is allowed." ] + }, "PYTHON_UDF_IN_ON_CLAUSE" : { "message" : [ "Python UDF in the ON clause of a JOIN." ] }, diff --git a/sql/catalyst/src/main/scala/org/apache/spark/sql/errors/QueryParsingErrors.scala b/sql/catalyst/src/main/scala/org/apache/spark/sql/errors/QueryParsingErrors.scala index 1d15557c9d014..3c37fcb2b56eb 100644 --- a/sql/catalyst/src/main/scala/org/apache/spark/sql/errors/QueryParsingErrors.scala +++ b/sql/catalyst/src/main/scala/org/apache/spark/sql/errors/QueryParsingErrors.scala @@ -267,16 +267,26 @@ object QueryParsingErrors extends QueryErrorsBase { def cannotCleanReservedNamespacePropertyError( property: String, ctx: ParserRuleContext, msg: String): Throwable = { - new ParseException(s"$property is a reserved namespace property, $msg.", ctx) + new ParseException( + errorClass = "UNSUPPORTED_FEATURE", + messageParameters = Array("CLEAN_RESERVED_NAMESPACE_PROPERTY", s"$property", s"$msg"), + ctx) } def propertiesAndDbPropertiesBothSpecifiedError(ctx: CreateNamespaceContext): Throwable = { - new ParseException("Either PROPERTIES or DBPROPERTIES is allowed.", ctx) + new ParseException( + errorClass = "UNSUPPORTED_FEATURE", + messageParameters = Array("PROPERTIES_AND_DBPROPERTIES_BOTH_SPECIFIED_CONFLICT"), + ctx + ) } def cannotCleanReservedTablePropertyError( property: String, ctx: ParserRuleContext, msg: String): Throwable = { - new ParseException(s"$property is a reserved table property, $msg.", ctx) + new ParseException( + errorClass = "UNSUPPORTED_FEATURE", + messageParameters = Array("CLEAN_RESERVED_TABLE_PROPERTY", s"$property", s"$msg"), + ctx) } def duplicatedTablePathsFoundError( @@ -380,14 +390,16 @@ object QueryParsingErrors extends QueryErrorsBase { def invalidPropertyKeyForSetQuotedConfigurationError( keyCandidate: String, valueStr: String, ctx: ParserRuleContext): Throwable = { - new ParseException(s"'$keyCandidate' is an invalid property key, please " + - s"use quotes, e.g. SET `$keyCandidate`=`$valueStr`", ctx) + new ParseException(errorClass = "INVALID_PROPERTY_KEY", + messageParameters = Array(keyCandidate, keyCandidate, valueStr), + ctx) } def invalidPropertyValueForSetQuotedConfigurationError( valueCandidate: String, keyStr: String, ctx: ParserRuleContext): Throwable = { - new ParseException(s"'$valueCandidate' is an invalid property value, please " + - s"use quotes, e.g. SET `$keyStr`=`$valueCandidate`", ctx) + new ParseException(errorClass = "INVALID_PROPERTY_VALUE", + messageParameters = Array(valueCandidate, keyStr, valueCandidate), + ctx) } def unexpectedFormatForResetConfigurationError(ctx: ResetConfigurationContext): Throwable = { diff --git a/sql/core/src/test/scala/org/apache/spark/sql/errors/QueryParsingErrorsSuite.scala b/sql/core/src/test/scala/org/apache/spark/sql/errors/QueryParsingErrorsSuite.scala index 50966db2a213a..6d20c3c5d524f 100644 --- a/sql/core/src/test/scala/org/apache/spark/sql/errors/QueryParsingErrorsSuite.scala +++ b/sql/core/src/test/scala/org/apache/spark/sql/errors/QueryParsingErrorsSuite.scala @@ -642,4 +642,92 @@ class QueryParsingErrorsSuite extends QueryTest with QueryErrorsSuiteBase { |^^^ |""".stripMargin) } + + test("UNSUPPORTED_FEATURE: cannot clean reserved namespace property") { + val sql = "CREATE NAMESPACE IF NOT EXISTS a.b.c WITH PROPERTIES ('location'='/home/user/db')" + validateParsingError( + sqlText = sql, + errorClass = "UNSUPPORTED_FEATURE", + errorSubClass = Some("CLEAN_RESERVED_NAMESPACE_PROPERTY"), + sqlState = "0A000", + message = + """The feature is not supported: location is a reserved namespace property, """ + + """please use the LOCATION clause to specify it.(line 1, pos 0)""" + + s""" + | + |== SQL == + |$sql + |^^^ + |""".stripMargin) + } + + test("UNSUPPORTED_FEATURE: cannot clean reserved table property") { + val sql = "CREATE TABLE student (id INT, name STRING, age INT) " + + "USING PARQUET TBLPROPERTIES ('provider'='parquet')" + validateParsingError( + sqlText = sql, + errorClass = "UNSUPPORTED_FEATURE", + errorSubClass = Some("CLEAN_RESERVED_TABLE_PROPERTY"), + sqlState = "0A000", + message = + """The feature is not supported: provider is a reserved table property, """ + + """please use the USING clause to specify it.(line 1, pos 66)""" + + s""" + | + |== SQL == + |$sql + |------------------------------------------------------------------^^^ + |""".stripMargin) + } + + test("INVALID_PROPERTY_KEY: invalid property key for set quoted configuration") { + val sql = "set =`value`" + validateParsingError( + sqlText = sql, + errorClass = "INVALID_PROPERTY_KEY", + sqlState = null, + message = + s"""'' is an invalid property key, please use quotes, e.g. SET ``=`value`(line 1, pos 0) + | + |== SQL == + |$sql + |^^^ + |""".stripMargin) + } + + test("INVALID_PROPERTY_VALUE: invalid property value for set quoted configuration") { + val sql = "set `key`=1;2;;" + validateParsingError( + sqlText = sql, + errorClass = "INVALID_PROPERTY_VALUE", + sqlState = null, + message = + """'1;2;;' is an invalid property value, please use quotes, """ + + """e.g. SET `key`=`1;2;;`(line 1, pos 0)""" + + s""" + | + |== SQL == + |$sql + |^^^ + |""".stripMargin) + } + + test("UNSUPPORTED_FEATURE: Properties and DbProperties both specified") { + val sql = "CREATE NAMESPACE IF NOT EXISTS a.b.c WITH PROPERTIES ('a'='a', 'b'='b', 'c'='c') " + + "WITH DBPROPERTIES('a'='a', 'b'='b', 'c'='c')" + validateParsingError( + sqlText = sql, + errorClass = "UNSUPPORTED_FEATURE", + errorSubClass = Some("PROPERTIES_AND_DBPROPERTIES_BOTH_SPECIFIED_CONFLICT"), + sqlState = "0A000", + message = + """The feature is not supported: Either PROPERTIES or DBPROPERTIES """ + + """is allowed.(line 1, pos 0)""" + + s""" + | + |== SQL == + |$sql + |^^^ + |""".stripMargin) + } } From dfeb18cbd19e2a5c0e519478f87d4658f70d9ca7 Mon Sep 17 00:00:00 2001 From: panbingkun Date: Mon, 16 May 2022 18:57:39 +0800 Subject: [PATCH 2/4] [SPARK-37939][SQL] Use error classes in the parsing errors of properties --- core/src/main/resources/error/error-classes.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/core/src/main/resources/error/error-classes.json b/core/src/main/resources/error/error-classes.json index 2a9905eb59bc2..b93ff1d544247 100644 --- a/core/src/main/resources/error/error-classes.json +++ b/core/src/main/resources/error/error-classes.json @@ -212,15 +212,15 @@ "AES_MODE" : { "message" : [ "AES- with the padding by the function." ] }, - "DESC_TABLE_COLUMN_PARTITION" : { - "message" : [ "DESC TABLE COLUMN for a specific partition." ] - }, "CLEAN_RESERVED_NAMESPACE_PROPERTY" : { "message" : [ " is a reserved namespace property, ." ] }, "CLEAN_RESERVED_TABLE_PROPERTY" : { "message" : [ " is a reserved table property, ." ] }, + "DESC_TABLE_COLUMN_PARTITION" : { + "message" : [ "DESC TABLE COLUMN for a specific partition." ] + }, "DISTRIBUTE_BY" : { "message" : [ "DISTRIBUTE BY clause." ] }, From da5524050529103509bee654108c5f9812553c49 Mon Sep 17 00:00:00 2001 From: panbingkun Date: Tue, 17 May 2022 08:28:06 +0800 Subject: [PATCH 3/4] [SPARK-37939][SQL] Use error classes in the parsing errors of properties --- .../main/resources/error/error-classes.json | 18 +++++++++--------- .../spark/sql/errors/QueryParsingErrors.scala | 6 +++--- .../sql/errors/QueryParsingErrorsSuite.scala | 12 ++++++------ 3 files changed, 18 insertions(+), 18 deletions(-) diff --git a/core/src/main/resources/error/error-classes.json b/core/src/main/resources/error/error-classes.json index b93ff1d544247..4a2ad23fd4d59 100644 --- a/core/src/main/resources/error/error-classes.json +++ b/core/src/main/resources/error/error-classes.json @@ -212,12 +212,6 @@ "AES_MODE" : { "message" : [ "AES- with the padding by the function." ] }, - "CLEAN_RESERVED_NAMESPACE_PROPERTY" : { - "message" : [ " is a reserved namespace property, ." ] - }, - "CLEAN_RESERVED_TABLE_PROPERTY" : { - "message" : [ " is a reserved table property, ." ] - }, "DESC_TABLE_COLUMN_PARTITION" : { "message" : [ "DESC TABLE COLUMN for a specific partition." ] }, @@ -257,15 +251,21 @@ "PIVOT_TYPE" : { "message" : [ "Pivoting by the value '' of the column data type ." ] }, - "PROPERTIES_AND_DBPROPERTIES_BOTH_SPECIFIED_CONFLICT" : { - "message" : [ "Either PROPERTIES or DBPROPERTIES is allowed." ] - }, "PYTHON_UDF_IN_ON_CLAUSE" : { "message" : [ "Python UDF in the ON clause of a JOIN." ] }, "REPEATED_PIVOT" : { "message" : [ "Repeated PIVOT operation." ] }, + "SET_NAMESPACE_PROPERTY" : { + "message" : [ " is a reserved namespace property, ." ] + }, + "SET_PROPERTIES_AND_DBPROPERTIES" : { + "message" : [ "Either PROPERTIES or DBPROPERTIES is allowed." ] + }, + "SET_TABLE_PROPERTY" : { + "message" : [ " is a reserved table property, ." ] + }, "TOO_MANY_TYPE_ARGUMENTS_FOR_UDF_CLASS" : { "message" : [ "UDF class with type arguments." ] }, diff --git a/sql/catalyst/src/main/scala/org/apache/spark/sql/errors/QueryParsingErrors.scala b/sql/catalyst/src/main/scala/org/apache/spark/sql/errors/QueryParsingErrors.scala index 3c37fcb2b56eb..0a8542c090cc2 100644 --- a/sql/catalyst/src/main/scala/org/apache/spark/sql/errors/QueryParsingErrors.scala +++ b/sql/catalyst/src/main/scala/org/apache/spark/sql/errors/QueryParsingErrors.scala @@ -269,14 +269,14 @@ object QueryParsingErrors extends QueryErrorsBase { property: String, ctx: ParserRuleContext, msg: String): Throwable = { new ParseException( errorClass = "UNSUPPORTED_FEATURE", - messageParameters = Array("CLEAN_RESERVED_NAMESPACE_PROPERTY", s"$property", s"$msg"), + messageParameters = Array("SET_NAMESPACE_PROPERTY", property, msg), ctx) } def propertiesAndDbPropertiesBothSpecifiedError(ctx: CreateNamespaceContext): Throwable = { new ParseException( errorClass = "UNSUPPORTED_FEATURE", - messageParameters = Array("PROPERTIES_AND_DBPROPERTIES_BOTH_SPECIFIED_CONFLICT"), + messageParameters = Array("SET_PROPERTIES_AND_DBPROPERTIES"), ctx ) } @@ -285,7 +285,7 @@ object QueryParsingErrors extends QueryErrorsBase { property: String, ctx: ParserRuleContext, msg: String): Throwable = { new ParseException( errorClass = "UNSUPPORTED_FEATURE", - messageParameters = Array("CLEAN_RESERVED_TABLE_PROPERTY", s"$property", s"$msg"), + messageParameters = Array("SET_TABLE_PROPERTY", property, msg), ctx) } diff --git a/sql/core/src/test/scala/org/apache/spark/sql/errors/QueryParsingErrorsSuite.scala b/sql/core/src/test/scala/org/apache/spark/sql/errors/QueryParsingErrorsSuite.scala index 6d20c3c5d524f..7517fa25d1717 100644 --- a/sql/core/src/test/scala/org/apache/spark/sql/errors/QueryParsingErrorsSuite.scala +++ b/sql/core/src/test/scala/org/apache/spark/sql/errors/QueryParsingErrorsSuite.scala @@ -643,12 +643,12 @@ class QueryParsingErrorsSuite extends QueryTest with QueryErrorsSuiteBase { |""".stripMargin) } - test("UNSUPPORTED_FEATURE: cannot clean reserved namespace property") { + test("UNSUPPORTED_FEATURE: cannot set reserved namespace property") { val sql = "CREATE NAMESPACE IF NOT EXISTS a.b.c WITH PROPERTIES ('location'='/home/user/db')" validateParsingError( sqlText = sql, errorClass = "UNSUPPORTED_FEATURE", - errorSubClass = Some("CLEAN_RESERVED_NAMESPACE_PROPERTY"), + errorSubClass = Some("SET_NAMESPACE_PROPERTY"), sqlState = "0A000", message = """The feature is not supported: location is a reserved namespace property, """ + @@ -661,13 +661,13 @@ class QueryParsingErrorsSuite extends QueryTest with QueryErrorsSuiteBase { |""".stripMargin) } - test("UNSUPPORTED_FEATURE: cannot clean reserved table property") { + test("UNSUPPORTED_FEATURE: cannot set reserved table property") { val sql = "CREATE TABLE student (id INT, name STRING, age INT) " + "USING PARQUET TBLPROPERTIES ('provider'='parquet')" validateParsingError( sqlText = sql, errorClass = "UNSUPPORTED_FEATURE", - errorSubClass = Some("CLEAN_RESERVED_TABLE_PROPERTY"), + errorSubClass = Some("SET_TABLE_PROPERTY"), sqlState = "0A000", message = """The feature is not supported: provider is a reserved table property, """ + @@ -712,13 +712,13 @@ class QueryParsingErrorsSuite extends QueryTest with QueryErrorsSuiteBase { |""".stripMargin) } - test("UNSUPPORTED_FEATURE: Properties and DbProperties both specified") { + test("UNSUPPORTED_FEATURE: cannot set Properties and DbProperties at the same time") { val sql = "CREATE NAMESPACE IF NOT EXISTS a.b.c WITH PROPERTIES ('a'='a', 'b'='b', 'c'='c') " + "WITH DBPROPERTIES('a'='a', 'b'='b', 'c'='c')" validateParsingError( sqlText = sql, errorClass = "UNSUPPORTED_FEATURE", - errorSubClass = Some("PROPERTIES_AND_DBPROPERTIES_BOTH_SPECIFIED_CONFLICT"), + errorSubClass = Some("SET_PROPERTIES_AND_DBPROPERTIES"), sqlState = "0A000", message = """The feature is not supported: Either PROPERTIES or DBPROPERTIES """ + From ad7bd20a526f2da0213dfebff66368551c10caae Mon Sep 17 00:00:00 2001 From: panbingkun Date: Wed, 18 May 2022 20:15:45 +0800 Subject: [PATCH 4/4] [SPARK-37939][SQL] Use error classes in the parsing errors of properties --- core/src/main/resources/error/error-classes.json | 6 +++--- .../apache/spark/sql/errors/QueryParsingErrors.scala | 6 ++++-- .../spark/sql/errors/QueryParsingErrorsSuite.scala | 10 +++++----- .../spark/sql/execution/SparkSqlParserSuite.scala | 6 +++--- .../execution/command/CreateNamespaceParserSuite.scala | 3 ++- 5 files changed, 17 insertions(+), 14 deletions(-) diff --git a/core/src/main/resources/error/error-classes.json b/core/src/main/resources/error/error-classes.json index 150dc03600323..b87c6c91bfe1e 100644 --- a/core/src/main/resources/error/error-classes.json +++ b/core/src/main/resources/error/error-classes.json @@ -134,10 +134,10 @@ "sqlState" : "22023" }, "INVALID_PROPERTY_KEY" : { - "message" : [ "'' is an invalid property key, please use quotes, e.g. SET ``=``" ] + "message" : [ " is an invalid property key, please use quotes, e.g. SET =" ] }, "INVALID_PROPERTY_VALUE" : { - "message" : [ "'' is an invalid property value, please use quotes, e.g. SET ``=``" ] + "message" : [ " is an invalid property value, please use quotes, e.g. SET =" ] }, "INVALID_SQL_SYNTAX" : { "message" : [ "Invalid SQL syntax: " ], @@ -272,7 +272,7 @@ "message" : [ " is a reserved namespace property, ." ] }, "SET_PROPERTIES_AND_DBPROPERTIES" : { - "message" : [ "Either PROPERTIES or DBPROPERTIES is allowed." ] + "message" : [ "set PROPERTIES and DBPROPERTIES at the same time." ] }, "SET_TABLE_PROPERTY" : { "message" : [ " is a reserved table property, ." ] diff --git a/sql/catalyst/src/main/scala/org/apache/spark/sql/errors/QueryParsingErrors.scala b/sql/catalyst/src/main/scala/org/apache/spark/sql/errors/QueryParsingErrors.scala index 0a8542c090cc2..3bb0970afeb17 100644 --- a/sql/catalyst/src/main/scala/org/apache/spark/sql/errors/QueryParsingErrors.scala +++ b/sql/catalyst/src/main/scala/org/apache/spark/sql/errors/QueryParsingErrors.scala @@ -391,14 +391,16 @@ object QueryParsingErrors extends QueryErrorsBase { def invalidPropertyKeyForSetQuotedConfigurationError( keyCandidate: String, valueStr: String, ctx: ParserRuleContext): Throwable = { new ParseException(errorClass = "INVALID_PROPERTY_KEY", - messageParameters = Array(keyCandidate, keyCandidate, valueStr), + messageParameters = Array(toSQLConf(keyCandidate), + toSQLConf(keyCandidate), toSQLConf(valueStr)), ctx) } def invalidPropertyValueForSetQuotedConfigurationError( valueCandidate: String, keyStr: String, ctx: ParserRuleContext): Throwable = { new ParseException(errorClass = "INVALID_PROPERTY_VALUE", - messageParameters = Array(valueCandidate, keyStr, valueCandidate), + messageParameters = Array(toSQLConf(valueCandidate), + toSQLConf(keyStr), toSQLConf(valueCandidate)), ctx) } diff --git a/sql/core/src/test/scala/org/apache/spark/sql/errors/QueryParsingErrorsSuite.scala b/sql/core/src/test/scala/org/apache/spark/sql/errors/QueryParsingErrorsSuite.scala index 7517fa25d1717..6dc40c3eadb6a 100644 --- a/sql/core/src/test/scala/org/apache/spark/sql/errors/QueryParsingErrorsSuite.scala +++ b/sql/core/src/test/scala/org/apache/spark/sql/errors/QueryParsingErrorsSuite.scala @@ -687,7 +687,7 @@ class QueryParsingErrorsSuite extends QueryTest with QueryErrorsSuiteBase { errorClass = "INVALID_PROPERTY_KEY", sqlState = null, message = - s"""'' is an invalid property key, please use quotes, e.g. SET ``=`value`(line 1, pos 0) + s""""" is an invalid property key, please use quotes, e.g. SET ""="value"(line 1, pos 0) | |== SQL == |$sql @@ -702,8 +702,8 @@ class QueryParsingErrorsSuite extends QueryTest with QueryErrorsSuiteBase { errorClass = "INVALID_PROPERTY_VALUE", sqlState = null, message = - """'1;2;;' is an invalid property value, please use quotes, """ + - """e.g. SET `key`=`1;2;;`(line 1, pos 0)""" + + """"1;2;;" is an invalid property value, please use quotes, """ + + """e.g. SET "key"="1;2;;"(line 1, pos 0)""" + s""" | |== SQL == @@ -721,8 +721,8 @@ class QueryParsingErrorsSuite extends QueryTest with QueryErrorsSuiteBase { errorSubClass = Some("SET_PROPERTIES_AND_DBPROPERTIES"), sqlState = "0A000", message = - """The feature is not supported: Either PROPERTIES or DBPROPERTIES """ + - """is allowed.(line 1, pos 0)""" + + """The feature is not supported: set PROPERTIES and DBPROPERTIES at the same time.""" + + """(line 1, pos 0)""" + s""" | |== SQL == diff --git a/sql/core/src/test/scala/org/apache/spark/sql/execution/SparkSqlParserSuite.scala b/sql/core/src/test/scala/org/apache/spark/sql/execution/SparkSqlParserSuite.scala index 050c27ede1539..86cf08e672224 100644 --- a/sql/core/src/test/scala/org/apache/spark/sql/execution/SparkSqlParserSuite.scala +++ b/sql/core/src/test/scala/org/apache/spark/sql/execution/SparkSqlParserSuite.scala @@ -168,11 +168,11 @@ class SparkSqlParserSuite extends AnalysisTest { intercept("SET a=1;2;;", expectedErrMsg) intercept("SET a b=`1;;`", - "'a b' is an invalid property key, please use quotes, e.g. SET `a b`=`1;;`") + "\"a b\" is an invalid property key, please use quotes, e.g. SET \"a b\"=\"1;;\"") intercept("SET `a`=1;2;;", - "'1;2;;' is an invalid property value, please use quotes, e.g." + - " SET `a`=`1;2;;`") + "\"1;2;;\" is an invalid property value, please use quotes, e.g." + + " SET \"a\"=\"1;2;;\"") } test("refresh resource") { diff --git a/sql/core/src/test/scala/org/apache/spark/sql/execution/command/CreateNamespaceParserSuite.scala b/sql/core/src/test/scala/org/apache/spark/sql/execution/command/CreateNamespaceParserSuite.scala index 69a208b942429..6c59512148a53 100644 --- a/sql/core/src/test/scala/org/apache/spark/sql/execution/command/CreateNamespaceParserSuite.scala +++ b/sql/core/src/test/scala/org/apache/spark/sql/execution/command/CreateNamespaceParserSuite.scala @@ -84,7 +84,8 @@ class CreateNamespaceParserSuite extends AnalysisTest { |WITH PROPERTIES ('a'='a', 'b'='b', 'c'='c') |WITH DBPROPERTIES ('a'='a', 'b'='b', 'c'='c') """.stripMargin - intercept(sql, "Either PROPERTIES or DBPROPERTIES is allowed") + intercept(sql, "The feature is not supported: " + + "set PROPERTIES and DBPROPERTIES at the same time.") } test("create namespace - support for other types in PROPERTIES") {