Skip to content
Snippets Groups Projects
sql.go 60 KiB
Newer Older
  • Learn to ignore specific revisions
  • 	nextResultSet, ok := rs.rowsi.(driver.RowsNextResultSet)
    	if !ok {
    		rs.Close()
    		return false
    	}
    	rs.lasterr = nextResultSet.NextResultSet()
    
    		rs.Close()
    
    // Err returns the error, if any, that was encountered during iteration.
    
    // Err may be called after an explicit or implicit Close.
    
    	if rs.lasterr == io.EOF {
    
    Brad Fitzpatrick's avatar
    Brad Fitzpatrick committed
    // 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) {
    
    Brad Fitzpatrick's avatar
    Brad Fitzpatrick committed
    		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
    
    // at by dest. The number of values in dest must be the same as the
    // number of columns in Rows.
    
    // Scan converts columns read from the database into the following
    // common Go types and special types provided by the sql package:
    //
    //    *string
    //    *[]byte
    //    *int, *int8, *int16, *int32, *int64
    //    *uint, *uint8, *uint16, *uint32, *uint64
    //    *bool
    //    *float32, *float64
    //    *interface{}
    //    *RawBytes
    //    any type implementing Scanner (see Scanner docs)
    //
    // In the most simple case, if the type of the value from the source
    // column is an integer, bool or string type T and dest is of type *T,
    // Scan simply assigns the value through the pointer.
    //
    // Scan also converts between string and numeric types, as long as no
    // information would be lost. While Scan stringifies all numbers
    // scanned from numeric database columns into *string, scans into
    // numeric types are checked for overflow. For example, a float64 with
    // value 300 or a string with value "300" can scan into a uint16, but
    // not into a uint8, though float64(255) or "255" can scan into a
    // uint8. One exception is that scans of some float64 numbers to
    // strings may lose information when stringifying. In general, scan
    // floating point columns into *float64.
    //
    // If a dest argument has type *[]byte, Scan saves in that argument a
    // copy of the corresponding data. The copy is owned by the caller and
    // can be modified and held indefinitely. The copy can be avoided by
    // using an argument of type *RawBytes instead; see the documentation
    // for RawBytes for restrictions on its use.
    
    //
    // If an argument has type *interface{}, Scan copies the value
    
    // provided by the underlying driver without conversion. When scanning
    // from a source value of type []byte to *interface{}, a copy of the
    // slice is made and the caller owns the result.
    //
    // Source values of type time.Time may be scanned into values of type
    // *time.Time, *interface{}, *string, or *[]byte. When converting to
    // the latter two, time.Format3339Nano is used.
    //
    // Source values of type bool may be scanned into types *bool,
    // *interface{}, *string, *[]byte, or *RawBytes.
    //
    // For scanning into *bool, the source may be true, false, 1, 0, or
    // string inputs parseable by strconv.ParseBool.
    
    func (rs *Rows) Scan(dest ...interface{}) error {
    
    		return errors.New("sql: Rows are closed")
    
    	}
    	if rs.lastcols == nil {
    
    Brad Fitzpatrick's avatar
    Brad Fitzpatrick committed
    		return errors.New("sql: Scan called without calling Next")
    
    	}
    	if len(dest) != len(rs.lastcols) {
    
    Brad Fitzpatrick's avatar
    Brad Fitzpatrick committed
    		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)
    		if err != nil {
    
    Brad Fitzpatrick's avatar
    Brad Fitzpatrick committed
    			return fmt.Errorf("sql: Scan error on column index %d: %v", i, err)
    
    var rowsCloseHook func(*Rows, *error)
    
    
    func (rs *Rows) isClosed() bool {
    	return atomic.LoadInt32(&rs.closed) != 0
    }
    
    
    // Close closes the Rows, preventing further enumeration. If Next and
    // NextResultSet both return
    
    // false, the Rows are closed automatically and it will suffice to check the
    // result of Err. Close is idempotent and does not affect the result of Err.
    
    func (rs *Rows) Close() error {
    
    	if !atomic.CompareAndSwapInt32(&rs.closed, 0, 1) {
    
    	if rs.ctxClose != nil {
    		close(rs.ctxClose)
    	}
    
    	err := rs.rowsi.Close()
    
    	if fn := rowsCloseHook; fn != nil {
    		fn(rs, &err)
    	}
    
    	if rs.closeStmt != nil {
    		rs.closeStmt.Close()
    	}
    
    	return err
    }
    
    // Row is the result of calling QueryRow to select a single row.
    type Row struct {
    	// One of these two will be non-nil:
    
    	err  error // deferred error for easy chaining
    
    	rows *Rows
    }
    
    // Scan copies the columns from the matched row into the values
    
    // pointed at by dest. See the documentation on Rows.Scan for details.
    // If more than one row matches the query,
    // Scan uses the first row and discards the rest. If no row matches
    
    // the query, Scan returns ErrNoRows.
    
    func (r *Row) Scan(dest ...interface{}) error {
    
    	if r.err != nil {
    		return r.err
    	}
    
    
    	// TODO(bradfitz): for now we need to defensively clone all
    
    	// []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
    
    	// only valid until the next Scan/Close. But the TODO is that
    	// for a lot of drivers, this copy will be unnecessary. We
    
    	// should provide an optional interface for drivers to
    	// implement to say, "don't worry, the []bytes that I return
    	// from Next will not be modified again." (for instance, if
    	// they were obtained from the network anyway) But for now we
    	// don't care.
    
    		if _, ok := dp.(*RawBytes); ok {
    			return errors.New("sql: RawBytes isn't allowed on Row.Scan")
    		}
    
    		if err := r.rows.Err(); err != nil {
    			return err
    		}
    
    		return ErrNoRows
    	}
    	err := r.rows.Scan(dest...)
    	if err != nil {
    		return err
    	}
    
    	// Make sure the query can be processed to completion with no errors.
    	if err := r.rows.Close(); err != nil {
    		return err
    	}
    
    }
    
    // A Result summarizes an executed SQL command.
    type Result interface {
    
    	// LastInsertId returns the integer generated by the database
    	// in response to a command. Typically this will be from an
    	// "auto increment" column when inserting a new row. Not all
    	// databases support this feature, and the syntax of such
    	// statements varies.
    
    	LastInsertId() (int64, error)
    
    
    	// RowsAffected returns the number of rows affected by an
    	// update, insert, or delete. Not every database or database
    	// driver may support this.
    
    	RowsAffected() (int64, error)
    
    type driverResult struct {
    	sync.Locker // the *driverConn
    	resi        driver.Result
    }
    
    func (dr driverResult) LastInsertId() (int64, error) {
    	dr.Lock()
    	defer dr.Unlock()
    	return dr.resi.LastInsertId()
    }
    
    func (dr driverResult) RowsAffected() (int64, error) {
    	dr.Lock()
    	defer dr.Unlock()
    	return dr.resi.RowsAffected()
    
    	return string(buf[:runtime.Stack(buf[:], false)])
    }
    
    
    // withLock runs while holding lk.
    func withLock(lk sync.Locker, fn func()) {
    	lk.Lock()
    
    	defer lk.Unlock() // in case fn panics