/
reader.go
61 lines (58 loc) · 1.54 KB
/
reader.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
package sql
import (
"database/sql"
"github.com/tobgu/qframe/qerrors"
"github.com/tobgu/qframe/types"
)
// ReadSQL returns a named map of types.DataSlice for consumption
// by the qframe.New constructor.
func ReadSQL(rows *sql.Rows, conf SQLConfig) (map[string]types.DataSlice, []string, error) {
var (
columns []interface{}
colNames []string
)
for rows.Next() {
// Allocate columns for the returning query
if columns == nil {
names, err := rows.Columns()
if err != nil {
return nil, colNames, qerrors.New("ReadSQL Columns", err.Error())
}
for _, name := range names {
col := &Column{precision: conf.Precision}
if conf.CoerceMap != nil {
fn, ok := conf.CoerceMap[name]
if ok {
col.coerce = fn(col)
}
}
columns = append(columns, col)
}
// ensure any column in the coercion map
// exists in the resulting columns or return
// an error explicitly.
if conf.CoerceMap != nil {
checkMap:
for name := range conf.CoerceMap {
for _, colName := range colNames {
if name == colName {
continue checkMap
}
return nil, colNames, qerrors.New("ReadSQL Columns", "column %s does not exist to coerce", name)
}
}
}
colNames = names
}
// Scan the result into our columns
err := rows.Scan(columns...)
if err != nil {
return nil, colNames, qerrors.New("ReadSQL Scan", err.Error())
}
}
result := map[string]types.DataSlice{}
for i, column := range columns {
result[colNames[i]] = column.(*Column).Data()
}
return result, colNames, nil
}