blob: 04522a28fca4798c64d8fe121d56f9598fe0a02c [file] [log] [blame]
package sqlmock
import (
"database/sql/driver"
"encoding/csv"
"io"
"strings"
)
// Rows interface allows to construct rows
// which also satisfies database/sql/driver.Rows interface
type Rows interface {
driver.Rows // composed interface, supports sql driver.Rows
AddRow(...driver.Value) Rows
FromCSVString(s string) Rows
}
// a struct which implements database/sql/driver.Rows
type rows struct {
cols []string
rows [][]driver.Value
pos int
}
func (r *rows) Columns() []string {
return r.cols
}
func (r *rows) Close() error {
return nil
}
func (r *rows) Err() error {
return nil
}
// advances to next row
func (r *rows) Next(dest []driver.Value) error {
r.pos++
if r.pos > len(r.rows) {
return io.EOF // per interface spec
}
for i, col := range r.rows[r.pos-1] {
dest[i] = col
}
return nil
}
// NewRows allows Rows to be created from a group of
// sql driver.Value or from the CSV string and
// to be used as sql driver.Rows
func NewRows(columns []string) Rows {
return &rows{cols: columns}
}
// AddRow adds a row which is built from arguments
// in the same column order, returns sql driver.Rows
// compatible interface
func (r *rows) AddRow(values ...driver.Value) Rows {
if len(values) != len(r.cols) {
panic("Expected number of values to match number of columns")
}
row := make([]driver.Value, len(r.cols))
for i, v := range values {
row[i] = v
}
r.rows = append(r.rows, row)
return r
}
// FromCSVString adds rows from CSV string.
// Returns sql driver.Rows compatible interface
func (r *rows) FromCSVString(s string) Rows {
res := strings.NewReader(strings.TrimSpace(s))
csvReader := csv.NewReader(res)
for {
res, err := csvReader.Read()
if err != nil || res == nil {
break
}
row := make([]driver.Value, len(r.cols))
for i, v := range res {
row[i] = []byte(strings.TrimSpace(v))
}
r.rows = append(r.rows, row)
}
return r
}
// RowsFromCSVString creates Rows from CSV string
// to be used for mocked queries. Returns sql driver Rows interface
// ** DEPRECATED ** will be removed in the future, use Rows.FromCSVString
func RowsFromCSVString(columns []string, s string) driver.Rows {
rs := &rows{}
rs.cols = columns
r := strings.NewReader(strings.TrimSpace(s))
csvReader := csv.NewReader(r)
for {
r, err := csvReader.Read()
if err != nil || r == nil {
break
}
row := make([]driver.Value, len(columns))
for i, v := range r {
v := strings.TrimSpace(v)
row[i] = []byte(v)
}
rs.rows = append(rs.rows, row)
}
return rs
}