Skip to content

Commit 3253ded

Browse files
authored
chore: delay transaction activation until actual use (#552)
* chore: store temp TransactionOptions in connection state Store temporary TransactionOptions in the connection state as local options. Local options only apply to the current transaction. This simplifies the internal state handling of the driver, as all transaction state should only be read from the connection state, and not also from a temporary variable. This also enables the use of a combination of temporary transaction options and using SQL statements to set further options. The shared library always includes temporary transaction options, as the BeginTransaction function accepts TransactionOptions as an input argument. This meant that using SQL statements to set further transaction options was not supported through the shared library. * chore: delay transaction activation until actual use Delay the actual transaction activation until the first actual usage of the transaction. That is; the first time that a statement is being sent to Spanner. This allows the application to amend the transaction options after calling BeginTx or executing `BEGIN TRANSACTION`. The transaction options can be amended by executing a statement like `SET TRANSACTION READ ONLY`.
1 parent e8de7f7 commit 3253ded

File tree

13 files changed

+381
-167
lines changed

13 files changed

+381
-167
lines changed

aborted_transactions_test.go

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,9 @@ func TestCommitAborted(t *testing.T) {
4141
if err != nil {
4242
t.Fatalf("begin failed: %v", err)
4343
}
44+
if _, err := tx.ExecContext(ctx, testutil.UpdateBarSetFoo); err != nil {
45+
t.Fatal(err)
46+
}
4447
server.TestSpanner.PutExecutionTime(testutil.MethodCommitTransaction, testutil.SimulatedExecutionTime{
4548
Errors: []error{status.Error(codes.Aborted, "Aborted")},
4649
})
@@ -51,7 +54,7 @@ func TestCommitAborted(t *testing.T) {
5154
reqs := server.TestSpanner.DrainRequestsFromServer()
5255
commitReqs := testutil.RequestsOfType(reqs, reflect.TypeOf(&sppb.CommitRequest{}))
5356
if g, w := len(commitReqs), 2; g != w {
54-
t.Fatalf("commit request count mismatch\nGot: %v\nWant: %v", g, w)
57+
t.Fatalf("commit request count mismatch\n Got: %v\nWant: %v", g, w)
5558
}
5659

5760
// Verify that the db is still usable.
@@ -117,6 +120,9 @@ func TestCommitAbortedWithInternalRetriesDisabled(t *testing.T) {
117120
if err != nil {
118121
t.Fatalf("begin failed: %v", err)
119122
}
123+
if _, err := tx.ExecContext(ctx, testutil.UpdateBarSetFoo); err != nil {
124+
t.Fatal(err)
125+
}
120126
server.TestSpanner.PutExecutionTime(testutil.MethodCommitTransaction, testutil.SimulatedExecutionTime{
121127
Errors: []error{status.Error(codes.Aborted, "Aborted")},
122128
})

client_side_statement_test.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ func TestStatementExecutor_StartBatchDdl(t *testing.T) {
6565
}
6666

6767
// Starting a DDL batch while the connection is in a transaction is not allowed.
68-
c.tx = &readWriteTransaction{}
68+
c.tx = &delegatingTransaction{conn: c, ctx: ctx}
6969
if _, err := c.ExecContext(ctx, "start batch ddl", []driver.NamedValue{}); spanner.ErrCode(err) != codes.FailedPrecondition {
7070
t.Fatalf("error mismatch for starting a DDL batch while in a transaction\nGot: %v\nWant: %v", spanner.ErrCode(err), codes.FailedPrecondition)
7171
}
@@ -102,13 +102,13 @@ func TestStatementExecutor_StartBatchDml(t *testing.T) {
102102
}
103103

104104
// Starting a DML batch while the connection is in a read-only transaction is not allowed.
105-
c.tx = &readOnlyTransaction{logger: noopLogger}
105+
c.tx = &delegatingTransaction{conn: c, contextTransaction: &readOnlyTransaction{logger: noopLogger}}
106106
if _, err := c.ExecContext(ctx, "start batch dml", []driver.NamedValue{}); spanner.ErrCode(err) != codes.FailedPrecondition {
107107
t.Fatalf("error mismatch for starting a DML batch while in a read-only transaction\nGot: %v\nWant: %v", spanner.ErrCode(err), codes.FailedPrecondition)
108108
}
109109

110110
// Starting a DML batch while the connection is in a read/write transaction is allowed.
111-
c.tx = &readWriteTransaction{logger: noopLogger}
111+
c.tx = &delegatingTransaction{conn: c, contextTransaction: &readWriteTransaction{logger: noopLogger}}
112112
if _, err := c.ExecContext(ctx, "start batch dml", []driver.NamedValue{}); err != nil {
113113
t.Fatalf("could not start a DML batch while in a read/write transaction: %v", err)
114114
}

0 commit comments

Comments
 (0)