@@ -53,6 +53,8 @@ type contextTransaction interface {
5353 AbortBatch () (driver.Result , error )
5454
5555 BufferWrite (ms []* spanner.Mutation ) error
56+
57+ setRetryAbortsInternally (retry bool ) (driver.Result , error )
5658}
5759
5860type rowIterator interface {
@@ -195,6 +197,11 @@ func (tx *readOnlyTransaction) BufferWrite([]*spanner.Mutation) error {
195197 return spanner .ToSpannerError (status .Errorf (codes .FailedPrecondition , "read-only transactions cannot write" ))
196198}
197199
200+ func (tx * readOnlyTransaction ) setRetryAbortsInternally (_ bool ) (driver.Result , error ) {
201+ // no-op, ignore
202+ return driver .ResultNoRows , nil
203+ }
204+
198205// ErrAbortedDueToConcurrentModification is returned by a read/write transaction
199206// that was aborted by Cloud Spanner, and where the internal retry attempt
200207// failed because it detected that the results during the retry were different
@@ -222,6 +229,8 @@ type readWriteTransaction struct {
222229 // rwTx is the underlying Spanner read/write transaction. This transaction
223230 // will be replaced with a new one if the initial transaction is aborted.
224231 rwTx * spanner.ReadWriteStmtBasedTransaction
232+ // active indicates whether at least one statement has been executed on this transaction.
233+ active bool
225234 // batch is any DML batch that is active for this transaction.
226235 batch * batch
227236 close func (commitTs * time.Time , commitErr error )
@@ -391,6 +400,7 @@ func (tx *readWriteTransaction) retry(ctx context.Context) (err error) {
391400// unless internal retries have been disabled.
392401func (tx * readWriteTransaction ) Commit () (err error ) {
393402 tx .logger .Debug ("committing transaction" )
403+ tx .active = true
394404 if err := tx .maybeRunAutoDmlBatch (tx .ctx ); err != nil {
395405 _ = tx .rollback (tx .ctx )
396406 return err
@@ -447,6 +457,7 @@ func (tx *readWriteTransaction) resetForRetry(ctx context.Context) error {
447457// transaction is aborted during the query or while iterating the returned rows.
448458func (tx * readWriteTransaction ) Query (ctx context.Context , stmt spanner.Statement , execOptions ExecOptions ) (rowIterator , error ) {
449459 tx .logger .Debug ("Query" , "stmt" , stmt .SQL )
460+ tx .active = true
450461 if err := tx .maybeRunAutoDmlBatch (ctx ); err != nil {
451462 return nil , err
452463 }
@@ -478,6 +489,7 @@ func (tx *readWriteTransaction) partitionQuery(ctx context.Context, stmt spanner
478489
479490func (tx * readWriteTransaction ) ExecContext (ctx context.Context , stmt spanner.Statement , statementInfo * statementInfo , options spanner.QueryOptions ) (res * result , err error ) {
480491 tx .logger .Debug ("ExecContext" , "stmt" , stmt .SQL )
492+ tx .active = true
481493 if tx .batch != nil {
482494 tx .logger .Debug ("adding statement to batch" )
483495 tx .batch .statements = append (tx .batch .statements , stmt )
@@ -515,6 +527,7 @@ func (tx *readWriteTransaction) StartBatchDML(options spanner.QueryOptions, auto
515527 return nil , spanner .ToSpannerError (status .Errorf (codes .FailedPrecondition , "This transaction already has an active batch." ))
516528 }
517529 tx .logger .Debug ("starting dml batch in transaction" , "automatic" , automatic )
530+ tx .active = true
518531 tx .batch = & batch {tp : dml , options : ExecOptions {QueryOptions : options }, automatic : automatic }
519532 return driver .ResultNoRows , nil
520533}
@@ -629,3 +642,11 @@ func errorsEqualForRetry(err1, err2 error) bool {
629642 }
630643 return false
631644}
645+
646+ func (tx * readWriteTransaction ) setRetryAbortsInternally (retry bool ) (driver.Result , error ) {
647+ if tx .active {
648+ return nil , spanner .ToSpannerError (status .Error (codes .FailedPrecondition , "cannot change retry mode while a transaction is active" ))
649+ }
650+ tx .retryAborts = retry
651+ return driver .ResultNoRows , nil
652+ }
0 commit comments