4
4
*/
5
5
package org .hibernate .community .dialect .lock .internal ;
6
6
7
+ import jakarta .persistence .Timeout ;
8
+ import org .hibernate .HibernateException ;
9
+ import org .hibernate .Timeouts ;
7
10
import org .hibernate .dialect .RowLockStrategy ;
11
+ import org .hibernate .dialect .lock .internal .Helper ;
8
12
import org .hibernate .dialect .lock .spi .ConnectionLockTimeoutStrategy ;
13
+ import org .hibernate .dialect .lock .spi .LockTimeoutType ;
9
14
import org .hibernate .dialect .lock .spi .LockingSupport ;
10
15
import org .hibernate .dialect .lock .spi .OuterJoinLockingType ;
16
+ import org .hibernate .engine .spi .SessionFactoryImplementor ;
11
17
18
+ import java .sql .Connection ;
19
+
20
+ import static org .hibernate .Timeouts .NO_WAIT_MILLI ;
21
+ import static org .hibernate .Timeouts .SKIP_LOCKED_MILLI ;
22
+ import static org .hibernate .Timeouts .WAIT_FOREVER_MILLI ;
23
+ import static org .hibernate .dialect .lock .spi .LockTimeoutType .QUERY ;
12
24
13
25
14
26
/**
18
30
*/
19
31
public class GaussDBLockingSupport implements LockingSupport , LockingSupport .Metadata , ConnectionLockTimeoutStrategy {
20
32
public static final LockingSupport LOCKING_SUPPORT = new GaussDBLockingSupport ();
33
+ private final boolean supportsNoWait ;
34
+ private final boolean supportsSkipLocked ;
35
+
36
+ public GaussDBLockingSupport () {
37
+ this ( true , true );
38
+ }
21
39
40
+ public GaussDBLockingSupport (boolean supportsNoWait , boolean supportsSkipLocked ) {
41
+ this .supportsNoWait = supportsNoWait ;
42
+ this .supportsSkipLocked = supportsSkipLocked ;
43
+ }
22
44
23
45
@ Override
24
46
public Metadata getMetadata () {
@@ -42,6 +64,71 @@ public ConnectionLockTimeoutStrategy getConnectionLockTimeoutStrategy() {
42
64
43
65
@ Override
44
66
public Level getSupportedLevel () {
45
- return Level .NONE ;
67
+ return Level .SUPPORTED ;
68
+ }
69
+
70
+ @ Override
71
+ public LockTimeoutType getLockTimeoutType (Timeout timeout ) {
72
+ return switch ( timeout .milliseconds () ) {
73
+ case NO_WAIT_MILLI -> supportsNoWait ? QUERY : LockTimeoutType .NONE ;
74
+ case SKIP_LOCKED_MILLI -> supportsSkipLocked ? QUERY : LockTimeoutType .NONE ;
75
+ case WAIT_FOREVER_MILLI -> LockTimeoutType .NONE ;
76
+ // we can apply a timeout via the connection
77
+ default -> LockTimeoutType .CONNECTION ;
78
+ };
79
+ }
80
+
81
+ @ Override
82
+ public Timeout getLockTimeout (Connection connection , SessionFactoryImplementor factory ) {
83
+ return Helper .getLockTimeout (
84
+ "select current_setting('lockwait_timeout')" ,
85
+ (resultSet ) -> {
86
+ // even though lock_timeout is "in milliseconds", `current_setting`
87
+ // returns a String form which unfortunately varies depending on
88
+ // the actual value:
89
+ // * for zero (no timeout), "0" is returned
90
+ // * for non-zero, `{timeout-in-seconds}s` is returned (e.g. "4s")
91
+ // so we need to "parse" that form here
92
+ final String value = resultSet .getString ( 1 );
93
+ if ( "0" .equals ( value ) ) {
94
+ return Timeouts .WAIT_FOREVER ;
95
+ }
96
+ if ( value .endsWith ( "min" ) ) {
97
+ final int min = Integer .parseInt ( value .substring ( 0 , value .length () - 3 ) );
98
+ return Timeout .milliseconds ( min * 60 * 1000 );
99
+ }
100
+ else if ( value .endsWith ( "s" ) ) {
101
+ final int second = Integer .parseInt ( value .substring ( 0 , value .length () - 1 ) );
102
+ return Timeout .seconds (second );
103
+ }
104
+ final int milliseconds = Integer .parseInt ( value .substring ( 0 , value .length () - 2 ) );
105
+ return Timeout .milliseconds (milliseconds );
106
+ },
107
+ connection ,
108
+ factory
109
+ );
110
+ }
111
+
112
+ @ Override
113
+ public void setLockTimeout (Timeout timeout , Connection connection , SessionFactoryImplementor factory ) {
114
+ Helper .setLockTimeout (
115
+ timeout ,
116
+ (t ) -> {
117
+ final int milliseconds = timeout .milliseconds ();
118
+ if ( milliseconds == SKIP_LOCKED_MILLI ) {
119
+ throw new HibernateException ( "Connection lock-timeout does not accept skip-locked" );
120
+ }
121
+
122
+ if ( milliseconds == NO_WAIT_MILLI ) {
123
+ throw new HibernateException ( "Connection lock-timeout does not accept no-wait" );
124
+ }
125
+ return milliseconds == WAIT_FOREVER_MILLI
126
+ ? 0
127
+ : milliseconds ;
128
+ },
129
+ "set local lockwait_timeout = %s" ,
130
+ connection ,
131
+ factory
132
+ );
46
133
}
47
134
}
0 commit comments