@@ -275,8 +275,9 @@ type conn struct {
275275	// tempExecOptions can be set by passing it in as an argument to ExecContext or QueryContext 
276276	// and are applied only to that statement. 
277277	tempExecOptions  * ExecOptions 
278- 	// tempTransactionOptions are temporarily set right before a read/write transaction is started. 
279- 	tempTransactionOptions  * ReadWriteTransactionOptions 
278+ 	// tempTransactionCloseFunc is set right before a transaction is started, and is set as the 
279+ 	// close function for that transaction. 
280+ 	tempTransactionCloseFunc  func ()
280281	// tempReadOnlyTransactionOptions are temporarily set right before a read-only 
281282	// transaction is started on a Spanner connection. 
282283	tempReadOnlyTransactionOptions  * ReadOnlyTransactionOptions 
@@ -1011,8 +1012,10 @@ func (c *conn) options(reset bool) *ExecOptions {
10111012			TransactionTag :              c .TransactionTag (),
10121013			IsolationLevel :              toProtoIsolationLevelOrDefault (c .IsolationLevel ()),
10131014			ReadLockMode :                c .ReadLockMode (),
1015+ 			CommitPriority :              propertyCommitPriority .GetValueOrDefault (c .state ),
10141016			CommitOptions : spanner.CommitOptions {
1015- 				MaxCommitDelay : c .maxCommitDelayPointer (),
1017+ 				MaxCommitDelay :    c .maxCommitDelayPointer (),
1018+ 				ReturnCommitStats : propertyReturnCommitStats .GetValueOrDefault (c .state ),
10161019			},
10171020		},
10181021		PartitionedQueryOptions : PartitionedQueryOptions {},
@@ -1045,16 +1048,43 @@ func (c *conn) resetTransactionForRetry(ctx context.Context, errDuringCommit boo
10451048}
10461049
10471050func  (c  * conn ) withTempTransactionOptions (options  * ReadWriteTransactionOptions ) {
1048- 	c .tempTransactionOptions  =  options 
1051+ 	if  options  ==  nil  {
1052+ 		return 
1053+ 	}
1054+ 	c .tempTransactionCloseFunc  =  options .close 
1055+ 	// Start a transaction for the connection state, so we can set the transaction options 
1056+ 	// as local options in the current transaction. 
1057+ 	_  =  c .state .Begin ()
1058+ 	if  options .DisableInternalRetries  {
1059+ 		_  =  propertyRetryAbortsInternally .SetLocalValue (c .state , ! options .DisableInternalRetries )
1060+ 	}
1061+ 	if  options .TransactionOptions .BeginTransactionOption  !=  spanner .DefaultBeginTransaction  {
1062+ 		_  =  propertyBeginTransactionOption .SetLocalValue (c .state , options .TransactionOptions .BeginTransactionOption )
1063+ 	}
1064+ 	if  options .TransactionOptions .CommitOptions .MaxCommitDelay  !=  nil  {
1065+ 		_  =  propertyMaxCommitDelay .SetLocalValue (c .state , * options .TransactionOptions .CommitOptions .MaxCommitDelay )
1066+ 	}
1067+ 	if  options .TransactionOptions .CommitOptions .ReturnCommitStats  {
1068+ 		_  =  propertyReturnCommitStats .SetLocalValue (c .state , options .TransactionOptions .CommitOptions .ReturnCommitStats )
1069+ 	}
1070+ 	if  options .TransactionOptions .TransactionTag  !=  ""  {
1071+ 		_  =  propertyTransactionTag .SetLocalValue (c .state , options .TransactionOptions .TransactionTag )
1072+ 	}
1073+ 	if  options .TransactionOptions .ReadLockMode  !=  spannerpb .TransactionOptions_ReadWrite_READ_LOCK_MODE_UNSPECIFIED  {
1074+ 		_  =  propertyReadLockMode .SetLocalValue (c .state , options .TransactionOptions .ReadLockMode )
1075+ 	}
1076+ 	if  options .TransactionOptions .IsolationLevel  !=  spannerpb .TransactionOptions_ISOLATION_LEVEL_UNSPECIFIED  {
1077+ 		_  =  propertyIsolationLevel .SetLocalValue (c .state , toSqlIsolationLevelOrDefault (options .TransactionOptions .IsolationLevel ))
1078+ 	}
1079+ 	if  options .TransactionOptions .ExcludeTxnFromChangeStreams  {
1080+ 		_  =  propertyExcludeTxnFromChangeStreams .SetLocalValue (c .state , options .TransactionOptions .ExcludeTxnFromChangeStreams )
1081+ 	}
1082+ 	if  options .TransactionOptions .CommitPriority  !=  spannerpb .RequestOptions_PRIORITY_UNSPECIFIED  {
1083+ 		_  =  propertyCommitPriority .SetLocalValue (c .state , options .TransactionOptions .CommitPriority )
1084+ 	}
10491085}
10501086
10511087func  (c  * conn ) getTransactionOptions (execOptions  * ExecOptions ) ReadWriteTransactionOptions  {
1052- 	if  c .tempTransactionOptions  !=  nil  {
1053- 		defer  func () { c .tempTransactionOptions  =  nil  }()
1054- 		opts  :=  * c .tempTransactionOptions 
1055- 		opts .TransactionOptions .BeginTransactionOption  =  c .convertDefaultBeginTransactionOption (opts .TransactionOptions .BeginTransactionOption )
1056- 		return  opts 
1057- 	}
10581088	txOpts  :=  ReadWriteTransactionOptions {
10591089		TransactionOptions :     execOptions .TransactionOptions ,
10601090		DisableInternalRetries : ! c .RetryAbortsInternally (),
@@ -1122,7 +1152,6 @@ func (c *conn) BeginReadWriteTransaction(ctx context.Context, options *ReadWrite
11221152	c .withTempTransactionOptions (options )
11231153	tx , err  :=  c .BeginTx (ctx , driver.TxOptions {})
11241154	if  err  !=  nil  {
1125- 		c .withTempTransactionOptions (nil )
11261155		return  nil , err 
11271156	}
11281157	return  tx , nil 
@@ -1133,6 +1162,13 @@ func (c *conn) Begin() (driver.Tx, error) {
11331162}
11341163
11351164func  (c  * conn ) BeginTx (ctx  context.Context , driverOpts  driver.TxOptions ) (driver.Tx , error ) {
1165+ 	defer  func () {
1166+ 		c .tempTransactionCloseFunc  =  nil 
1167+ 	}()
1168+ 	return  c .beginTx (ctx , driverOpts , c .tempTransactionCloseFunc )
1169+ }
1170+ 
1171+ func  (c  * conn ) beginTx (ctx  context.Context , driverOpts  driver.TxOptions , closeFunc  func ()) (driver.Tx , error ) {
11361172	if  c .resetForRetry  {
11371173		c .resetForRetry  =  false 
11381174		return  c .tx , nil 
@@ -1141,6 +1177,10 @@ func (c *conn) BeginTx(ctx context.Context, driverOpts driver.TxOptions) (driver
11411177	defer  func () {
11421178		if  c .tx  !=  nil  {
11431179			_  =  c .state .Begin ()
1180+ 		} else  {
1181+ 			// Rollback in case the connection state transaction was started before this function 
1182+ 			// was called, for example if the caller set temporary transaction options. 
1183+ 			_  =  c .state .Rollback ()
11441184		}
11451185	}()
11461186
@@ -1219,17 +1259,18 @@ func (c *conn) BeginTx(ctx context.Context, driverOpts driver.TxOptions) (driver
12191259		return  c .tx , nil 
12201260	}
12211261
1262+ 	// These options are only used to determine how to start the transaction. 
1263+ 	// All other options are fetched in a callback that is called when the transaction is actually started. 
1264+ 	// That callback reads all transaction options from the connection state at that moment. This allows 
1265+ 	// applications to execute a series of statement like this: 
1266+ 	// BEGIN TRANSACTION; 
1267+ 	// SET LOCAL transaction_tag='my_tag'; 
1268+ 	// SET LOCAL commit_priority=LOW; 
1269+ 	// INSERT INTO my_table ... -- This starts the transaction with the options above included. 
12221270	opts  :=  spanner.TransactionOptions {}
1223- 	if  c .tempTransactionOptions  !=  nil  {
1224- 		opts  =  c .tempTransactionOptions .TransactionOptions 
1225- 	}
1226- 	opts .BeginTransactionOption  =  c .convertDefaultBeginTransactionOption (opts .BeginTransactionOption )
1227- 	tempCloseFunc  :=  func () {}
1228- 	if  c .tempTransactionOptions  !=  nil  &&  c .tempTransactionOptions .close  !=  nil  {
1229- 		tempCloseFunc  =  c .tempTransactionOptions .close 
1230- 	}
1231- 	if  ! disableRetryAborts  &&  c .tempTransactionOptions  !=  nil  {
1232- 		disableRetryAborts  =  c .tempTransactionOptions .DisableInternalRetries 
1271+ 	opts .BeginTransactionOption  =  c .convertDefaultBeginTransactionOption (propertyBeginTransactionOption .GetValueOrDefault (c .state ))
1272+ 	if  closeFunc  ==  nil  {
1273+ 		closeFunc  =  func () {}
12331274	}
12341275
12351276	tx , err  :=  spanner .NewReadWriteStmtBasedTransactionWithCallbackForOptions (ctx , c .client , opts , func () spanner.TransactionOptions  {
@@ -1249,7 +1290,7 @@ func (c *conn) BeginTx(ctx context.Context, driverOpts driver.TxOptions) (driver
12491290		logger : logger ,
12501291		rwTx :   tx ,
12511292		close : func (result  txResult , commitResponse  * spanner.CommitResponse , commitErr  error ) {
1252- 			tempCloseFunc ()
1293+ 			closeFunc ()
12531294			c .prevTx  =  c .tx 
12541295			c .tx  =  nil 
12551296			if  commitErr  ==  nil  {
0 commit comments