mirror of
https://github.com/golang/go
synced 2024-11-25 13:27:57 -07:00
sql: add Rows.Columns
Also, fix package name in error messages. Fixes #2453 R=rsc CC=golang-dev https://golang.org/cl/5483088
This commit is contained in:
parent
f89b5746fb
commit
ea51dd23b4
@ -22,10 +22,10 @@ var drivers = make(map[string]driver.Driver)
|
|||||||
// it panics.
|
// it panics.
|
||||||
func Register(name string, driver driver.Driver) {
|
func Register(name string, driver driver.Driver) {
|
||||||
if driver == nil {
|
if driver == nil {
|
||||||
panic("db: Register driver is nil")
|
panic("sql: Register driver is nil")
|
||||||
}
|
}
|
||||||
if _, dup := drivers[name]; dup {
|
if _, dup := drivers[name]; dup {
|
||||||
panic("db: Register called twice for driver " + name)
|
panic("sql: Register called twice for driver " + name)
|
||||||
}
|
}
|
||||||
drivers[name] = driver
|
drivers[name] = driver
|
||||||
}
|
}
|
||||||
@ -80,7 +80,7 @@ type ScannerInto interface {
|
|||||||
// ErrNoRows is returned by Scan when QueryRow doesn't return a
|
// ErrNoRows is returned by Scan when QueryRow doesn't return a
|
||||||
// row. In such a case, QueryRow returns a placeholder *Row value that
|
// row. In such a case, QueryRow returns a placeholder *Row value that
|
||||||
// defers this error until a Scan.
|
// defers this error until a Scan.
|
||||||
var ErrNoRows = errors.New("db: no rows in result set")
|
var ErrNoRows = errors.New("sql: no rows in result set")
|
||||||
|
|
||||||
// DB is a database handle. It's safe for concurrent use by multiple
|
// DB is a database handle. It's safe for concurrent use by multiple
|
||||||
// goroutines.
|
// goroutines.
|
||||||
@ -102,7 +102,7 @@ type DB struct {
|
|||||||
func Open(driverName, dataSourceName string) (*DB, error) {
|
func Open(driverName, dataSourceName string) (*DB, error) {
|
||||||
driver, ok := drivers[driverName]
|
driver, ok := drivers[driverName]
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, fmt.Errorf("db: unknown driver %q (forgotten import?)", driverName)
|
return nil, fmt.Errorf("sql: unknown driver %q (forgotten import?)", driverName)
|
||||||
}
|
}
|
||||||
return &DB{driver: driver, dsn: dataSourceName}, nil
|
return &DB{driver: driver, dsn: dataSourceName}, nil
|
||||||
}
|
}
|
||||||
@ -514,7 +514,7 @@ func (s *Stmt) Exec(args ...interface{}) (Result, error) {
|
|||||||
// placeholders, so we won't sanity check input here and instead let the
|
// placeholders, so we won't sanity check input here and instead let the
|
||||||
// driver deal with errors.
|
// driver deal with errors.
|
||||||
if want := si.NumInput(); want != -1 && len(args) != want {
|
if want := si.NumInput(); want != -1 && len(args) != want {
|
||||||
return nil, fmt.Errorf("db: expected %d arguments, got %d", want, len(args))
|
return nil, fmt.Errorf("sql: expected %d arguments, got %d", want, len(args))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert args to subset types.
|
// Convert args to subset types.
|
||||||
@ -522,10 +522,10 @@ func (s *Stmt) Exec(args ...interface{}) (Result, error) {
|
|||||||
for n, arg := range args {
|
for n, arg := range args {
|
||||||
args[n], err = cc.ColumnConverter(n).ConvertValue(arg)
|
args[n], err = cc.ColumnConverter(n).ConvertValue(arg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("db: converting Exec argument #%d's type: %v", n, err)
|
return nil, fmt.Errorf("sql: converting Exec argument #%d's type: %v", n, err)
|
||||||
}
|
}
|
||||||
if !driver.IsParameterSubsetType(args[n]) {
|
if !driver.IsParameterSubsetType(args[n]) {
|
||||||
return nil, fmt.Errorf("db: driver ColumnConverter error converted %T to unsupported type %T",
|
return nil, fmt.Errorf("sql: driver ColumnConverter error converted %T to unsupported type %T",
|
||||||
arg, args[n])
|
arg, args[n])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -533,7 +533,7 @@ func (s *Stmt) Exec(args ...interface{}) (Result, error) {
|
|||||||
for n, arg := range args {
|
for n, arg := range args {
|
||||||
args[n], err = driver.DefaultParameterConverter.ConvertValue(arg)
|
args[n], err = driver.DefaultParameterConverter.ConvertValue(arg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("db: converting Exec argument #%d's type: %v", n, err)
|
return nil, fmt.Errorf("sql: converting Exec argument #%d's type: %v", n, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -555,7 +555,7 @@ func (s *Stmt) connStmt() (ci driver.Conn, releaseConn func(), si driver.Stmt, e
|
|||||||
s.mu.Lock()
|
s.mu.Lock()
|
||||||
if s.closed {
|
if s.closed {
|
||||||
s.mu.Unlock()
|
s.mu.Unlock()
|
||||||
err = errors.New("db: statement is closed")
|
err = errors.New("sql: statement is closed")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -617,7 +617,7 @@ func (s *Stmt) Query(args ...interface{}) (*Rows, error) {
|
|||||||
// placeholders, so we won't sanity check input here and instead let the
|
// placeholders, so we won't sanity check input here and instead let the
|
||||||
// driver deal with errors.
|
// driver deal with errors.
|
||||||
if want := si.NumInput(); want != -1 && len(args) != want {
|
if want := si.NumInput(); want != -1 && len(args) != want {
|
||||||
return nil, fmt.Errorf("db: statement expects %d inputs; got %d", si.NumInput(), len(args))
|
return nil, fmt.Errorf("sql: statement expects %d inputs; got %d", si.NumInput(), len(args))
|
||||||
}
|
}
|
||||||
sargs, err := subsetTypeArgs(args)
|
sargs, err := subsetTypeArgs(args)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -737,27 +737,40 @@ func (rs *Rows) Err() error {
|
|||||||
return rs.lasterr
|
return rs.lasterr
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Columns returns the column names.
|
||||||
|
// Columns returns an error if the rows are closed, or if the rows
|
||||||
|
// are from QueryRow and there was a deferred error.
|
||||||
|
func (rs *Rows) Columns() ([]string, error) {
|
||||||
|
if rs.closed {
|
||||||
|
return nil, errors.New("sql: Rows are closed")
|
||||||
|
}
|
||||||
|
if rs.rowsi == nil {
|
||||||
|
return nil, errors.New("sql: no Rows available")
|
||||||
|
}
|
||||||
|
return rs.rowsi.Columns(), nil
|
||||||
|
}
|
||||||
|
|
||||||
// Scan copies the columns in the current row into the values pointed
|
// Scan copies the columns in the current row into the values pointed
|
||||||
// at by dest. If dest contains pointers to []byte, the slices should
|
// at by dest. If dest contains pointers to []byte, the slices should
|
||||||
// not be modified and should only be considered valid until the next
|
// not be modified and should only be considered valid until the next
|
||||||
// call to Next or Scan.
|
// call to Next or Scan.
|
||||||
func (rs *Rows) Scan(dest ...interface{}) error {
|
func (rs *Rows) Scan(dest ...interface{}) error {
|
||||||
if rs.closed {
|
if rs.closed {
|
||||||
return errors.New("db: Rows closed")
|
return errors.New("sql: Rows closed")
|
||||||
}
|
}
|
||||||
if rs.lasterr != nil {
|
if rs.lasterr != nil {
|
||||||
return rs.lasterr
|
return rs.lasterr
|
||||||
}
|
}
|
||||||
if rs.lastcols == nil {
|
if rs.lastcols == nil {
|
||||||
return errors.New("db: Scan called without calling Next")
|
return errors.New("sql: Scan called without calling Next")
|
||||||
}
|
}
|
||||||
if len(dest) != len(rs.lastcols) {
|
if len(dest) != len(rs.lastcols) {
|
||||||
return fmt.Errorf("db: expected %d destination arguments in Scan, not %d", len(rs.lastcols), len(dest))
|
return fmt.Errorf("sql: expected %d destination arguments in Scan, not %d", len(rs.lastcols), len(dest))
|
||||||
}
|
}
|
||||||
for i, sv := range rs.lastcols {
|
for i, sv := range rs.lastcols {
|
||||||
err := convertAssign(dest[i], sv)
|
err := convertAssign(dest[i], sv)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("db: Scan error on column index %d: %v", i, err)
|
return fmt.Errorf("sql: Scan error on column index %d: %v", i, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
@ -75,6 +75,23 @@ func TestQuery(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestRowsColumns(t *testing.T) {
|
||||||
|
db := newTestDB(t, "people")
|
||||||
|
defer closeDB(t, db)
|
||||||
|
rows, err := db.Query("SELECT|people|age,name|")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Query: %v", err)
|
||||||
|
}
|
||||||
|
cols, err := rows.Columns()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Columns: %v", err)
|
||||||
|
}
|
||||||
|
want := []string{"age", "name"}
|
||||||
|
if !reflect.DeepEqual(cols, want) {
|
||||||
|
t.Errorf("got %#v; want %#v", cols, want)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestQueryRow(t *testing.T) {
|
func TestQueryRow(t *testing.T) {
|
||||||
db := newTestDB(t, "people")
|
db := newTestDB(t, "people")
|
||||||
defer closeDB(t, db)
|
defer closeDB(t, db)
|
||||||
@ -187,12 +204,12 @@ func TestExec(t *testing.T) {
|
|||||||
{[]interface{}{7, 9}, ""},
|
{[]interface{}{7, 9}, ""},
|
||||||
|
|
||||||
// Invalid conversions:
|
// Invalid conversions:
|
||||||
{[]interface{}{"Brad", int64(0xFFFFFFFF)}, "db: converting Exec argument #1's type: sql/driver: value 4294967295 overflows int32"},
|
{[]interface{}{"Brad", int64(0xFFFFFFFF)}, "sql: converting Exec argument #1's type: sql/driver: value 4294967295 overflows int32"},
|
||||||
{[]interface{}{"Brad", "strconv fail"}, "db: converting Exec argument #1's type: sql/driver: value \"strconv fail\" can't be converted to int32"},
|
{[]interface{}{"Brad", "strconv fail"}, "sql: converting Exec argument #1's type: sql/driver: value \"strconv fail\" can't be converted to int32"},
|
||||||
|
|
||||||
// Wrong number of args:
|
// Wrong number of args:
|
||||||
{[]interface{}{}, "db: expected 2 arguments, got 0"},
|
{[]interface{}{}, "sql: expected 2 arguments, got 0"},
|
||||||
{[]interface{}{1, 2, 3}, "db: expected 2 arguments, got 3"},
|
{[]interface{}{1, 2, 3}, "sql: expected 2 arguments, got 3"},
|
||||||
}
|
}
|
||||||
for n, et := range execTests {
|
for n, et := range execTests {
|
||||||
_, err := stmt.Exec(et.args...)
|
_, err := stmt.Exec(et.args...)
|
||||||
|
Loading…
Reference in New Issue
Block a user