Skip to content

Commit e709014

Browse files
committed
[SPARK-54030][SQL] Add user-friendly assertion message for view metadata corruption
1 parent 9b7ab21 commit e709014

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
@@ -1031,7 +1031,16 @@ class SessionCatalog(
10311031
// output is the same with the view output.
10321032
metadata.schema.fieldNames.toImmutableArraySeq
10331033
} else {
1034-
assert(metadata.viewQueryColumnNames.length == metadata.schema.length)
1034+
assert(metadata.viewQueryColumnNames.length == metadata.schema.length,
1035+
"Corrupted view metadata detected for view " +
1036+
metadata.identifier.quotedString + ". " +
1037+
"The number of view query column names " +
1038+
metadata.viewQueryColumnNames.length + " " +
1039+
"does not match the number of columns in the view schema " +
1040+
metadata.schema.length + ". " +
1041+
"View query column names: [" + metadata.viewQueryColumnNames.mkString(", ") + "], " +
1042+
"View schema columns: [" + metadata.schema.fieldNames.mkString(", ") + "]. " +
1043+
"This indicates corrupted view metadata that needs to be repaired.")
10351044
metadata.viewQueryColumnNames
10361045
}
10371046

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)