Skip to content
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
52 changes: 52 additions & 0 deletions core/src/main/resources/error/error-classes.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@
"message" : [ "Field name %s is ambiguous and has %s matching fields in the struct." ],
"sqlState" : "42000"
},
"COLUMN_ALIASES_NOT_ALLOWED_IN_OPERATION" : {
"message" : [ "Column aliases are not allowed in %s." ],
"sqlState" : "42000"
},
"DIVIDE_BY_ZERO" : {
"message" : [ "divide by zero" ],
"sqlState" : "22012"
Expand All @@ -11,6 +15,14 @@
"message" : [ "Found duplicate keys '%s'" ],
"sqlState" : "23000"
},
"EMPTY_PARTITION_KEY" : {
"message" : [ "Found an empty partition key '%s'." ],
"sqlState" : "42000"
},
"EMPTY_SOURCE_FOR_MERGE" : {
"message" : [ "Empty source for merge: you should specify a source table/subquery in merge." ],
"sqlState" : "42000"
},
"GROUPING_COLUMN_MISMATCH" : {
"message" : [ "Column of grouping (%s) can't be found in grouping columns %s" ],
"sqlState" : "42000"
Expand All @@ -29,10 +41,26 @@
"message" : [ "Invalid pivot column '%s'. Pivot columns must be comparable." ],
"sqlState" : "42000"
},
"INSERTED_VALUE_NUMBER_NOT_MATCH_FIELD_NUMBER" : {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The grammar is a bit strange. Maybe INSERTED_VALUE_AND_FIELD_NUMBER_MISMATCH?

"message" : [ "The number of inserted values cannot match the fields." ],
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: cannot -> does not

"sqlState" : "42000"
},
"INVALID_FIELD_NAME" : {
"message" : [ "Field name %s is invalid: %s is not a struct." ],
"sqlState" : "42000"
},
"INVALID_LATERAL_JOIN_RELATION" : {
"message" : [ "LATERAL can only be used with subquery" ],
"sqlState" : "42000"
},
"LATERAL_WITH_PIVOT_IN_FROM_CLAUSE_NOT_ALLOWED" : {
"message" : [ "LATERAL cannot be used together with PIVOT in FROM clause" ],
"sqlState" : "42000"
},
"MERGE_STATEMENT_WITHOUT_WHEN_CLAUSE" : {
"message" : [ "There must be at least one WHEN clause in a MERGE statement" ],
"sqlState" : "42000"
},
"MISSING_COLUMN" : {
"message" : [ "cannot resolve '%s' given input columns: [%s]" ],
"sqlState" : "42000"
Expand All @@ -41,6 +69,10 @@
"message" : [ "Unknown static partition column: %s" ],
"sqlState" : "42000"
},
"NON_LAST_CLAUSE_OMIT_CONDITION" : {
"message" : [ "When there are more than one %s clauses in a MERGE statement, only the last %s clause can omit the condition." ],
"sqlState" : "42000"
},
"NON_LITERAL_PIVOT_VALUES" : {
"message" : [ "Literal expressions required for pivot values, found '%s'" ],
"sqlState" : "42000"
Expand All @@ -49,6 +81,10 @@
"message" : [ "PARTITION clause cannot contain a non-partition column name: %s" ],
"sqlState" : "42000"
},
"OPERATION_UNSUPPORTED" : {
"message" : [ "%s is not supported" ],
"sqlState" : "0A000"
},
"PIVOT_VALUE_DATA_TYPE_MISMATCH" : {
"message" : [ "Invalid pivot value '%s': value data type %s does not match pivot column data type %s" ],
"sqlState" : "42000"
Expand All @@ -57,9 +93,25 @@
"message" : [ "The second argument of '%s' function needs to be an integer." ],
"sqlState" : "22023"
},
"TRANSFORM_NOT_SUPPORT_QUANTIFIER" : {
"message" : [ "TRANSFORM does not support DISTINCT/ALL in inputs" ],
"sqlState" : "42000"
},
"TRANSFORM_WITH_SERDE_UNSUPPORTED" : {
"message" : [ "TRANSFORM with serde is only supported in hive mode" ],
"sqlState" : "42000"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should probably be 0A000

},
"UNABLE_TO_ACQUIRE_MEMORY" : {
"message" : [ "Unable to acquire %s bytes of memory, got %s" ]
},
"UNRECOGNIZED_ACTION" : {
"message" : [ "Unrecognized %s action: %s" ],
"sqlState" : "42000"
},
"UNSUPPORTED_LATERAL_JOIN_TYPE" : {
"message" : [ "Unsupported LATERAL join type %s" ],
"sqlState" : "42000"
},
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should probably be 0A000

