forked from pinpt/go-drill
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathresult.go
136 lines (119 loc) · 2.8 KB
/
result.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
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
package drill
import (
"database/sql"
"database/sql/driver"
"fmt"
"io"
"io/ioutil"
"github.com/francoispqt/gojay"
)
type result struct {
columns columns
rows *rows
}
func newResult(r io.Reader) (driver.Rows, error) {
// FIXME: switch to make this a streaming result instead
var theresult result
buf, err := ioutil.ReadAll(r)
if err != nil {
return nil, err
}
if err := gojay.UnmarshalJSONObject(buf, &theresult); err != nil {
return nil, err
}
return theresult.rows, nil
}
type columns struct {
values []string
}
type rows struct {
parent *result
rows []row
index int
}
var _ driver.Rows = (*rows)(nil)
// Columns returns the names of the columns. The number of
// columns of the result is inferred from the length of the
// slice. If a particular column name isn't known, an empty
// string should be returned for that entry.
func (r *rows) Columns() []string {
return r.parent.columns.values
}
// Close closes the rows iterator.
func (r *rows) Close() error {
return nil
}
// Next is called to populate the next row of data into
// the provided slice. The provided slice will be the same
// size as the Columns() are wide.
//
// Next should return io.EOF when there are no more rows.
//
// The dest should not be written to outside of Next. Care
// should be taken when closing Rows not to modify
// a buffer held in dest.
func (r *rows) Next(dest []driver.Value) error {
if r.index >= len(r.rows) {
return sql.ErrNoRows
}
if len(dest) != len(r.parent.columns.values) {
return fmt.Errorf("invalid scan, expected %d arguments and received %d", len(r.parent.columns.values), len(dest))
}
therow := r.rows[r.index]
for i := 0; i < len(r.parent.columns.values); i++ {
key := r.parent.columns.values[i]
val := therow.kv[key]
dest[i] = val
}
r.index++
return nil
}
type row struct {
kv map[string]interface{}
}
func (c *columns) UnmarshalJSONArray(dec *gojay.Decoder) error {
str := ""
if err := dec.String(&str); err != nil {
return err
}
c.values = append(c.values, str)
return nil
}
func (r *rows) UnmarshalJSONArray(dec *gojay.Decoder) error {
var val row
val.kv = make(map[string]interface{})
if err := dec.Object(&val); err != nil {
return err
}
r.rows = append(r.rows, val)
return nil
}
func (r *row) UnmarshalJSONObject(dec *gojay.Decoder, key string) error {
var obj interface{}
if err := dec.Interface(&obj); err != nil {
return err
}
r.kv[key] = obj
return nil
}
func (r *row) NKeys() int {
return 0
}
func (r *result) UnmarshalJSONObject(dec *gojay.Decoder, key string) error {
switch key {
case "columns":
return dec.Array(&r.columns)
case "rows":
var therows rows
therows.rows = make([]row, 0)
if err := dec.Array(&therows); err != nil {
return err
}
therows.parent = r
r.rows = &therows
}
return nil
}
func (r *result) NKeys() int {
return 2
}