From bb127080f630558e14d019ba61611563b93d58af Mon Sep 17 00:00:00 2001 From: subhramit Date: Sun, 23 Aug 2026 14:17:41 +0530 Subject: [PATCH 01/24] [SPARK-58945][SQL] Fix `messageParameters` keys that do not match their error templates Signed-off-by: subhramit --- .../sql/errors/QueryCompilationErrors.scala | 2 +- .../sql/errors/QueryExecutionErrors.scala | 5 +- .../streaming/state/StateStoreErrors.scala | 6 +-- .../errors/ErrorMessageParametersSuite.scala | 54 +++++++++++++++++++ .../errors/QueryExecutionErrorsSuite.scala | 15 ++++++ 5 files changed, 75 insertions(+), 7 deletions(-) create mode 100644 sql/core/src/test/scala/org/apache/spark/sql/errors/ErrorMessageParametersSuite.scala diff --git a/sql/catalyst/src/main/scala/org/apache/spark/sql/errors/QueryCompilationErrors.scala b/sql/catalyst/src/main/scala/org/apache/spark/sql/errors/QueryCompilationErrors.scala index ada71af43d3b5..2fbf895264079 100644 --- a/sql/catalyst/src/main/scala/org/apache/spark/sql/errors/QueryCompilationErrors.scala +++ b/sql/catalyst/src/main/scala/org/apache/spark/sql/errors/QueryCompilationErrors.scala @@ -4675,7 +4675,7 @@ private[sql] object QueryCompilationErrors extends QueryErrorsBase with Compilat def invalidUDFClassError(invalidClass: String): Throwable = { new InvalidUDFClassException( errorClass = "_LEGACY_ERROR_TEMP_2450", - messageParameters = Map("invalidClass" -> invalidClass)) + messageParameters = Map("clazz" -> invalidClass)) } def cannotInstantiateHiveFunctionError(clazz: String, e: Throwable): Throwable = { diff --git a/sql/catalyst/src/main/scala/org/apache/spark/sql/errors/QueryExecutionErrors.scala b/sql/catalyst/src/main/scala/org/apache/spark/sql/errors/QueryExecutionErrors.scala index 63ab10b694222..9a3c039efecbf 100644 --- a/sql/catalyst/src/main/scala/org/apache/spark/sql/errors/QueryExecutionErrors.scala +++ b/sql/catalyst/src/main/scala/org/apache/spark/sql/errors/QueryExecutionErrors.scala @@ -3215,8 +3215,7 @@ private[sql] object QueryExecutionErrors extends QueryErrorsBase with ExecutionE messageParameters = Map( "functionName" -> toSQLId(functionName), "parameter" -> toSQLId("extension"), - "fileExtension" -> toSQLId(extension), - "acceptable" -> "Extension is limited to exactly 3 letters (e.g. csv, tsv, etc...)")) + "invalidValue" -> toSQLId(extension))) } def invalidCharsetError(functionName: String, charset: String): RuntimeException = { @@ -3240,7 +3239,7 @@ private[sql] object QueryExecutionErrors extends QueryErrorsBase with ExecutionE def invalidWriterCommitMessageError(details: String): Throwable = { new SparkRuntimeException( errorClass = "INVALID_WRITER_COMMIT_MESSAGE", - messageParameters = Map("details" -> details)) + messageParameters = Map("detail" -> details)) } def codecNotAvailableError(codecName: String, availableCodecs: String): Throwable = { diff --git a/sql/core/src/main/scala/org/apache/spark/sql/execution/streaming/state/StateStoreErrors.scala b/sql/core/src/main/scala/org/apache/spark/sql/execution/streaming/state/StateStoreErrors.scala index a301ecbf22dbf..a2daf93ad6918 100644 --- a/sql/core/src/main/scala/org/apache/spark/sql/execution/streaming/state/StateStoreErrors.scala +++ b/sql/core/src/main/scala/org/apache/spark/sql/execution/streaming/state/StateStoreErrors.scala @@ -398,9 +398,9 @@ class StateStoreColumnFamilyMismatch( extends SparkUnsupportedOperationException( errorClass = "STATE_STORE_COLUMN_FAMILY_SCHEMA_INCOMPATIBLE", messageParameters = Map( - "columnFamilyName" -> columnFamilyName, - "oldColumnFamilySchema" -> oldColumnFamilySchema, - "newColumnFamilySchema" -> newColumnFamilySchema)) + "colFamilyName" -> columnFamilyName, + "oldSchema" -> oldColumnFamilySchema, + "newSchema" -> newColumnFamilySchema)) class StatefulProcessorCannotPerformOperationWithInvalidTimeMode( operationType: String, diff --git a/sql/core/src/test/scala/org/apache/spark/sql/errors/ErrorMessageParametersSuite.scala b/sql/core/src/test/scala/org/apache/spark/sql/errors/ErrorMessageParametersSuite.scala new file mode 100644 index 0000000000000..63e1cd6552eea --- /dev/null +++ b/sql/core/src/test/scala/org/apache/spark/sql/errors/ErrorMessageParametersSuite.scala @@ -0,0 +1,54 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.spark.sql.errors + +import org.apache.spark.{SparkFunSuite, SparkThrowable} +import org.apache.spark.sql.execution.streaming.state.StateStoreColumnFamilyMismatch + +class ErrorMessageParametersSuite extends SparkFunSuite { + + private def asSparkThrowable(e: Throwable): SparkThrowable = { + e.asInstanceOf[SparkThrowable] + } + + test("SPARK-58945: invalid writer commit message reports detail") { + checkError( + exception = asSparkThrowable(QueryExecutionErrors.invalidWriterCommitMessageError("zero")), + condition = "INVALID_WRITER_COMMIT_MESSAGE", + parameters = Map("detail" -> "zero")) + } + + test("SPARK-58945: invalid UDF class error reports clazz") { + checkError( + exception = asSparkThrowable( + QueryCompilationErrors.invalidUDFClassError("example.InvalidFunction")), + condition = "_LEGACY_ERROR_TEMP_2450", + parameters = Map("clazz" -> "example.InvalidFunction")) + } + + test("SPARK-58945: state store mismatch reports schema details") { + checkError( + exception = new StateStoreColumnFamilyMismatch( + "state", "old_schema", "new_schema"), + condition = "STATE_STORE_COLUMN_FAMILY_SCHEMA_INCOMPATIBLE", + parameters = Map( + "colFamilyName" -> "state", + "oldSchema" -> "old_schema", + "newSchema" -> "new_schema")) + } +} diff --git a/sql/core/src/test/scala/org/apache/spark/sql/errors/QueryExecutionErrorsSuite.scala b/sql/core/src/test/scala/org/apache/spark/sql/errors/QueryExecutionErrorsSuite.scala index 7eccce3fe0490..78d3c44109a04 100644 --- a/sql/core/src/test/scala/org/apache/spark/sql/errors/QueryExecutionErrorsSuite.scala +++ b/sql/core/src/test/scala/org/apache/spark/sql/errors/QueryExecutionErrorsSuite.scala @@ -141,6 +141,21 @@ class QueryExecutionErrorsSuite (df1, df2) } + test("SPARK-58945: invalid file extension reports invalidValue") { + withTempDir { dir => + val path = new File(dir, "data").getCanonicalPath + checkError( + exception = intercept[SparkIllegalArgumentException] { + spark.range(1).write.option("extension", "12").csv(path) + }, + condition = "INVALID_PARAMETER_VALUE.EXTENSION", + parameters = Map( + "functionName" -> "`extension`", + "parameter" -> "`extension`", + "invalidValue" -> "`12`")) + } + } + test("INVALID_PARAMETER_VALUE.AES_KEY_LENGTH: invalid key lengths in AES functions") { val (df1, df2) = getAesInputs() def checkInvalidKeyLength(df: => DataFrame, inputBytes: Int): Unit = { From 6cc8eb309528ad70114f7b163d9475a3d52c9df5 Mon Sep 17 00:00:00 2001 From: subhramit Date: Sun, 23 Aug 2026 14:20:02 +0530 Subject: [PATCH 02/24] [SPARK-58945][SQL] Supply searchPath for TABLE_OR_VIEW_NOT_FOUND in H2Dialect Signed-off-by: subhramit --- .../scala/org/apache/spark/sql/jdbc/H2Dialect.scala | 7 ++++++- .../datasources/v2/jdbc/JDBCTableCatalogSuite.scala | 10 ++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/sql/core/src/main/scala/org/apache/spark/sql/jdbc/H2Dialect.scala b/sql/core/src/main/scala/org/apache/spark/sql/jdbc/H2Dialect.scala index 86420b84e50df..25727de1b003c 100644 --- a/sql/core/src/main/scala/org/apache/spark/sql/jdbc/H2Dialect.scala +++ b/sql/core/src/main/scala/org/apache/spark/sql/jdbc/H2Dialect.scala @@ -228,7 +228,12 @@ private[sql] case class H2Dialect() extends JdbcDialect with NoLegacyJDBCError { val relationName = messageParameters.getOrElse("tableName", "") throw new NoSuchTableException( errorClass = "TABLE_OR_VIEW_NOT_FOUND", - messageParameters = Map("relationName" -> relationName), + messageParameters = Map( + "relationName" -> relationName, + // classifyException receives only pre-rendered strings, so no Spark-side + // search path exists here; "not available" matches the rendering used for + // an empty search path. + "searchPath" -> "not available"), cause = Some(e)) // SCHEMA_NOT_FOUND_1 case 90079 => diff --git a/sql/core/src/test/scala/org/apache/spark/sql/execution/datasources/v2/jdbc/JDBCTableCatalogSuite.scala b/sql/core/src/test/scala/org/apache/spark/sql/execution/datasources/v2/jdbc/JDBCTableCatalogSuite.scala index 1caebf506a3d1..a7e313b077381 100644 --- a/sql/core/src/test/scala/org/apache/spark/sql/execution/datasources/v2/jdbc/JDBCTableCatalogSuite.scala +++ b/sql/core/src/test/scala/org/apache/spark/sql/execution/datasources/v2/jdbc/JDBCTableCatalogSuite.scala @@ -229,6 +229,16 @@ class JDBCTableCatalogSuite extends SharedSparkSession { } } + test("SPARK-58945: H2 loadTable reports unavailable search path") { + val e = intercept[AnalysisException] { + tableCatalog.loadTable(Identifier.of(Array("test"), "not_existing_table")) + } + checkErrorTableNotFoundWithSearchPath( + e, + "`test`.`not_existing_table`", + searchPath = "not available") + } + test("create a table") { withTable("h2.test.new_table") { sql("CREATE TABLE h2.test.new_table(i INT, j STRING)") From a1ec54a49be9a6c10f92cf84a113b0e77167f1bf Mon Sep 17 00:00:00 2001 From: subhramit Date: Sun, 23 Aug 2026 14:20:49 +0530 Subject: [PATCH 03/24] [SPARK-58945][SQL] Restore the correct message template for `_LEGACY_ERROR_TEMP_3070` Signed-off-by: subhramit --- .../main/resources/error/error-conditions.json | 2 +- .../FileSourceCustomMetadataStructSuite.scala | 17 ++++++++++++++++- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/common/utils/src/main/resources/error/error-conditions.json b/common/utils/src/main/resources/error/error-conditions.json index c642e0be953aa..599076dedf54b 100644 --- a/common/utils/src/main/resources/error/error-conditions.json +++ b/common/utils/src/main/resources/error/error-conditions.json @@ -11723,7 +11723,7 @@ }, "_LEGACY_ERROR_TEMP_3070" : { "message" : [ - " is a reserved column name that cannot be read in combination with column." + "Unrecognized file metadata field: " ] }, "_LEGACY_ERROR_TEMP_3071" : { diff --git a/sql/core/src/test/scala/org/apache/spark/sql/execution/datasources/FileSourceCustomMetadataStructSuite.scala b/sql/core/src/test/scala/org/apache/spark/sql/execution/datasources/FileSourceCustomMetadataStructSuite.scala index 1ace87deab471..0668e07daf5f5 100644 --- a/sql/core/src/test/scala/org/apache/spark/sql/execution/datasources/FileSourceCustomMetadataStructSuite.scala +++ b/sql/core/src/test/scala/org/apache/spark/sql/execution/datasources/FileSourceCustomMetadataStructSuite.scala @@ -21,7 +21,7 @@ import java.io.File import org.apache.hadoop.fs.{FileStatus, Path} -import org.apache.spark.sql.Row +import org.apache.spark.sql.{AnalysisException, Row} import org.apache.spark.sql.catalyst.InternalRow import org.apache.spark.sql.catalyst.expressions.{Expression, FileSourceConstantMetadataStructField, FileSourceGeneratedMetadataStructField, Literal} import org.apache.spark.sql.catalyst.util.GenericArrayData @@ -413,6 +413,21 @@ class FileSourceCustomMetadataStructSuite extends SharedSparkSession { Row(1, 112L, 1L, f1.getLen, f1.getPath.getName))) } } + + test("SPARK-58945: invalid file metadata fields report the field") { + withTempData("parquet", FILE_SCHEMA) { (_, f0, f1) => + val invalidField = StructField("bad", StringType) + val format = new TestFileFormat(Seq(invalidField)) + val df = createDF(format, Seq(FileStatusWithMetadata(f0), FileStatusWithMetadata(f1))) + + checkError( + exception = intercept[AnalysisException] { + df.select("_metadata.bad").collect() + }, + condition = "_LEGACY_ERROR_TEMP_3070", + parameters = Map("field" -> invalidField.toString)) + } + } } object FileSourceCustomMetadataStructSuite { From 327192b966163a9880b570ea57b26c7e45137470 Mon Sep 17 00:00:00 2001 From: subhramit Date: Sun, 23 Aug 2026 15:34:14 +0530 Subject: [PATCH 04/24] [SPARK-58945][SQL] Inline the SparkThrowable cast to match existing test style Signed-off-by: subhramit --- .../sql/errors/ErrorMessageParametersSuite.scala | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/sql/core/src/test/scala/org/apache/spark/sql/errors/ErrorMessageParametersSuite.scala b/sql/core/src/test/scala/org/apache/spark/sql/errors/ErrorMessageParametersSuite.scala index 63e1cd6552eea..6b33805a945a8 100644 --- a/sql/core/src/test/scala/org/apache/spark/sql/errors/ErrorMessageParametersSuite.scala +++ b/sql/core/src/test/scala/org/apache/spark/sql/errors/ErrorMessageParametersSuite.scala @@ -17,26 +17,24 @@ package org.apache.spark.sql.errors -import org.apache.spark.{SparkFunSuite, SparkThrowable} +import org.apache.spark.{SparkFunSuite, SparkRuntimeException} +import org.apache.spark.sql.catalyst.catalog.InvalidUDFClassException import org.apache.spark.sql.execution.streaming.state.StateStoreColumnFamilyMismatch class ErrorMessageParametersSuite extends SparkFunSuite { - private def asSparkThrowable(e: Throwable): SparkThrowable = { - e.asInstanceOf[SparkThrowable] - } - test("SPARK-58945: invalid writer commit message reports detail") { checkError( - exception = asSparkThrowable(QueryExecutionErrors.invalidWriterCommitMessageError("zero")), + exception = QueryExecutionErrors.invalidWriterCommitMessageError("zero") + .asInstanceOf[SparkRuntimeException], condition = "INVALID_WRITER_COMMIT_MESSAGE", parameters = Map("detail" -> "zero")) } test("SPARK-58945: invalid UDF class error reports clazz") { checkError( - exception = asSparkThrowable( - QueryCompilationErrors.invalidUDFClassError("example.InvalidFunction")), + exception = QueryCompilationErrors.invalidUDFClassError("example.InvalidFunction") + .asInstanceOf[InvalidUDFClassException], condition = "_LEGACY_ERROR_TEMP_2450", parameters = Map("clazz" -> "example.InvalidFunction")) } From 970f868ac34bde1169fcfdfe192dce01b29df851 Mon Sep 17 00:00:00 2001 From: subhramit Date: Sun, 23 Aug 2026 16:04:38 +0530 Subject: [PATCH 05/24] [SPARK-58945][SQL] Test the H2 dialect directly since loadTable is intercepted earlier Signed-off-by: subhramit --- .../v2/jdbc/JDBCTableCatalogSuite.scala | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/sql/core/src/test/scala/org/apache/spark/sql/execution/datasources/v2/jdbc/JDBCTableCatalogSuite.scala b/sql/core/src/test/scala/org/apache/spark/sql/execution/datasources/v2/jdbc/JDBCTableCatalogSuite.scala index a7e313b077381..ac2f0a45e4761 100644 --- a/sql/core/src/test/scala/org/apache/spark/sql/execution/datasources/v2/jdbc/JDBCTableCatalogSuite.scala +++ b/sql/core/src/test/scala/org/apache/spark/sql/execution/datasources/v2/jdbc/JDBCTableCatalogSuite.scala @@ -16,7 +16,7 @@ */ package org.apache.spark.sql.execution.datasources.v2.jdbc -import java.sql.{Connection, DriverManager} +import java.sql.{Connection, DriverManager, SQLException} import java.util.Properties import scala.jdk.CollectionConverters._ @@ -25,13 +25,17 @@ import org.apache.logging.log4j.Level import org.apache.spark.{SparkConf, SparkIllegalArgumentException, SparkRuntimeException} import org.apache.spark.sql.{AnalysisException, Row} -import org.apache.spark.sql.catalyst.analysis.{NoSuchNamespaceException, TableAlreadyExistsException} +import org.apache.spark.sql.catalyst.analysis.{ + NoSuchNamespaceException, + NoSuchTableException, + TableAlreadyExistsException} import org.apache.spark.sql.catalyst.parser.ParseException import org.apache.spark.sql.catalyst.util.CharVarcharUtils import org.apache.spark.sql.connector.catalog.{Identifier, TableSummary} import org.apache.spark.sql.errors.DataTypeErrors.{toSQLConf, toSQLStmt} import org.apache.spark.sql.execution.columnar.InMemoryTableScanExec import org.apache.spark.sql.internal.SQLConf +import org.apache.spark.sql.jdbc.H2Dialect import org.apache.spark.sql.test.SharedSparkSession import org.apache.spark.sql.types._ import org.apache.spark.sql.util.CaseInsensitiveStringMap @@ -229,9 +233,14 @@ class JDBCTableCatalogSuite extends SharedSparkSession { } } - test("SPARK-58945: H2 loadTable reports unavailable search path") { - val e = intercept[AnalysisException] { - tableCatalog.loadTable(Identifier.of(Array("test"), "not_existing_table")) + test("SPARK-58945: H2 dialect supplies searchPath for TABLE_OR_VIEW_NOT_FOUND") { + val e = intercept[NoSuchTableException] { + H2Dialect().classifyException( + new SQLException("""Table "NOT_EXISTING_TABLE" not found""", "42S02", 42102), + condition = "FAILED_JDBC.LOAD_TABLE", + messageParameters = Map("tableName" -> "`test`.`not_existing_table`"), + description = "Failed to load table: [test, not_existing_table]", + isRuntime = false) } checkErrorTableNotFoundWithSearchPath( e, From ec20e1574d2c140c76df6e46204d7e17066fec0d Mon Sep 17 00:00:00 2001 From: Subhramit Basu Date: Sun, 23 Aug 2026 11:13:31 +0000 Subject: [PATCH 06/24] SPARK-58945][SQL] Put imports in one line in JDBCTableCatalogSuite Signed-off-by: Subhramit Basu --- .../datasources/v2/jdbc/JDBCTableCatalogSuite.scala | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/sql/core/src/test/scala/org/apache/spark/sql/execution/datasources/v2/jdbc/JDBCTableCatalogSuite.scala b/sql/core/src/test/scala/org/apache/spark/sql/execution/datasources/v2/jdbc/JDBCTableCatalogSuite.scala index ac2f0a45e4761..429ff20203f87 100644 --- a/sql/core/src/test/scala/org/apache/spark/sql/execution/datasources/v2/jdbc/JDBCTableCatalogSuite.scala +++ b/sql/core/src/test/scala/org/apache/spark/sql/execution/datasources/v2/jdbc/JDBCTableCatalogSuite.scala @@ -25,10 +25,7 @@ import org.apache.logging.log4j.Level import org.apache.spark.{SparkConf, SparkIllegalArgumentException, SparkRuntimeException} import org.apache.spark.sql.{AnalysisException, Row} -import org.apache.spark.sql.catalyst.analysis.{ - NoSuchNamespaceException, - NoSuchTableException, - TableAlreadyExistsException} +import org.apache.spark.sql.catalyst.analysis.{NoSuchNamespaceException, NoSuchTableException, TableAlreadyExistsException} import org.apache.spark.sql.catalyst.parser.ParseException import org.apache.spark.sql.catalyst.util.CharVarcharUtils import org.apache.spark.sql.connector.catalog.{Identifier, TableSummary} From 7e7827012142637f4f1a027032ae6d6d78fd0da4 Mon Sep 17 00:00:00 2001 From: subhramit Date: Mon, 31 Aug 2026 08:08:48 +0530 Subject: [PATCH 07/24] [SPARK-58945][SQL] Fix CURSOR_OUTSIDE_SCRIPT message parameters Signed-off-by: subhramit --- .../utils/src/main/resources/error/error-conditions.json | 2 +- .../spark/sql/catalyst/analysis/ResolveCursors.scala | 5 +++-- .../spark/sql/scripting/SqlScriptingCursorE2eSuite.scala | 9 +++++++++ 3 files changed, 13 insertions(+), 3 deletions(-) diff --git a/common/utils/src/main/resources/error/error-conditions.json b/common/utils/src/main/resources/error/error-conditions.json index 599076dedf54b..64a3625ac7ac2 100644 --- a/common/utils/src/main/resources/error/error-conditions.json +++ b/common/utils/src/main/resources/error/error-conditions.json @@ -1826,7 +1826,7 @@ }, "CURSOR_OUTSIDE_SCRIPT" : { "message" : [ - "Cursor operations can only be used within SQL scripts." + "Cursor can only be used within SQL scripts." ], "sqlState" : "0A000" }, diff --git a/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/analysis/ResolveCursors.scala b/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/analysis/ResolveCursors.scala index f108dd3e74f45..cc97a1058141e 100644 --- a/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/analysis/ResolveCursors.scala +++ b/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/analysis/ResolveCursors.scala @@ -25,6 +25,7 @@ import org.apache.spark.sql.catalyst.expressions.{CursorReference, UnresolvedCur import org.apache.spark.sql.catalyst.plans.logical.LogicalPlan import org.apache.spark.sql.catalyst.rules.Rule import org.apache.spark.sql.catalyst.trees.TreePattern.UNRESOLVED_CURSOR +import org.apache.spark.sql.errors.DataTypeErrorsBase import org.apache.spark.sql.internal.SQLConf /** @@ -35,7 +36,7 @@ import org.apache.spark.sql.internal.SQLConf * 3. Looks up the cursor definition from the scripting context * 4. Fails early if cursor is not found */ -class ResolveCursors extends Rule[LogicalPlan] { +class ResolveCursors extends Rule[LogicalPlan] with DataTypeErrorsBase { override def apply(plan: LogicalPlan): LogicalPlan = plan.resolveExpressionsWithPruning( _.containsPattern(UNRESOLVED_CURSOR)) { @@ -82,7 +83,7 @@ class ResolveCursors extends Rule[LogicalPlan] { // Cursors are only allowed within SQL scripts throw new AnalysisException( errorClass = "CURSOR_OUTSIDE_SCRIPT", - messageParameters = Map("cursorName" -> nameParts.mkString("."))) + messageParameters = Map("cursorName" -> toSQLId(nameParts))) } // Use the SqlScriptingExecutionContextExtension API for cursor lookup diff --git a/sql/core/src/test/scala/org/apache/spark/sql/scripting/SqlScriptingCursorE2eSuite.scala b/sql/core/src/test/scala/org/apache/spark/sql/scripting/SqlScriptingCursorE2eSuite.scala index f93b75a7ef24a..fe35577822532 100644 --- a/sql/core/src/test/scala/org/apache/spark/sql/scripting/SqlScriptingCursorE2eSuite.scala +++ b/sql/core/src/test/scala/org/apache/spark/sql/scripting/SqlScriptingCursorE2eSuite.scala @@ -117,6 +117,15 @@ class SqlScriptingCursorE2eSuite extends SharedSparkSession { } } + test("SPARK-58945: OPEN cursor outside script reports cursor name") { + checkError( + exception = intercept[AnalysisException] { + sql("OPEN cur") + }, + condition = "CURSOR_OUTSIDE_SCRIPT", + parameters = Map("cursorName" -> "`cur`")) + } + test("Test 5: Cursors have a separate namespace from local variables") { val result = sql( """ From 6bd5bec19b6d4eab628502f715d4878a685bc44d Mon Sep 17 00:00:00 2001 From: subhramit Date: Mon, 31 Aug 2026 08:10:07 +0530 Subject: [PATCH 08/24] [SPARK-58945][SQL] Add cursor outside script test Signed-off-by: subhramit --- .../command/v2/CursorCommandUtilsSuite.scala | 35 +++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 sql/core/src/test/scala/org/apache/spark/sql/execution/command/v2/CursorCommandUtilsSuite.scala diff --git a/sql/core/src/test/scala/org/apache/spark/sql/execution/command/v2/CursorCommandUtilsSuite.scala b/sql/core/src/test/scala/org/apache/spark/sql/execution/command/v2/CursorCommandUtilsSuite.scala new file mode 100644 index 0000000000000..3a324a7ca7446 --- /dev/null +++ b/sql/core/src/test/scala/org/apache/spark/sql/execution/command/v2/CursorCommandUtilsSuite.scala @@ -0,0 +1,35 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.spark.sql.execution.command.v2 + +import org.apache.spark.SparkFunSuite +import org.apache.spark.sql.AnalysisException +import org.apache.spark.sql.catalyst.SqlScriptingContextManager + +class CursorCommandUtilsSuite extends SparkFunSuite { + + test("SPARK-58945: CursorCommandUtils reports cursor name outside scripts") { + assert(SqlScriptingContextManager.get().isEmpty) + checkError( + exception = intercept[AnalysisException] { + CursorCommandUtils.getScriptingContext("cur") + }, + condition = "CURSOR_OUTSIDE_SCRIPT", + parameters = Map("cursorName" -> "`cur`")) + } +} From e37e909bf534a49f1be030b32a9dc5a1b6ea4df4 Mon Sep 17 00:00:00 2001 From: subhramit Date: Mon, 31 Aug 2026 08:13:00 +0530 Subject: [PATCH 09/24] [SPARK-58945][SQL] Reuse empty search path rendering in H2Dialect Signed-off-by: subhramit --- .../catalyst/analysis/noSuchItemsExceptions.scala | 2 +- .../org/apache/spark/sql/jdbc/H2Dialect.scala | 14 +++++++++----- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/sql/api/src/main/scala/org/apache/spark/sql/catalyst/analysis/noSuchItemsExceptions.scala b/sql/api/src/main/scala/org/apache/spark/sql/catalyst/analysis/noSuchItemsExceptions.scala index 369aeef498c0b..d7963d377e5d9 100644 --- a/sql/api/src/main/scala/org/apache/spark/sql/catalyst/analysis/noSuchItemsExceptions.scala +++ b/sql/api/src/main/scala/org/apache/spark/sql/catalyst/analysis/noSuchItemsExceptions.scala @@ -23,7 +23,7 @@ import org.apache.spark.sql.catalyst.util.QuotingUtils.{quoted, quoteIdentifier, import org.apache.spark.sql.connector.catalog.Identifier import org.apache.spark.util.ArrayImplicits._ -private[analysis] object NoSuchItemExceptionHelper { +private[sql] object NoSuchItemExceptionHelper { /** Format a search path for TABLE_OR_VIEW_NOT_FOUND (e.g. [`cat`.`ns`]). */ def formatSearchPath(searchPath: Seq[String]): String = diff --git a/sql/core/src/main/scala/org/apache/spark/sql/jdbc/H2Dialect.scala b/sql/core/src/main/scala/org/apache/spark/sql/jdbc/H2Dialect.scala index 25727de1b003c..29cb519336672 100644 --- a/sql/core/src/main/scala/org/apache/spark/sql/jdbc/H2Dialect.scala +++ b/sql/core/src/main/scala/org/apache/spark/sql/jdbc/H2Dialect.scala @@ -26,7 +26,13 @@ import scala.jdk.CollectionConverters._ import scala.util.control.NonFatal import org.apache.spark.{SparkThrowable, SparkUnsupportedOperationException} -import org.apache.spark.sql.catalyst.analysis.{IndexAlreadyExistsException, NoSuchIndexException, NoSuchNamespaceException, NoSuchTableException, TableAlreadyExistsException} +import org.apache.spark.sql.catalyst.analysis.{ + IndexAlreadyExistsException, + NoSuchIndexException, + NoSuchItemExceptionHelper, + NoSuchNamespaceException, + NoSuchTableException, + TableAlreadyExistsException} import org.apache.spark.sql.connector.catalog.Identifier import org.apache.spark.sql.connector.catalog.functions.UnboundFunction import org.apache.spark.sql.connector.catalog.index.TableIndex @@ -230,10 +236,8 @@ private[sql] case class H2Dialect() extends JdbcDialect with NoLegacyJDBCError { errorClass = "TABLE_OR_VIEW_NOT_FOUND", messageParameters = Map( "relationName" -> relationName, - // classifyException receives only pre-rendered strings, so no Spark-side - // search path exists here; "not available" matches the rendering used for - // an empty search path. - "searchPath" -> "not available"), + // Use the shared empty-search-path rendering for this dialect-classification path. + "searchPath" -> NoSuchItemExceptionHelper.formatSearchPath(Seq.empty)), cause = Some(e)) // SCHEMA_NOT_FOUND_1 case 90079 => From 9a4764181e4216176ab2c260ab6e7074f744c602 Mon Sep 17 00:00:00 2001 From: subhramit Date: Mon, 31 Aug 2026 08:21:43 +0530 Subject: [PATCH 10/24] [SPARK-58945][SQL] Use csv in invalid extension errors Signed-off-by: subhramit --- .../spark/sql/catalyst/csv/CSVOptions.scala | 2 +- .../errors/QueryExecutionErrorsSuite.scala | 32 ++++++++++--------- 2 files changed, 18 insertions(+), 16 deletions(-) diff --git a/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/csv/CSVOptions.scala b/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/csv/CSVOptions.scala index 7db03a8a23231..43746b3663bfd 100644 --- a/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/csv/CSVOptions.scala +++ b/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/csv/CSVOptions.scala @@ -125,7 +125,7 @@ class CSVOptions( val extension = { val ext = parameters.getOrElse(EXTENSION, "csv") if (ext.size != 3 && !ext.forall(_.isLetter)) { - throw QueryExecutionErrors.invalidFileExtensionError(EXTENSION, ext) + throw QueryExecutionErrors.invalidFileExtensionError("csv", ext) } ext diff --git a/sql/core/src/test/scala/org/apache/spark/sql/errors/QueryExecutionErrorsSuite.scala b/sql/core/src/test/scala/org/apache/spark/sql/errors/QueryExecutionErrorsSuite.scala index 78d3c44109a04..5352bc754ef7b 100644 --- a/sql/core/src/test/scala/org/apache/spark/sql/errors/QueryExecutionErrorsSuite.scala +++ b/sql/core/src/test/scala/org/apache/spark/sql/errors/QueryExecutionErrorsSuite.scala @@ -141,21 +141,6 @@ class QueryExecutionErrorsSuite (df1, df2) } - test("SPARK-58945: invalid file extension reports invalidValue") { - withTempDir { dir => - val path = new File(dir, "data").getCanonicalPath - checkError( - exception = intercept[SparkIllegalArgumentException] { - spark.range(1).write.option("extension", "12").csv(path) - }, - condition = "INVALID_PARAMETER_VALUE.EXTENSION", - parameters = Map( - "functionName" -> "`extension`", - "parameter" -> "`extension`", - "invalidValue" -> "`12`")) - } - } - test("INVALID_PARAMETER_VALUE.AES_KEY_LENGTH: invalid key lengths in AES functions") { val (df1, df2) = getAesInputs() def checkInvalidKeyLength(df: => DataFrame, inputBytes: Int): Unit = { @@ -242,6 +227,23 @@ class QueryExecutionErrorsSuite "CBC", "NoPadding") } + test("SPARK-58945: invalid file extension reports invalidValue") { + withTempDir { dir => + val path = new File(dir, "data").getCanonicalPath + // Use a value that is unambiguously invalid so this test focuses on the + // rendered error message rather than the full extension validation matrix. + checkError( + exception = intercept[SparkIllegalArgumentException] { + spark.range(1).write.option("extension", "12").csv(path) + }, + condition = "INVALID_PARAMETER_VALUE.EXTENSION", + parameters = Map( + "functionName" -> "`csv`", + "parameter" -> "`extension`", + "invalidValue" -> "`12`")) + } + } + test("UNSUPPORTED_FEATURE: unsupported types (map and struct) in lit()") { def checkUnsupportedTypeInLiteral(v: Any, literal: String, dataType: String): Unit = { checkError( From bdec4c9b1d321d483885612f2d1e361e155e68d8 Mon Sep 17 00:00:00 2001 From: subhramit Date: Mon, 31 Aug 2026 08:24:32 +0530 Subject: [PATCH 11/24] [SPARK-58945][SQL] Move error parameter tests to owning suite Signed-off-by: subhramit --- .../errors/QueryCompilationErrorsSuite.scala | 9 +++++++ .../errors/QueryExecutionErrorsSuite.scala | 8 ++++++ .../state/StateStoreErrorsSuite.scala} | 26 +++---------------- 3 files changed, 21 insertions(+), 22 deletions(-) rename sql/core/src/test/scala/org/apache/spark/sql/{errors/ErrorMessageParametersSuite.scala => execution/streaming/state/StateStoreErrorsSuite.scala} (53%) diff --git a/sql/core/src/test/scala/org/apache/spark/sql/errors/QueryCompilationErrorsSuite.scala b/sql/core/src/test/scala/org/apache/spark/sql/errors/QueryCompilationErrorsSuite.scala index 7ec699353e687..e9fa56648cd30 100644 --- a/sql/core/src/test/scala/org/apache/spark/sql/errors/QueryCompilationErrorsSuite.scala +++ b/sql/core/src/test/scala/org/apache/spark/sql/errors/QueryCompilationErrorsSuite.scala @@ -20,6 +20,7 @@ package org.apache.spark.sql.errors import java.util.IllegalFormatException import org.apache.spark.{SPARK_DOC_ROOT, SparkIllegalArgumentException, SparkUnsupportedOperationException} +import org.apache.spark.sql.catalyst.catalog.InvalidUDFClassException import org.apache.spark.sql._ import org.apache.spark.sql.api.java.{UDF1, UDF2, UDF23Test} import org.apache.spark.sql.catalyst.TableIdentifier @@ -283,6 +284,14 @@ class QueryCompilationErrorsSuite sqlState = "0A000") } + test("SPARK-58945: invalid UDF class error reports clazz") { + checkError( + exception = QueryCompilationErrors.invalidUDFClassError("example.InvalidFunction") + .asInstanceOf[InvalidUDFClassException], + condition = "_LEGACY_ERROR_TEMP_2450", + parameters = Map("clazz" -> "example.InvalidFunction")) + } + test("GROUPING_COLUMN_MISMATCH: not found the grouping column") { val groupingColMismatchEx = intercept[AnalysisException] { courseSales.cube("course", "year").agg(grouping("earnings")).explain() diff --git a/sql/core/src/test/scala/org/apache/spark/sql/errors/QueryExecutionErrorsSuite.scala b/sql/core/src/test/scala/org/apache/spark/sql/errors/QueryExecutionErrorsSuite.scala index 5352bc754ef7b..03b932710aa7f 100644 --- a/sql/core/src/test/scala/org/apache/spark/sql/errors/QueryExecutionErrorsSuite.scala +++ b/sql/core/src/test/scala/org/apache/spark/sql/errors/QueryExecutionErrorsSuite.scala @@ -244,6 +244,14 @@ class QueryExecutionErrorsSuite } } + test("SPARK-58945: invalid writer commit message reports detail") { + checkError( + exception = QueryExecutionErrors.invalidWriterCommitMessageError("zero") + .asInstanceOf[SparkRuntimeException], + condition = "INVALID_WRITER_COMMIT_MESSAGE", + parameters = Map("detail" -> "zero")) + } + test("UNSUPPORTED_FEATURE: unsupported types (map and struct) in lit()") { def checkUnsupportedTypeInLiteral(v: Any, literal: String, dataType: String): Unit = { checkError( diff --git a/sql/core/src/test/scala/org/apache/spark/sql/errors/ErrorMessageParametersSuite.scala b/sql/core/src/test/scala/org/apache/spark/sql/execution/streaming/state/StateStoreErrorsSuite.scala similarity index 53% rename from sql/core/src/test/scala/org/apache/spark/sql/errors/ErrorMessageParametersSuite.scala rename to sql/core/src/test/scala/org/apache/spark/sql/execution/streaming/state/StateStoreErrorsSuite.scala index 6b33805a945a8..564a9b21e3695 100644 --- a/sql/core/src/test/scala/org/apache/spark/sql/errors/ErrorMessageParametersSuite.scala +++ b/sql/core/src/test/scala/org/apache/spark/sql/execution/streaming/state/StateStoreErrorsSuite.scala @@ -15,33 +15,15 @@ * limitations under the License. */ -package org.apache.spark.sql.errors +package org.apache.spark.sql.execution.streaming.state -import org.apache.spark.{SparkFunSuite, SparkRuntimeException} -import org.apache.spark.sql.catalyst.catalog.InvalidUDFClassException -import org.apache.spark.sql.execution.streaming.state.StateStoreColumnFamilyMismatch +import org.apache.spark.SparkFunSuite -class ErrorMessageParametersSuite extends SparkFunSuite { - - test("SPARK-58945: invalid writer commit message reports detail") { - checkError( - exception = QueryExecutionErrors.invalidWriterCommitMessageError("zero") - .asInstanceOf[SparkRuntimeException], - condition = "INVALID_WRITER_COMMIT_MESSAGE", - parameters = Map("detail" -> "zero")) - } - - test("SPARK-58945: invalid UDF class error reports clazz") { - checkError( - exception = QueryCompilationErrors.invalidUDFClassError("example.InvalidFunction") - .asInstanceOf[InvalidUDFClassException], - condition = "_LEGACY_ERROR_TEMP_2450", - parameters = Map("clazz" -> "example.InvalidFunction")) - } +class StateStoreErrorsSuite extends SparkFunSuite { test("SPARK-58945: state store mismatch reports schema details") { checkError( - exception = new StateStoreColumnFamilyMismatch( + exception = StateStoreErrors.stateStoreColumnFamilyMismatch( "state", "old_schema", "new_schema"), condition = "STATE_STORE_COLUMN_FAMILY_SCHEMA_INCOMPATIBLE", parameters = Map( From 4faca26186b2923288d3aec34e8378c46f3acbe7 Mon Sep 17 00:00:00 2001 From: subhramit Date: Mon, 31 Aug 2026 08:57:13 +0530 Subject: [PATCH 12/24] [SPARK-58945][SQL] Fix import order in QueryCompilationErrorsSuite Signed-off-by: subhramit --- .../apache/spark/sql/errors/QueryCompilationErrorsSuite.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql/core/src/test/scala/org/apache/spark/sql/errors/QueryCompilationErrorsSuite.scala b/sql/core/src/test/scala/org/apache/spark/sql/errors/QueryCompilationErrorsSuite.scala index e9fa56648cd30..e8c466f229fce 100644 --- a/sql/core/src/test/scala/org/apache/spark/sql/errors/QueryCompilationErrorsSuite.scala +++ b/sql/core/src/test/scala/org/apache/spark/sql/errors/QueryCompilationErrorsSuite.scala @@ -20,8 +20,8 @@ package org.apache.spark.sql.errors import java.util.IllegalFormatException import org.apache.spark.{SPARK_DOC_ROOT, SparkIllegalArgumentException, SparkUnsupportedOperationException} -import org.apache.spark.sql.catalyst.catalog.InvalidUDFClassException import org.apache.spark.sql._ +import org.apache.spark.sql.catalyst.catalog.InvalidUDFClassException import org.apache.spark.sql.api.java.{UDF1, UDF2, UDF23Test} import org.apache.spark.sql.catalyst.TableIdentifier import org.apache.spark.sql.catalyst.catalog.{CatalogStorageFormat, CatalogTable, CatalogTableType} From 4886995e4754edce47d45831e41be9fd855c805e Mon Sep 17 00:00:00 2001 From: subhramit Date: Mon, 31 Aug 2026 09:09:12 +0530 Subject: [PATCH 13/24] [SPARK-58945][SQL] Lint: Group imports in QueryCompilationErrorsSuite Signed-off-by: subhramit --- .../apache/spark/sql/errors/QueryCompilationErrorsSuite.scala | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/sql/core/src/test/scala/org/apache/spark/sql/errors/QueryCompilationErrorsSuite.scala b/sql/core/src/test/scala/org/apache/spark/sql/errors/QueryCompilationErrorsSuite.scala index e8c466f229fce..f0573d7a97d7f 100644 --- a/sql/core/src/test/scala/org/apache/spark/sql/errors/QueryCompilationErrorsSuite.scala +++ b/sql/core/src/test/scala/org/apache/spark/sql/errors/QueryCompilationErrorsSuite.scala @@ -21,10 +21,9 @@ import java.util.IllegalFormatException import org.apache.spark.{SPARK_DOC_ROOT, SparkIllegalArgumentException, SparkUnsupportedOperationException} import org.apache.spark.sql._ -import org.apache.spark.sql.catalyst.catalog.InvalidUDFClassException import org.apache.spark.sql.api.java.{UDF1, UDF2, UDF23Test} import org.apache.spark.sql.catalyst.TableIdentifier -import org.apache.spark.sql.catalyst.catalog.{CatalogStorageFormat, CatalogTable, CatalogTableType} +import org.apache.spark.sql.catalyst.catalog.{CatalogStorageFormat, CatalogTable, CatalogTableType, InvalidUDFClassException} import org.apache.spark.sql.catalyst.expressions.{Coalesce, Literal, UnsafeRow} import org.apache.spark.sql.catalyst.parser.ParseException import org.apache.spark.sql.execution.datasources.SaveIntoDataSourceCommand From 7e4262ac71f6b68adbf445e07b68b67f041b79ad Mon Sep 17 00:00:00 2001 From: subhramit Date: Fri, 4 Sep 2026 23:16:39 +0530 Subject: [PATCH 14/24] [SPARK-58945][SQL] Fix H2 rename table-not-found error Signed-off-by: subhramit --- .../scala/org/apache/spark/sql/jdbc/H2Dialect.scala | 3 ++- .../datasources/v2/jdbc/JDBCTableCatalogSuite.scala | 11 ++++------- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/sql/core/src/main/scala/org/apache/spark/sql/jdbc/H2Dialect.scala b/sql/core/src/main/scala/org/apache/spark/sql/jdbc/H2Dialect.scala index 29cb519336672..a06f7ad0e028b 100644 --- a/sql/core/src/main/scala/org/apache/spark/sql/jdbc/H2Dialect.scala +++ b/sql/core/src/main/scala/org/apache/spark/sql/jdbc/H2Dialect.scala @@ -231,7 +231,8 @@ private[sql] case class H2Dialect() extends JdbcDialect with NoLegacyJDBCError { cause = Some(e)) // TABLE_OR_VIEW_NOT_FOUND_1 case 42102 => - val relationName = messageParameters.getOrElse("tableName", "") + val relationName = messageParameters + .getOrElse("tableName", messageParameters.getOrElse("oldName", "")) throw new NoSuchTableException( errorClass = "TABLE_OR_VIEW_NOT_FOUND", messageParameters = Map( diff --git a/sql/core/src/test/scala/org/apache/spark/sql/execution/datasources/v2/jdbc/JDBCTableCatalogSuite.scala b/sql/core/src/test/scala/org/apache/spark/sql/execution/datasources/v2/jdbc/JDBCTableCatalogSuite.scala index 429ff20203f87..1c5ac9a4b7e25 100644 --- a/sql/core/src/test/scala/org/apache/spark/sql/execution/datasources/v2/jdbc/JDBCTableCatalogSuite.scala +++ b/sql/core/src/test/scala/org/apache/spark/sql/execution/datasources/v2/jdbc/JDBCTableCatalogSuite.scala @@ -230,14 +230,11 @@ class JDBCTableCatalogSuite extends SharedSparkSession { } } - test("SPARK-58945: H2 dialect supplies searchPath for TABLE_OR_VIEW_NOT_FOUND") { + test("SPARK-58945: H2 renameTable reports source table when it is missing") { val e = intercept[NoSuchTableException] { - H2Dialect().classifyException( - new SQLException("""Table "NOT_EXISTING_TABLE" not found""", "42S02", 42102), - condition = "FAILED_JDBC.LOAD_TABLE", - messageParameters = Map("tableName" -> "`test`.`not_existing_table`"), - description = "Failed to load table: [test, not_existing_table]", - isRuntime = false) + tableCatalog.renameTable( + Identifier.of(Array("test"), "not_existing_table"), + Identifier.of(Array("test"), "dst_table")) } checkErrorTableNotFoundWithSearchPath( e, From b524b6ed0c5bcfc6b194c9d3f506350724d60151 Mon Sep 17 00:00:00 2001 From: subhramit Date: Fri, 4 Sep 2026 23:25:49 +0530 Subject: [PATCH 15/24] [SPARK-58945][SQL] Fix semi-structured parse syntax error params Signed-off-by: subhramit --- .../org/apache/spark/sql/catalyst/parser/AstBuilder.scala | 5 ++++- .../spark/sql/catalyst/parser/ExpressionParserSuite.scala | 7 +++++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/parser/AstBuilder.scala b/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/parser/AstBuilder.scala index d65a9c7a36442..9d8f165b8ec6a 100644 --- a/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/parser/AstBuilder.scala +++ b/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/parser/AstBuilder.scala @@ -4539,7 +4539,10 @@ class AstBuilder extends DataTypeAstBuilder val path = if (field.startsWith("[")) "$" + field else s"$$.$field" val parsedPath = JsonPathParser.parse(path) if (parsedPath.isEmpty) { - throw new ParseException(errorClass = "PARSE_SYNTAX_ERROR", ctx = ctx) + throw new ParseException( + errorClass = "PARSE_SYNTAX_ERROR", + messageParameters = Map("error" -> s"'$field'", "hint" -> ""), + ctx = ctx) } val potentialAlias = parsedPath.get.collect { case Named(name) => name }.lastOption val node = SemiStructuredExtract(expression(ctx.col), path) diff --git a/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/parser/ExpressionParserSuite.scala b/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/parser/ExpressionParserSuite.scala index d46c85d8ed093..9d7bb30b9496a 100644 --- a/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/parser/ExpressionParserSuite.scala +++ b/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/parser/ExpressionParserSuite.scala @@ -282,6 +282,13 @@ class ExpressionParserSuite extends AnalysisTest { assertEqual("a is not distinct from b", $"a" <=> $"b") } + test("invalid semi-structured extract path") { + checkError( + exception = parseException("c:['']"), + condition = "PARSE_SYNTAX_ERROR", + parameters = Map("error" -> "'[''']'", "hint" -> "")) + } + test("binary arithmetic expressions") { // Simple operations assertEqual("a * b", $"a" * $"b") From 2c7626a30adc855b75a11beb85b4b74f19ef67d9 Mon Sep 17 00:00:00 2001 From: subhramit Date: Fri, 4 Sep 2026 23:59:21 +0530 Subject: [PATCH 16/24] [SPARK-58945][SQL] Remove obsolete imports in JDBCTableCatalogSuite Signed-off-by: subhramit --- .../execution/datasources/v2/jdbc/JDBCTableCatalogSuite.scala | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/sql/core/src/test/scala/org/apache/spark/sql/execution/datasources/v2/jdbc/JDBCTableCatalogSuite.scala b/sql/core/src/test/scala/org/apache/spark/sql/execution/datasources/v2/jdbc/JDBCTableCatalogSuite.scala index 1c5ac9a4b7e25..f9db5ef1ec9de 100644 --- a/sql/core/src/test/scala/org/apache/spark/sql/execution/datasources/v2/jdbc/JDBCTableCatalogSuite.scala +++ b/sql/core/src/test/scala/org/apache/spark/sql/execution/datasources/v2/jdbc/JDBCTableCatalogSuite.scala @@ -16,7 +16,7 @@ */ package org.apache.spark.sql.execution.datasources.v2.jdbc -import java.sql.{Connection, DriverManager, SQLException} +import java.sql.{Connection, DriverManager} import java.util.Properties import scala.jdk.CollectionConverters._ @@ -32,7 +32,6 @@ import org.apache.spark.sql.connector.catalog.{Identifier, TableSummary} import org.apache.spark.sql.errors.DataTypeErrors.{toSQLConf, toSQLStmt} import org.apache.spark.sql.execution.columnar.InMemoryTableScanExec import org.apache.spark.sql.internal.SQLConf -import org.apache.spark.sql.jdbc.H2Dialect import org.apache.spark.sql.test.SharedSparkSession import org.apache.spark.sql.types._ import org.apache.spark.sql.util.CaseInsensitiveStringMap From 856cc118422aa950e5de3d7014213ff71df48830 Mon Sep 17 00:00:00 2001 From: subhramit Date: Sat, 5 Sep 2026 07:39:52 +0530 Subject: [PATCH 17/24] [SPARK-58945][SQL] Fix semi-structured extract parser test Signed-off-by: subhramit --- .../spark/sql/catalyst/parser/ExpressionParserSuite.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/parser/ExpressionParserSuite.scala b/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/parser/ExpressionParserSuite.scala index 9d7bb30b9496a..252bc3c9658ed 100644 --- a/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/parser/ExpressionParserSuite.scala +++ b/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/parser/ExpressionParserSuite.scala @@ -286,7 +286,7 @@ class ExpressionParserSuite extends AnalysisTest { checkError( exception = parseException("c:['']"), condition = "PARSE_SYNTAX_ERROR", - parameters = Map("error" -> "'[''']'", "hint" -> "")) + parameters = Map("error" -> "'['']'", "hint" -> "")) } test("binary arithmetic expressions") { From fecb36eb7234a5ee67ef9c5e2988e34f2f1609d8 Mon Sep 17 00:00:00 2001 From: subhramit Date: Sat, 5 Sep 2026 08:25:57 +0530 Subject: [PATCH 18/24] [SPARK-58945][SQL] Assert semi-structured extract parse context Signed-off-by: subhramit --- .../spark/sql/catalyst/parser/ExpressionParserSuite.scala | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/parser/ExpressionParserSuite.scala b/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/parser/ExpressionParserSuite.scala index 252bc3c9658ed..4b2db7feab491 100644 --- a/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/parser/ExpressionParserSuite.scala +++ b/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/parser/ExpressionParserSuite.scala @@ -286,7 +286,8 @@ class ExpressionParserSuite extends AnalysisTest { checkError( exception = parseException("c:['']"), condition = "PARSE_SYNTAX_ERROR", - parameters = Map("error" -> "'['']'", "hint" -> "")) + parameters = Map("error" -> "'['']'", "hint" -> ""), + queryContext = Array(ExpectedContext("c:['']", 0, 5))) } test("binary arithmetic expressions") { From c4237cfb60522dd445bb822042f2f4f73832a3d0 Mon Sep 17 00:00:00 2001 From: subhramit Date: Sat, 5 Sep 2026 08:30:48 +0530 Subject: [PATCH 19/24] [SPARK-58945][SQL] Fix non-foldable interval input error params Signed-off-by: subhramit --- .../aggregate/ApproxCountDistinctForIntervals.scala | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/expressions/aggregate/ApproxCountDistinctForIntervals.scala b/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/expressions/aggregate/ApproxCountDistinctForIntervals.scala index e5e798495c199..df8c99bbc9fd2 100644 --- a/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/expressions/aggregate/ApproxCountDistinctForIntervals.scala +++ b/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/expressions/aggregate/ApproxCountDistinctForIntervals.scala @@ -86,7 +86,8 @@ case class ApproxCountDistinctForIntervals( errorSubClass = "NON_FOLDABLE_INPUT", messageParameters = Map( "inputName" -> toSQLId("endpointsExpression"), - "inputType" -> toSQLType(endpointsExpression.dataType))) + "inputType" -> toSQLType(endpointsExpression.dataType), + "inputExpr" -> toSQLExpr(endpointsExpression))) } else { endpointsExpression.dataType match { case ArrayType(_: NumericType | DateType | TimestampType | TimestampNTZType | From 9059389198686ade214f0d8b0c6e0179e192add4 Mon Sep 17 00:00:00 2001 From: subhramit Date: Sat, 5 Sep 2026 08:33:32 +0530 Subject: [PATCH 20/24] [SPARK-58945][SQL] Update interval input error test expectations Signed-off-by: subhramit --- .../aggregate/ApproxCountDistinctForIntervalsSuite.scala | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/expressions/aggregate/ApproxCountDistinctForIntervalsSuite.scala b/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/expressions/aggregate/ApproxCountDistinctForIntervalsSuite.scala index b7eb0d26c0b46..eba5124c587db 100644 --- a/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/expressions/aggregate/ApproxCountDistinctForIntervalsSuite.scala +++ b/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/expressions/aggregate/ApproxCountDistinctForIntervalsSuite.scala @@ -75,7 +75,8 @@ class ApproxCountDistinctForIntervalsSuite extends SparkFunSuite { errorSubClass = "NON_FOLDABLE_INPUT", messageParameters = Map( "inputName" -> "`endpointsExpression`", - "inputType" -> "\"ARRAY\""))) + "inputType" -> "\"ARRAY\"", + "inputExpr" -> "\"array(b)\""))) wrongEndpoints = ApproxCountDistinctForIntervals( AttributeReference("a", DoubleType)(), From d2809f8375a0031cae79ad2e56738a946366d6ca Mon Sep 17 00:00:00 2001 From: subhramit Date: Sat, 5 Sep 2026 09:07:24 +0530 Subject: [PATCH 21/24] Retrigger CI Signed-off-by: subhramit From a2f3be1e3d6446aabd398d7013290009939540a0 Mon Sep 17 00:00:00 2001 From: subhramit Date: Sat, 5 Sep 2026 13:31:46 +0530 Subject: [PATCH 22/24] Retrigger CI Signed-off-by: subhramit From fe4db406cf5618794634d66e54e835e6a14796f1 Mon Sep 17 00:00:00 2001 From: subhramit Date: Sat, 5 Sep 2026 16:00:00 +0530 Subject: [PATCH 23/24] Retrigger CI again Signed-off-by: subhramit From 54d369c24005bc8bc7233c188a9fbb9244ba7c61 Mon Sep 17 00:00:00 2001 From: subhramit Date: Sun, 6 Sep 2026 00:04:20 +0530 Subject: [PATCH 24/24] Retrigger CI Signed-off-by: subhramit