Skip to content

Commit c6713ce

Browse files
committed
Merge branch 'upmaster' into SPARK-36970
2 parents 1bc02ad + 73edf31 commit c6713ce

File tree

60 files changed

+1295
-198
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

60 files changed

+1295
-198
lines changed

core/src/main/resources/error/error-classes.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@
9090
"message" : [ "Key %s does not exist." ]
9191
},
9292
"MISSING_COLUMN" : {
93-
"message" : [ "cannot resolve '%s' given input columns: [%s]" ],
93+
"message" : [ "Column '%s' does not exist. Did you mean one of the following? [%s]" ],
9494
"sqlState" : "42000"
9595
},
9696
"MISSING_STATIC_PARTITION_COLUMN" : {

core/src/test/scala/org/apache/spark/SparkThrowableSuite.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -128,8 +128,8 @@ class SparkThrowableSuite extends SparkFunSuite {
128128
}
129129

130130
test("Error message is formatted") {
131-
assert(getMessage("MISSING_COLUMN", Array("foo", "bar")) ==
132-
"cannot resolve 'foo' given input columns: [bar]")
131+
assert(getMessage("MISSING_COLUMN", Array("foo", "bar, baz")) ==
132+
"Column 'foo' does not exist. Did you mean one of the following? [bar, baz]")
133133
}
134134

135135
test("Try catching legacy SparkError") {

python/pyspark/pandas/tests/test_indexops_spark.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ def test_series_transform_negative(self):
3939
):
4040
self.psser.spark.transform(lambda scol: 1)
4141

42-
with self.assertRaisesRegex(AnalysisException, "cannot resolve.*non-existent.*"):
42+
with self.assertRaisesRegex(AnalysisException, "Column.*non-existent.*does not exist"):
4343
self.psser.spark.transform(lambda scol: F.col("non-existent"))
4444

4545
def test_multiindex_transform_negative(self):
@@ -59,7 +59,7 @@ def test_series_apply_negative(self):
5959
):
6060
self.psser.spark.apply(lambda scol: 1)
6161

62-
with self.assertRaisesRegex(AnalysisException, "cannot resolve.*non-existent.*"):
62+
with self.assertRaisesRegex(AnalysisException, "Column.*non-existent.*does not exist"):
6363
self.psser.spark.transform(lambda scol: F.col("non-existent"))
6464

6565

python/pyspark/sql/tests/test_utils.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ def test_capture_user_friendly_exception(self):
3131
try:
3232
self.spark.sql("select `中文字段`")
3333
except AnalysisException as e:
34-
self.assertRegex(str(e), "cannot resolve '`中文字段`'")
34+
self.assertRegex(str(e), "Column '`中文字段`' does not exist")
3535

3636
def test_capture_parse_exception(self):
3737
self.assertRaises(ParseException, lambda: self.spark.sql("abc"))

