diff options
author | Ian Lance Taylor <iant@golang.org> | 2017-01-14 00:05:42 +0000 |
---|---|---|
committer | Ian Lance Taylor <ian@gcc.gnu.org> | 2017-01-14 00:05:42 +0000 |
commit | c2047754c300b68c05d65faa8dc2925fe67b71b4 (patch) | |
tree | e183ae81a1f48a02945cb6de463a70c5be1b06f6 /libgo/go/database/sql/driver | |
parent | 829afb8f05602bb31c9c597b24df7377fed4f059 (diff) | |
download | gcc-c2047754c300b68c05d65faa8dc2925fe67b71b4.zip gcc-c2047754c300b68c05d65faa8dc2925fe67b71b4.tar.gz gcc-c2047754c300b68c05d65faa8dc2925fe67b71b4.tar.bz2 |
libgo: update to Go 1.8 release candidate 1
Compiler changes:
* Change map assignment to use mapassign and assign value directly.
* Change string iteration to use decoderune, faster for ASCII strings.
* Change makeslice to take int, and use makeslice64 for larger values.
* Add new noverflow field to hmap struct used for maps.
Unresolved problems, to be fixed later:
* Commented out test in go/types/sizes_test.go that doesn't compile.
* Commented out reflect.TestStructOf test for padding after zero-sized field.
Reviewed-on: https://go-review.googlesource.com/35231
gotools/:
Updates for Go 1.8rc1.
* Makefile.am (go_cmd_go_files): Add bug.go.
(s-zdefaultcc): Write defaultPkgConfig.
* Makefile.in: Rebuild.
From-SVN: r244456
Diffstat (limited to 'libgo/go/database/sql/driver')
-rw-r--r-- | libgo/go/database/sql/driver/driver.go | 195 | ||||
-rw-r--r-- | libgo/go/database/sql/driver/types.go | 42 | ||||
-rw-r--r-- | libgo/go/database/sql/driver/types_test.go | 16 |
3 files changed, 247 insertions, 6 deletions
diff --git a/libgo/go/database/sql/driver/driver.go b/libgo/go/database/sql/driver/driver.go index 4dba85a..d66196f 100644 --- a/libgo/go/database/sql/driver/driver.go +++ b/libgo/go/database/sql/driver/driver.go @@ -8,7 +8,11 @@ // Most code should use package sql. package driver -import "errors" +import ( + "context" + "errors" + "reflect" +) // Value is a value that drivers must be able to handle. // It is either nil or an instance of one of these types: @@ -21,6 +25,21 @@ import "errors" // time.Time type Value interface{} +// NamedValue holds both the value name and value. +type NamedValue struct { + // If the Name is not empty it should be used for the parameter identifier and + // not the ordinal position. + // + // Name will not have a symbol prefix. + Name string + + // Ordinal position of the parameter starting from one and is always set. + Ordinal int + + // Value is the parameter value. + Value Value +} + // Driver is the interface that must be implemented by a database // driver. type Driver interface { @@ -54,6 +73,17 @@ var ErrSkip = errors.New("driver: skip fast-path; continue as if unimplemented") // you shouldn't return ErrBadConn. var ErrBadConn = errors.New("driver: bad connection") +// Pinger is an optional interface that may be implemented by a Conn. +// +// If a Conn does not implement Pinger, the sql package's DB.Ping and +// DB.PingContext will check if there is at least one Conn available. +// +// If Conn.Ping returns ErrBadConn, DB.Ping and DB.PingContext will remove +// the Conn from pool. +type Pinger interface { + Ping(ctx context.Context) error +} + // Execer is an optional interface that may be implemented by a Conn. // // If a Conn does not implement Execer, the sql package's DB.Exec will @@ -61,10 +91,25 @@ var ErrBadConn = errors.New("driver: bad connection") // statement. // // Exec may return ErrSkip. +// +// Deprecated: Drivers should implement ExecerContext instead (or additionally). type Execer interface { Exec(query string, args []Value) (Result, error) } +// ExecerContext is an optional interface that may be implemented by a Conn. +// +// If a Conn does not implement ExecerContext, the sql package's DB.Exec will +// first prepare a query, execute the statement, and then close the +// statement. +// +// ExecerContext may return ErrSkip. +// +// ExecerContext must honor the context timeout and return when the context is canceled. +type ExecerContext interface { + ExecContext(ctx context.Context, query string, args []NamedValue) (Result, error) +} + // Queryer is an optional interface that may be implemented by a Conn. // // If a Conn does not implement Queryer, the sql package's DB.Query will @@ -72,10 +117,25 @@ type Execer interface { // statement. // // Query may return ErrSkip. +// +// Deprecated: Drivers should implement QueryerContext instead (or additionally). type Queryer interface { Query(query string, args []Value) (Rows, error) } +// QueryerContext is an optional interface that may be implemented by a Conn. +// +// If a Conn does not implement QueryerContext, the sql package's DB.Query will +// first prepare a query, execute the statement, and then close the +// statement. +// +// QueryerContext may return ErrSkip. +// +// QueryerContext must honor the context timeout and return when the context is canceled. +type QueryerContext interface { + QueryContext(ctx context.Context, query string, args []NamedValue) (Rows, error) +} + // Conn is a connection to a database. It is not used concurrently // by multiple goroutines. // @@ -95,9 +155,50 @@ type Conn interface { Close() error // Begin starts and returns a new transaction. + // + // Deprecated: Drivers should implement ConnBeginTx instead (or additionally). Begin() (Tx, error) } +// ConnPrepareContext enhances the Conn interface with context. +type ConnPrepareContext interface { + // PrepareContext returns a prepared statement, bound to this connection. + // context is for the preparation of the statement, + // it must not store the context within the statement itself. + PrepareContext(ctx context.Context, query string) (Stmt, error) +} + +// IsolationLevel is the transaction isolation level stored in TxOptions. +// +// This type should be considered identical to sql.IsolationLevel along +// with any values defined on it. +type IsolationLevel int + +// TxOptions holds the transaction options. +// +// This type should be considered identical to sql.TxOptions. +type TxOptions struct { + Isolation IsolationLevel + ReadOnly bool +} + +// ConnBeginTx enhances the Conn interface with context and TxOptions. +type ConnBeginTx interface { + // BeginTx starts and returns a new transaction. + // If the context is canceled by the user the sql package will + // call Tx.Rollback before discarding and closing the connection. + // + // This must check opts.Isolation to determine if there is a set + // isolation level. If the driver does not support a non-default + // level and one is set or if there is a non-default isolation level + // that is not supported, an error must be returned. + // + // This must also check opts.ReadOnly to determine if the read-only + // value is true to either set the read-only transaction property if supported + // or return an error if it is not supported. + BeginTx(ctx context.Context, opts TxOptions) (Tx, error) +} + // Result is the result of a query execution. type Result interface { // LastInsertId returns the database's auto-generated ID @@ -132,13 +233,35 @@ type Stmt interface { // Exec executes a query that doesn't return rows, such // as an INSERT or UPDATE. + // + // Deprecated: Drivers should implement StmtExecContext instead (or additionally). Exec(args []Value) (Result, error) // Query executes a query that may return rows, such as a // SELECT. + // + // Deprecated: Drivers should implement StmtQueryContext instead (or additionally). Query(args []Value) (Rows, error) } +// StmtExecContext enhances the Stmt interface by providing Exec with context. +type StmtExecContext interface { + // ExecContext executes a query that doesn't return rows, such + // as an INSERT or UPDATE. + // + // ExecContext must honor the context timeout and return when it is canceled. + ExecContext(ctx context.Context, args []NamedValue) (Result, error) +} + +// StmtQueryContext enhances the Stmt interface by providing Query with context. +type StmtQueryContext interface { + // QueryContext executes a query that may return rows, such as a + // SELECT. + // + // QueryContext must honor the context timeout and return when it is canceled. + QueryContext(ctx context.Context, args []NamedValue) (Rows, error) +} + // ColumnConverter may be optionally implemented by Stmt if the // statement is aware of its own columns' types and can convert from // any type to a driver Value. @@ -169,6 +292,76 @@ type Rows interface { Next(dest []Value) error } +// RowsNextResultSet extends the Rows interface by providing a way to signal +// the driver to advance to the next result set. +type RowsNextResultSet interface { + Rows + + // HasNextResultSet is called at the end of the current result set and + // reports whether there is another result set after the current one. + HasNextResultSet() bool + + // NextResultSet advances the driver to the next result set even + // if there are remaining rows in the current result set. + // + // NextResultSet should return io.EOF when there are no more result sets. + NextResultSet() error +} + +// RowsColumnTypeScanType may be implemented by Rows. It should return +// the value type that can be used to scan types into. For example, the database +// column type "bigint" this should return "reflect.TypeOf(int64(0))". +type RowsColumnTypeScanType interface { + Rows + ColumnTypeScanType(index int) reflect.Type +} + +// RowsColumnTypeDatabaseTypeName may be implemented by Rows. It should return the +// database system type name without the length. Type names should be uppercase. +// Examples of returned types: "VARCHAR", "NVARCHAR", "VARCHAR2", "CHAR", "TEXT", +// "DECIMAL", "SMALLINT", "INT", "BIGINT", "BOOL", "[]BIGINT", "JSONB", "XML", +// "TIMESTAMP". +type RowsColumnTypeDatabaseTypeName interface { + Rows + ColumnTypeDatabaseTypeName(index int) string +} + +// RowsColumnTypeLength may be implemented by Rows. It should return the length +// of the column type if the column is a variable length type. If the column is +// not a variable length type ok should return false. +// If length is not limited other than system limits, it should return math.MaxInt64. +// The following are examples of returned values for various types: +// TEXT (math.MaxInt64, true) +// varchar(10) (10, true) +// nvarchar(10) (10, true) +// decimal (0, false) +// int (0, false) +// bytea(30) (30, true) +type RowsColumnTypeLength interface { + Rows + ColumnTypeLength(index int) (length int64, ok bool) +} + +// RowsColumnTypeNullable may be implemented by Rows. The nullable value should +// be true if it is known the column may be null, or false if the column is known +// to be not nullable. +// If the column nullability is unknown, ok should be false. +type RowsColumnTypeNullable interface { + Rows + ColumnTypeNullable(index int) (nullable, ok bool) +} + +// RowsColumnTypePrecisionScale may be implemented by Rows. It should return +// the precision and scale for decimal types. If not applicable, ok should be false. +// The following are examples of returned values for various types: +// decimal(38, 4) (38, 4, true) +// int (0, 0, false) +// decimal (math.MaxInt64, math.MaxInt64, true) +type RowsColumnTypePrecisionScale interface { + Rows + ColumnTypePrecisionScale(index int) (precision, scale int64, ok bool) +} + // Tx is a transaction. type Tx interface { Commit() error diff --git a/libgo/go/database/sql/driver/types.go b/libgo/go/database/sql/driver/types.go index e480e70..8b3cb6c 100644 --- a/libgo/go/database/sql/driver/types.go +++ b/libgo/go/database/sql/driver/types.go @@ -198,9 +198,9 @@ func IsScanValue(v interface{}) bool { // Value method is used to return a Value. As a fallback, the provided // argument's underlying type is used to convert it to a Value: // underlying integer types are converted to int64, floats to float64, -// and strings to []byte. If the argument is a nil pointer, -// ConvertValue returns a nil Value. If the argument is a non-nil -// pointer, it is dereferenced and ConvertValue is called +// bool, string, and []byte to themselves. If the argument is a nil +// pointer, ConvertValue returns a nil Value. If the argument is a +// non-nil pointer, it is dereferenced and ConvertValue is called // recursively. Other types are an error. var DefaultParameterConverter defaultConverter @@ -208,13 +208,35 @@ type defaultConverter struct{} var _ ValueConverter = defaultConverter{} +var valuerReflectType = reflect.TypeOf((*Valuer)(nil)).Elem() + +// callValuerValue returns vr.Value(), with one exception: +// If vr.Value is an auto-generated method on a pointer type and the +// pointer is nil, it would panic at runtime in the panicwrap +// method. Treat it like nil instead. +// Issue 8415. +// +// This is so people can implement driver.Value on value types and +// still use nil pointers to those types to mean nil/NULL, just like +// string/*string. +// +// This function is mirrored in the database/sql package. +func callValuerValue(vr Valuer) (v Value, err error) { + if rv := reflect.ValueOf(vr); rv.Kind() == reflect.Ptr && + rv.IsNil() && + rv.Type().Elem().Implements(valuerReflectType) { + return nil, nil + } + return vr.Value() +} + func (defaultConverter) ConvertValue(v interface{}) (Value, error) { if IsValue(v) { return v, nil } - if svi, ok := v.(Valuer); ok { - sv, err := svi.Value() + if vr, ok := v.(Valuer); ok { + sv, err := callValuerValue(vr) if err != nil { return nil, err } @@ -245,6 +267,16 @@ func (defaultConverter) ConvertValue(v interface{}) (Value, error) { return int64(u64), nil case reflect.Float32, reflect.Float64: return rv.Float(), nil + case reflect.Bool: + return rv.Bool(), nil + case reflect.Slice: + ek := rv.Type().Elem().Kind() + if ek == reflect.Uint8 { + return rv.Bytes(), nil + } + return nil, fmt.Errorf("unsupported type %T, a slice of %s", v, ek) + case reflect.String: + return rv.String(), nil } return nil, fmt.Errorf("unsupported type %T, a %s", v, rv.Kind()) } diff --git a/libgo/go/database/sql/driver/types_test.go b/libgo/go/database/sql/driver/types_test.go index 1ce0ff0..0379bf8 100644 --- a/libgo/go/database/sql/driver/types_test.go +++ b/libgo/go/database/sql/driver/types_test.go @@ -20,6 +20,16 @@ type valueConverterTest struct { var now = time.Now() var answer int64 = 42 +type ( + i int64 + f float64 + b bool + bs []byte + s string + t time.Time + is []int +) + var valueConverterTests = []valueConverterTest{ {Bool, "true", true, ""}, {Bool, "True", true, ""}, @@ -41,6 +51,12 @@ var valueConverterTests = []valueConverterTest{ {DefaultParameterConverter, (*int64)(nil), nil, ""}, {DefaultParameterConverter, &answer, answer, ""}, {DefaultParameterConverter, &now, now, ""}, + {DefaultParameterConverter, i(9), int64(9), ""}, + {DefaultParameterConverter, f(0.1), float64(0.1), ""}, + {DefaultParameterConverter, b(true), true, ""}, + {DefaultParameterConverter, bs{1}, []byte{1}, ""}, + {DefaultParameterConverter, s("a"), "a", ""}, + {DefaultParameterConverter, is{1}, nil, "unsupported type driver.is, a slice of int"}, } func TestValueConverters(t *testing.T) { |