mattfaltyn opened a new issue, #3061:
URL: https://github.com/apache/iceberg-rust/issues/3061
## Apache Iceberg Rust version
`0.10.1` and current `main` (`7b33321f34d9322ce5ede780ba3bc1f4e3741f47`).
## Describe the bug
`SqlCatalog::execute` ignores errors returned by `Transaction::commit` when
it creates the transaction itself:
```rust
let result = sqlx_query.execute(&mut *tx).await.map_err(from_sqlx_error);
let _ = tx.commit().await.map_err(from_sqlx_error);
result
```
If the statement succeeds but `COMMIT` fails, the helper returns the
statement's successful `AnyQueryResult`. Callers therefore proceed as though
the catalog mutation committed.
This shared path is used by namespace creation/deletion and table creation,
registration, deletion, rename, and metadata commits. In the most serious path,
`purge_table` calls `drop_table` and then deletes table data. If the catalog
`DELETE` executes but its commit fails, `drop_table` still returns success and
`purge_table` can delete the files while the catalog continues to reference the
table.
Commit-time failure is distinct from statement failure and can occur with
deferred database constraints, serialization failures, or a lost database
connection during commit.
## To reproduce
With SQLite foreign-key enforcement enabled:
1. Create a parent table and a child table whose foreign key is `DEFERRABLE
INITIALLY DEFERRED`.
2. Begin a transaction and insert a child row with no corresponding parent.
3. Observe that the `INSERT` succeeds.
4. Observe that `COMMIT` fails and rolls the row back.
5. Run the same sequence through the current `SqlCatalog::execute` control
flow.
The helper returns `Ok`, while `SELECT COUNT(*) FROM child` returns `0`.
I reproduced this twice with SQLx 0.8.1, matching the workspace dependency.
A valid control transaction returns `Ok` and persists one row.
## Expected behavior
`SqlCatalog::execute` should return the commit error whenever a transaction
it owns fails to commit. Callers must not report success or continue
destructive follow-up work when catalog commit status is unsuccessful.
The minimal change is to propagate both statement and commit failures:
```rust
let result = sqlx_query
.execute(&mut *tx)
.await
.map_err(from_sqlx_error)?;
tx.commit().await.map_err(from_sqlx_error)?;
Ok(result)
```
## Willingness to contribute
I can contribute a fix for this bug independently, including a regression
test that forces a deferred SQLite constraint failure at commit time.
## AI disclosure
AI assistance was used to audit callers and help draft this report. I
independently traced the affected paths, reproduced the failure, and verified
the proposed behavior and test strategy.
--
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]
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]