diff options
Diffstat (limited to 'libgo/go/database/sql/sql.go')
-rw-r--r-- | libgo/go/database/sql/sql.go | 56 |
1 files changed, 36 insertions, 20 deletions
diff --git a/libgo/go/database/sql/sql.go b/libgo/go/database/sql/sql.go index 36179855db2..b0353ab4dc7 100644 --- a/libgo/go/database/sql/sql.go +++ b/libgo/go/database/sql/sql.go @@ -133,6 +133,7 @@ const ( LevelLinearizable ) +// String returns the name of the transaction isolation level. func (i IsolationLevel) String() string { switch i { case LevelDefault: @@ -567,7 +568,6 @@ type finalCloser interface { // addDep notes that x now depends on dep, and x's finalClose won't be // called until all of x's dependencies are removed with removeDep. func (db *DB) addDep(x finalCloser, dep interface{}) { - //println(fmt.Sprintf("addDep(%T %p, %T %p)", x, x, dep, dep)) db.mu.Lock() defer db.mu.Unlock() db.addDepLocked(x, dep) @@ -597,7 +597,6 @@ func (db *DB) removeDep(x finalCloser, dep interface{}) error { } func (db *DB) removeDepLocked(x finalCloser, dep interface{}) func() error { - //println(fmt.Sprintf("removeDep(%T %p, %T %p)", x, x, dep, dep)) xdep, ok := db.dep[x] if !ok { @@ -1322,11 +1321,13 @@ func (db *DB) putConnDBLocked(dc *driverConn, err error) bool { err: err, } return true - } else if err == nil && !db.closed && db.maxIdleConnsLocked() > len(db.freeConn) { - db.freeConn = append(db.freeConn, dc) + } else if err == nil && !db.closed { + if db.maxIdleConnsLocked() > len(db.freeConn) { + db.freeConn = append(db.freeConn, dc) + db.startCleanerLocked() + return true + } db.maxIdleClosed++ - db.startCleanerLocked() - return true } return false } @@ -2605,6 +2606,15 @@ type Rows struct { lastcols []driver.Value } +// lasterrOrErrLocked returns either lasterr or the provided err. +// rs.closemu must be read-locked. +func (rs *Rows) lasterrOrErrLocked(err error) error { + if rs.lasterr != nil && rs.lasterr != io.EOF { + return rs.lasterr + } + return err +} + func (rs *Rows) initContextClose(ctx, txctx context.Context) { if ctx.Done() == nil && (txctx == nil || txctx.Done() == nil) { return @@ -2681,7 +2691,7 @@ func (rs *Rows) nextLocked() (doClose, ok bool) { return false, true } -// NextResultSet prepares the next result set for reading. It returns true if +// NextResultSet prepares the next result set for reading. It reports whether // there is further result sets, or false if there is no further result set // or if there is an error advancing to it. The Err method should be consulted // to distinguish between the two cases. @@ -2728,23 +2738,22 @@ func (rs *Rows) NextResultSet() bool { func (rs *Rows) Err() error { rs.closemu.RLock() defer rs.closemu.RUnlock() - if rs.lasterr == io.EOF { - return nil - } - return rs.lasterr + return rs.lasterrOrErrLocked(nil) } +var errRowsClosed = errors.New("sql: Rows are closed") +var errNoRows = errors.New("sql: no Rows available") + // 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. +// Columns returns an error if the rows are closed. func (rs *Rows) Columns() ([]string, error) { rs.closemu.RLock() defer rs.closemu.RUnlock() if rs.closed { - return nil, errors.New("sql: Rows are closed") + return nil, rs.lasterrOrErrLocked(errRowsClosed) } if rs.rowsi == nil { - return nil, errors.New("sql: no Rows available") + return nil, rs.lasterrOrErrLocked(errNoRows) } rs.dc.Lock() defer rs.dc.Unlock() @@ -2758,10 +2767,10 @@ func (rs *Rows) ColumnTypes() ([]*ColumnType, error) { rs.closemu.RLock() defer rs.closemu.RUnlock() if rs.closed { - return nil, errors.New("sql: Rows are closed") + return nil, rs.lasterrOrErrLocked(errRowsClosed) } if rs.rowsi == nil { - return nil, errors.New("sql: no Rows available") + return nil, rs.lasterrOrErrLocked(errNoRows) } rs.dc.Lock() defer rs.dc.Unlock() @@ -2812,7 +2821,7 @@ func (ci *ColumnType) ScanType() reflect.Type { return ci.scanType } -// Nullable returns whether the column may be null. +// Nullable reports whether the column may be null. // If a driver does not support this property ok will be false. func (ci *ColumnType) Nullable() (nullable, ok bool) { return ci.nullable, ci.hasNullable @@ -2873,6 +2882,7 @@ func rowsColumnInfoSetupConnLocked(rowsi driver.Rows) []*ColumnType { // *float32, *float64 // *interface{} // *RawBytes +// *Rows (cursor value) // any type implementing Scanner (see Scanner docs) // // In the most simple case, if the type of the value from the source @@ -2909,6 +2919,11 @@ func rowsColumnInfoSetupConnLocked(rowsi driver.Rows) []*ColumnType { // // For scanning into *bool, the source may be true, false, 1, 0, or // string inputs parseable by strconv.ParseBool. +// +// Scan can also convert a cursor returned from a query, such as +// "select cursor(select * from my_table) from dual", into a +// *Rows value that can itself be scanned from. The parent +// select query will close any cursor *Rows if the parent *Rows is closed. func (rs *Rows) Scan(dest ...interface{}) error { rs.closemu.RLock() @@ -2917,8 +2932,9 @@ func (rs *Rows) Scan(dest ...interface{}) error { return rs.lasterr } if rs.closed { + err := rs.lasterrOrErrLocked(errRowsClosed) rs.closemu.RUnlock() - return errors.New("sql: Rows are closed") + return err } rs.closemu.RUnlock() @@ -2929,7 +2945,7 @@ func (rs *Rows) Scan(dest ...interface{}) error { return fmt.Errorf("sql: expected %d destination arguments in Scan, not %d", len(rs.lastcols), len(dest)) } for i, sv := range rs.lastcols { - err := convertAssign(dest[i], sv) + err := convertAssignRows(dest[i], sv, rs) if err != nil { return fmt.Errorf(`sql: Scan error on column index %d, name %q: %v`, i, rs.rowsi.Columns()[i], err) } |