diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/lock/internal/CockroachLockingSupport.java b/hibernate-core/src/main/java/org/hibernate/dialect/lock/internal/CockroachLockingSupport.java index 4db473322ad2..1803bbd23bdc 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/lock/internal/CockroachLockingSupport.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/lock/internal/CockroachLockingSupport.java @@ -55,6 +55,8 @@ public LockTimeoutType getLockTimeoutType(Timeout timeout) { return switch (timeout.milliseconds()) { case WAIT_FOREVER_MILLI -> QUERY; case NO_WAIT_MILLI -> supportsNoWait ? QUERY : LockTimeoutType.NONE; + // Due to https://github.com/cockroachdb/cockroach/issues/88995, locking doesn't work properly + // without certain configuration options and hence skipping locked rows also doesn't work correctly. case SKIP_LOCKED_MILLI -> LockTimeoutType.NONE; // it does not, however, support WAIT as part of for-update, but does support a connection-level lock_timeout setting default -> CONNECTION; diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/jpa/lock/LockExceptionTests.java b/hibernate-core/src/test/java/org/hibernate/orm/test/jpa/lock/LockExceptionTests.java index ba6ed85fbcb0..85ccd2f50e29 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/jpa/lock/LockExceptionTests.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/jpa/lock/LockExceptionTests.java @@ -53,7 +53,6 @@ protected void tearDown() { @Test @JiraKey( value = "HHH-8786" ) - @SkipForDialect(dialectClass = CockroachDialect.class, reason = "for update clause does not imply locking. See https://github.com/cockroachdb/cockroach/issues/88995") @SkipForDialect(dialectClass = InformixDialect.class, reason = "no failure") public void testLockTimeoutFind() { final Item item = new Item( "find" ); diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/jpa/lock/LockTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/jpa/lock/LockTest.java index ec004f531f9c..c8e6e9f191d3 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/jpa/lock/LockTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/jpa/lock/LockTest.java @@ -107,7 +107,6 @@ public void testFindWithTimeoutHint() { @RequiresDialectFeature( value = DialectChecks.SupportsLockTimeouts.class, comment = "Test verifies proper exception throwing when a lock timeout is specified.", jiraKey = "HHH-7252" ) - @SkipForDialect(value = CockroachDialect.class, comment = "for update clause does not imply locking. See https://github.com/cockroachdb/cockroach/issues/88995") @SkipForDialect(value = AltibaseDialect.class, comment = "Altibase close socket after lock timeout occurred") public void testFindWithPessimisticWriteLockTimeoutException() { Lock lock = new Lock(); @@ -157,7 +156,6 @@ public void testFindWithPessimisticWriteLockTimeoutException() { @RequiresDialectFeature( value = DialectChecks.SupportsLockTimeouts.class, comment = "Test verifies proper exception throwing when a lock timeout is specified for Query#getSingleResult.", jiraKey = "HHH-13364" ) - @SkipForDialect(value = CockroachDialect.class, comment = "for update clause does not imply locking. See https://github.com/cockroachdb/cockroach/issues/88995") @SkipForDialect(value = AltibaseDialect.class, comment = "Altibase close socket after lock timeout occurred") public void testQuerySingleResultPessimisticWriteLockTimeoutException() { Lock lock = new Lock(); @@ -204,7 +202,6 @@ public void testQuerySingleResultPessimisticWriteLockTimeoutException() { @RequiresDialectFeature( value = DialectChecks.SupportsLockTimeouts.class, comment = "Test verifies proper exception throwing when a lock timeout is specified for Query#getResultList.", jiraKey = "HHH-13364" ) - @SkipForDialect(value = CockroachDialect.class, comment = "for update clause does not imply locking. See https://github.com/cockroachdb/cockroach/issues/88995") @SkipForDialect(value = AltibaseDialect.class, comment = "Altibase close socket after lock timeout occurred") public void testQueryResultListPessimisticWriteLockTimeoutException() { Lock lock = new Lock(); @@ -254,7 +251,6 @@ public void testQueryResultListPessimisticWriteLockTimeoutException() { @RequiresDialectFeature( value = DialectChecks.SupportsLockTimeouts.class, comment = "Test verifies proper exception throwing when a lock timeout is specified for NamedQuery#getResultList.", jiraKey = "HHH-13364" ) - @SkipForDialect(value = CockroachDialect.class, comment = "for update clause does not imply locking. See https://github.com/cockroachdb/cockroach/issues/88995") @SkipForDialect(value = AltibaseDialect.class, comment = "Altibase close socket after lock timeout occurred") public void testNamedQueryResultListPessimisticWriteLockTimeoutException() { Lock lock = new Lock(); @@ -298,7 +294,6 @@ public void testNamedQueryResultListPessimisticWriteLockTimeoutException() { @Test @RequiresDialectFeature( value = DialectChecks.SupportsSkipLocked.class ) - @SkipForDialect(value = CockroachDialect.class, comment = "for update clause does not imply locking. See https://github.com/cockroachdb/cockroach/issues/88995") public void testUpdateWithPessimisticReadLockSkipLocked() { Lock lock = new Lock(); lock.setName( "name" ); @@ -343,7 +338,6 @@ public void testUpdateWithPessimisticReadLockSkipLocked() { @Test @RequiresDialectFeature(value = DialectChecks.SupportsLockTimeouts.class) - @SkipForDialect(value = CockroachDialect.class, comment = "for update clause does not imply locking. See https://github.com/cockroachdb/cockroach/issues/88995") public void testUpdateWithPessimisticReadLockWithoutNoWait() { Lock lock = new Lock(); lock.setName( "name" ); diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/jpa/lock/StatementIsClosedAfterALockExceptionTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/jpa/lock/StatementIsClosedAfterALockExceptionTest.java index 1fafd6166559..8baa34f13999 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/jpa/lock/StatementIsClosedAfterALockExceptionTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/jpa/lock/StatementIsClosedAfterALockExceptionTest.java @@ -14,7 +14,6 @@ import org.hibernate.cfg.AvailableSettings; import org.hibernate.community.dialect.AltibaseDialect; import org.hibernate.community.dialect.InformixDialect; -import org.hibernate.dialect.CockroachDialect; import org.hibernate.orm.test.jpa.BaseEntityManagerFunctionalTestCase; import org.hibernate.testing.orm.jdbc.PreparedStatementSpyConnectionProvider; import org.hibernate.testing.DialectChecks; @@ -35,7 +34,6 @@ * @author Andrea Boriero */ @RequiresDialectFeature({DialectChecks.SupportsLockTimeouts.class}) -@SkipForDialect(value = CockroachDialect.class, comment = "for update clause does not imply locking. See https://github.com/cockroachdb/cockroach/issues/88995") @SkipForDialect(value = AltibaseDialect.class, comment = "Altibase does not close Statement after lock timeout") public class StatementIsClosedAfterALockExceptionTest extends BaseEntityManagerFunctionalTestCase { diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/locking/LockModeTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/locking/LockModeTest.java index a7ab40e814cc..43d3ff9919fd 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/locking/LockModeTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/locking/LockModeTest.java @@ -87,7 +87,6 @@ public void prepareTest() throws Exception { @Test @RequiresDialectFeature( feature = DialectFeatureChecks.SupportsLockTimeouts.class ) - @SkipForDialect(dialectClass = CockroachDialect.class, reason = "for update clause does not imply locking. See https://github.com/cockroachdb/cockroach/issues/88995") @SkipForDialect(dialectClass = AltibaseDialect.class, reason = "Can't commit transaction because Altibase closes socket after lock timeout") public void testLoading() { // open a session, begin a transaction and lock row @@ -104,7 +103,6 @@ public void testLoading() { @Test @RequiresDialectFeature( feature = DialectFeatureChecks.SupportsLockTimeouts.class ) - @SkipForDialect(dialectClass = CockroachDialect.class, reason = "for update clause does not imply locking. See https://github.com/cockroachdb/cockroach/issues/88995") @SkipForDialect(dialectClass = AltibaseDialect.class, reason = "Can't commit transaction because Altibase closes socket after lock timeout") public void testCriteria() { // open a session, begin a transaction and lock row @@ -128,7 +126,6 @@ public void testCriteria() { @Test @RequiresDialectFeature( feature = DialectFeatureChecks.SupportsLockTimeouts.class ) - @SkipForDialect(dialectClass = CockroachDialect.class, reason = "for update clause does not imply locking. See https://github.com/cockroachdb/cockroach/issues/88995") @SkipForDialect(dialectClass = AltibaseDialect.class, reason = "Can't commit transaction because Altibase closes socket after lock timeout") public void testCriteriaAliasSpecific() { // open a session, begin a transaction and lock row @@ -154,7 +151,6 @@ public void testCriteriaAliasSpecific() { @Test @RequiresDialectFeature( feature = DialectFeatureChecks.SupportsLockTimeouts.class ) - @SkipForDialect(dialectClass = CockroachDialect.class, reason = "for update clause does not imply locking. See https://github.com/cockroachdb/cockroach/issues/88995") @SkipForDialect(dialectClass = AltibaseDialect.class, reason = "Can't commit transaction because Altibase closes socket after lock timeout") public void testQuery() { // open a session, begin a transaction and lock row diff --git a/hibernate-testing/src/main/java/org/hibernate/testing/orm/transaction/TransactionUtil.java b/hibernate-testing/src/main/java/org/hibernate/testing/orm/transaction/TransactionUtil.java index 7634fac22af4..c243b3c21656 100644 --- a/hibernate-testing/src/main/java/org/hibernate/testing/orm/transaction/TransactionUtil.java +++ b/hibernate-testing/src/main/java/org/hibernate/testing/orm/transaction/TransactionUtil.java @@ -10,6 +10,7 @@ import java.util.function.Function; import jakarta.persistence.EntityManager; +import jakarta.persistence.QueryTimeoutException; import org.hibernate.LockMode; import org.hibernate.LockOptions; import org.hibernate.SharedSessionContract; @@ -172,7 +173,8 @@ public static void deleteRow(SessionFactoryScope factoryScope, String tableName, } catch (RuntimeException re) { if ( re.getCause() instanceof jakarta.persistence.LockTimeoutException - || re.getCause() instanceof org.hibernate.exception.LockTimeoutException ) { + || re.getCause() instanceof org.hibernate.exception.LockTimeoutException + || re.getCause() instanceof QueryTimeoutException ) { if ( !expectingToBlock ) { fail( "Expecting update to " + tableName + " to succeed, but failed due to async timeout (presumably due to locks)", re.getCause() ); } @@ -227,7 +229,8 @@ else if ( !expectingToBlock && resultSize == 0 ) { } catch (RuntimeException re) { if ( re.getCause() instanceof jakarta.persistence.LockTimeoutException - || re.getCause() instanceof org.hibernate.exception.LockTimeoutException ) { + || re.getCause() instanceof org.hibernate.exception.LockTimeoutException + || re.getCause() instanceof QueryTimeoutException ) { if ( !expectingToBlock ) { fail( "Expecting update to " + tableName + " to succeed, but failed due to async timeout (presumably due to locks)", re.getCause() ); } diff --git a/local-build-plugins/src/main/groovy/local.databases.gradle b/local-build-plugins/src/main/groovy/local.databases.gradle index 49fbf19502db..4e6702baa3a2 100644 --- a/local-build-plugins/src/main/groovy/local.databases.gradle +++ b/local-build-plugins/src/main/groovy/local.databases.gradle @@ -371,7 +371,8 @@ ext { 'jdbc.url' : 'jdbc:postgresql://' + dbHost + ':26257/defaultdb?sslmode=disable&preparedStatementCacheQueries=0&escapeSyntaxCallMode=callIfNoReturn', 'jdbc.datasource' : 'org.postgresql.Driver', // 'jdbc.datasource' : 'org.postgresql.ds.PGSimpleDataSource', - 'connection.init_sql' : '' + // Configure the for-update clause to use proper locks: https://github.com/cockroachdb/cockroach/issues/88995 + 'connection.init_sql' : 'set enable_durable_locking_for_serializable = on; set optimizer_use_lock_op_for_serializable = on;' ], firebird : [ 'db.dialect' : 'org.hibernate.community.dialect.FirebirdDialect',