Skip to content

Commit b7c6c84

Browse files
belieferMaxGekk
authored andcommitted
[SPARK-44328][SQL] Assign names to the error class _LEGACY_ERROR_TEMP_[2325-2328]
### What changes were proposed in this pull request? The pr aims to assign names to the error class _LEGACY_ERROR_TEMP_[2325-2328]. ### Why are the changes needed? Improve the error framework. ### Does this PR introduce _any_ user-facing change? 'No'. ### How was this patch tested? Exists test cases updated and added new test cases. Closes #41889 from beliefer/SPARK-44328. Authored-by: Jiaan Geng <[email protected]> Signed-off-by: Max Gekk <[email protected]>
1 parent 990affd commit b7c6c84

File tree

5 files changed

+153
-58
lines changed

5 files changed

+153
-58
lines changed

common/utils/src/main/resources/error/error-classes.json

+32-25
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,38 @@
221221
"Failed to set permissions on created path <path> back to <permission>."
222222
]
223223
},
224+
"CANNOT_UPDATE_FIELD" : {
225+
"message" : [
226+
"Cannot update <table> field <fieldName> type:"
227+
],
228+
"subClass" : {
229+
"ARRAY_TYPE" : {
230+
"message" : [
231+
"Update the element by updating <fieldName>.element."
232+
]
233+
},
234+
"INTERVAL_TYPE" : {
235+
"message" : [
236+
"Update an interval by updating its fields."
237+
]
238+
},
239+
"MAP_TYPE" : {
240+
"message" : [
241+
"Update a map by updating <fieldName>.key or <fieldName>.value."
242+
]
243+
},
244+
"STRUCT_TYPE" : {
245+
"message" : [
246+
"Update a struct by updating its fields."
247+
]
248+
},
249+
"USER_DEFINED_TYPE" : {
250+
"message" : [
251+
"Update a UserDefinedType[<udtSql>] by updating its fields."
252+
]
253+
}
254+
}
255+
},
224256
"CANNOT_UP_CAST_DATATYPE" : {
225257
"message" : [
226258
"Cannot up cast <expression> from <sourceType> to <targetType>.",
@@ -2965,11 +2997,6 @@
29652997
"3. set \"spark.sql.legacy.allowUntypedScalaUDF\" to \"true\" and use this API with caution."
29662998
]
29672999
},
2968-
"UPDATE_FIELD_WITH_STRUCT_UNSUPPORTED" : {
2969-
"message" : [
2970-
"Cannot update <table> field <fieldName> type: update a struct by updating its fields."
2971-
]
2972-
},
29733000
"VIEW_ALREADY_EXISTS" : {
29743001
"message" : [
29753002
"Cannot create view <relationName> because it already exists.",
@@ -5688,26 +5715,6 @@
56885715
"Number of dynamic partitions created is <numWrittenParts>, which is more than <maxDynamicPartitions>. To solve this try to set <maxDynamicPartitionsKey> to at least <numWrittenParts>."
56895716
]
56905717
},
5691-
"_LEGACY_ERROR_TEMP_2325" : {
5692-
"message" : [
5693-
"Cannot update <table> field <fieldName> type: update a map by updating <fieldName>.key or <fieldName>.value."
5694-
]
5695-
},
5696-
"_LEGACY_ERROR_TEMP_2326" : {
5697-
"message" : [
5698-
"Cannot update <table> field <fieldName> type: update the element by updating <fieldName>.element."
5699-
]
5700-
},
5701-
"_LEGACY_ERROR_TEMP_2327" : {
5702-
"message" : [
5703-
"Cannot update <table> field <fieldName> type: update a UserDefinedType[<udtSql>] by updating its fields."
5704-
]
5705-
},
5706-
"_LEGACY_ERROR_TEMP_2328" : {
5707-
"message" : [
5708-
"Cannot update <table> field <fieldName> to interval type."
5709-
]
5710-
},
57115718
"_LEGACY_ERROR_TEMP_2330" : {
57125719
"message" : [
57135720
"Cannot change nullable column to non-nullable: <fieldName>."
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
---
2+
layout: global
3+
title: CANNOT_UPDATE_FIELD error class
4+
displayTitle: CANNOT_UPDATE_FIELD error class
5+
license: |
6+
Licensed to the Apache Software Foundation (ASF) under one or more
7+
contributor license agreements. See the NOTICE file distributed with
8+
this work for additional information regarding copyright ownership.
9+
The ASF licenses this file to You under the Apache License, Version 2.0
10+
(the "License"); you may not use this file except in compliance with
11+
the License. You may obtain a copy of the License at
12+
13+
http://www.apache.org/licenses/LICENSE-2.0
14+
15+
Unless required by applicable law or agreed to in writing, software
16+
distributed under the License is distributed on an "AS IS" BASIS,
17+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18+
See the License for the specific language governing permissions and
19+
limitations under the License.
20+
---
21+
22+
SQLSTATE: none assigned
23+
24+
Cannot update `<table>` field `<fieldName>` type:
25+
26+
This error class has the following derived error classes:
27+
28+
## ARRAY_TYPE
29+
30+
Update the element by updating `<fieldName>`.element.
31+
32+
## INTERVAL_TYPE
33+
34+
Update an interval by updating its fields.
35+
36+
## MAP_TYPE
37+
38+
Update a map by updating `<fieldName>`.key or `<fieldName>`.value.
39+
40+
## STRUCT_TYPE
41+
42+
Update a struct by updating its fields.
43+
44+
## USER_DEFINED_TYPE
45+
46+
Update a UserDefinedType[`<udtSql>`] by updating its fields.
47+
48+

docs/sql-error-conditions.md

+8-6
Original file line numberDiff line numberDiff line change
@@ -254,6 +254,14 @@ SQLSTATE: none assigned
254254

255255
Failed to set permissions on created path `<path>` back to `<permission>`.
256256

257+
### [CANNOT_UPDATE_FIELD](sql-error-conditions-cannot-update-field-error-class.html)
258+
259+
SQLSTATE: none assigned
260+
261+
Cannot update `<table>` field `<fieldName>` type:
262+
263+
For more details see [CANNOT_UPDATE_FIELD](sql-error-conditions-cannot-update-field-error-class.html)
264+
257265
### CANNOT_UP_CAST_DATATYPE
258266

259267
SQLSTATE: none assigned
@@ -1922,12 +1930,6 @@ You're using untyped Scala UDF, which does not have the input type information.
19221930
2. use Java UDF APIs, e.g. `udf(new UDF1[String, Integer] { override def call(s: String): Integer = s.length() }, IntegerType)`, if input types are all non primitive.
19231931
3. set "spark.sql.legacy.allowUntypedScalaUDF" to "true" and use this API with caution.
19241932

1925-
### UPDATE_FIELD_WITH_STRUCT_UNSUPPORTED
1926-
1927-
SQLSTATE: none assigned
1928-
1929-
Cannot update `<table>` field `<fieldName>` type: update a struct by updating its fields.
1930-
19311933
### VIEW_ALREADY_EXISTS
19321934

19331935
[SQLSTATE: 42P07](sql-error-conditions-sqlstates.html#class-42-syntax-error-or-access-rule-violation)

sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/analysis/CheckAnalysis.scala

+12-6
Original file line numberDiff line numberDiff line change
@@ -1436,17 +1436,23 @@ trait CheckAnalysis extends PredicateHelper with LookupCatalog with QueryErrorsB
14361436
val newDataType = a.dataType.get
14371437
newDataType match {
14381438
case _: StructType => alter.failAnalysis(
1439-
"UPDATE_FIELD_WITH_STRUCT_UNSUPPORTED",
1439+
"CANNOT_UPDATE_FIELD.STRUCT_TYPE",
14401440
Map("table" -> toSQLId(table.name), "fieldName" -> toSQLId(fieldName)))
14411441
case _: MapType => alter.failAnalysis(
1442-
"_LEGACY_ERROR_TEMP_2325", Map("table" -> table.name, "fieldName" -> fieldName))
1442+
"CANNOT_UPDATE_FIELD.MAP_TYPE",
1443+
Map("table" -> toSQLId(table.name), "fieldName" -> toSQLId(fieldName)))
14431444
case _: ArrayType => alter.failAnalysis(
1444-
"_LEGACY_ERROR_TEMP_2326", Map("table" -> table.name, "fieldName" -> fieldName))
1445+
"CANNOT_UPDATE_FIELD.ARRAY_TYPE",
1446+
Map("table" -> toSQLId(table.name), "fieldName" -> toSQLId(fieldName)))
14451447
case u: UserDefinedType[_] => alter.failAnalysis(
1446-
"_LEGACY_ERROR_TEMP_2327",
1447-
Map("table" -> table.name, "fieldName" -> fieldName, "udtSql" -> u.sql))
1448+
"CANNOT_UPDATE_FIELD.USER_DEFINED_TYPE",
1449+
Map(
1450+
"table" -> toSQLId(table.name),
1451+
"fieldName" -> toSQLId(fieldName),
1452+
"udtSql" -> toSQLType(u)))
14481453
case _: CalendarIntervalType | _: AnsiIntervalType => alter.failAnalysis(
1449-
"_LEGACY_ERROR_TEMP_2328", Map("table" -> table.name, "fieldName" -> fieldName))
1454+
"CANNOT_UPDATE_FIELD.INTERVAL_TYPE",
1455+
Map("table" -> toSQLId(table.name), "fieldName" -> toSQLId(fieldName)))
14501456
case _ => // update is okay
14511457
}
14521458

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

