-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmapquery.go
More file actions
95 lines (80 loc) · 1.97 KB
/
mapquery.go
File metadata and controls
95 lines (80 loc) · 1.97 KB
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
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
package mapquery
import (
"fmt"
"database/sql"
)
/**
Used to map rows with unknown columns from a DB query so we can add them to a JSON response
*/
type MapStringScan struct {
// cp are the column pointers
cp []interface{}
// row contains the final result
row map[string]string
colCount int
colNames []string
}
/**
Initialise a mop for a row in the DB query result that will be updated with `rows.Scan()`
*/
func newMapStringScan(columnNames []string) *MapStringScan {
lenCN := len(columnNames)
s := &MapStringScan{
cp: make([]interface{}, lenCN),
row: make(map[string]string, lenCN),
colCount: lenCN,
colNames: columnNames,
}
for i := 0; i < lenCN; i++ {
s.cp[i] = new(sql.RawBytes)
}
return s
}
/**
Update a row map from the db query result
*/
func (s *MapStringScan) Update(rows *sql.Rows) error {
if err := rows.Scan(s.cp...); err != nil {
return err
}
for i := 0; i < s.colCount; i++ {
if rb, ok := s.cp[i].(*sql.RawBytes); ok {
s.row[s.colNames[i]] = string(*rb)
*rb = nil // reset pointer to discard current value to avoid a bug
} else {
return fmt.Errorf("Cannot convert index %d column %s to type *sql.RawBytes", i, s.colNames[i])
}
}
return nil
}
/**
Get a map representing a row from DB query results
*/
func (s *MapStringScan) Get() map[string]string {
rowCopy := make(map[string]string, len(s.row))
// Create a copy of the map for this row, as it will be updated for every row
for k, v := range s.row {
rowCopy[k] = v
}
return rowCopy
}
/**
Take the sql.Rows from a db query and return a slice of `map[string]string`s for the columns in each row
*/
func MapRows(rows *sql.Rows) ([]map[string]string, error) {
columnNames, err := rows.Columns()
if err != nil {
return nil, err
}
var response []map[string]string
rc := newMapStringScan(columnNames)
for rows.Next() {
err := rc.Update(rows)
if err != nil {
fmt.Println(err)
}
response = append(response, rc.Get())
}
rows.Close()
return response, nil;
}