@@ -1176,7 +1176,7 @@ def execute_scheme(self, yql_text, settings=None):
11761176 pass
11771177
11781178 @abstractmethod
1179- def transaction (self , tx_mode = None ):
1179+ def transaction (self , tx_mode = None , deny_split_transactions = False ):
11801180 pass
11811181
11821182 @abstractmethod
@@ -1681,8 +1681,14 @@ def execute_scheme(self, yql_text, settings=None):
16811681 self ._state .endpoint ,
16821682 )
16831683
1684- def transaction (self , tx_mode = None ):
1685- return TxContext (self ._driver , self ._state , self , tx_mode )
1684+ def transaction (self , tx_mode = None , deny_split_transactions = False ):
1685+ return TxContext (
1686+ self ._driver ,
1687+ self ._state ,
1688+ self ,
1689+ tx_mode ,
1690+ deny_split_transactions = deny_split_transactions ,
1691+ )
16861692
16871693 def has_prepared (self , query ):
16881694 return query in self ._state
@@ -2194,9 +2200,27 @@ def begin(self, settings=None):
21942200
21952201
21962202class BaseTxContext (ITxContext ):
2197- __slots__ = ("_tx_state" , "_session_state" , "_driver" , "session" )
2203+ __slots__ = (
2204+ "_tx_state" ,
2205+ "_session_state" ,
2206+ "_driver" ,
2207+ "session" ,
2208+ "_finished" ,
2209+ "_deny_split_transactions" ,
2210+ )
21982211
2199- def __init__ (self , driver , session_state , session , tx_mode = None ):
2212+ _COMMIT = "commit"
2213+ _ROLLBACK = "rollback"
2214+
2215+ def __init__ (
2216+ self ,
2217+ driver ,
2218+ session_state ,
2219+ session ,
2220+ tx_mode = None ,
2221+ * ,
2222+ deny_split_transactions = False
2223+ ):
22002224 """
22012225 An object that provides a simple transaction context manager that allows statements execution
22022226 in a transaction. You don't have to open transaction explicitly, because context manager encapsulates
@@ -2219,6 +2243,8 @@ def __init__(self, driver, session_state, session, tx_mode=None):
22192243 self ._tx_state = _tx_ctx_impl .TxState (tx_mode )
22202244 self ._session_state = session_state
22212245 self .session = session
2246+ self ._finished = ""
2247+ self ._deny_split_transactions = deny_split_transactions
22222248
22232249 def __enter__ (self ):
22242250 """
@@ -2276,6 +2302,9 @@ def execute(self, query, parameters=None, commit_tx=False, settings=None):
22762302
22772303 :return: A result sets or exception in case of execution errors
22782304 """
2305+
2306+ self ._check_split ()
2307+
22792308 return self ._driver (
22802309 _tx_ctx_impl .execute_request_factory (
22812310 self ._session_state ,
@@ -2302,8 +2331,12 @@ def commit(self, settings=None):
23022331
23032332 :return: A committed transaction or exception if commit is failed
23042333 """
2334+
2335+ self ._set_finish (self ._COMMIT )
2336+
23052337 if self ._tx_state .tx_id is None and not self ._tx_state .dead :
23062338 return self
2339+
23072340 return self ._driver (
23082341 _tx_ctx_impl .commit_request_factory (self ._session_state , self ._tx_state ),
23092342 _apis .TableService .Stub ,
@@ -2323,8 +2356,12 @@ def rollback(self, settings=None):
23232356
23242357 :return: A rolled back transaction or exception if rollback is failed
23252358 """
2359+
2360+ self ._set_finish (self ._ROLLBACK )
2361+
23262362 if self ._tx_state .tx_id is None and not self ._tx_state .dead :
23272363 return self
2364+
23282365 return self ._driver (
23292366 _tx_ctx_impl .rollback_request_factory (self ._session_state , self ._tx_state ),
23302367 _apis .TableService .Stub ,
@@ -2345,6 +2382,9 @@ def begin(self, settings=None):
23452382 """
23462383 if self ._tx_state .tx_id is not None :
23472384 return self
2385+
2386+ self ._check_split ()
2387+
23482388 return self ._driver (
23492389 _tx_ctx_impl .begin_request_factory (self ._session_state , self ._tx_state ),
23502390 _apis .TableService .Stub ,
@@ -2355,6 +2395,21 @@ def begin(self, settings=None):
23552395 self ._session_state .endpoint ,
23562396 )
23572397
2398+ def _set_finish (self , val ):
2399+ self ._check_split (val )
2400+ self ._finished = val
2401+
2402+ def _check_split (self , allow = "" ):
2403+ """
2404+ Deny all operaions with transaction after commit/rollback.
2405+ Exception: double commit and double rollbacks, because it is safe
2406+ """
2407+ if not self ._deny_split_transactions :
2408+ return
2409+
2410+ if self ._finished != "" and self ._finished != allow :
2411+ raise RuntimeError ("Any operation with finished transaction is denied" )
2412+
23582413
23592414class TxContext (BaseTxContext ):
23602415 @_utilities .wrap_async_call_exceptions
@@ -2370,6 +2425,9 @@ def async_execute(self, query, parameters=None, commit_tx=False, settings=None):
23702425
23712426 :return: A future of query execution
23722427 """
2428+
2429+ self ._check_split ()
2430+
23732431 return self ._driver .future (
23742432 _tx_ctx_impl .execute_request_factory (
23752433 self ._session_state ,
@@ -2401,8 +2459,11 @@ def async_commit(self, settings=None):
24012459
24022460 :return: A future of commit call
24032461 """
2462+ self ._set_finish (self ._COMMIT )
2463+
24042464 if self ._tx_state .tx_id is None and not self ._tx_state .dead :
24052465 return _utilities .wrap_result_in_future (self )
2466+
24062467 return self ._driver .future (
24072468 _tx_ctx_impl .commit_request_factory (self ._session_state , self ._tx_state ),
24082469 _apis .TableService .Stub ,
@@ -2423,8 +2484,11 @@ def async_rollback(self, settings=None):
24232484
24242485 :return: A future of rollback call
24252486 """
2487+ self ._set_finish (self ._ROLLBACK )
2488+
24262489 if self ._tx_state .tx_id is None and not self ._tx_state .dead :
24272490 return _utilities .wrap_result_in_future (self )
2491+
24282492 return self ._driver .future (
24292493 _tx_ctx_impl .rollback_request_factory (self ._session_state , self ._tx_state ),
24302494 _apis .TableService .Stub ,
@@ -2446,6 +2510,9 @@ def async_begin(self, settings=None):
24462510 """
24472511 if self ._tx_state .tx_id is not None :
24482512 return _utilities .wrap_result_in_future (self )
2513+
2514+ self ._check_split ()
2515+
24492516 return self ._driver .future (
24502517 _tx_ctx_impl .begin_request_factory (self ._session_state , self ._tx_state ),
24512518 _apis .TableService .Stub ,
0 commit comments