diff options
author | Ian Lance Taylor <ian@gcc.gnu.org> | 2012-02-01 19:26:59 +0000 |
---|---|---|
committer | Ian Lance Taylor <ian@gcc.gnu.org> | 2012-02-01 19:26:59 +0000 |
commit | 9af4cb9545ce481b8d9d4a13acfe26512032e21b (patch) | |
tree | 7e7e6083ebe59999943a211a17f8ef6f07f17c2f /libgo/go/database/sql/sql.go | |
parent | 6b6cd722f329a168f98d1f421834cf40bb33a77d (diff) | |
download | gcc-9af4cb9545ce481b8d9d4a13acfe26512032e21b.zip gcc-9af4cb9545ce481b8d9d4a13acfe26512032e21b.tar.gz gcc-9af4cb9545ce481b8d9d4a13acfe26512032e21b.tar.bz2 |
libgo: Update to weekly.2012-01-27.
From-SVN: r183810
Diffstat (limited to 'libgo/go/database/sql/sql.go')
-rw-r--r-- | libgo/go/database/sql/sql.go | 120 |
1 files changed, 101 insertions, 19 deletions
diff --git a/libgo/go/database/sql/sql.go b/libgo/go/database/sql/sql.go index a8bf2a8..34a7652 100644 --- a/libgo/go/database/sql/sql.go +++ b/libgo/go/database/sql/sql.go @@ -47,7 +47,6 @@ type RawBytes []byte // // NULL value // } // -// TODO(bradfitz): add other types. type NullString struct { String string Valid bool // Valid is true if String is not NULL @@ -71,6 +70,84 @@ func (ns NullString) SubsetValue() (interface{}, error) { return ns.String, nil } +// NullInt64 represents an int64 that may be null. +// NullInt64 implements the ScannerInto interface so +// it can be used as a scan destination, similar to NullString. +type NullInt64 struct { + Int64 int64 + Valid bool // Valid is true if Int64 is not NULL +} + +// ScanInto implements the ScannerInto interface. +func (n *NullInt64) ScanInto(value interface{}) error { + if value == nil { + n.Int64, n.Valid = 0, false + return nil + } + n.Valid = true + return convertAssign(&n.Int64, value) +} + +// SubsetValue implements the driver SubsetValuer interface. +func (n NullInt64) SubsetValue() (interface{}, error) { + if !n.Valid { + return nil, nil + } + return n.Int64, nil +} + +// NullFloat64 represents a float64 that may be null. +// NullFloat64 implements the ScannerInto interface so +// it can be used as a scan destination, similar to NullString. +type NullFloat64 struct { + Float64 float64 + Valid bool // Valid is true if Float64 is not NULL +} + +// ScanInto implements the ScannerInto interface. +func (n *NullFloat64) ScanInto(value interface{}) error { + if value == nil { + n.Float64, n.Valid = 0, false + return nil + } + n.Valid = true + return convertAssign(&n.Float64, value) +} + +// SubsetValue implements the driver SubsetValuer interface. +func (n NullFloat64) SubsetValue() (interface{}, error) { + if !n.Valid { + return nil, nil + } + return n.Float64, nil +} + +// NullBool represents a bool that may be null. +// NullBool implements the ScannerInto interface so +// it can be used as a scan destination, similar to NullString. +type NullBool struct { + Bool bool + Valid bool // Valid is true if Bool is not NULL +} + +// ScanInto implements the ScannerInto interface. +func (n *NullBool) ScanInto(value interface{}) error { + if value == nil { + n.Bool, n.Valid = false, false + return nil + } + n.Valid = true + return convertAssign(&n.Bool, value) +} + +// SubsetValue implements the driver SubsetValuer interface. +func (n NullBool) SubsetValue() (interface{}, error) { + if !n.Valid { + return nil, nil + } + return n.Bool, nil +} + // ScannerInto is an interface used by Scan. type ScannerInto interface { // ScanInto assigns a value from a database driver. @@ -479,8 +556,11 @@ func (tx *Tx) Query(query string, args ...interface{}) (*Rows, error) { if err != nil { return nil, err } - defer stmt.Close() - return stmt.Query(args...) + rows, err := stmt.Query(args...) + if err == nil { + rows.closeStmt = stmt + } + return rows, err } // QueryRow executes a query that is expected to return at most one row. @@ -824,6 +904,12 @@ func (rs *Rows) Scan(dest ...interface{}) error { if !ok { continue } + if *b == nil { + // If the []byte is now nil (for a NULL value), + // don't fall through to below which would + // turn it into a non-nil 0-length byte slice + continue + } if _, ok = dp.(*RawBytes); ok { continue } @@ -865,17 +951,10 @@ func (r *Row) Scan(dest ...interface{}) error { if r.err != nil { return r.err } - defer r.rows.Close() - if !r.rows.Next() { - return ErrNoRows - } - err := r.rows.Scan(dest...) - if err != nil { - return err - } // TODO(bradfitz): for now we need to defensively clone all - // []byte that the driver returned, since we're about to close + // []byte that the driver returned (not permitting + // *RawBytes in Rows.Scan), since we're about to close // the Rows in our defer, when we return from this function. // the contract with the driver.Next(...) interface is that it // can return slices into read-only temporary memory that's @@ -890,14 +969,17 @@ func (r *Row) Scan(dest ...interface{}) error { if _, ok := dp.(*RawBytes); ok { return errors.New("sql: RawBytes isn't allowed on Row.Scan") } - b, ok := dp.(*[]byte) - if !ok { - continue - } - clone := make([]byte, len(*b)) - copy(clone, *b) - *b = clone } + + defer r.rows.Close() + if !r.rows.Next() { + return ErrNoRows + } + err := r.rows.Scan(dest...) + if err != nil { + return err + } + return nil } |