Skip to content

Commit 09d1d89

Browse files
committed
HHH-19551 - Address deficiencies in pessimistic locking
1 parent 562c5c6 commit 09d1d89

File tree

214 files changed

+6775
-2832
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

214 files changed

+6775
-2832
lines changed

hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/AltibaseDialect.java

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,7 @@
44
*/
55
package org.hibernate.community.dialect;
66

7-
import java.sql.DatabaseMetaData;
8-
import java.sql.SQLException;
9-
import java.sql.Types;
10-
import java.time.temporal.TemporalAccessor;
11-
import java.util.Date;
12-
import java.util.TimeZone;
13-
7+
import jakarta.persistence.TemporalType;
148
import org.hibernate.boot.model.FunctionContributions;
159
import org.hibernate.boot.model.TypeContributions;
1610
import org.hibernate.community.dialect.pagination.AltibaseLimitHandler;
@@ -25,6 +19,8 @@
2519
import org.hibernate.dialect.OracleDialect;
2620
import org.hibernate.dialect.function.CommonFunctionFactory;
2721
import org.hibernate.dialect.function.OracleTruncFunction;
22+
import org.hibernate.dialect.lock.internal.NoLockingSupport;
23+
import org.hibernate.dialect.lock.spi.LockingSupport;
2824
import org.hibernate.dialect.pagination.LimitHandler;
2925
import org.hibernate.dialect.sequence.SequenceSupport;
3026
import org.hibernate.engine.jdbc.dialect.spi.DialectResolutionInfo;
@@ -36,9 +32,9 @@
3632
import org.hibernate.exception.LockTimeoutException;
3733
import org.hibernate.exception.spi.SQLExceptionConversionDelegate;
3834
import org.hibernate.internal.util.JdbcExceptionHelper;
35+
import org.hibernate.query.common.TemporalUnit;
3936
import org.hibernate.query.sqm.CastType;
4037
import org.hibernate.query.sqm.IntervalType;
41-
import org.hibernate.query.common.TemporalUnit;
4238
import org.hibernate.query.sqm.TrimSpec;
4339
import org.hibernate.query.sqm.produce.function.FunctionParameterType;
4440
import org.hibernate.query.sqm.produce.function.StandardFunctionArgumentTypeResolvers;
@@ -56,7 +52,12 @@
5652
import org.hibernate.type.descriptor.sql.spi.DdlTypeRegistry;
5753
import org.hibernate.type.spi.TypeConfiguration;
5854

59-
import jakarta.persistence.TemporalType;
55+
import java.sql.DatabaseMetaData;
56+
import java.sql.SQLException;
57+
import java.sql.Types;
58+
import java.time.temporal.TemporalAccessor;
59+
import java.util.Date;
60+
import java.util.TimeZone;
6061

6162
import static org.hibernate.type.SqlTypes.BINARY;
6263
import static org.hibernate.type.SqlTypes.BIT;
@@ -585,9 +586,8 @@ public boolean supportsFromClauseInUpdate() {
585586
}
586587

587588
@Override
588-
public boolean supportsOuterJoinForUpdate() {
589-
// "SELECT FOR UPDATE can only be used with a single-table SELECT statement"
590-
return false;
589+
public LockingSupport getLockingSupport() {
590+
return NoLockingSupport.NO_LOCKING_SUPPORT;
591591
}
592592

593593
@Override

hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/AltibaseSqlAstTranslator.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -113,10 +113,10 @@ protected void renderTableGroupJoin(TableGroupJoin tableGroupJoin, List<TableGro
113113
predicate = tableGroupJoin.getPredicate();
114114
}
115115
if ( predicate != null && !predicate.isEmpty() ) {
116-
renderTableGroup( tableGroupJoin.getJoinedGroup(), predicate, tableGroupJoinCollector );
116+
renderJoinedTableGroup( tableGroupJoin.getJoinedGroup(), predicate, tableGroupJoinCollector );
117117
}
118118
else {
119-
renderTableGroup( tableGroupJoin.getJoinedGroup(), null, tableGroupJoinCollector );
119+
renderJoinedTableGroup( tableGroupJoin.getJoinedGroup(), null, tableGroupJoinCollector );
120120
}
121121
}
122122

hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/CUBRIDDialect.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717
import org.hibernate.dialect.TimeZoneSupport;
1818
import org.hibernate.dialect.function.CommonFunctionFactory;
1919
import org.hibernate.dialect.identity.IdentityColumnSupport;
20+
import org.hibernate.dialect.lock.internal.LockingSupportSimple;
21+
import org.hibernate.dialect.lock.spi.LockingSupport;
2022
import org.hibernate.dialect.pagination.LimitHandler;
2123
import org.hibernate.dialect.pagination.LimitLimitHandler;
2224
import org.hibernate.dialect.sequence.SequenceSupport;
@@ -316,6 +318,11 @@ public char closeQuote() {
316318
return ']';
317319
}
318320

321+
@Override
322+
public LockingSupport getLockingSupport() {
323+
return LockingSupportSimple.STANDARD_SUPPORT;
324+
}
325+
319326
@Override
320327
public String getForUpdateString() {
321328
return "";

hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/CacheDialect.java

Lines changed: 31 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,11 @@
44
*/
55
package org.hibernate.community.dialect;
66

7-
import java.sql.CallableStatement;
8-
import java.sql.ResultSet;
9-
import java.sql.SQLException;
10-
import java.sql.Types;
11-
7+
import jakarta.persistence.GenerationType;
8+
import jakarta.persistence.TemporalType;
129
import org.hibernate.LockMode;
10+
import org.hibernate.LockOptions;
11+
import org.hibernate.Locking;
1312
import org.hibernate.boot.model.FunctionContributions;
1413
import org.hibernate.cfg.Environment;
1514
import org.hibernate.community.dialect.identity.CacheIdentityColumnSupport;
@@ -20,13 +19,10 @@
2019
import org.hibernate.dialect.function.CommonFunctionFactory;
2120
import org.hibernate.dialect.identity.IdentityColumnSupport;
2221
import org.hibernate.dialect.lock.LockingStrategy;
23-
import org.hibernate.dialect.lock.OptimisticForceIncrementLockingStrategy;
24-
import org.hibernate.dialect.lock.OptimisticLockingStrategy;
25-
import org.hibernate.dialect.lock.PessimisticForceIncrementLockingStrategy;
2622
import org.hibernate.dialect.lock.PessimisticReadUpdateLockingStrategy;
2723
import org.hibernate.dialect.lock.PessimisticWriteUpdateLockingStrategy;
28-
import org.hibernate.dialect.lock.SelectLockingStrategy;
29-
import org.hibernate.dialect.lock.UpdateLockingStrategy;
24+
import org.hibernate.dialect.lock.internal.NoLockingSupport;
25+
import org.hibernate.dialect.lock.spi.LockingSupport;
3026
import org.hibernate.dialect.pagination.LimitHandler;
3127
import org.hibernate.dialect.pagination.TopLimitHandler;
3228
import org.hibernate.dialect.sequence.SequenceSupport;
@@ -39,24 +35,29 @@
3935
import org.hibernate.exception.spi.ViolatedConstraintNameExtractor;
4036
import org.hibernate.internal.util.JdbcExceptionHelper;
4137
import org.hibernate.persister.entity.EntityPersister;
42-
import org.hibernate.query.sqm.IntervalType;
4338
import org.hibernate.query.common.TemporalUnit;
39+
import org.hibernate.query.sqm.IntervalType;
4440
import org.hibernate.sql.ast.SqlAstTranslator;
4541
import org.hibernate.sql.ast.SqlAstTranslatorFactory;
42+
import org.hibernate.sql.ast.spi.LockingClauseStrategy;
4643
import org.hibernate.sql.ast.spi.SqlAppender;
4744
import org.hibernate.sql.ast.spi.StandardSqlAstTranslatorFactory;
4845
import org.hibernate.sql.ast.tree.Statement;
46+
import org.hibernate.sql.ast.tree.select.QuerySpec;
4947
import org.hibernate.sql.exec.spi.JdbcOperation;
5048
import org.hibernate.type.StandardBasicTypes;
5149
import org.hibernate.type.descriptor.jdbc.JdbcType;
5250
import org.hibernate.type.descriptor.jdbc.spi.JdbcTypeRegistry;
5351

54-
import jakarta.persistence.GenerationType;
55-
import jakarta.persistence.TemporalType;
52+
import java.sql.CallableStatement;
53+
import java.sql.ResultSet;
54+
import java.sql.SQLException;
55+
import java.sql.Types;
5656

5757
import static org.hibernate.exception.spi.TemplatedViolatedConstraintNameExtractor.extractUsingTemplate;
5858
import static org.hibernate.query.sqm.produce.function.FunctionParameterType.INTEGER;
5959
import static org.hibernate.query.sqm.produce.function.FunctionParameterType.STRING;
60+
import static org.hibernate.sql.ast.internal.NonLockingClauseStrategy.NON_CLAUSE_STRATEGY;
6061
import static org.hibernate.type.SqlTypes.BLOB;
6162
import static org.hibernate.type.SqlTypes.BOOLEAN;
6263
import static org.hibernate.type.SqlTypes.CLOB;
@@ -309,33 +310,29 @@ public String getQuerySequencesString() {
309310

310311
// lock acquisition support ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
311312

313+
312314
@Override
313-
public boolean supportsOuterJoinForUpdate() {
314-
return false;
315+
public LockingSupport getLockingSupport() {
316+
return NoLockingSupport.NO_LOCKING_SUPPORT;
315317
}
316318

317319
@Override
318-
public LockingStrategy getLockingStrategy(EntityPersister lockable, LockMode lockMode) {
320+
public LockingClauseStrategy getLockingClauseStrategy(QuerySpec querySpec, LockOptions lockOptions) {
321+
return NON_CLAUSE_STRATEGY;
322+
}
323+
324+
@Override
325+
protected LockingStrategy buildPessimisticWriteStrategy(EntityPersister lockable, LockMode lockMode, Locking.Scope lockScope) {
319326
// InterSystems Cache' does not current support "SELECT ... FOR UPDATE" syntax...
320327
// Set your transaction mode to READ_COMMITTED before using
321-
switch (lockMode) {
322-
case PESSIMISTIC_FORCE_INCREMENT:
323-
return new PessimisticForceIncrementLockingStrategy(lockable, lockMode);
324-
case PESSIMISTIC_WRITE:
325-
return new PessimisticWriteUpdateLockingStrategy(lockable, lockMode);
326-
case PESSIMISTIC_READ:
327-
return new PessimisticReadUpdateLockingStrategy(lockable, lockMode);
328-
case OPTIMISTIC:
329-
return new OptimisticLockingStrategy(lockable, lockMode);
330-
case OPTIMISTIC_FORCE_INCREMENT:
331-
return new OptimisticForceIncrementLockingStrategy(lockable, lockMode);
332-
}
333-
if ( lockMode.greaterThan( LockMode.READ ) ) {
334-
return new UpdateLockingStrategy( lockable, lockMode );
335-
}
336-
else {
337-
return new SelectLockingStrategy( lockable, lockMode );
338-
}
328+
return new PessimisticWriteUpdateLockingStrategy( lockable, lockMode );
329+
}
330+
331+
@Override
332+
protected LockingStrategy buildPessimisticReadStrategy(EntityPersister lockable, LockMode lockMode, Locking.Scope lockScope) {
333+
// InterSystems Cache' does not current support "SELECT ... FOR UPDATE" syntax...
334+
// Set your transaction mode to READ_COMMITTED before using
335+
return new PessimisticReadUpdateLockingStrategy( lockable, lockMode );
339336
}
340337

341338
@Override

hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/CacheSqlAstTranslator.java

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
import java.util.List;
88

9+
import org.hibernate.Locking;
910
import org.hibernate.engine.spi.SessionFactoryImplementor;
1011
import org.hibernate.query.sqm.ComparisonOperator;
1112
import org.hibernate.sql.ast.spi.AbstractSqlAstTranslator;
@@ -34,16 +35,10 @@ public CacheSqlAstTranslator(SessionFactoryImplementor sessionFactory, Statement
3435
@Override
3536
protected LockStrategy determineLockingStrategy(
3637
QuerySpec querySpec,
37-
ForUpdateClause forUpdateClause,
38-
Boolean followOnLocking) {
38+
Locking.FollowOn followOnLocking) {
3939
return LockStrategy.NONE;
4040
}
4141

42-
@Override
43-
protected void renderForUpdateClause(QuerySpec querySpec, ForUpdateClause forUpdateClause) {
44-
// Cache does not support the FOR UPDATE clause
45-
}
46-
4742
@Override
4843
protected boolean needsRowsToSkip() {
4944
return true;

hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/CockroachLegacyDialect.java

Lines changed: 10 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@
2323
import org.hibernate.dialect.NationalizationSupport;
2424
import org.hibernate.dialect.NullOrdering;
2525
import org.hibernate.dialect.PostgreSQLDriverKind;
26-
import org.hibernate.dialect.RowLockStrategy;
2726
import org.hibernate.dialect.SimpleDatabaseVersion;
2827
import org.hibernate.dialect.SpannerDialect;
2928
import org.hibernate.dialect.TimeZoneSupport;
@@ -34,6 +33,7 @@
3433
import org.hibernate.dialect.function.PostgreSQLTruncFunction;
3534
import org.hibernate.dialect.identity.CockroachDBIdentityColumnSupport;
3635
import org.hibernate.dialect.identity.IdentityColumnSupport;
36+
import org.hibernate.dialect.lock.spi.LockingSupport;
3737
import org.hibernate.dialect.pagination.LimitHandler;
3838
import org.hibernate.dialect.pagination.OffsetFetchLimitHandler;
3939
import org.hibernate.dialect.sequence.PostgreSQLSequenceSupport;
@@ -92,11 +92,12 @@
9292
import java.time.temporal.TemporalAccessor;
9393
import java.util.Calendar;
9494
import java.util.Date;
95-
import java.util.Map;
9695
import java.util.TimeZone;
9796
import java.util.regex.Matcher;
9897
import java.util.regex.Pattern;
9998

99+
import static org.hibernate.dialect.lock.internal.CockroachLockingSupport.COCKROACH_LOCKING_SUPPORT;
100+
import static org.hibernate.dialect.lock.internal.CockroachLockingSupport.LEGACY_COCKROACH_LOCKING_SUPPORT;
100101
import static org.hibernate.exception.spi.TemplatedViolatedConstraintNameExtractor.extractUsingTemplate;
101102
import static org.hibernate.query.common.TemporalUnit.DAY;
102103
import static org.hibernate.query.common.TemporalUnit.EPOCH;
@@ -994,25 +995,10 @@ public String getForUpdateString(String aliases, LockOptions lockOptions) {
994995
if ( getVersion().isBefore( 20, 1 ) ) {
995996
return "";
996997
}
997-
/*
998-
* Parent's implementation for (aliases, lockOptions) ignores aliases.
999-
*/
1000-
if ( aliases.isEmpty() ) {
1001-
LockMode lockMode = lockOptions.getLockMode();
1002-
for ( Map.Entry<String, LockMode> entry : lockOptions.getAliasSpecificLocks() ) {
1003-
// seek the highest lock mode
1004-
if ( entry.getValue().greaterThan(lockMode) ) {
1005-
aliases = entry.getKey();
1006-
}
1007-
}
1008-
}
1009-
LockMode lockMode = lockOptions.getAliasSpecificLockMode( aliases );
1010-
if (lockMode == null ) {
1011-
lockMode = lockOptions.getLockMode();
1012-
}
998+
final LockMode lockMode = lockOptions.getLockMode();
1013999
return switch ( lockMode ) {
1014-
case PESSIMISTIC_READ -> getReadLockString( aliases, lockOptions.getTimeOut() );
1015-
case PESSIMISTIC_WRITE -> getWriteLockString( aliases, lockOptions.getTimeOut() );
1000+
case PESSIMISTIC_READ -> getReadLockString( aliases, lockOptions.getTimeout() );
1001+
case PESSIMISTIC_WRITE -> getWriteLockString( aliases, lockOptions.getTimeout() );
10161002
case UPGRADE_NOWAIT, PESSIMISTIC_FORCE_INCREMENT -> getForUpdateNowaitString( aliases );
10171003
case UPGRADE_SKIPLOCKED -> getForUpdateSkipLockedString( aliases );
10181004
default -> "";
@@ -1100,8 +1086,10 @@ public String getForUpdateSkipLockedString(String aliases) {
11001086
}
11011087

11021088
@Override
1103-
public boolean supportsOuterJoinForUpdate() {
1104-
return false;
1089+
public LockingSupport getLockingSupport() {
1090+
return getVersion().isSameOrAfter( 20, 1 )
1091+
? COCKROACH_LOCKING_SUPPORT
1092+
: LEGACY_COCKROACH_LOCKING_SUPPORT;
11051093
}
11061094

11071095
@Override
@@ -1129,32 +1117,11 @@ public boolean supportsLateral() {
11291117
return getVersion().isSameOrAfter( 20, 1 );
11301118
}
11311119

1132-
@Override
1133-
public boolean supportsNoWait() {
1134-
return getVersion().isSameOrAfter( 20, 1 );
1135-
}
1136-
1137-
@Override
1138-
public boolean supportsWait() {
1139-
return false;
1140-
}
1141-
1142-
@Override
1143-
public boolean supportsSkipLocked() {
1144-
// See https://www.cockroachlabs.com/docs/stable/select-for-update.html#wait-policies
1145-
return false;
1146-
}
1147-
11481120
@Override
11491121
public FunctionalDependencyAnalysisSupport getFunctionalDependencyAnalysisSupport() {
11501122
return FunctionalDependencyAnalysisSupportImpl.TABLE_REFERENCE;
11511123
}
11521124

1153-
@Override
1154-
public RowLockStrategy getWriteRowLockStrategy() {
1155-
return getVersion().isSameOrAfter( 20, 1 ) ? RowLockStrategy.TABLE : RowLockStrategy.NONE;
1156-
}
1157-
11581125
@Override
11591126
public NameQualifierSupport getNameQualifierSupport() {
11601127
// This method is overridden so the correct value will be returned when

hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/CockroachLegacySqlAstTranslator.java

Lines changed: 3 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
*/
55
package org.hibernate.community.dialect;
66

7+
import org.hibernate.Locking;
78
import org.hibernate.engine.spi.SessionFactoryImplementor;
89
import org.hibernate.sql.ast.Clause;
910
import org.hibernate.sql.ast.spi.AbstractSqlAstTranslator;
@@ -129,35 +130,15 @@ protected void renderMaterializationHint(CteMaterialization materialization) {
129130
}
130131
}
131132

132-
@Override
133-
protected String getForShare(int timeoutMillis) {
134-
return " for share";
135-
}
136-
137-
@Override
138-
protected String getForUpdate() {
139-
return getDialect().getVersion().isBefore( 20, 1 ) ? "" : " for update";
140-
}
141-
142133
@Override
143134
protected LockStrategy determineLockingStrategy(
144135
QuerySpec querySpec,
145-
ForUpdateClause forUpdateClause,
146-
Boolean followOnLocking) {
136+
Locking.FollowOn followOnLocking) {
147137
// Support was added in 20.1: https://www.cockroachlabs.com/docs/v20.1/select-for-update.html
148138
if ( getDialect().getVersion().isBefore( 20, 1 ) ) {
149139
return LockStrategy.NONE;
150140
}
151-
return super.determineLockingStrategy( querySpec, forUpdateClause, followOnLocking );
152-
}
153-
154-
@Override
155-
protected void renderForUpdateClause(QuerySpec querySpec, ForUpdateClause forUpdateClause) {
156-
// Support was added in 20.1: https://www.cockroachlabs.com/docs/v20.1/select-for-update.html
157-
if ( getDialect().getVersion().isBefore( 20, 1 ) ) {
158-
return;
159-
}
160-
super.renderForUpdateClause( querySpec, forUpdateClause );
141+
return super.determineLockingStrategy( querySpec, followOnLocking );
161142
}
162143

163144
protected boolean shouldEmulateFetchClause(QueryPart queryPart) {

0 commit comments

Comments
 (0)