sql/catalyst/src/main/antlr4/org/apache/spark/sql/catalyst/parser/SqlBase.g4

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,8 @@ singleTableSchema
106106
statement
107107
: query #statementDefault
108108
| ctes? dmlStatementNoWith #dmlStatement
109-
| USE NAMESPACE? multipartIdentifier #use
109+
| USE multipartIdentifier #use
110+
| USE NAMESPACE multipartIdentifier #useNamespace
110111
| SET CATALOG (identifier | STRING) #setCatalog
111112
| CREATE namespace (IF NOT EXISTS)? multipartIdentifier
112113
(commentSpec |

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

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ import org.apache.spark.sql.catalyst.expressions.aggregate.AggregateExpression
2525
import org.apache.spark.sql.catalyst.optimizer.BooleanSimplification
2626
import org.apache.spark.sql.catalyst.plans._
2727
import org.apache.spark.sql.catalyst.plans.logical._
28-
import org.apache.spark.sql.catalyst.util.{CharVarcharUtils, TypeUtils}
28+
import org.apache.spark.sql.catalyst.util.{CharVarcharUtils, StringUtils, TypeUtils}
2929
import org.apache.spark.sql.connector.catalog.{LookupCatalog, SupportsPartitionManagement}
3030
import org.apache.spark.sql.errors.{QueryCompilationErrors, QueryExecutionErrors}
3131
import org.apache.spark.sql.internal.SQLConf
@@ -167,9 +167,12 @@ trait CheckAnalysis extends PredicateHelper with LookupCatalog {
167167

168168
operator transformExpressionsUp {
169169
case a: Attribute if !a.resolved =>
170-
val from = operator.inputSet.toSeq.map(_.qualifiedName).mkString(", ")
171-
// cannot resolve '${a.sql}' given input columns: [$from]
172-
a.failAnalysis(errorClass = "MISSING_COLUMN", messageParameters = Array(a.sql, from))
170+
val missingCol = a.sql
171+
val candidates = operator.inputSet.toSeq.map(_.qualifiedName)
172+
val orderedCandidates = StringUtils.orderStringsBySimilarity(missingCol, candidates)
173+
a.failAnalysis(
174+
errorClass = "MISSING_COLUMN",
175+
messageParameters = Array(missingCol, orderedCandidates.mkString(", ")))
173176

174177
case s: Star =>
175178
withPosition(s) {

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

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -82,15 +82,6 @@ class ResolveCatalogs(val catalogManager: CatalogManager)
8282
convertTableProperties(c),
8383
writeOptions = c.writeOptions,
8484
orCreate = c.orCreate)
85-
86-
case UseStatement(isNamespaceSet, nameParts) =>
87-
if (isNamespaceSet) {
88-
SetCatalogAndNamespace(catalogManager, None, Some(nameParts))
89-
} else {
90-
val CatalogAndNamespace(catalog, ns) = nameParts
91-
val namespace = if (ns.nonEmpty) Some(ns) else None
92-
SetCatalogAndNamespace(catalogManager, Some(catalog.name()), namespace)
93-
}
9485
}
9586

9687
object NonSessionCatalogAndTable {

sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/parser/AstBuilder.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3565,11 +3565,11 @@ class AstBuilder extends SqlBaseBaseVisitor[AnyRef] with SQLConfHelper with Logg
35653565
}
35663566

35673567
/**
3568-
* Create a [[UseStatement]] logical plan.
3568+
* Create a [[SetCatalogAndNamespace]] command.
35693569
*/
35703570
override def visitUse(ctx: UseContext): LogicalPlan = withOrigin(ctx) {
35713571
val nameParts = visitMultipartIdentifier(ctx.multipartIdentifier)
3572-
UseStatement(ctx.NAMESPACE != null, nameParts)
3572+
SetCatalogAndNamespace(UnresolvedDBObjectName(nameParts, isNamespace = true))
35733573
}
35743574

35753575
/**

sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/plans/logical/statements.scala

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -272,8 +272,3 @@ case class InsertIntoStatement(
272272
override protected def withNewChildInternal(newChild: LogicalPlan): InsertIntoStatement =
273273
copy(query = newChild)
274274
}
275-
276-
/**
277-
* A USE statement, as parsed from SQL.
278-
*/
279-
case class UseStatement(isNamespaceSet: Boolean, nameParts: Seq[String]) extends LeafParsedStatement

sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/plans/logical/v2Commands.scala

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -622,12 +622,13 @@ object ShowViews {
622622
}
623623

624624
/**
625-
* The logical plan of the USE/USE NAMESPACE command.
625+
* The logical plan of the USE command.
626626
*/
627-
case class SetCatalogAndNamespace(
628-
catalogManager: CatalogManager,
629-
catalogName: Option[String],
630-
namespace: Option[Seq[String]]) extends LeafCommand
627+
case class SetCatalogAndNamespace(child: LogicalPlan) extends UnaryCommand {
628+
override protected def withNewChildInternal(newChild: LogicalPlan): SetCatalogAndNamespace = {
629+
copy(child = newChild)
630+
}
631+
}
631632

632633
/**
633634
* The logical plan of the REFRESH TABLE command.

0 commit comments

Comments
 (0)