+53-21
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,14 @@ trait AlterTableTests extends SharedSparkSession with QueryErrorsBase {
4747
}
4848
}
4949

50+
private def prependCatalogName(tableName: String): String = {
51+
if (catalogAndNamespace.isEmpty) {
52+
s"spark_catalog.$tableName"
53+
} else {
54+
tableName
55+
}
56+
}
57+
5058
test("AlterTable: table does not exist") {
5159
val t2 = s"${catalogAndNamespace}fake_table"
5260
val quoted = UnresolvedAttribute.parseAttributeName(s"${catalogAndNamespace}table_name")
@@ -486,9 +494,21 @@ trait AlterTableTests extends SharedSparkSession with QueryErrorsBase {
486494
(DataTypeTestUtils.dayTimeIntervalTypes ++ DataTypeTestUtils.yearMonthIntervalTypes)
487495
.foreach {
488496
case d: DataType => d.typeName
489-
val e = intercept[AnalysisException](
490-
sql(s"ALTER TABLE $t ALTER COLUMN id TYPE ${d.typeName}"))
491-
assert(e.getMessage.contains("id to interval type"))
497+
val sqlText = s"ALTER TABLE $t ALTER COLUMN id TYPE ${d.typeName}"
498+
499+
checkError(
500+
exception = intercept[AnalysisException] {
501+
sql(sqlText)
502+
},
503+
errorClass = "CANNOT_UPDATE_FIELD.INTERVAL_TYPE",
504+
parameters = Map(
505+
"table" -> s"${toSQLId(prependCatalogName(t))}",
506+
"fieldName" -> "`id`"),
507+
context = ExpectedContext(
508+
fragment = sqlText,
509+
start = 0,
510+
stop = 33 + d.typeName.length + t.length)
511+
)
492512
}
493513
}
494514
}
@@ -538,19 +558,13 @@ trait AlterTableTests extends SharedSparkSession with QueryErrorsBase {
538558
val sqlText =
539559
s"ALTER TABLE $t ALTER COLUMN point TYPE struct<x: double, y: double, z: double>"
540560

541-
val fullName = if (catalogAndNamespace.isEmpty) {
542-
s"spark_catalog.default.table_name"
543-
} else {
544-
t
545-
}
546-
547561
checkError(
548562
exception = intercept[AnalysisException] {
549563
sql(sqlText)
550564
},
551-
errorClass = "UPDATE_FIELD_WITH_STRUCT_UNSUPPORTED",
565+
errorClass = "CANNOT_UPDATE_FIELD.STRUCT_TYPE",
552566
parameters = Map(
553-
"table" -> s"${toSQLId(fullName)}",
567+
"table" -> s"${toSQLId(prependCatalogName(t))}",
554568
"fieldName" -> "`point`"),
555569
context = ExpectedContext(
556570
fragment = sqlText,
@@ -573,12 +587,21 @@ trait AlterTableTests extends SharedSparkSession with QueryErrorsBase {
573587
val t = fullTableName("table_name")
574588
withTable(t) {
575589
sql(s"CREATE TABLE $t (id int, points array<int>) USING $v2Format")
590+
val sqlText = s"ALTER TABLE $t ALTER COLUMN points TYPE array<long>"
576591

577-
val exc = intercept[AnalysisException] {
578-
sql(s"ALTER TABLE $t ALTER COLUMN points TYPE array<long>")
579-
}
580-
581-
assert(exc.getMessage.contains("update the element by updating points.element"))
592+
checkError(
593+
exception = intercept[AnalysisException] {
594+
sql(sqlText)
595+
},
596+
errorClass = "CANNOT_UPDATE_FIELD.ARRAY_TYPE",
597+
parameters = Map(
598+
"table" -> s"${toSQLId(prependCatalogName(t))}",
599+
"fieldName" -> "`points`"),
600+
context = ExpectedContext(
601+
fragment = sqlText,
602+
start = 0,
603+
stop = 48 + t.length)
604+
)
582605

583606
val table = getTableMetadata(t)
584607

@@ -608,12 +631,21 @@ trait AlterTableTests extends SharedSparkSession with QueryErrorsBase {
608631
val t = fullTableName("table_name")
609632
withTable(t) {
610633
sql(s"CREATE TABLE $t (id int, m map<string, int>) USING $v2Format")
634+
val sqlText = s"ALTER TABLE $t ALTER COLUMN m TYPE map<string, long>"
611635

612-
val exc = intercept[AnalysisException] {
613-
sql(s"ALTER TABLE $t ALTER COLUMN m TYPE map<string, long>")
614-
}
615-
616-
assert(exc.getMessage.contains("update a map by updating m.key or m.value"))
636+
checkError(
637+
exception = intercept[AnalysisException] {
638+
sql(sqlText)
639+
},
640+
errorClass = "CANNOT_UPDATE_FIELD.MAP_TYPE",
641+
parameters = Map(
642+
"table" -> s"${toSQLId(prependCatalogName(t))}",
643+
"fieldName" -> "`m`"),
644+
context = ExpectedContext(
645+
fragment = sqlText,
646+
start = 0,
647+
stop = 49 + t.length)
648+
)
617649

618650
val table = getTableMetadata(t)
619651

0 commit comments

Comments
 (0)