"WRITING_JOB_ABORTED" : {
"message" : [ "Writing job aborted" ],
"sqlState" : "40000"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -292,8 +292,6 @@ class AstBuilder extends SqlBaseBaseVisitor[AnyRef] with SQLConfHelper with Logg
case hiveDir: InsertOverwriteHiveDirContext =>
val (isLocal, storage, provider) = visitInsertOverwriteHiveDir(hiveDir)
InsertIntoDir(isLocal, storage, provider, query, overwrite = true)
case _ =>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why was this removed?

throw QueryParsingErrors.invalidInsertIntoError(ctx)
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,91 +29,84 @@ import org.apache.spark.sql.catalyst.trees.Origin
*/
object QueryParsingErrors {

def invalidInsertIntoError(ctx: InsertIntoContext): Throwable = {
new ParseException("Invalid InsertIntoContext", ctx)
}

def insertOverwriteDirectoryUnsupportedError(ctx: InsertIntoContext): Throwable = {
new ParseException("INSERT OVERWRITE DIRECTORY is not supported", ctx)
new ParseException("OPERATION_UNSUPPORTED", Array("INSERT OVERWRITE DIRECTORY"), ctx)
}

def columnAliasInOperationNotAllowedError(op: String, ctx: TableAliasContext): Throwable = {
new ParseException(s"Columns aliases are not allowed in $op.", ctx.identifierList())
new ParseException("COLUMN_ALIASES_NOT_ALLOWED_IN_OPERATION", Array(op), ctx.identifierList())
}

def emptySourceForMergeError(ctx: MergeIntoTableContext): Throwable = {
new ParseException("Empty source for merge: you should specify a source" +
" table/subquery in merge.", ctx.source)
new ParseException("EMPTY_SOURCE_FOR_MERGE", Array.empty, ctx.source)
}

def unrecognizedMatchedActionError(ctx: MatchedClauseContext): Throwable = {
new ParseException(s"Unrecognized matched action: ${ctx.matchedAction().getText}",
ctx.matchedAction())
new ParseException("UNRECOGNIZED_ACTION",
Array("matched", ctx.matchedAction().getText), ctx.matchedAction())
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we make matched all caps? This may make it clearer.

}

def insertedValueNumberNotMatchFieldNumberError(ctx: NotMatchedClauseContext): Throwable = {
new ParseException("The number of inserted values cannot match the fields.",
new ParseException("INSERTED_VALUE_NUMBER_NOT_MATCH_FIELD_NUMBER", Array.empty,
ctx.notMatchedAction())
}

def unrecognizedNotMatchedActionError(ctx: NotMatchedClauseContext): Throwable = {
new ParseException(s"Unrecognized not matched action: ${ctx.notMatchedAction().getText}",
ctx.notMatchedAction())
new ParseException("UNRECOGNIZED_ACTION",
Array("not matched", ctx.notMatchedAction().getText), ctx.notMatchedAction())
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we make not matched all caps? This may make it clearer.

}

def mergeStatementWithoutWhenClauseError(ctx: MergeIntoTableContext): Throwable = {
new ParseException("There must be at least one WHEN clause in a MERGE statement", ctx)
new ParseException("MERGE_STATEMENT_WITHOUT_WHEN_CLAUSE", Array.empty, ctx)
}

def nonLastMatchedClauseOmitConditionError(ctx: MergeIntoTableContext): Throwable = {
new ParseException("When there are more than one MATCHED clauses in a MERGE " +
"statement, only the last MATCHED clause can omit the condition.", ctx)
new ParseException("NON_LAST_CLAUSE_OMIT_CONDITION", Array("MATCHED", "MATCHED"), ctx)
}

def nonLastNotMatchedClauseOmitConditionError(ctx: MergeIntoTableContext): Throwable = {
new ParseException("When there are more than one NOT MATCHED clauses in a MERGE " +
"statement, only the last NOT MATCHED clause can omit the condition.", ctx)
new ParseException("NON_LAST_CLAUSE_OMIT_CONDITION", Array("NOT MATCHED", "NOT MATCHED"), ctx)
}

def emptyPartitionKeyError(key: String, ctx: PartitionSpecContext): Throwable = {
new ParseException(s"Found an empty partition key '$key'.", ctx)
new ParseException("EMPTY_PARTITION_KEY", Array(key), ctx)
}

def combinationQueryResultClausesUnsupportedError(ctx: QueryOrganizationContext): Throwable = {
new ParseException(
"Combination of ORDER BY/SORT BY/DISTRIBUTE BY/CLUSTER BY is not supported", ctx)
new ParseException("OPERATION_UNSUPPORTED",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should probably have a separate error class for unsupported combinations.

Array("Combination of ORDER BY/SORT BY/DISTRIBUTE BY/CLUSTER BY"), ctx)
}

def distributeByUnsupportedError(ctx: QueryOrganizationContext): Throwable = {
new ParseException("DISTRIBUTE BY is not supported", ctx)
new ParseException("OPERATION_UNSUPPORTED", Array("DISTRIBUTE BY"), ctx)
}

def transformNotSupportQuantifierError(ctx: ParserRuleContext): Throwable = {
new ParseException("TRANSFORM does not support DISTINCT/ALL in inputs", ctx)
new ParseException("TRANSFORM_NOT_SUPPORT_QUANTIFIER", Array.empty, ctx)
}

def transformWithSerdeUnsupportedError(ctx: ParserRuleContext): Throwable = {
new ParseException("TRANSFORM with serde is only supported in hive mode", ctx)
new ParseException("TRANSFORM_WITH_SERDE_UNSUPPORTED", Array.empty, ctx)
}

def lateralWithPivotInFromClauseNotAllowedError(ctx: FromClauseContext): Throwable = {
new ParseException("LATERAL cannot be used together with PIVOT in FROM clause", ctx)
new ParseException("LATERAL_WITH_PIVOT_IN_FROM_CLAUSE_NOT_ALLOWED", Array.empty, ctx)
}

def lateralJoinWithNaturalJoinUnsupportedError(ctx: ParserRuleContext): Throwable = {
new ParseException("LATERAL join with NATURAL join is not supported", ctx)
new ParseException("OPERATION_UNSUPPORTED", Array("LATERAL join with NATURAL join"), ctx)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we can also make a separate error class here as well, maybe about how different join types are incompatible.

}

def lateralJoinWithUsingJoinUnsupportedError(ctx: ParserRuleContext): Throwable = {
new ParseException("LATERAL join with USING join is not supported", ctx)
new ParseException("OPERATION_UNSUPPORTED", Array("LATERAL join with USING join"), ctx)
}

def unsupportedLateralJoinTypeError(ctx: ParserRuleContext, joinType: String): Throwable = {
new ParseException(s"Unsupported LATERAL join type $joinType", ctx)
new ParseException("UNSUPPORTED_LATERAL_JOIN_TYPE", Array(joinType), ctx)
}

def invalidLateralJoinRelationError(ctx: RelationPrimaryContext): Throwable = {
new ParseException(s"LATERAL can only be used with subquery", ctx)
new ParseException("INVALID_LATERAL_JOIN_RELATION", Array.empty, ctx)
}

def repetitiveWindowDefinitionError(name: String, ctx: WindowClauseContext): Throwable = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -163,10 +163,11 @@ trait AnalysisTest extends PlanTest {
}

protected def interceptParseException(
parser: String => Any)(sqlCommand: String, messages: String*): Unit = {
parser: String => Any)(sqlCommand: String, messages: String*): ParseException = {
val e = intercept[ParseException](parser(sqlCommand))
messages.foreach { message =>
assert(e.message.contains(message))
}
e
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -1408,7 +1408,8 @@ class DDLParserSuite extends AnalysisTest {
parsePlan("DELETE FROM testcat.ns1.ns2.tbl AS t(a,b,c,d) WHERE d = 2")
}

assert(exc.getMessage.contains("Columns aliases are not allowed in DELETE."))
assert(exc.getMessage.contains("Column aliases are not allowed in DELETE."))
assert(exc.getErrorClass == "COLUMN_ALIASES_NOT_ALLOWED_IN_OPERATION")
}

test("update table: basic") {
Expand Down Expand Up @@ -1448,7 +1449,8 @@ class DDLParserSuite extends AnalysisTest {
""".stripMargin)
}

assert(exc.getMessage.contains("Columns aliases are not allowed in UPDATE."))
assert(exc.getMessage.contains("Column aliases are not allowed in UPDATE."))
assert(exc.getErrorClass == "COLUMN_ALIASES_NOT_ALLOWED_IN_OPERATION")
}

test("merge into table: basic") {
Expand Down Expand Up @@ -1584,7 +1586,8 @@ class DDLParserSuite extends AnalysisTest {
""".stripMargin)
}

assert(exc.getMessage.contains("Columns aliases are not allowed in MERGE."))
assert(exc.getMessage.contains("Column aliases are not allowed in MERGE."))
assert(exc.getErrorClass == "COLUMN_ALIASES_NOT_ALLOWED_IN_OPERATION")
}
}

Expand Down Expand Up @@ -1635,6 +1638,7 @@ class DDLParserSuite extends AnalysisTest {
}

assert(exc.getMessage.contains("only the last MATCHED clause can omit the condition"))
assert(exc.getErrorClass == "NON_LAST_CLAUSE_OMIT_CONDITION")
}

