1313 * @author Aleksandr Gorshenin
1414 */
1515public class YdbTxState {
16+ private final int transactionLevel ;
17+ private final boolean isReadOnly ;
18+ private final boolean isAutoCommit ;
19+
1620 private final TxControl <?> txControl ;
17- protected final int transactionLevel ;
1821
19- protected YdbTxState (TxControl <?> tx , int level ) {
20- this .txControl = tx ;
22+ protected YdbTxState (TxControl <?> txControl , int level , boolean isReadOnly , boolean isAutoCommit ) {
2123 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 ;
2234 }
2335
2436 @ Override
2537 public String toString () {
26- return "NoTx" + transactionLevel ;
38+ return "NoTx" ;
2739 }
2840
2941 public String txID () {
3042 return null ;
3143 }
3244
45+ public boolean isInsideTransaction () {
46+ return false ;
47+ }
48+
3349 public TxControl <?> txControl () {
3450 return txControl ;
3551 }
3652
3753 public boolean isAutoCommit () {
38- return txControl . isCommitTx () ;
54+ return isAutoCommit ;
3955 }
4056
4157 public boolean isReadOnly () {
42- return transactionLevel != Connection . TRANSACTION_SERIALIZABLE ;
58+ return isReadOnly ;
4359 }
4460
45- public boolean isInsideTransaction () {
46- return false ;
47- }
48-
49- public int transactionLevel () throws SQLException {
61+ public int transactionLevel () {
5062 return transactionLevel ;
5163 }
5264
5365 public YdbTxState withAutoCommit (boolean newAutoCommit ) throws SQLException {
54- if (newAutoCommit == isAutoCommit () ) {
66+ if (newAutoCommit == isAutoCommit ) {
5567 return this ;
5668 }
57- 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 );
5875 }
5976
60- public YdbTxState withReadOnly (boolean readOnly ) throws SQLException {
61- if (readOnly == isReadOnly ()) {
77+ public YdbTxState withReadOnly (boolean newReadOnly ) throws SQLException {
78+ if (newReadOnly == isReadOnly ()) {
6279 return this ;
6380 }
6481
65- if (readOnly ) {
66- return create (YdbConst .ONLINE_CONSISTENT_READ_ONLY , isAutoCommit ());
67- } else {
68- return create (Connection .TRANSACTION_SERIALIZABLE , isAutoCommit ());
82+ if (isInsideTransaction ()) {
83+ throw new SQLFeatureNotSupportedException (YdbConst .READONLY_INSIDE_TRANSACTION );
6984 }
85+
86+ return emptyTx (transactionLevel , newReadOnly , isAutoCommit );
7087 }
7188
7289 public YdbTxState withTransactionLevel (int newTransactionLevel ) throws SQLException {
73- if (newTransactionLevel == transactionLevel () ) {
90+ if (newTransactionLevel == transactionLevel ) {
7491 return this ;
7592 }
7693
77- 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 );
78100 }
79101
80102 public YdbTxState withCommit (Session session ) {
@@ -94,7 +116,7 @@ public YdbTxState withKeepAlive(Session session) {
94116
95117 public YdbTxState withDataQuery (Session session , String txID ) {
96118 if (txID != null && !txID .isEmpty ()) {
97- return new TransactionInProgress (txID , session , isAutoCommit () );
119+ return new TransactionInProgress (txID , session , this );
98120 }
99121
100122 session .close ();
@@ -105,88 +127,59 @@ public Session getSession(YdbContext ctx, YdbExecutor executor) throws SQLExcept
105127 return executor .createSession (ctx );
106128 }
107129
108- public static YdbTxState create (int level , boolean autoCommit ) throws SQLException {
109- return create (null , null , level , autoCommit );
110- }
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+ }
111139
112- private static YdbTxState create (Session session , String txId , int level , boolean autoCommit )
113- throws SQLException {
114140 switch (level ) {
115141 case Connection .TRANSACTION_SERIALIZABLE :
116- if (txId != null ) {
117- return new TransactionInProgress (txId , session , autoCommit );
118- } else {
119- if (autoCommit ) {
120- return new YdbTxState (TxControl .serializableRw (), level );
121- } else {
122- return new EmptyTransaction ();
123- }
124- }
142+ return TxControl .snapshotRo ().setCommitTx (isAutoCommit );
125143 case YdbConst .ONLINE_CONSISTENT_READ_ONLY :
126- return new YdbTxState (TxControl .onlineRo (), level );
127- case YdbConst .STALE_CONSISTENT_READ_ONLY :
128- return new YdbTxState (TxControl .staleRo (), level );
144+ return TxControl .onlineRo ().setAllowInconsistentReads (false ).setCommitTx (isAutoCommit );
129145 case YdbConst .ONLINE_INCONSISTENT_READ_ONLY :
130- 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 );
131149 default :
132150 throw new SQLException (YdbConst .UNSUPPORTED_TRANSACTION_LEVEL + level );
133151 }
134152 }
135153
136- private static class EmptyTransaction extends YdbTxState {
137- EmptyTransaction () {
138- super (TxControl .serializableRw ().setCommitTx (false ), Connection .TRANSACTION_SERIALIZABLE );
139- }
140-
141- @ Override
142- public String toString () {
143- return "EmptyTx" + transactionLevel ;
144- }
145-
146- @ Override
147- public YdbTxState withDataQuery (Session session , String txID ) {
148- if (txID != null && !txID .isEmpty ()) {
149- return new TransactionInProgress (txID , session , isAutoCommit ());
150- }
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+ }
151158
152- session .close ();
153- return this ;
154- }
159+ public static YdbTxState create (int level , boolean isAutoCommit ) throws SQLException {
160+ return emptyTx (level , level != Connection .TRANSACTION_SERIALIZABLE , isAutoCommit );
155161 }
156162
157163 private static class TransactionInProgress extends YdbTxState {
158- private final String id ;
164+ private final String txID ;
159165 private final Session session ;
166+ private final YdbTxState previos ;
160167
161- TransactionInProgress (String id , Session session , boolean autoCommit ) {
162- super (TxControl .id (id ).setCommitTx (autoCommit ), Connection . TRANSACTION_SERIALIZABLE );
163- this .id = id ;
168+ TransactionInProgress (String id , Session session , YdbTxState previosState ) {
169+ super (TxControl .id (id ).setCommitTx (previosState . isAutoCommit ), previosState );
170+ this .txID = id ;
164171 this .session = session ;
172+ this .previos = previosState ;
165173 }
166174
167175 @ Override
168176 public String toString () {
169- return "InTx" + transactionLevel + "[" + id + "]" ;
177+ return "InTx" + transactionLevel () + "[" + txID + "]" ;
170178 }
171179
172180 @ Override
173181 public String txID () {
174- return id ;
175- }
176-
177- @ Override
178- public YdbTxState withAutoCommit (boolean newAutoCommit ) throws SQLException {
179- throw new SQLFeatureNotSupportedException (YdbConst .CHANGE_ISOLATION_INSIDE_TX );
180- }
181-
182- @ Override
183- public YdbTxState withTransactionLevel (int newTransactionLevel ) throws SQLException {
184- throw new SQLFeatureNotSupportedException (YdbConst .CHANGE_ISOLATION_INSIDE_TX );
185- }
186-
187- @ Override
188- public YdbTxState withReadOnly (boolean readOnly ) throws SQLException {
189- throw new SQLFeatureNotSupportedException (YdbConst .READONLY_INSIDE_TRANSACTION );
182+ return txID ;
190183 }
191184
192185 @ Override
@@ -202,13 +195,13 @@ public Session getSession(YdbContext ctx, YdbExecutor executor) throws SQLExcept
202195 @ Override
203196 public YdbTxState withCommit (Session session ) {
204197 session .close ();
205- return new EmptyTransaction () ;
198+ return previos ;
206199 }
207200
208201 @ Override
209202 public YdbTxState withRollback (Session session ) {
210203 session .close ();
211- return new EmptyTransaction () ;
204+ return previos ;
212205 }
213206
214207 @ Override
@@ -223,15 +216,15 @@ public YdbTxState withDataQuery(Session session, String txID) {
223216 session .close ();
224217 }
225218 this .session .close ();
226- return new EmptyTransaction () ;
219+ return previos ;
227220 }
228221
229- if (this . id . equals (txID )) {
222+ if (txID . equals (txID () )) {
230223 if (this .session == session ) {
231224 return this ;
232225 }
233226 this .session .close ();
234- return new TransactionInProgress (txID , session , isAutoCommit () );
227+ return new TransactionInProgress (txID , session , previos );
235228 }
236229
237230 session .close ();
0 commit comments