aboutsummaryrefslogtreecommitdiff
path: root/src/database/sql/sql.go
diff options
context:
space:
mode:
authorDaniel Theophanes <kardianos@gmail.com>2016-10-16 23:11:55 -0700
committerBrad Fitzpatrick <bradfitz@golang.org>2016-10-30 17:05:28 +0000
commitce6aa2ebdab0c6616ef17acc9282b0e168f5f21a (patch)
treed2760dee9bb27c34f113f15152b72431b1d1497c /src/database/sql/sql.go
parent042264ef1b073b1b485e6e24977e506e1a6bdb3f (diff)
downloadgo-ce6aa2ebdab0c6616ef17acc9282b0e168f5f21a.tar.xz
database/sql: add context helper methods and transaction types
Prior to this change, it was implied that transaction properties would be carried in the context value. However, no such properties were defined, not even common ones. Define two common properties: isolation level and read-only. Drivers may choose to support additional transaction properties. It is not expected any further transaction properties will be added in the future. Change-Id: I2f680115a14a1333c65ba6f943d9a1149d412918 Reviewed-on: https://go-review.googlesource.com/31258 Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
Diffstat (limited to 'src/database/sql/sql.go')
-rw-r--r--src/database/sql/sql.go44
1 files changed, 40 insertions, 4 deletions
diff --git a/src/database/sql/sql.go b/src/database/sql/sql.go
index d363008993..3cef4b6404 100644
--- a/src/database/sql/sql.go
+++ b/src/database/sql/sql.go
@@ -15,6 +15,7 @@ package sql
import (
"context"
"database/sql/driver"
+ "database/sql/internal"
"errors"
"fmt"
"io"
@@ -89,6 +90,38 @@ func Param(name string, value interface{}) NamedParam {
return NamedParam{Name: name, Value: value}
}
+// IsolationLevel is the transaction isolation level stored in Context.
+// The IsolationLevel is set with IsolationContext and the context
+// should be passed to BeginContext.
+type IsolationLevel int
+
+// Various isolation levels that drivers may support in BeginContext.
+// If a driver does not support a given isolation level an error may be returned.
+const (
+ LevelDefault IsolationLevel = iota
+ LevelReadUncommited
+ LevelReadCommited
+ LevelWriteCommited
+ LevelRepeatableRead
+ LevelSnapshot
+ LevelSerializable
+ LevelLinearizable
+)
+
+// IsolationContext returns a new Context that carries the provided isolation level.
+// The context must contain the isolation level before beginning the transaction
+// with BeginContext.
+func IsolationContext(ctx context.Context, level IsolationLevel) context.Context {
+ return context.WithValue(ctx, internal.IsolationLevelKey{}, driver.IsolationLevel(level))
+}
+
+// ReadOnlyWithContext returns a new Context that carries the provided
+// read-only transaction property. The context must contain the read-only property
+// before beginning the transaction with BeginContext.
+func ReadOnlyContext(ctx context.Context) context.Context {
+ return context.WithValue(ctx, internal.ReadOnlyKey{}, true)
+}
+
// RawBytes is a byte slice that holds a reference to memory owned by
// the database itself. After a Scan into a RawBytes, the slice is only
// valid until the next call to Next, Scan, or Close.
@@ -1224,7 +1257,10 @@ func (db *DB) QueryRow(query string, args ...interface{}) *Row {
return db.QueryRowContext(context.Background(), query, args...)
}
-// BeginContext starts a transaction. If a non-default isolation level is used
+// BeginContext starts a transaction.
+//
+// An isolation level may be set by setting the value in the context
+// before calling this. If a non-default isolation level is used
// that the driver doesn't support an error will be returned. Different drivers
// may have slightly different meanings for the same isolation level.
func (db *DB) BeginContext(ctx context.Context) (*Tx, error) {
@@ -2212,9 +2248,9 @@ func (rs *Rows) isClosed() bool {
return atomic.LoadInt32(&rs.closed) != 0
}
-// Close closes the Rows, preventing further enumeration. If Next and
-// NextResultSet both return
-// false, the Rows are closed automatically and it will suffice to check the
+// Close closes the Rows, preventing further enumeration. If Next is called
+// and returns false and there are no further result sets,
+// the Rows are closed automatically and it will suffice to check the
// result of Err. Close is idempotent and does not affect the result of Err.
func (rs *Rows) Close() error {
if !atomic.CompareAndSwapInt32(&rs.closed, 0, 1) {