test("merge into table: only the last not matched clause can omit the condition") {
Expand Down Expand Up @@ -1669,6 +1673,7 @@ class DDLParserSuite extends AnalysisTest {
}

assert(exc.getMessage.contains("There must be at least one WHEN clause in a MERGE statement"))
assert(exc.getErrorClass == "MERGE_STATEMENT_WITHOUT_WHEN_CLAUSE")
}

test("show views") {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ class ErrorParserSuite extends AnalysisTest {
interceptParseException(CatalystSqlParser.parsePlan)(sqlCommand, messages: _*)

def intercept(sql: String, line: Int, startPosition: Int, stopPosition: Int,
messages: String*): Unit = {
messages: String*): ParseException = {
val e = intercept[ParseException](CatalystSqlParser.parsePlan(sql))

// Check position.
Expand All @@ -51,6 +51,18 @@ class ErrorParserSuite extends AnalysisTest {
messages.foreach { message =>
assert(error.contains(message))
}
e
}

def interceptWithErrorClass(sqlCommand: String, messages: String*)(errorClass: String): Unit = {
val e = interceptParseException(CatalystSqlParser.parsePlan)(sqlCommand, messages: _*)
assert(e.getErrorClass == errorClass)
}

def interceptWithErrorClass(sql: String, line: Int, startPosition: Int, stopPosition: Int,
messages: String*)(errorClass: String): Unit = {
val e = intercept(sql, line, startPosition, stopPosition, messages: _*)
assert(e.getErrorClass == errorClass)
}

test("no viable input") {
Expand All @@ -71,9 +83,9 @@ class ErrorParserSuite extends AnalysisTest {
}

test("semantic errors") {
intercept("select *\nfrom r\norder by q\ncluster by q", 3, 0, 11,
interceptWithErrorClass("select *\nfrom r\norder by q\ncluster by q", 3, 0, 11,
"Combination of ORDER BY/SORT BY/DISTRIBUTE BY/CLUSTER BY is not supported",
"^^^")
"^^^")("OPERATION_UNSUPPORTED")
}

test("SPARK-21136: misleading error message due to problematic antlr grammar") {
Expand Down Expand Up @@ -211,11 +223,16 @@ class ErrorParserSuite extends AnalysisTest {

test("SPARK-35789: lateral join with non-subquery relations") {
val msg = "LATERAL can only be used with subquery"
intercept("SELECT * FROM t1, LATERAL t2", msg)
intercept("SELECT * FROM t1 JOIN LATERAL t2", msg)
intercept("SELECT * FROM t1, LATERAL (t2 JOIN t3)", msg)
intercept("SELECT * FROM t1, LATERAL (LATERAL t2)", msg)
intercept("SELECT * FROM t1, LATERAL VALUES (0, 1)", msg)
intercept("SELECT * FROM t1, LATERAL RANGE(0, 1)", msg)
interceptWithErrorClass("SELECT * FROM t1, LATERAL t2", msg)("INVALID_LATERAL_JOIN_RELATION")
interceptWithErrorClass("SELECT * FROM t1 JOIN LATERAL t2", msg)(
"INVALID_LATERAL_JOIN_RELATION")
interceptWithErrorClass("SELECT * FROM t1, LATERAL (t2 JOIN t3)", msg)(
"INVALID_LATERAL_JOIN_RELATION")
interceptWithErrorClass("SELECT * FROM t1, LATERAL (LATERAL t2)", msg)(
"INVALID_LATERAL_JOIN_RELATION")
interceptWithErrorClass("SELECT * FROM t1, LATERAL VALUES (0, 1)", msg)(
"INVALID_LATERAL_JOIN_RELATION")
interceptWithErrorClass("SELECT * FROM t1, LATERAL RANGE(0, 1)", msg)(
"INVALID_LATERAL_JOIN_RELATION")
}
}
Loading