Skip to content

Commit 3f22ef1

Browse files
cloud-fanRui Wang
andcommitted
[SPARK-49246][SQL][FOLLOW-UP] The behavior of SaveAsTable should not be changed by falling back to v1 command
This is a followup of #47772 . The behavior of SaveAsTable should not be changed by switching v1 to v2 command. This is similar to #47995. For the case of `DelegatingCatalogExtension` we need it goes to V1 commands to be consistent with previous behavior. Behavior regression. No UT No Closes #48019 from amaliujia/regress_v2. Lead-authored-by: Wenchen Fan <[email protected]> Co-authored-by: Rui Wang <[email protected]> Signed-off-by: Wenchen Fan <[email protected]> (cherry picked from commit 37b39b4) Signed-off-by: Wenchen Fan <[email protected]>
1 parent 46214da commit 3f22ef1

3 files changed

Lines changed: 19 additions & 14 deletions

File tree

sql/core/src/main/scala/org/apache/spark/sql/DataFrameWriter.scala

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -565,8 +565,10 @@ final class DataFrameWriter[T] private[sql](ds: Dataset[T]) {
565565
import org.apache.spark.sql.connector.catalog.CatalogV2Implicits._
566566

567567
val session = df.sparkSession
568-
val canUseV2 = lookupV2Provider().isDefined ||
569-
df.sparkSession.sessionState.conf.getConf(SQLConf.V2_SESSION_CATALOG_IMPLEMENTATION).isDefined
568+
val canUseV2 = lookupV2Provider().isDefined || (df.sparkSession.sessionState.conf.getConf(
569+
SQLConf.V2_SESSION_CATALOG_IMPLEMENTATION).isDefined &&
570+
!df.sparkSession.sessionState.catalogManager.catalog(CatalogManager.SESSION_CATALOG_NAME)
571+
.isInstanceOf[DelegatingCatalogExtension])
570572

571573
session.sessionState.sqlParser.parseMultipartIdentifier(tableName) match {
572574
case nameParts @ NonSessionCatalogAndIdentifier(catalog, ident) =>

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

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,8 +55,7 @@ class DataSourceV2DataFrameSessionCatalogSuite
5555
"and a same-name temp view exist") {
5656
withTable("same_name") {
5757
withTempView("same_name") {
58-
val format = spark.sessionState.conf.defaultDataSourceName
59-
sql(s"CREATE TABLE same_name(id LONG) USING $format")
58+
sql(s"CREATE TABLE same_name(id LONG) USING $v2Format")
6059
spark.range(10).createTempView("same_name")
6160
spark.range(20).write.format(v2Format).mode(SaveMode.Append).saveAsTable("same_name")
6261
checkAnswer(spark.table("same_name"), spark.range(10).toDF())
@@ -88,6 +87,15 @@ class DataSourceV2DataFrameSessionCatalogSuite
8887
assert(tableInfo.properties().get("provider") === v2Format)
8988
}
9089
}
90+
91+
test("SPARK-49246: saveAsTable with v1 format") {
92+
withTable("t") {
93+
sql("CREATE TABLE t(c INT) USING csv")
94+
val df = spark.range(10).toDF()
95+
df.write.mode(SaveMode.Overwrite).format("csv").saveAsTable("t")
96+
verifyTable("t", df)
97+
}
98+
}
9199
}
92100

93101
class InMemoryTableSessionCatalog extends TestV2SessionCatalogBase[InMemoryTable] {

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

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,7 @@ import java.util.concurrent.atomic.AtomicBoolean
2222

2323
import scala.collection.JavaConverters._
2424

25-
import org.apache.spark.sql.catalyst.catalog.CatalogTableType
26-
import org.apache.spark.sql.connector.catalog.{CatalogV2Util, Column, DelegatingCatalogExtension, Identifier, Table, TableCatalog, V1Table}
25+
import org.apache.spark.sql.connector.catalog.{CatalogV2Util, Column, DelegatingCatalogExtension, Identifier, Table, TableCatalog}
2726
import org.apache.spark.sql.connector.expressions.Transform
2827
import org.apache.spark.sql.types.StructType
2928

@@ -53,14 +52,10 @@ private[connector] trait TestV2SessionCatalogBase[T <: Table] extends Delegating
5352
if (tables.containsKey(ident)) {
5453
tables.get(ident)
5554
} else {
56-
// Table was created through the built-in catalog
57-
super.loadTable(ident) match {
58-
case v1Table: V1Table if v1Table.v1Table.tableType == CatalogTableType.VIEW => v1Table
59-
case t =>
60-
val table = newTable(t.name(), t.schema(), t.partitioning(), t.properties())
61-
addTable(ident, table)
62-
table
63-
}
55+
// Table was created through the built-in catalog via v1 command, this is OK as the
56+
// `loadTable` should always be invoked, and we set the `tableCreated` to pass validation.
57+
tableCreated.set(true)
58+
super.loadTable(ident)
6459
}
6560
}
6661

0 commit comments

Comments
 (0)