aboutsummaryrefslogtreecommitdiff
path: root/libgo/go/database/sql
diff options
context:
space:
mode:
authorIan Lance Taylor <iant@golang.org>2021-07-30 14:28:58 -0700
committerIan Lance Taylor <iant@golang.org>2021-08-12 20:23:07 -0700
commitc5b21c3f4c17b0649155035d2f9aa97b2da8a813 (patch)
treec6d3a68b503ba5b16182acbb958e3e5dbc95a43b /libgo/go/database/sql
parent72be20e20299ec57b4bc9ba03d5b7d6bf10e97cc (diff)
downloadgcc-c5b21c3f4c17b0649155035d2f9aa97b2da8a813.zip
gcc-c5b21c3f4c17b0649155035d2f9aa97b2da8a813.tar.gz
gcc-c5b21c3f4c17b0649155035d2f9aa97b2da8a813.tar.bz2
libgo: update to Go1.17rc2
Reviewed-on: https://go-review.googlesource.com/c/gofrontend/+/341629
Diffstat (limited to 'libgo/go/database/sql')
-rw-r--r--libgo/go/database/sql/driver/driver.go3
-rw-r--r--libgo/go/database/sql/fakedb_test.go23
-rw-r--r--libgo/go/database/sql/sql.go104
-rw-r--r--libgo/go/database/sql/sql_test.go57
4 files changed, 170 insertions, 17 deletions
diff --git a/libgo/go/database/sql/driver/driver.go b/libgo/go/database/sql/driver/driver.go
index 5bbcf20..f093961 100644
--- a/libgo/go/database/sql/driver/driver.go
+++ b/libgo/go/database/sql/driver/driver.go
@@ -115,6 +115,9 @@ type DriverContext interface {
// DriverContext's OpenConnector method, to allow drivers
// access to context and to avoid repeated parsing of driver
// configuration.
+//
+// If a Connector implements io.Closer, the sql package's DB.Close
+// method will call Close and return error (if any).
type Connector interface {
// Connect returns a connection to the database.
// Connect may return a cached connection (one previously
diff --git a/libgo/go/database/sql/fakedb_test.go b/libgo/go/database/sql/fakedb_test.go
index 7605a2a..4b68f1c 100644
--- a/libgo/go/database/sql/fakedb_test.go
+++ b/libgo/go/database/sql/fakedb_test.go
@@ -56,6 +56,7 @@ type fakeConnector struct {
name string
waiter func(context.Context)
+ closed bool
}
func (c *fakeConnector) Connect(context.Context) (driver.Conn, error) {
@@ -68,6 +69,14 @@ func (c *fakeConnector) Driver() driver.Driver {
return fdriver
}
+func (c *fakeConnector) Close() error {
+ if c.closed {
+ return errors.New("fakedb: connector is closed")
+ }
+ c.closed = true
+ return nil
+}
+
type fakeDriverCtx struct {
fakeDriver
}
@@ -906,7 +915,7 @@ func (s *fakeStmt) QueryContext(ctx context.Context, args []driver.NamedValue) (
parentMem: s.c,
posRow: -1,
rows: [][]*row{
- []*row{
+ {
{
cols: []interface{}{
txStatus,
@@ -915,12 +924,12 @@ func (s *fakeStmt) QueryContext(ctx context.Context, args []driver.NamedValue) (
},
},
cols: [][]string{
- []string{
+ {
"tx_status",
},
},
colType: [][]string{
- []string{
+ {
"string",
},
},
@@ -1177,9 +1186,11 @@ func converterForType(typ string) driver.ValueConverter {
return driver.Bool
case "nullbool":
return driver.Null{Converter: driver.Bool}
+ case "byte", "int16":
+ return driver.NotNull{Converter: driver.DefaultParameterConverter}
case "int32":
return driver.Int32
- case "nullint32":
+ case "nullbyte", "nullint32", "nullint16":
return driver.Null{Converter: driver.DefaultParameterConverter}
case "string":
return driver.NotNull{Converter: fakeDriverString{}}
@@ -1213,6 +1224,10 @@ func colTypeToReflectType(typ string) reflect.Type {
return reflect.TypeOf(false)
case "nullbool":
return reflect.TypeOf(NullBool{})
+ case "int16":
+ return reflect.TypeOf(int16(0))
+ case "nullint16":
+ return reflect.TypeOf(NullInt16{})
case "int32":
return reflect.TypeOf(int32(0))
case "nullint32":
diff --git a/libgo/go/database/sql/sql.go b/libgo/go/database/sql/sql.go
index 726aadb..68fb392 100644
--- a/libgo/go/database/sql/sql.go
+++ b/libgo/go/database/sql/sql.go
@@ -260,6 +260,60 @@ func (n NullInt32) Value() (driver.Value, error) {
return int64(n.Int32), nil
}
+// NullInt16 represents an int16 that may be null.
+// NullInt16 implements the Scanner interface so
+// it can be used as a scan destination, similar to NullString.
+type NullInt16 struct {
+ Int16 int16
+ Valid bool // Valid is true if Int16 is not NULL
+}
+
+// Scan implements the Scanner interface.
+func (n *NullInt16) Scan(value interface{}) error {
+ if value == nil {
+ n.Int16, n.Valid = 0, false
+ return nil
+ }
+ err := convertAssign(&n.Int16, value)
+ n.Valid = err == nil
+ return err
+}
+
+// Value implements the driver Valuer interface.
+func (n NullInt16) Value() (driver.Value, error) {
+ if !n.Valid {
+ return nil, nil
+ }
+ return int64(n.Int16), nil
+}
+
+// NullByte represents a byte that may be null.
+// NullByte implements the Scanner interface so
+// it can be used as a scan destination, similar to NullString.
+type NullByte struct {
+ Byte byte
+ Valid bool // Valid is true if Byte is not NULL
+}
+
+// Scan implements the Scanner interface.
+func (n *NullByte) Scan(value interface{}) error {
+ if value == nil {
+ n.Byte, n.Valid = 0, false
+ return nil
+ }
+ err := convertAssign(&n.Byte, value)
+ n.Valid = err == nil
+ return err
+}
+
+// Value implements the driver Valuer interface.
+func (n NullByte) Value() (driver.Value, error) {
+ if !n.Valid {
+ return nil, nil
+ }
+ return int64(n.Byte), nil
+}
+
// NullFloat64 represents a float64 that may be null.
// NullFloat64 implements the Scanner interface so
// it can be used as a scan destination, similar to NullString.
@@ -813,6 +867,9 @@ func (db *DB) PingContext(ctx context.Context) error {
// Ping verifies a connection to the database is still alive,
// establishing a connection if necessary.
+//
+// Ping uses context.Background internally; to specify the context, use
+// PingContext.
func (db *DB) Ping() error {
return db.PingContext(context.Background())
}
@@ -850,6 +907,12 @@ func (db *DB) Close() error {
}
}
db.stop()
+ if c, ok := db.connector.(io.Closer); ok {
+ err1 := c.Close()
+ if err1 != nil {
+ err = err1
+ }
+ }
return err
}
@@ -1475,6 +1538,9 @@ func (db *DB) PrepareContext(ctx context.Context, query string) (*Stmt, error) {
// returned statement.
// The caller must call the statement's Close method
// when the statement is no longer needed.
+//
+// Prepare uses context.Background internally; to specify the context, use
+// PrepareContext.
func (db *DB) Prepare(query string) (*Stmt, error) {
return db.PrepareContext(context.Background(), query)
}
@@ -1545,6 +1611,9 @@ func (db *DB) ExecContext(ctx context.Context, query string, args ...interface{}
// Exec executes a query without returning any rows.
// The args are for any placeholder parameters in the query.
+//
+// Exec uses context.Background internally; to specify the context, use
+// ExecContext.
func (db *DB) Exec(query string, args ...interface{}) (Result, error) {
return db.ExecContext(context.Background(), query, args...)
}
@@ -1615,6 +1684,9 @@ func (db *DB) QueryContext(ctx context.Context, query string, args ...interface{
// Query executes a query that returns rows, typically a SELECT.
// The args are for any placeholder parameters in the query.
+//
+// Query uses context.Background internally; to specify the context, use
+// QueryContext.
func (db *DB) Query(query string, args ...interface{}) (*Rows, error) {
return db.QueryContext(context.Background(), query, args...)
}
@@ -1713,6 +1785,9 @@ func (db *DB) QueryRowContext(ctx context.Context, query string, args ...interfa
// If the query selects no rows, the *Row's Scan will return ErrNoRows.
// Otherwise, the *Row's Scan scans the first selected row and discards
// the rest.
+//
+// QueryRow uses context.Background internally; to specify the context, use
+// QueryRowContext.
func (db *DB) QueryRow(query string, args ...interface{}) *Row {
return db.QueryRowContext(context.Background(), query, args...)
}
@@ -1744,6 +1819,9 @@ func (db *DB) BeginTx(ctx context.Context, opts *TxOptions) (*Tx, error) {
// Begin starts a transaction. The default isolation level is dependent on
// the driver.
+//
+// Begin uses context.Background internally; to specify the context, use
+// BeginTx.
func (db *DB) Begin() (*Tx, error) {
return db.BeginTx(context.Background(), nil)
}
@@ -1771,7 +1849,7 @@ func (db *DB) beginDC(ctx context.Context, dc *driverConn, release func(error),
return nil, err
}
- // Schedule the transaction to rollback when the context is cancelled.
+ // Schedule the transaction to rollback when the context is canceled.
// The cancel function in Tx will be called after done is set to true.
ctx, cancel := context.WithCancel(ctx)
tx = &Tx{
@@ -2249,6 +2327,9 @@ func (tx *Tx) PrepareContext(ctx context.Context, query string) (*Stmt, error) {
// be used once the transaction has been committed or rolled back.
//
// To use an existing prepared statement on this transaction, see Tx.Stmt.
+//
+// Prepare uses context.Background internally; to specify the context, use
+// PrepareContext.
func (tx *Tx) Prepare(query string) (*Stmt, error) {
return tx.PrepareContext(context.Background(), query)
}
@@ -2352,6 +2433,9 @@ func (tx *Tx) StmtContext(ctx context.Context, stmt *Stmt) *Stmt {
//
// The returned statement operates within the transaction and will be closed
// when the transaction has been committed or rolled back.
+//
+// Stmt uses context.Background internally; to specify the context, use
+// StmtContext.
func (tx *Tx) Stmt(stmt *Stmt) *Stmt {
return tx.StmtContext(context.Background(), stmt)
}
@@ -2368,6 +2452,9 @@ func (tx *Tx) ExecContext(ctx context.Context, query string, args ...interface{}
// Exec executes a query that doesn't return rows.
// For example: an INSERT and UPDATE.
+//
+// Exec uses context.Background internally; to specify the context, use
+// ExecContext.
func (tx *Tx) Exec(query string, args ...interface{}) (Result, error) {
return tx.ExecContext(context.Background(), query, args...)
}
@@ -2383,6 +2470,9 @@ func (tx *Tx) QueryContext(ctx context.Context, query string, args ...interface{
}
// Query executes a query that returns rows, typically a SELECT.
+//
+// Query uses context.Background internally; to specify the context, use
+// QueryContext.
func (tx *Tx) Query(query string, args ...interface{}) (*Rows, error) {
return tx.QueryContext(context.Background(), query, args...)
}
@@ -2404,6 +2494,9 @@ func (tx *Tx) QueryRowContext(ctx context.Context, query string, args ...interfa
// If the query selects no rows, the *Row's Scan will return ErrNoRows.
// Otherwise, the *Row's Scan scans the first selected row and discards
// the rest.
+//
+// QueryRow uses context.Background internally; to specify the context, use
+// QueryRowContext.
func (tx *Tx) QueryRow(query string, args ...interface{}) *Row {
return tx.QueryRowContext(context.Background(), query, args...)
}
@@ -2510,6 +2603,9 @@ func (s *Stmt) ExecContext(ctx context.Context, args ...interface{}) (Result, er
// Exec executes a prepared statement with the given arguments and
// returns a Result summarizing the effect of the statement.
+//
+// Exec uses context.Background internally; to specify the context, use
+// ExecContext.
func (s *Stmt) Exec(args ...interface{}) (Result, error) {
return s.ExecContext(context.Background(), args...)
}
@@ -2681,6 +2777,9 @@ func (s *Stmt) QueryContext(ctx context.Context, args ...interface{}) (*Rows, er
// Query executes a prepared query statement with the given arguments
// and returns the query results as a *Rows.
+//
+// Query uses context.Background internally; to specify the context, use
+// QueryContext.
func (s *Stmt) Query(args ...interface{}) (*Rows, error) {
return s.QueryContext(context.Background(), args...)
}
@@ -2720,6 +2819,9 @@ func (s *Stmt) QueryRowContext(ctx context.Context, args ...interface{}) *Row {
//
// var name string
// err := nameByUseridStmt.QueryRow(id).Scan(&name)
+//
+// QueryRow uses context.Background internally; to specify the context, use
+// QueryRowContext.
func (s *Stmt) QueryRow(args ...interface{}) *Row {
return s.QueryRowContext(context.Background(), args...)
}
diff --git a/libgo/go/database/sql/sql_test.go b/libgo/go/database/sql/sql_test.go
index c968852..f771dee 100644
--- a/libgo/go/database/sql/sql_test.go
+++ b/libgo/go/database/sql/sql_test.go
@@ -431,25 +431,24 @@ func TestTxContextWait(t *testing.T) {
db := newTestDB(t, "people")
defer closeDB(t, db)
- ctx, cancel := context.WithTimeout(context.Background(), 15*time.Millisecond)
- defer cancel()
+ ctx, cancel := context.WithCancel(context.Background())
tx, err := db.BeginTx(ctx, nil)
if err != nil {
- // Guard against the context being canceled before BeginTx completes.
- if err == context.DeadlineExceeded {
- t.Skip("tx context canceled prior to first use")
- }
t.Fatal(err)
}
tx.keepConnOnRollback = false
+ go func() {
+ time.Sleep(15 * time.Millisecond)
+ cancel()
+ }()
// This will trigger the *fakeConn.Prepare method which will take time
// performing the query. The ctxDriverPrepare func will check the context
// after this and close the rows and return an error.
_, err = tx.QueryContext(ctx, "WAIT|1s|SELECT|people|age,name|")
- if err != context.DeadlineExceeded {
- t.Fatalf("expected QueryContext to error with context deadline exceeded but returned %v", err)
+ if err != context.Canceled {
+ t.Fatalf("expected QueryContext to error with context canceled but returned %v", err)
}
waitForFree(t, db, 5*time.Second, 0)
@@ -657,7 +656,7 @@ func TestPoolExhaustOnCancel(t *testing.T) {
db.SetMaxOpenConns(max)
// First saturate the connection pool.
- // Then start new requests for a connection that is cancelled after it is requested.
+ // Then start new requests for a connection that is canceled after it is requested.
state = 1
for i := 0; i < max; i++ {
@@ -1820,6 +1819,30 @@ func TestNullInt32Param(t *testing.T) {
nullTestRun(t, spec)
}
+func TestNullInt16Param(t *testing.T) {
+ spec := nullTestSpec{"nullint16", "int16", [6]nullTestRow{
+ {NullInt16{31, true}, 1, NullInt16{31, true}},
+ {NullInt16{-22, false}, 1, NullInt16{0, false}},
+ {22, 1, NullInt16{22, true}},
+ {NullInt16{33, true}, 1, NullInt16{33, true}},
+ {NullInt16{222, false}, 1, NullInt16{0, false}},
+ {0, NullInt16{31, false}, nil},
+ }}
+ nullTestRun(t, spec)
+}
+
+func TestNullByteParam(t *testing.T) {
+ spec := nullTestSpec{"nullbyte", "byte", [6]nullTestRow{
+ {NullByte{31, true}, 1, NullByte{31, true}},
+ {NullByte{0, false}, 1, NullByte{0, false}},
+ {22, 1, NullByte{22, true}},
+ {NullByte{33, true}, 1, NullByte{33, true}},
+ {NullByte{222, false}, 1, NullByte{0, false}},
+ {0, NullByte{31, false}, nil},
+ }}
+ nullTestRun(t, spec)
+}
+
func TestNullFloat64Param(t *testing.T) {
spec := nullTestSpec{"nullfloat64", "float64", [6]nullTestRow{
{NullFloat64{31.2, true}, 1, NullFloat64{31.2, true}},
@@ -2785,7 +2808,7 @@ func TestTxCannotCommitAfterRollback(t *testing.T) {
// 3. Check if 2.A has committed in Tx (pass) or outside of Tx (fail).
sendQuery := make(chan struct{})
// The Tx status is returned through the row results, ensure
- // that the rows results are not cancelled.
+ // that the rows results are not canceled.
bypassRowsAwaitDone = true
hookTxGrabConn = func() {
cancel()
@@ -2815,7 +2838,7 @@ func TestTxStmtDeadlock(t *testing.T) {
db := newTestDB(t, "people")
defer closeDB(t, db)
- ctx, cancel := context.WithTimeout(context.Background(), 5*time.Millisecond)
+ ctx, cancel := context.WithCancel(context.Background())
defer cancel()
tx, err := db.BeginTx(ctx, nil)
if err != nil {
@@ -2826,6 +2849,7 @@ func TestTxStmtDeadlock(t *testing.T) {
if err != nil {
t.Fatal(err)
}
+ cancel()
// Run number of stmt queries to reproduce deadlock from context cancel
for i := 0; i < 1e3; i++ {
// Encounter any close related errors (e.g. ErrTxDone, stmt is closed)
@@ -4060,9 +4084,18 @@ func TestOpenConnector(t *testing.T) {
}
defer db.Close()
- if _, is := db.connector.(*fakeConnector); !is {
+ c, ok := db.connector.(*fakeConnector)
+ if !ok {
t.Fatal("not using *fakeConnector")
}
+
+ if err := db.Close(); err != nil {
+ t.Fatal(err)
+ }
+
+ if !c.closed {
+ t.Fatal("connector is not closed")
+ }
}
type ctxOnlyDriver struct {