Skip to content

Commit 1803771

Browse files
committed
chore: move connection variables to connection state
Move individual connection variables to the generic connection state.
1 parent 4825aa4 commit 1803771

11 files changed

+739
-275
lines changed

client_side_statement_test.go

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ import (
3131
)
3232

3333
func TestStatementExecutor_StartBatchDdl(t *testing.T) {
34-
c := &conn{retryAborts: true, logger: noopLogger, state: createInitialConnectionState(connectionstate.TypeNonTransactional, map[string]connectionstate.ConnectionPropertyValue{})}
34+
c := &conn{logger: noopLogger, state: createInitialConnectionState(connectionstate.TypeNonTransactional, map[string]connectionstate.ConnectionPropertyValue{})}
3535
s := &statementExecutor{}
3636
ctx := context.Background()
3737

@@ -62,7 +62,7 @@ func TestStatementExecutor_StartBatchDdl(t *testing.T) {
6262
}
6363

6464
func TestStatementExecutor_StartBatchDml(t *testing.T) {
65-
c := &conn{retryAborts: true, logger: noopLogger, state: createInitialConnectionState(connectionstate.TypeNonTransactional, map[string]connectionstate.ConnectionPropertyValue{})}
65+
c := &conn{logger: noopLogger, state: createInitialConnectionState(connectionstate.TypeNonTransactional, map[string]connectionstate.ConnectionPropertyValue{})}
6666
s := &statementExecutor{}
6767
ctx := context.Background()
6868

@@ -99,7 +99,7 @@ func TestStatementExecutor_StartBatchDml(t *testing.T) {
9999
}
100100

101101
func TestStatementExecutor_RetryAbortsInternally(t *testing.T) {
102-
c := &conn{retryAborts: true, logger: noopLogger, state: createInitialConnectionState(connectionstate.TypeNonTransactional, map[string]connectionstate.ConnectionPropertyValue{})}
102+
c := &conn{logger: noopLogger, state: createInitialConnectionState(connectionstate.TypeNonTransactional, map[string]connectionstate.ConnectionPropertyValue{})}
103103
s := &statementExecutor{}
104104
ctx := context.Background()
105105
for i, test := range []struct {
@@ -283,7 +283,7 @@ func TestStatementExecutor_ReadOnlyStaleness(t *testing.T) {
283283
func TestShowCommitTimestamp(t *testing.T) {
284284
t.Parallel()
285285

286-
c := &conn{retryAborts: true, logger: noopLogger, state: createInitialConnectionState(connectionstate.TypeNonTransactional, map[string]connectionstate.ConnectionPropertyValue{})}
286+
c := &conn{logger: noopLogger, state: createInitialConnectionState(connectionstate.TypeNonTransactional, map[string]connectionstate.ConnectionPropertyValue{})}
287287
s := &statementExecutor{}
288288
ctx := context.Background()
289289

@@ -329,7 +329,7 @@ func TestShowCommitTimestamp(t *testing.T) {
329329
}
330330

331331
func TestStatementExecutor_ExcludeTxnFromChangeStreams(t *testing.T) {
332-
c := &conn{retryAborts: true, logger: noopLogger, state: createInitialConnectionState(connectionstate.TypeNonTransactional, map[string]connectionstate.ConnectionPropertyValue{})}
332+
c := &conn{logger: noopLogger, state: createInitialConnectionState(connectionstate.TypeNonTransactional, map[string]connectionstate.ConnectionPropertyValue{})}
333333
s := &statementExecutor{}
334334
ctx := context.Background()
335335
for i, test := range []struct {
@@ -458,7 +458,7 @@ func TestStatementExecutor_SetTransactionTag(t *testing.T) {
458458
{"", "tag-with-missing-opening-quote'", true},
459459
{"", "'tag-with-missing-closing-quote", true},
460460
} {
461-
c := &conn{retryAborts: true, logger: noopLogger, state: createInitialConnectionState(connectionstate.TypeNonTransactional, map[string]connectionstate.ConnectionPropertyValue{})}
461+
c := &conn{logger: noopLogger, state: createInitialConnectionState(connectionstate.TypeNonTransactional, map[string]connectionstate.ConnectionPropertyValue{})}
462462
s := &statementExecutor{}
463463

464464
it, err := s.ShowTransactionTag(ctx, c, "", ExecOptions{}, nil)
@@ -518,7 +518,7 @@ func TestStatementExecutor_SetTransactionTag(t *testing.T) {
518518

519519
func TestStatementExecutor_UsesExecOptions(t *testing.T) {
520520
ctx := context.Background()
521-
c := &conn{retryAborts: true, logger: noopLogger, state: createInitialConnectionState(connectionstate.TypeNonTransactional, map[string]connectionstate.ConnectionPropertyValue{})}
521+
c := &conn{logger: noopLogger, state: createInitialConnectionState(connectionstate.TypeNonTransactional, map[string]connectionstate.ConnectionPropertyValue{})}
522522
s := &statementExecutor{}
523523

524524
it, err := s.ShowTransactionTag(ctx, c, "", ExecOptions{DecodeOption: DecodeOptionProto, ReturnResultSetMetadata: true, ReturnResultSetStats: true}, nil)

conn.go

Lines changed: 28 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -225,7 +225,6 @@ type conn struct {
225225
resetForRetry bool
226226
commitResponse *spanner.CommitResponse
227227
database string
228-
retryAborts bool
229228

230229
execSingleQuery func(ctx context.Context, c *spanner.Client, statement spanner.Statement, bound spanner.TimestampBound, options ExecOptions) *spanner.RowIterator
231230
execSingleQueryTransactional func(ctx context.Context, c *spanner.Client, statement spanner.Statement, options ExecOptions) (rowIterator, *spanner.CommitResponse, error)
@@ -236,25 +235,6 @@ type conn struct {
236235
state *connectionstate.ConnectionState
237236
// batch is the currently active DDL or DML batch on this connection.
238237
batch *batch
239-
// autoBatchDml determines whether DML statements should automatically
240-
// be batched and sent to Spanner when a non-DML statement is encountered.
241-
autoBatchDml bool
242-
// autoBatchDmlUpdateCount determines the update count that is returned for
243-
// DML statements that are executed when autoBatchDml is true.
244-
autoBatchDmlUpdateCount int64
245-
// autoBatchDmlUpdateCountVerification enables/disables the verification
246-
// that the update count that was returned for automatically batched DML
247-
// statements was correct.
248-
autoBatchDmlUpdateCountVerification bool
249-
250-
// readOnlyStaleness is used for queries in autocommit mode and for read-only transactions.
251-
readOnlyStaleness spanner.TimestampBound
252-
// isolationLevel determines the default isolation level that is used for read/write
253-
// transactions on this connection. This default is ignored if the BeginTx function is
254-
// called with an isolation level other than sql.LevelDefault.
255-
isolationLevel sql.IsolationLevel
256-
// beginTransactionOption determines the default transactions start mode.
257-
beginTransactionOption spanner.BeginTransactionOption
258238

259239
// execOptions are applied to the next statement or transaction that is executed
260240
// on this connection. It can also be set by passing it in as an argument to
@@ -289,7 +269,7 @@ func (c *conn) CommitResponse() (commitResponse *spanner.CommitResponse, err err
289269
}
290270

291271
func (c *conn) RetryAbortsInternally() bool {
292-
return c.retryAborts
272+
return propertyRetryAbortsInternally.GetValueOrDefault(c.state)
293273
}
294274

295275
func (c *conn) SetRetryAbortsInternally(retry bool) error {
@@ -299,9 +279,13 @@ func (c *conn) SetRetryAbortsInternally(retry bool) error {
299279

300280
func (c *conn) setRetryAbortsInternally(retry bool) (driver.Result, error) {
301281
if c.inTransaction() {
302-
return c.tx.setRetryAbortsInternally(retry)
282+
if _, err := c.tx.setRetryAbortsInternally(retry); err != nil {
283+
return nil, err
284+
}
285+
}
286+
if err := propertyRetryAbortsInternally.SetValue(c.state, retry, connectionstate.ContextUser); err != nil {
287+
return nil, err
303288
}
304-
c.retryAborts = retry
305289
return driver.ResultNoRows, nil
306290
}
307291

@@ -325,7 +309,7 @@ func (c *conn) setAutocommitDMLMode(mode AutocommitDMLMode) (driver.Result, erro
325309
}
326310

327311
func (c *conn) ReadOnlyStaleness() spanner.TimestampBound {
328-
return c.readOnlyStaleness
312+
return propertyReadOnlyStaleness.GetValueOrDefault(c.state)
329313
}
330314

331315
func (c *conn) SetReadOnlyStaleness(staleness spanner.TimestampBound) error {
@@ -334,17 +318,18 @@ func (c *conn) SetReadOnlyStaleness(staleness spanner.TimestampBound) error {
334318
}
335319

336320
func (c *conn) setReadOnlyStaleness(staleness spanner.TimestampBound) (driver.Result, error) {
337-
c.readOnlyStaleness = staleness
321+
if err := propertyReadOnlyStaleness.SetValue(c.state, staleness, connectionstate.ContextUser); err != nil {
322+
return nil, err
323+
}
338324
return driver.ResultNoRows, nil
339325
}
340326

341327
func (c *conn) IsolationLevel() sql.IsolationLevel {
342-
return c.isolationLevel
328+
return propertyIsolationLevel.GetValueOrDefault(c.state)
343329
}
344330

345331
func (c *conn) SetIsolationLevel(level sql.IsolationLevel) error {
346-
c.isolationLevel = level
347-
return nil
332+
return propertyIsolationLevel.SetValue(c.state, level, connectionstate.ContextUser)
348333
}
349334

350335
func (c *conn) MaxCommitDelay() time.Duration {
@@ -419,30 +404,27 @@ func (c *conn) setStatementTag(statementTag string) (driver.Result, error) {
419404
}
420405

421406
func (c *conn) AutoBatchDml() bool {
422-
return c.autoBatchDml
407+
return propertyAutoBatchDml.GetValueOrDefault(c.state)
423408
}
424409

425410
func (c *conn) SetAutoBatchDml(autoBatch bool) error {
426-
c.autoBatchDml = autoBatch
427-
return nil
411+
return propertyAutoBatchDml.SetValue(c.state, autoBatch, connectionstate.ContextUser)
428412
}
429413

430414
func (c *conn) AutoBatchDmlUpdateCount() int64 {
431-
return c.autoBatchDmlUpdateCount
415+
return propertyAutoBatchDmlUpdateCount.GetValueOrDefault(c.state)
432416
}
433417

434418
func (c *conn) SetAutoBatchDmlUpdateCount(updateCount int64) error {
435-
c.autoBatchDmlUpdateCount = updateCount
436-
return nil
419+
return propertyAutoBatchDmlUpdateCount.SetValue(c.state, updateCount, connectionstate.ContextUser)
437420
}
438421

439422
func (c *conn) AutoBatchDmlUpdateCountVerification() bool {
440-
return c.autoBatchDmlUpdateCountVerification
423+
return propertyAutoBatchDmlUpdateCountVerification.GetValueOrDefault(c.state)
441424
}
442425

443426
func (c *conn) SetAutoBatchDmlUpdateCountVerification(verify bool) error {
444-
c.autoBatchDmlUpdateCountVerification = verify
445-
return nil
427+
return propertyAutoBatchDmlUpdateCountVerification.SetValue(c.state, verify, connectionstate.ContextUser)
446428
}
447429

448430
func (c *conn) StartBatchDDL() error {
@@ -683,16 +665,8 @@ func (c *conn) ResetSession(_ context.Context) error {
683665
}
684666
c.commitResponse = nil
685667
c.batch = nil
686-
c.autoBatchDml = c.connector.connectorConfig.AutoBatchDml
687-
c.autoBatchDmlUpdateCount = c.connector.connectorConfig.AutoBatchDmlUpdateCount
688-
c.autoBatchDmlUpdateCountVerification = !c.connector.connectorConfig.DisableAutoBatchDmlUpdateCountVerification
689-
c.retryAborts = c.connector.retryAbortsInternally
690-
c.isolationLevel = c.connector.connectorConfig.IsolationLevel
691-
c.beginTransactionOption = c.connector.connectorConfig.BeginTransactionOption
692668

693669
_ = c.state.Reset(connectionstate.ContextUser)
694-
// TODO: Reset the following fields to the connector default
695-
c.readOnlyStaleness = spanner.TimestampBound{}
696670
c.execOptions = ExecOptions{
697671
DecodeToNativeArrays: c.connector.connectorConfig.DecodeToNativeArrays,
698672
}
@@ -817,7 +791,7 @@ func (c *conn) queryContext(ctx context.Context, query string, execOptions ExecO
817791
// The statement was either detected as being a query, or potentially not recognized at all.
818792
// In that case, just default to using a single-use read-only transaction and let Spanner
819793
// return an error if the statement is not suited for that type of transaction.
820-
iter = &readOnlyRowIterator{c.execSingleQuery(ctx, c.client, stmt, c.readOnlyStaleness, execOptions)}
794+
iter = &readOnlyRowIterator{c.execSingleQuery(ctx, c.client, stmt, c.ReadOnlyStaleness(), execOptions)}
821795
}
822796
} else {
823797
if execOptions.PartitionedQueryOptions.PartitionQuery {
@@ -875,7 +849,7 @@ func (c *conn) execContext(ctx context.Context, query string, execOptions ExecOp
875849
}
876850

877851
// Start an automatic DML batch.
878-
if c.autoBatchDml && !c.inBatch() && c.inReadWriteTransaction() {
852+
if c.AutoBatchDml() && !c.inBatch() && c.inReadWriteTransaction() {
879853
if _, err := c.startBatchDML( /* automatic = */ true); err != nil {
880854
return nil, err
881855
}
@@ -964,19 +938,19 @@ func (c *conn) getTransactionOptions() ReadWriteTransactionOptions {
964938
}()
965939
txOpts := ReadWriteTransactionOptions{
966940
TransactionOptions: c.execOptions.TransactionOptions,
967-
DisableInternalRetries: !c.retryAborts,
941+
DisableInternalRetries: !c.RetryAbortsInternally(),
968942
}
969943
// Only use the default isolation level from the connection if the ExecOptions
970944
// did not contain a more specific isolation level.
971945
if txOpts.TransactionOptions.IsolationLevel == spannerpb.TransactionOptions_ISOLATION_LEVEL_UNSPECIFIED {
972946
// This should never really return an error, but we check just to be absolutely sure.
973-
level, err := toProtoIsolationLevel(c.isolationLevel)
947+
level, err := toProtoIsolationLevel(c.IsolationLevel())
974948
if err == nil {
975949
txOpts.TransactionOptions.IsolationLevel = level
976950
}
977951
}
978952
if txOpts.TransactionOptions.BeginTransactionOption == spanner.DefaultBeginTransaction {
979-
txOpts.TransactionOptions.BeginTransactionOption = c.convertDefaultBeginTransactionOption(c.beginTransactionOption)
953+
txOpts.TransactionOptions.BeginTransactionOption = c.convertDefaultBeginTransactionOption(propertyBeginTransactionOption.GetValueOrDefault(c.state))
980954
}
981955
return txOpts
982956
}
@@ -992,7 +966,7 @@ func (c *conn) getReadOnlyTransactionOptions() ReadOnlyTransactionOptions {
992966
opts.BeginTransactionOption = c.convertDefaultBeginTransactionOption(opts.BeginTransactionOption)
993967
return opts
994968
}
995-
return ReadOnlyTransactionOptions{TimestampBound: c.readOnlyStaleness, BeginTransactionOption: c.convertDefaultBeginTransactionOption(c.beginTransactionOption)}
969+
return ReadOnlyTransactionOptions{TimestampBound: c.ReadOnlyStaleness(), BeginTransactionOption: c.convertDefaultBeginTransactionOption(propertyBeginTransactionOption.GetValueOrDefault(c.state))}
996970
}
997971

998972
func (c *conn) withTempBatchReadOnlyTransactionOptions(options *BatchReadOnlyTransactionOptions) {
@@ -1004,7 +978,7 @@ func (c *conn) getBatchReadOnlyTransactionOptions() BatchReadOnlyTransactionOpti
1004978
defer func() { c.tempBatchReadOnlyTransactionOptions = nil }()
1005979
return *c.tempBatchReadOnlyTransactionOptions
1006980
}
1007-
return BatchReadOnlyTransactionOptions{TimestampBound: c.readOnlyStaleness}
981+
return BatchReadOnlyTransactionOptions{TimestampBound: c.ReadOnlyStaleness()}
1008982
}
1009983

1010984
func (c *conn) Begin() (driver.Tx, error) {
@@ -1134,10 +1108,10 @@ func (c *conn) BeginTx(ctx context.Context, opts driver.TxOptions) (driver.Tx, e
11341108

11351109
func (c *conn) convertDefaultBeginTransactionOption(opt spanner.BeginTransactionOption) spanner.BeginTransactionOption {
11361110
if opt == spanner.DefaultBeginTransaction {
1137-
if c.beginTransactionOption == spanner.DefaultBeginTransaction {
1111+
if propertyBeginTransactionOption.GetValueOrDefault(c.state) == spanner.DefaultBeginTransaction {
11381112
return spanner.InlinedBeginTransaction
11391113
}
1140-
return c.beginTransactionOption
1114+
return propertyBeginTransactionOption.GetValueOrDefault(c.state)
11411115
}
11421116
return opt
11431117
}

conn_with_mockserver_test.go

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -551,3 +551,86 @@ func TestSetAutocommitDMLMode(t *testing.T) {
551551
})
552552
}
553553
}
554+
555+
func TestConfigureConnectionProperty(t *testing.T) {
556+
t.Parallel()
557+
558+
type config int
559+
const (
560+
configConnString config = iota
561+
configConnectorConfig
562+
configConnectorConfigAndParams
563+
)
564+
565+
for _, cfg := range []config{configConnString, configConnectorConfig, configConnectorConfigAndParams} {
566+
var db *sql.DB
567+
var teardown func()
568+
switch cfg {
569+
case configConnString:
570+
db, _, teardown = setupTestDBConnectionWithParams(t, "isolationLevel=repeatable_read")
571+
case configConnectorConfig:
572+
db, _, teardown = setupTestDBConnectionWithConnectorConfig(t, ConnectorConfig{
573+
Project: "p",
574+
Instance: "i",
575+
Database: "d",
576+
IsolationLevel: sql.LevelRepeatableRead,
577+
})
578+
case configConnectorConfigAndParams:
579+
db, _, teardown = setupTestDBConnectionWithConnectorConfig(t, ConnectorConfig{
580+
Project: "p",
581+
Instance: "i",
582+
Database: "d",
583+
IsolationLevel: sql.LevelSerializable,
584+
// The configuration in the params (which come from the connection string)
585+
// take precedence over the configuration in the ConnectorConfig.
586+
Params: map[string]string{
587+
"isolation_level": "repeatable_read",
588+
},
589+
})
590+
default:
591+
t.Fatalf("invalid config: %v", cfg)
592+
}
593+
defer teardown()
594+
// Limit the number of open connections to 1 to ensure that the test re-uses the same connection.
595+
db.SetMaxOpenConns(1)
596+
597+
// Repeat twice to ensure that we get a connection that has been reset
598+
// when getting a fresh connection from the pool
599+
for range 2 {
600+
sqlConn, err := db.Conn(context.Background())
601+
if err != nil {
602+
t.Fatal(err)
603+
}
604+
_ = sqlConn.Raw(func(driverConn interface{}) error {
605+
c, _ := driverConn.(SpannerConn)
606+
if g, w := c.IsolationLevel(), sql.LevelRepeatableRead; g != w {
607+
t.Fatalf("isolation level mismatch\n Got: %v\nWant: %v", g, w)
608+
}
609+
if err := c.SetIsolationLevel(sql.LevelSerializable); err != nil {
610+
t.Fatal(err)
611+
}
612+
if g, w := c.IsolationLevel(), sql.LevelSerializable; g != w {
613+
t.Fatalf("isolation level mismatch\n Got: %v\nWant: %v", g, w)
614+
}
615+
// Reset the connection manually (this should also happen automatically when the connection is closed).
616+
sc := c.(*conn)
617+
if err := sc.ResetSession(context.Background()); err != nil {
618+
t.Fatal(err)
619+
}
620+
// Verify that the isolation level is reset to the value it had when the connection was created.
621+
if g, w := c.IsolationLevel(), sql.LevelRepeatableRead; g != w {
622+
t.Fatalf("isolation level mismatch\n Got: %v\nWant: %v", g, w)
623+
}
624+
// Set the isolation level back to serializable in order to ensure that it is also correctly reset
625+
// when the connection is closed.
626+
if err := c.SetIsolationLevel(sql.LevelSerializable); err != nil {
627+
t.Fatal(err)
628+
}
629+
return nil
630+
})
631+
if err := sqlConn.Close(); err != nil {
632+
t.Fatal(err)
633+
}
634+
}
635+
}
636+
}

0 commit comments

Comments
 (0)