11package tech .ydb .jdbc .context ;
22
3+ import java .sql .Connection ;
34import java .sql .SQLException ;
45import java .sql .SQLFeatureNotSupportedException ;
56
1213 * @author Aleksandr Gorshenin
1314 */
1415public class YdbTxState {
16+ private final int transactionLevel ;
17+ private final boolean isReadOnly ;
18+ private final boolean isAutoCommit ;
19+
1520 private final TxControl <?> txControl ;
16- protected final int transactionLevel ;
1721
18- protected YdbTxState (TxControl <?> tx , int level ) {
19- this .txControl = tx ;
22+ protected YdbTxState (TxControl <?> txControl , int level , boolean isReadOnly , boolean isAutoCommit ) {
2023 this .transactionLevel = level ;
24+ this .isReadOnly = isReadOnly ;
25+ this .isAutoCommit = isAutoCommit ;
26+ this .txControl = txControl ;
27+ }
28+
29+ protected YdbTxState (TxControl <?> txControl , YdbTxState other ) {
30+ this .transactionLevel = other .transactionLevel ;
31+ this .isReadOnly = other .isReadOnly ;
32+ this .isAutoCommit = other .isAutoCommit ;
33+ this .txControl = txControl ;
2134 }
2235
2336 @ Override
2437 public String toString () {
25- return "NoTx" + transactionLevel ;
38+ return "NoTx" ;
2639 }
2740
2841 public String txID () {
2942 return null ;
3043 }
3144
45+ public boolean isInsideTransaction () {
46+ return false ;
47+ }
48+
3249 public TxControl <?> txControl () {
3350 return txControl ;
3451 }
3552
3653 public boolean isAutoCommit () {
37- return txControl . isCommitTx () ;
54+ return isAutoCommit ;
3855 }
3956
4057 public boolean isReadOnly () {
41- return transactionLevel != YdbConst . TRANSACTION_SERIALIZABLE_READ_WRITE ;
58+ return isReadOnly ;
4259 }
4360
44- public boolean isInsideTransaction () {
45- return false ;
46- }
47-
48- public int transactionLevel () throws SQLException {
61+ public int transactionLevel () {
4962 return transactionLevel ;
5063 }
5164
5265 public YdbTxState withAutoCommit (boolean newAutoCommit ) throws SQLException {
53- if (newAutoCommit == isAutoCommit () ) {
66+ if (newAutoCommit == isAutoCommit ) {
5467 return this ;
5568 }
56- return create (transactionLevel (), newAutoCommit );
69+
70+ if (isInsideTransaction ()) {
71+ throw new SQLFeatureNotSupportedException (YdbConst .CHANGE_ISOLATION_INSIDE_TX );
72+ }
73+
74+ return emptyTx (transactionLevel , isReadOnly , newAutoCommit );
5775 }
5876
59- public YdbTxState withReadOnly (boolean readOnly ) throws SQLException {
60- if (readOnly == isReadOnly ()) {
77+ public YdbTxState withReadOnly (boolean newReadOnly ) throws SQLException {
78+ if (newReadOnly == isReadOnly ()) {
6179 return this ;
6280 }
6381
64- if (readOnly ) {
65- return create (YdbConst .ONLINE_CONSISTENT_READ_ONLY , isAutoCommit ());
66- } else {
67- return create (YdbConst .TRANSACTION_SERIALIZABLE_READ_WRITE , isAutoCommit ());
82+ if (isInsideTransaction ()) {
83+ throw new SQLFeatureNotSupportedException (YdbConst .READONLY_INSIDE_TRANSACTION );
6884 }
85+
86+ return emptyTx (transactionLevel , newReadOnly , isAutoCommit );
6987 }
7088
7189 public YdbTxState withTransactionLevel (int newTransactionLevel ) throws SQLException {
72- if (newTransactionLevel == transactionLevel () ) {
90+ if (newTransactionLevel == transactionLevel ) {
7391 return this ;
7492 }
7593
76- return create (newTransactionLevel , isAutoCommit ());
94+ if (isInsideTransaction ()) {
95+ throw new SQLFeatureNotSupportedException (YdbConst .CHANGE_ISOLATION_INSIDE_TX );
96+ }
97+
98+ boolean newReadOnly = isReadOnly || newTransactionLevel != Connection .TRANSACTION_SERIALIZABLE ;
99+ return emptyTx (newTransactionLevel , newReadOnly , isAutoCommit );
77100 }
78101
79102 public YdbTxState withCommit (Session session ) {
@@ -93,7 +116,7 @@ public YdbTxState withKeepAlive(Session session) {
93116
94117 public YdbTxState withDataQuery (Session session , String txID ) {
95118 if (txID != null && !txID .isEmpty ()) {
96- return new TransactionInProgress (txID , session , isAutoCommit () );
119+ return new TransactionInProgress (txID , session , this );
97120 }
98121
99122 session .close ();
@@ -104,88 +127,59 @@ public Session getSession(YdbContext ctx, YdbExecutor executor) throws SQLExcept
104127 return executor .createSession (ctx );
105128 }
106129
107- public static YdbTxState create (int level , boolean autoCommit ) throws SQLException {
108- return create (null , null , level , autoCommit );
109- }
130+ private static TxControl <?> txControl (int level , boolean isReadOnly , boolean isAutoCommit ) throws SQLException {
131+ if (!isReadOnly ) {
132+ // YDB support only one RW mode
133+ if (level != Connection .TRANSACTION_SERIALIZABLE ) {
134+ throw new SQLException (YdbConst .UNSUPPORTED_TRANSACTION_LEVEL + level );
135+ }
136+
137+ return TxControl .serializableRw ().setCommitTx (isAutoCommit );
138+ }
110139
111- private static YdbTxState create (Session session , String txId , int level , boolean autoCommit )
112- throws SQLException {
113140 switch (level ) {
114- case YdbConst .TRANSACTION_SERIALIZABLE_READ_WRITE :
115- if (txId != null ) {
116- return new TransactionInProgress (txId , session , autoCommit );
117- } else {
118- if (autoCommit ) {
119- return new YdbTxState (TxControl .serializableRw (), level );
120- } else {
121- return new EmptyTransaction ();
122- }
123- }
141+ case Connection .TRANSACTION_SERIALIZABLE :
142+ return TxControl .snapshotRo ().setCommitTx (isAutoCommit );
124143 case YdbConst .ONLINE_CONSISTENT_READ_ONLY :
125- return new YdbTxState (TxControl .onlineRo (), level );
126- case YdbConst .STALE_CONSISTENT_READ_ONLY :
127- return new YdbTxState (TxControl .staleRo (), level );
144+ return TxControl .onlineRo ().setAllowInconsistentReads (false ).setCommitTx (isAutoCommit );
128145 case YdbConst .ONLINE_INCONSISTENT_READ_ONLY :
129- return new YdbTxState (TxControl .onlineRo ().setAllowInconsistentReads (true ), level );
146+ return TxControl .onlineRo ().setAllowInconsistentReads (true ).setCommitTx (isAutoCommit );
147+ case YdbConst .STALE_CONSISTENT_READ_ONLY :
148+ return TxControl .staleRo ().setCommitTx (isAutoCommit );
130149 default :
131150 throw new SQLException (YdbConst .UNSUPPORTED_TRANSACTION_LEVEL + level );
132151 }
133152 }
134153
135- private static class EmptyTransaction extends YdbTxState {
136- EmptyTransaction () {
137- super (TxControl .serializableRw ().setCommitTx (false ), YdbConst .TRANSACTION_SERIALIZABLE_READ_WRITE );
138- }
139-
140- @ Override
141- public String toString () {
142- return "EmptyTx" + transactionLevel ;
143- }
144-
145- @ Override
146- public YdbTxState withDataQuery (Session session , String txID ) {
147- if (txID != null && !txID .isEmpty ()) {
148- return new TransactionInProgress (txID , session , isAutoCommit ());
149- }
154+ private static YdbTxState emptyTx (int level , boolean isReadOnly , boolean isAutoCommit ) throws SQLException {
155+ TxControl <?> tx = txControl (level , isReadOnly , isAutoCommit );
156+ return new YdbTxState (tx , level , isReadOnly , isAutoCommit );
157+ }
150158
151- session .close ();
152- return this ;
153- }
159+ public static YdbTxState create (int level , boolean isAutoCommit ) throws SQLException {
160+ return emptyTx (level , level != Connection .TRANSACTION_SERIALIZABLE , isAutoCommit );
154161 }
155162
156163 private static class TransactionInProgress extends YdbTxState {
157- private final String id ;
164+ private final String txID ;
158165 private final Session session ;
166+ private final YdbTxState previos ;
159167
160- TransactionInProgress (String id , Session session , boolean autoCommit ) {
161- super (TxControl .id (id ).setCommitTx (autoCommit ), YdbConst . TRANSACTION_SERIALIZABLE_READ_WRITE );
162- this .id = id ;
168+ TransactionInProgress (String id , Session session , YdbTxState previosState ) {
169+ super (TxControl .id (id ).setCommitTx (previosState . isAutoCommit ), previosState );
170+ this .txID = id ;
163171 this .session = session ;
172+ this .previos = previosState ;
164173 }
165174
166175 @ Override
167176 public String toString () {
168- return "InTx" + transactionLevel + "[" + id + "]" ;
177+ return "InTx" + transactionLevel () + "[" + txID + "]" ;
169178 }
170179
171180 @ Override
172181 public String txID () {
173- return id ;
174- }
175-
176- @ Override
177- public YdbTxState withAutoCommit (boolean newAutoCommit ) throws SQLException {
178- throw new SQLFeatureNotSupportedException (YdbConst .CHANGE_ISOLATION_INSIDE_TX );
179- }
180-
181- @ Override
182- public YdbTxState withTransactionLevel (int newTransactionLevel ) throws SQLException {
183- throw new SQLFeatureNotSupportedException (YdbConst .CHANGE_ISOLATION_INSIDE_TX );
184- }
185-
186- @ Override
187- public YdbTxState withReadOnly (boolean readOnly ) throws SQLException {
188- throw new SQLFeatureNotSupportedException (YdbConst .READONLY_INSIDE_TRANSACTION );
182+ return txID ;
189183 }
190184
191185 @ Override
@@ -201,13 +195,13 @@ public Session getSession(YdbContext ctx, YdbExecutor executor) throws SQLExcept
201195 @ Override
202196 public YdbTxState withCommit (Session session ) {
203197 session .close ();
204- return new EmptyTransaction () ;
198+ return previos ;
205199 }
206200
207201 @ Override
208202 public YdbTxState withRollback (Session session ) {
209203 session .close ();
210- return new EmptyTransaction () ;
204+ return previos ;
211205 }
212206
213207 @ Override
@@ -222,15 +216,15 @@ public YdbTxState withDataQuery(Session session, String txID) {
222216 session .close ();
223217 }
224218 this .session .close ();
225- return new EmptyTransaction () ;
219+ return previos ;
226220 }
227221
228- if (this . id . equals (txID )) {
222+ if (txID . equals (txID () )) {
229223 if (this .session == session ) {
230224 return this ;
231225 }
232226 this .session .close ();
233- return new TransactionInProgress (txID , session , isAutoCommit () );
227+ return new TransactionInProgress (txID , session , previos );
234228 }
235229
236230 session .close ();
0 commit comments