wombatu-kun opened a new issue, #19250:
URL: https://github.com/apache/hudi/issues/19250
### Bug Description
`BasicStagedTable.newWriteBuilder` pattern-matches its `LogicalWriteInfo`
argument against `SupportsWrite`, instead of matching the staged `Table`:
```scala
override def newWriteBuilder(info: LogicalWriteInfo): WriteBuilder = {
info match {
case supportsWrite: SupportsWrite => supportsWrite.newWriteBuilder(info)
case _ => throw new HoodieException(s"Table `${ident.name}` does not
support writes.")
}
}
```
`SupportsWrite` is a `Table` mixin (`SupportsWrite extends Table`, in
`org.apache.spark.sql.connector.catalog`), while `LogicalWriteInfo` is an
unrelated interface in `org.apache.spark.sql.connector.write` whose only Spark
implementation, `LogicalWriteInfoImpl`, implements `LogicalWriteInfo, Product,
Serializable`. No `LogicalWriteInfo` can ever satisfy the first case, so the
delegating branch is dead and the method throws for every input, including one
whose underlying table is perfectly writable.
**What happened:** every write staged through `BasicStagedTable` is rejected
with ``Table `x` does not support writes.``
**What was expected:** the write is delegated to the underlying table when
that table is `SupportsWrite`; the exception is raised only when it is not.
`BasicStagedTable` is what `HoodieCatalog` returns from `stageCreate`,
`stageReplace` and `stageCreateOrReplace` for non-Hudi tables, so an atomic
CTAS or RTAS against a writable V2 table reaches this method.
**Steps to reproduce:** a unit test is enough:
```scala
val table = mock(classOf[SupportsWrite])
val info = mock(classOf[LogicalWriteInfo])
when(table.newWriteBuilder(info)).thenReturn(mock(classOf[WriteBuilder]))
BasicStagedTable(Identifier.of(Array("db"), "tbl"), table,
mock(classOf[TableCatalog])).newWriteBuilder(info)
// throws HoodieException: Table `tbl` does not support writes.
```
**Why it survived:** Scala compiles a match between two unrelated interfaces
without a warning, since a class could in principle implement both, and
`BasicStagedTable` had no test coverage at all. Present since #4611 (2022).
Spark's own `BasicStagedTable` delegates via `table.asWritable`.
**Fix:** match on `table` instead of `info`.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]