/
sql.go
78 lines (65 loc) · 2.18 KB
/
sql.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
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
package sqlutil
import (
"database/sql"
"fmt"
"github.com/grafana/grafana-plugin-sdk-go/data"
)
// FrameFromRows returns a new Frame populated with the data from rows. The field types
// will be nullable ([]*T) if the SQL column is nullable or if the nullable property is unknown.
// Otherwise, the field types will be non-nullable ([]T) types.
//
// The number of rows scanned is limited to rowLimit. If maxRows is reached, then a data.Notice with a warning severity
// will be attached to the frame. If rowLimit is less than 0, there is no limit.
//
// Fields will be named to match name of the SQL columns.
//
// A converter must be supplied in order to support data types that are scanned from sql.Rows, but not supported in data.Frame.
// The converter defines what type to use for scanning, what type to place in the data frame, and a function for converting from one to the other.
// If you find yourself here after upgrading, you can continue to your StringConverters here by using the `ToConverters` function.
func FrameFromRows(rows *sql.Rows, rowLimit int64, converters ...Converter) (*data.Frame, error) {
types, err := rows.ColumnTypes()
if err != nil {
return nil, err
}
if isDynamic(converters) {
rows := Rows{itr: rows}
return frameDynamic(rows, rowLimit, types, converters)
}
names, err := rows.Columns()
if err != nil {
return nil, err
}
scanRow, err := MakeScanRow(types, names, converters...)
if err != nil {
return nil, err
}
frame := NewFrame(names, scanRow.Converters...)
var i int64
for {
// first iterate over rows may be nop if not switched result set to next
for rows.Next() {
if i == rowLimit {
frame.AppendNotices(data.Notice{
Severity: data.NoticeSeverityWarning,
Text: fmt.Sprintf("Results have been limited to %v because the SQL row limit was reached", rowLimit),
})
break
}
r := scanRow.NewScannableRow()
if err := rows.Scan(r...); err != nil {
return nil, err
}
if err := Append(frame, r, scanRow.Converters...); err != nil {
return nil, err
}
i++
}
if i == rowLimit || !rows.NextResultSet() {
break
}
}
if err := rows.Err(); err != nil {
return frame, err
}
return frame, nil
}