Skip to content

Commit 8f67ee8

Browse files
committed
[SPARK-54030][SQL] Add user-friendly assertion message for view metadata corruption
1 parent c5b58b5 commit 8f67ee8

File tree

2 files changed

+75
-1
lines changed

2 files changed

+75
-1
lines changed

sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/catalog/SessionCatalog.scala

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1024,7 +1024,16 @@ class SessionCatalog(
10241024
// output is the same with the view output.
10251025
metadata.schema.fieldNames.toImmutableArraySeq
10261026
} else {
1027-
assert(metadata.viewQueryColumnNames.length == metadata.schema.length)
1027+
assert(metadata.viewQueryColumnNames.length == metadata.schema.length,
1028+
"Corrupted view metadata detected for view " +
1029+
metadata.identifier.unquotedString + ". " +
1030+
"The number of view query column names " +
1031+
metadata.viewQueryColumnNames.length + " " +
1032+
"does not match the number of columns in the view schema " +
1033+
metadata.schema.length + ". " +
1034+
"View query column names: [" + metadata.viewQueryColumnNames.mkString(", ") + "], " +
1035+
"View schema columns: [" + metadata.schema.fieldNames.mkString(", ") + "]. " +
1036+
"This indicates corrupted view metadata that needs to be repaired.")
10281037
metadata.viewQueryColumnNames
10291038
}
10301039

sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/catalog/SessionCatalogSuite.scala

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1951,4 +1951,69 @@ abstract class SessionCatalogSuite extends AnalysisTest with Eventually {
19511951
assert(catalog.getCachedTable(qualifiedName2) != null)
19521952
}
19531953
}
1954+
1955+
test("corrupted view metadata: mismatch between viewQueryColumnNames and schema") {
1956+
withSQLConf("spark.sql.viewSchemaBinding.enabled" -> "true") {
1957+
val catalog = new SessionCatalog(newBasicCatalog())
1958+
val db = "test_db"
1959+
catalog.createDatabase(newDb(db), ignoreIfExists = false)
1960+
1961+
// First create a base table for the view to reference
1962+
val baseTable = CatalogTable(
1963+
identifier = TableIdentifier("base_table", Some(db)),
1964+
tableType = CatalogTableType.MANAGED,
1965+
storage = CatalogStorageFormat.empty,
1966+
schema = new StructType()
1967+
.add("id", IntegerType)
1968+
.add("name", StringType)
1969+
.add("value", DoubleType)
1970+
)
1971+
catalog.createTable(baseTable, ignoreIfExists = false)
1972+
1973+
// Create a view with corrupted metadata where viewQueryColumnNames length
1974+
// doesn't match schema length
1975+
// We need to set the properties to define viewQueryColumnNames
1976+
val properties = Map(
1977+
"view.query.out.numCols" -> "2",
1978+
"view.query.out.col.0" -> "id",
1979+
"view.query.out.col.1" -> "name",
1980+
"view.schema.mode" -> "binding" // Ensure it's not SchemaEvolution
1981+
)
1982+
val corruptedView = CatalogTable(
1983+
identifier = TableIdentifier("corrupted_view", Some(db)),
1984+
tableType = CatalogTableType.VIEW,
1985+
storage = CatalogStorageFormat.empty,
1986+
schema = new StructType()
1987+
.add("id", IntegerType)
1988+
.add("name", StringType)
1989+
.add("value", DoubleType),
1990+
viewText = Some("SELECT * FROM test_db.base_table"),
1991+
provider = Some("spark"), // Ensure it's not Hive-created
1992+
properties = properties // Only 2 query column names but schema has 3 columns
1993+
)
1994+
1995+
catalog.createTable(corruptedView, ignoreIfExists = false)
1996+
1997+
// Verify the view was created with corrupted metadata
1998+
val retrievedView = catalog.getTableMetadata(TableIdentifier("corrupted_view", Some(db)))
1999+
assert(retrievedView.viewQueryColumnNames.length == 2)
2000+
assert(retrievedView.schema.length == 3)
2001+
2002+
// Attempting to look up the view should throw an assertion error with detailed message
2003+
val exception = intercept[AssertionError] {
2004+
catalog.lookupRelation(TableIdentifier("corrupted_view", Some(db)))
2005+
}
2006+
2007+
// The expected message pattern allows for optional catalog prefix
2008+
val expectedPattern =
2009+
"assertion failed: Corrupted view metadata detected for view " +
2010+
"(\\w+\\.)?test_db\\.corrupted_view\\. " +
2011+
"The number of view query column names 2 " +
2012+
"does not match the number of columns in the view schema 3\\. " +
2013+
"View query column names: \\[id, name\\], " +
2014+
"View schema columns: \\[id, name, value\\]\\. " +
2015+
"This indicates corrupted view metadata that needs to be repaired\\."
2016+
assert(exception.getMessage.matches(expectedPattern))
2017+
}
2018+
}
19542019
}

0 commit comments

Comments
 (0)