23
23
from google .cloud .spanner_v1 import RequestOptions
24
24
from google .cloud .spanner_v1 .session import _get_retry_delay
25
25
from google .cloud .spanner_v1 .snapshot import Snapshot
26
+ from deprecated import deprecated
26
27
27
28
from google .cloud .spanner_dbapi .checksum import _compare_checksums
28
29
from google .cloud .spanner_dbapi .checksum import ResultsChecksum
35
36
36
37
37
38
CLIENT_TRANSACTION_NOT_STARTED_WARNING = (
38
- "This method is non-operational as transaction has not started"
39
+ "This method is non-operational as a transaction has not been started. "
39
40
)
40
41
MAX_INTERNAL_RETRIES = 50
41
42
@@ -107,6 +108,9 @@ def __init__(self, instance, database=None, read_only=False):
107
108
self ._staleness = None
108
109
self .request_priority = None
109
110
self ._transaction_begin_marked = False
111
+ # whether transaction started at Spanner. This means that we had
112
+ # made atleast one call to Spanner.
113
+ self ._spanner_transaction_started = False
110
114
111
115
@property
112
116
def autocommit (self ):
@@ -140,26 +144,15 @@ def database(self):
140
144
return self ._database
141
145
142
146
@property
143
- def _spanner_transaction_started (self ):
144
- """Flag: whether transaction started at Spanner. This means that we had
145
- made atleast one call to Spanner. Property client_transaction_started
146
- would always be true if this is true as transaction has to start first
147
- at clientside than at Spanner
148
-
149
- Returns:
150
- bool: True if Spanner transaction started, False otherwise.
151
- """
147
+ @deprecated (
148
+ reason = "This method is deprecated. Use _spanner_transaction_started field"
149
+ )
150
+ def inside_transaction (self ):
152
151
return (
153
152
self ._transaction
154
153
and not self ._transaction .committed
155
154
and not self ._transaction .rolled_back
156
- ) or (self ._snapshot is not None )
157
-
158
- @property
159
- def inside_transaction (self ):
160
- """Deprecated property which won't be supported in future versions.
161
- Please use spanner_transaction_started property instead."""
162
- return self ._spanner_transaction_started
155
+ )
163
156
164
157
@property
165
158
def _client_transaction_started (self ):
@@ -277,7 +270,8 @@ def _release_session(self):
277
270
"""
278
271
if self .database is None :
279
272
raise ValueError ("Database needs to be passed for this operation" )
280
- self .database ._pool .put (self ._session )
273
+ if self ._session is not None :
274
+ self .database ._pool .put (self ._session )
281
275
self ._session = None
282
276
283
277
def retry_transaction (self ):
@@ -293,7 +287,7 @@ def retry_transaction(self):
293
287
"""
294
288
attempt = 0
295
289
while True :
296
- self ._transaction = None
290
+ self ._spanner_transaction_started = False
297
291
attempt += 1
298
292
if attempt > MAX_INTERNAL_RETRIES :
299
293
raise
@@ -319,7 +313,6 @@ def _rerun_previous_statements(self):
319
313
status , res = transaction .batch_update (statements )
320
314
321
315
if status .code == ABORTED :
322
- self .connection ._transaction = None
323
316
raise Aborted (status .details )
324
317
325
318
retried_checksum = ResultsChecksum ()
@@ -363,6 +356,8 @@ def transaction_checkout(self):
363
356
if not self .read_only and self ._client_transaction_started :
364
357
if not self ._spanner_transaction_started :
365
358
self ._transaction = self ._session_checkout ().transaction ()
359
+ self ._snapshot = None
360
+ self ._spanner_transaction_started = True
366
361
self ._transaction .begin ()
367
362
368
363
return self ._transaction
@@ -377,11 +372,13 @@ def snapshot_checkout(self):
377
372
:returns: A Cloud Spanner snapshot object, ready to use.
378
373
"""
379
374
if self .read_only and self ._client_transaction_started :
380
- if not self ._snapshot :
375
+ if not self ._spanner_transaction_started :
381
376
self ._snapshot = Snapshot (
382
377
self ._session_checkout (), multi_use = True , ** self .staleness
383
378
)
379
+ self ._transaction = None
384
380
self ._snapshot .begin ()
381
+ self ._spanner_transaction_started = True
385
382
386
383
return self ._snapshot
387
384
@@ -391,7 +388,7 @@ def close(self):
391
388
The connection will be unusable from this point forward. If the
392
389
connection has an active transaction, it will be rolled back.
393
390
"""
394
- if self ._spanner_transaction_started and not self .read_only :
391
+ if self ._spanner_transaction_started and not self ._read_only :
395
392
self ._transaction .rollback ()
396
393
397
394
if self ._own_pool and self .database :
@@ -405,13 +402,15 @@ def begin(self):
405
402
Marks the transaction as started.
406
403
407
404
:raises: :class:`InterfaceError`: if this connection is closed.
408
- :raises: :class:`OperationalError`: if there is an existing transaction that has begin or is running
405
+ :raises: :class:`OperationalError`: if there is an existing transaction
406
+ that has been started
409
407
"""
410
408
if self ._transaction_begin_marked :
411
409
raise OperationalError ("A transaction has already started" )
412
410
if self ._spanner_transaction_started :
413
411
raise OperationalError (
414
- "Beginning a new transaction is not allowed when a transaction is already running"
412
+ "Beginning a new transaction is not allowed when a transaction "
413
+ "is already running"
415
414
)
416
415
self ._transaction_begin_marked = True
417
416
@@ -430,41 +429,37 @@ def commit(self):
430
429
return
431
430
432
431
self .run_prior_DDL_statements ()
433
- if self ._spanner_transaction_started :
434
- try :
435
- if self .read_only :
436
- self ._snapshot = None
437
- else :
438
- self ._transaction .commit ()
439
-
440
- self ._release_session ()
441
- self ._statements = []
442
- self ._transaction_begin_marked = False
443
- except Aborted :
444
- self .retry_transaction ()
445
- self .commit ()
432
+ try :
433
+ if self ._spanner_transaction_started and not self ._read_only :
434
+ self ._transaction .commit ()
435
+ except Aborted :
436
+ self .retry_transaction ()
437
+ self .commit ()
438
+ finally :
439
+ self ._release_session ()
440
+ self ._statements = []
441
+ self ._transaction_begin_marked = False
442
+ self ._spanner_transaction_started = False
446
443
447
444
def rollback (self ):
448
445
"""Rolls back any pending transaction.
449
446
450
447
This is a no-op if there is no active client transaction.
451
448
"""
452
-
453
449
if not self ._client_transaction_started :
454
450
warnings .warn (
455
451
CLIENT_TRANSACTION_NOT_STARTED_WARNING , UserWarning , stacklevel = 2
456
452
)
457
453
return
458
454
459
- if self ._spanner_transaction_started :
460
- if self .read_only :
461
- self ._snapshot = None
462
- else :
455
+ try :
456
+ if self ._spanner_transaction_started and not self ._read_only :
463
457
self ._transaction .rollback ()
464
-
458
+ finally :
465
459
self ._release_session ()
466
460
self ._statements = []
467
461
self ._transaction_begin_marked = False
462
+ self ._spanner_transaction_started = False
468
463
469
464
@check_not_closed
470
465
def cursor (self ):
0 commit comments