This is an automated email from the ASF dual-hosted git repository. snazy pushed a commit to branch main in repository https://gitbox.apache.org/repos/asf/polaris.git
The following commit(s) were added to refs/heads/main by this push: new b47677999 JDBC: SERIALIZABLE/EntityNotFoundException (#2219) b47677999 is described below commit b47677999d646c4adb6accfc489bef0ea5ab8512 Author: Robert Stupp <sn...@snazy.de> AuthorDate: Tue Aug 5 13:52:25 2025 +0200 JDBC: SERIALIZABLE/EntityNotFoundException (#2219) With serializable isolation level, if either the primary-key or the check-constraint are violated, the lookup of the conflicting entity is not guaranteed to yield a non-null result (transaction start matters). This changes works around this situation w/ serializable isolation. --- .../relational/jdbc/JdbcBasePersistenceImpl.java | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/persistence/relational-jdbc/src/main/java/org/apache/polaris/persistence/relational/jdbc/JdbcBasePersistenceImpl.java b/persistence/relational-jdbc/src/main/java/org/apache/polaris/persistence/relational/jdbc/JdbcBasePersistenceImpl.java index 8e2f905d6..7391d1d5e 100644 --- a/persistence/relational-jdbc/src/main/java/org/apache/polaris/persistence/relational/jdbc/JdbcBasePersistenceImpl.java +++ b/persistence/relational-jdbc/src/main/java/org/apache/polaris/persistence/relational/jdbc/JdbcBasePersistenceImpl.java @@ -183,11 +183,17 @@ public class JdbcBasePersistenceImpl implements BasePersistence, IntegrationPers entity.getParentId(), entity.getTypeCode(), entity.getName()); - throw new EntityAlreadyExistsException(existingEntity, e); - } else { - throw new RuntimeException( - String.format("Failed to write entity due to %s", e.getMessage()), e); + // This happens in two scenarios: + // 1. PRIMARY KEY violated + // 2. UNIQUE CONSTRAINT on (realm_id, catalog_id, parent_id, type_code, name) violated + // With SERIALIZABLE isolation, the conflicting entity may _not_ be visible and + // existingEntity can be null, which would cause an NPE in + // EntityAlreadyExistsException.message(). + throw new EntityAlreadyExistsException( + existingEntity != null ? existingEntity : entity, e); } + throw new RuntimeException( + String.format("Failed to write entity due to %s", e.getMessage()), e); } } else { Map<String, Object> params =