Skip to content

Commit 1dfcd8f

Browse files
alahvanhovell
authored andcommitted
[SPARK-52404][SQL] Give a separate error class to failures in BindReferences
### What changes were proposed in this pull request? We add a new error class to cover a distinct portion of the `INTERNAL_ERROR` class, that is, a situation where an attribute reference in the query plan cannot be bound. The error massage, once hardcoded in `BoundAttribute.scala` is now moved the the JSON file. ### Why are the changes needed? The error messages should be stored in the JSON files, and not hard-coded into the source. Failures in `BoundAttribute.scala` are a distinct and don't share much with the other `INTERNAL_ERROR` failures, yet they are currently bundled under the same error class. ### Does this PR introduce _any_ user-facing change? Yes. Change of error class. ### How was this patch tested? New test is added. ### Was this patch authored or co-authored using generative AI tooling? No. Closes apache#51066 from ala/attr_not_found. Authored-by: ala <[email protected]> Signed-off-by: Herman van Hovell <[email protected]>
1 parent 8c3194f commit 1dfcd8f

File tree

3 files changed

+64
-2
lines changed

3 files changed

+64
-2
lines changed

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

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2227,6 +2227,12 @@
22272227
],
22282228
"sqlState" : "XX000"
22292229
},
2230+
"INTERNAL_ERROR_ATTRIBUTE_NOT_FOUND" : {
2231+
"message" : [
2232+
"Could not find <missingAttr> in <inputAttrs>."
2233+
],
2234+
"sqlState" : "XX000"
2235+
},
22302236
"INTERNAL_ERROR_BROADCAST" : {
22312237
"message" : [
22322238
"<message>"

sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/expressions/BoundAttribute.scala

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -77,8 +77,7 @@ object BindReferences extends Logging {
7777
if (allowFailures) {
7878
a
7979
} else {
80-
throw SparkException.internalError(
81-
s"Couldn't find $a in ${input.attrs.mkString("[", ",", "]")}")
80+
throw attributeNotFoundException(a, input.attrs)
8281
}
8382
} else {
8483
BoundReference(ordinal, a.dataType, input(ordinal).nullable)
@@ -94,4 +93,18 @@ object BindReferences extends Logging {
9493
input: AttributeSeq): Seq[A] = {
9594
expressions.map(BindReferences.bindReference(_, input))
9695
}
96+
97+
/**
98+
* A helper function to produce an exception when binding a reference fails.
99+
* Public for testing.
100+
*/
101+
def attributeNotFoundException(
102+
missingAttr: AttributeReference,
103+
inputAttrs: Seq[Attribute]): SparkException =
104+
new SparkException(
105+
errorClass = "INTERNAL_ERROR_ATTRIBUTE_NOT_FOUND",
106+
messageParameters = Map(
107+
"missingAttr" -> missingAttr.toString,
108+
"inputAttrs" -> inputAttrs.mkString("[", ",", "]")),
109+
cause = null)
97110
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one or more
3+
* contributor license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright ownership.
5+
* The ASF licenses this file to You under the Apache License, Version 2.0
6+
* (the "License"); you may not use this file except in compliance with
7+
* the License. You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
18+
package org.apache.spark.sql.catalyst.expressions
19+
20+
import org.apache.spark.SparkFunSuite
21+
import org.apache.spark.sql.types.IntegerType
22+
23+
class BindReferencesSuite extends SparkFunSuite{
24+
test("attribute not found exception") {
25+
val missing = AttributeReference("missing", IntegerType)(qualifier = Seq.empty)
26+
val input1 = AttributeReference("one", IntegerType)(qualifier = Seq.empty)
27+
val input2 = AttributeReference("two", IntegerType)(qualifier = Seq.empty)
28+
val input3 = AttributeReference("three", IntegerType)(qualifier = Seq.empty)
29+
30+
val e = BindReferences.attributeNotFoundException(
31+
missingAttr = missing,
32+
inputAttrs = Seq(input1, input2, input3))
33+
34+
checkError(e,
35+
condition = "INTERNAL_ERROR_ATTRIBUTE_NOT_FOUND",
36+
sqlState = "XX000",
37+
parameters = Map(
38+
"missingAttr" -> s"$missing",
39+
"inputAttrs" -> s"[$input1,$input2,$input3]"
40+
)
41+
)
42+
}
43+
}

0 commit comments

Comments
 (0)