@@ -1173,7 +1173,7 @@ def execute_scheme(self, yql_text, settings=None):
11731173 pass
11741174
11751175 @abstractmethod
1176- def transaction (self , tx_mode = None ):
1176+ def transaction (self , tx_mode = None , deny_split_transactions = True ):
11771177 pass
11781178
11791179 @abstractmethod
@@ -1677,8 +1677,14 @@ def execute_scheme(self, yql_text, settings=None):
16771677 self ._state .endpoint ,
16781678 )
16791679
1680- def transaction (self , tx_mode = None ):
1681- return TxContext (self ._driver , self ._state , self , tx_mode )
1680+ def transaction (self , tx_mode = None , deny_split_transactions = True ):
1681+ return TxContext (
1682+ self ._driver ,
1683+ self ._state ,
1684+ self ,
1685+ tx_mode ,
1686+ deny_split_transactions = deny_split_transactions ,
1687+ )
16821688
16831689 def has_prepared (self , query ):
16841690 return query in self ._state
@@ -2189,9 +2195,27 @@ def begin(self, settings=None):
21892195
21902196
21912197class BaseTxContext (ITxContext ):
2192- __slots__ = ("_tx_state" , "_session_state" , "_driver" , "session" )
2198+ __slots__ = (
2199+ "_tx_state" ,
2200+ "_session_state" ,
2201+ "_driver" ,
2202+ "session" ,
2203+ "_finished" ,
2204+ "_deny_split_transactions" ,
2205+ )
21932206
2194- def __init__ (self , driver , session_state , session , tx_mode = None ):
2207+ _COMMIT = "commit"
2208+ _ROLLBACK = "rollback"
2209+
2210+ def __init__ (
2211+ self ,
2212+ driver ,
2213+ session_state ,
2214+ session ,
2215+ tx_mode = None ,
2216+ * ,
2217+ deny_split_transactions = True
2218+ ):
21952219 """
21962220 An object that provides a simple transaction context manager that allows statements execution
21972221 in a transaction. You don't have to open transaction explicitly, because context manager encapsulates
@@ -2214,6 +2238,8 @@ def __init__(self, driver, session_state, session, tx_mode=None):
22142238 self ._tx_state = _tx_ctx_impl .TxState (tx_mode )
22152239 self ._session_state = session_state
22162240 self .session = session
2241+ self ._finished = ""
2242+ self ._deny_split_transactions = deny_split_transactions
22172243
22182244 def __enter__ (self ):
22192245 """
@@ -2271,6 +2297,9 @@ def execute(self, query, parameters=None, commit_tx=False, settings=None):
22712297
22722298 :return: A result sets or exception in case of execution errors
22732299 """
2300+
2301+ self ._check_split ()
2302+
22742303 return self ._driver (
22752304 _tx_ctx_impl .execute_request_factory (
22762305 self ._session_state ,
@@ -2297,8 +2326,12 @@ def commit(self, settings=None):
22972326
22982327 :return: A committed transaction or exception if commit is failed
22992328 """
2329+
2330+ self ._set_finish (self ._COMMIT )
2331+
23002332 if self ._tx_state .tx_id is None and not self ._tx_state .dead :
23012333 return self
2334+
23022335 return self ._driver (
23032336 _tx_ctx_impl .commit_request_factory (self ._session_state , self ._tx_state ),
23042337 _apis .TableService .Stub ,
@@ -2318,8 +2351,12 @@ def rollback(self, settings=None):
23182351
23192352 :return: A rolled back transaction or exception if rollback is failed
23202353 """
2354+
2355+ self ._set_finish (self ._ROLLBACK )
2356+
23212357 if self ._tx_state .tx_id is None and not self ._tx_state .dead :
23222358 return self
2359+
23232360 return self ._driver (
23242361 _tx_ctx_impl .rollback_request_factory (self ._session_state , self ._tx_state ),
23252362 _apis .TableService .Stub ,
@@ -2340,6 +2377,9 @@ def begin(self, settings=None):
23402377 """
23412378 if self ._tx_state .tx_id is not None :
23422379 return self
2380+
2381+ self ._check_split ()
2382+
23432383 return self ._driver (
23442384 _tx_ctx_impl .begin_request_factory (self ._session_state , self ._tx_state ),
23452385 _apis .TableService .Stub ,
@@ -2350,6 +2390,21 @@ def begin(self, settings=None):
23502390 self ._session_state .endpoint ,
23512391 )
23522392
2393+ def _set_finish (self , val ):
2394+ self ._check_split (val )
2395+ self ._finished = val
2396+
2397+ def _check_split (self , allow = "" ):
2398+ """
2399+ Deny all operaions with transaction after commit/rollback.
2400+ Exception: double commit and double rollbacks, because it is safe
2401+ """
2402+ if not self ._deny_split_transactions :
2403+ return
2404+
2405+ if self ._finished != "" and self ._finished != allow :
2406+ raise RuntimeError ("Any operation with finished transaction is denied" )
2407+
23532408
23542409class TxContext (BaseTxContext ):
23552410 @_utilities .wrap_async_call_exceptions
@@ -2365,6 +2420,9 @@ def async_execute(self, query, parameters=None, commit_tx=False, settings=None):
23652420
23662421 :return: A future of query execution
23672422 """
2423+
2424+ self ._check_split ()
2425+
23682426 return self ._driver .future (
23692427 _tx_ctx_impl .execute_request_factory (
23702428 self ._session_state ,
@@ -2396,8 +2454,11 @@ def async_commit(self, settings=None):
23962454
23972455 :return: A future of commit call
23982456 """
2457+ self ._set_finish (self ._COMMIT )
2458+
23992459 if self ._tx_state .tx_id is None and not self ._tx_state .dead :
24002460 return _utilities .wrap_result_in_future (self )
2461+
24012462 return self ._driver .future (
24022463 _tx_ctx_impl .commit_request_factory (self ._session_state , self ._tx_state ),
24032464 _apis .TableService .Stub ,
@@ -2418,8 +2479,11 @@ def async_rollback(self, settings=None):
24182479
24192480 :return: A future of rollback call
24202481 """
2482+ self ._set_finish (self ._ROLLBACK )
2483+
24212484 if self ._tx_state .tx_id is None and not self ._tx_state .dead :
24222485 return _utilities .wrap_result_in_future (self )
2486+
24232487 return self ._driver .future (
24242488 _tx_ctx_impl .rollback_request_factory (self ._session_state , self ._tx_state ),
24252489 _apis .TableService .Stub ,
@@ -2441,6 +2505,9 @@ def async_begin(self, settings=None):
24412505 """
24422506 if self ._tx_state .tx_id is not None :
24432507 return _utilities .wrap_result_in_future (self )
2508+
2509+ self ._check_split ()
2510+
24442511 return self ._driver .future (
24452512 _tx_ctx_impl .begin_request_factory (self ._session_state , self ._tx_state ),
24462513 _apis .TableService .Stub ,
0 commit comments