diff options
author | Ian Lance Taylor <iant@golang.org> | 2021-07-30 14:28:58 -0700 |
---|---|---|
committer | Ian Lance Taylor <iant@golang.org> | 2021-08-12 20:23:07 -0700 |
commit | c5b21c3f4c17b0649155035d2f9aa97b2da8a813 (patch) | |
tree | c6d3a68b503ba5b16182acbb958e3e5dbc95a43b /libgo/go/database/sql | |
parent | 72be20e20299ec57b4bc9ba03d5b7d6bf10e97cc (diff) | |
download | gcc-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.go | 3 | ||||
-rw-r--r-- | libgo/go/database/sql/fakedb_test.go | 23 | ||||
-rw-r--r-- | libgo/go/database/sql/sql.go | 104 | ||||
-rw-r--r-- | libgo/go/database/sql/sql_test.go | 57 |
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 { |