Skip to content

[SPARK-37939][SQL][3.3] Use error classes in the parsing errors of properties #36916

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
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
6 changes: 6 additions & 0 deletions core/src/main/resources/error/error-classes.json
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,12 @@
"message" : [ "The value of parameter(s) '<parameter>' in <functionName> is invalid: <expected>" ],
"sqlState" : "22023"
},
"INVALID_PROPERTY_KEY" : {
"message" : [ "<key> is an invalid property key, please use quotes, e.g. SET <key>=<value>" ]
},
"INVALID_PROPERTY_VALUE" : {
"message" : [ "<value> is an invalid property value, please use quotes, e.g. SET <key>=<value>" ]
},
"INVALID_SQL_SYNTAX" : {
"message" : [ "Invalid SQL syntax: <inputString>" ],
"sqlState" : "42000"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -260,17 +260,20 @@ private[sql] object QueryParsingErrors extends QueryErrorsBase {
}

def cannotCleanReservedNamespacePropertyError(
property: String, ctx: ParserRuleContext, msg: String): Throwable = {
new ParseException(s"$property is a reserved namespace property, $msg.", ctx)
property: String, ctx: ParserRuleContext, msg: String): ParseException = {
new ParseException("UNSUPPORTED_FEATURE",
Array(s"$property is a reserved namespace property, $msg."), ctx)
}

def propertiesAndDbPropertiesBothSpecifiedError(ctx: CreateNamespaceContext): Throwable = {
new ParseException("Either PROPERTIES or DBPROPERTIES is allowed.", ctx)
def propertiesAndDbPropertiesBothSpecifiedError(ctx: CreateNamespaceContext): ParseException = {
new ParseException("UNSUPPORTED_FEATURE",
Array("set PROPERTIES and DBPROPERTIES at the same time."), ctx)
}

def cannotCleanReservedTablePropertyError(
property: String, ctx: ParserRuleContext, msg: String): Throwable = {
new ParseException(s"$property is a reserved table property, $msg.", ctx)
property: String, ctx: ParserRuleContext, msg: String): ParseException = {
new ParseException("UNSUPPORTED_FEATURE",
Array(s"$property is a reserved table property, $msg."), ctx)
}

def duplicatedTablePathsFoundError(
Expand Down Expand Up @@ -367,15 +370,17 @@ private[sql] 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)
keyCandidate: String, valueStr: String, ctx: ParserRuleContext): ParseException = {
new ParseException(errorClass = "INVALID_PROPERTY_KEY",
messageParameters = Array(toSQLConf(keyCandidate),
toSQLConf(keyCandidate), toSQLConf(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)
valueCandidate: String, keyStr: String, ctx: ParserRuleContext): ParseException = {
new ParseException(errorClass = "INVALID_PROPERTY_VALUE",
messageParameters = Array(toSQLConf(valueCandidate),
toSQLConf(keyStr), toSQLConf(valueCandidate)), ctx)
}

def unexpectedFormatForResetConfigurationError(ctx: ResetConfigurationContext): Throwable = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -213,4 +213,96 @@ class QueryParsingErrorsSuite extends QueryTest with SharedSparkSession {
|--------------------------------------------^^^
|""".stripMargin)
}

test("UNSUPPORTED_FEATURE: cannot set reserved namespace property") {
val sql = "CREATE NAMESPACE IF NOT EXISTS a.b.c WITH PROPERTIES ('location'='/home/user/db')"
val msg = """The feature is not supported: location is a reserved namespace property, """ +
"""please use the LOCATION clause to specify it.(line 1, pos 0)"""
validateParsingError(
sqlText = sql,
errorClass = "UNSUPPORTED_FEATURE",
sqlState = "0A000",
message =
s"""
|$msg
|
|== SQL ==
|$sql
|^^^
|""".stripMargin)
}

test("UNSUPPORTED_FEATURE: cannot set reserved table property") {
val sql = "CREATE TABLE student (id INT, name STRING, age INT) " +
"USING PARQUET TBLPROPERTIES ('provider'='parquet')"
val msg = """The feature is not supported: provider is a reserved table property, """ +
"""please use the USING clause to specify it.(line 1, pos 66)"""
validateParsingError(
sqlText = sql,
errorClass = "UNSUPPORTED_FEATURE",
sqlState = "0A000",
message =
s"""
|$msg
|
|== SQL ==
|$sql
|------------------------------------------------------------------^^^
|""".stripMargin)
}

test("INVALID_PROPERTY_KEY: invalid property key for set quoted configuration") {
val sql = "set =`value`"
val msg = """"" is an invalid property key, please use quotes, """ +
"""e.g. SET ""="value"(line 1, pos 0)"""
validateParsingError(
sqlText = sql,
errorClass = "INVALID_PROPERTY_KEY",
sqlState = null,
message =
s"""
|$msg
|
|== SQL ==
|$sql
|^^^
|""".stripMargin)
}

test("INVALID_PROPERTY_VALUE: invalid property value for set quoted configuration") {
val sql = "set `key`=1;2;;"
val msg = """"1;2;;" is an invalid property value, please use quotes, """ +
"""e.g. SET "key"="1;2;;"(line 1, pos 0)"""
validateParsingError(
sqlText = sql,
errorClass = "INVALID_PROPERTY_VALUE",
sqlState = null,
message =
s"""
|$msg
|
|== SQL ==
|$sql
|^^^
|""".stripMargin)
}

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')"
val msg = """The feature is not supported: set PROPERTIES and DBPROPERTIES at the same time.""" +
"""(line 1, pos 0)"""
validateParsingError(
sqlText = sql,
errorClass = "UNSUPPORTED_FEATURE",
sqlState = "0A000",
message =
s"""
|$msg
|
|== SQL ==
|$sql
|^^^
|""".stripMargin)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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") {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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") {
Expand Down