summaryrefslogtreecommitdiff
path: root/libgo/go/database/sql/sql.go
diff options
context:
space:
mode:
Diffstat (limited to 'libgo/go/database/sql/sql.go')
-rw-r--r--libgo/go/database/sql/sql.go56
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)
}