8
8
"net/http"
9
9
10
10
"github.com/src-d/gitbase-playground/server/serializer"
11
+ "gopkg.in/bblfsh/sdk.v1/uast"
12
+
13
+ "github.com/go-sql-driver/mysql"
11
14
)
12
15
13
16
type queryRequest struct {
@@ -16,12 +19,22 @@ type queryRequest struct {
16
19
}
17
20
18
21
// genericVals returns a slice of interface{}, each one a pointer to a NullString
19
- func genericVals (nColumns int ) []interface {} {
20
- columnVals := make ([]sql.NullString , nColumns )
21
- columnValsPtr := make ([]interface {}, nColumns )
22
-
23
- for i := range columnVals {
24
- columnValsPtr [i ] = & columnVals [i ]
22
+ func genericVals (colTypes []* sql.ColumnType ) []interface {} {
23
+ columnValsPtr := make ([]interface {}, len (colTypes ))
24
+
25
+ for i , colType := range colTypes {
26
+ switch colType .DatabaseTypeName () {
27
+ case "BIT" :
28
+ columnValsPtr [i ] = new (sql.NullBool )
29
+ case "TIMESTAMP" :
30
+ columnValsPtr [i ] = new (mysql.NullTime )
31
+ case "INT" :
32
+ columnValsPtr [i ] = new (sql.NullInt64 )
33
+ case "JSON" :
34
+ columnValsPtr [i ] = new ([]byte )
35
+ default : // "TEXT" and any others
36
+ columnValsPtr [i ] = new (sql.NullString )
37
+ }
25
38
}
26
39
27
40
return columnValsPtr
@@ -52,28 +65,69 @@ func Query(db *sql.DB) RequestProcessFunc {
52
65
}
53
66
defer rows .Close ()
54
67
55
- columnNames , _ := rows .Columns ()
56
- nColumns := len (columnNames )
57
- columnValsPtr := genericVals (nColumns )
68
+ columnNames , err := rows .Columns ()
69
+ if err != nil {
70
+ return nil , err
71
+ }
72
+
73
+ colTypes , err := rows .ColumnTypes ()
74
+ if err != nil {
75
+ return nil , err
76
+ }
77
+ columnValsPtr := genericVals (colTypes )
58
78
59
- tableData := make ([]map [string ]string , 0 )
79
+ tableData := make ([]map [string ]interface {} , 0 )
60
80
61
81
for rows .Next () {
62
82
if err := rows .Scan (columnValsPtr ... ); err != nil {
63
83
return nil , err
64
84
}
65
85
66
- colData := make (map [string ]string )
86
+ colData := make (map [string ]interface {} )
67
87
68
88
for i , val := range columnValsPtr {
69
- var st string
70
- sqlSt , _ := val .(* sql.NullString )
71
-
72
- if sqlSt .Valid {
73
- st = sqlSt .String
89
+ colData [columnNames [i ]] = nil
90
+
91
+ switch val .(type ) {
92
+ case * sql.NullBool :
93
+ sqlVal , _ := val .(* sql.NullBool )
94
+ if sqlVal .Valid {
95
+ colData [columnNames [i ]] = sqlVal .Bool
96
+ }
97
+ case * mysql.NullTime :
98
+ sqlVal , _ := val .(* mysql.NullTime )
99
+ if sqlVal .Valid {
100
+ colData [columnNames [i ]] = sqlVal .Time
101
+ }
102
+ case * sql.NullInt64 :
103
+ sqlVal , _ := val .(* sql.NullInt64 )
104
+ if sqlVal .Valid {
105
+ colData [columnNames [i ]] = sqlVal .Int64
106
+ }
107
+ case * sql.NullString :
108
+ sqlVal , _ := val .(* sql.NullString )
109
+ if sqlVal .Valid {
110
+ colData [columnNames [i ]] = sqlVal .String
111
+ }
112
+ case * []byte :
113
+ // TODO (carlosms) this may not be an array always
114
+ var protobufs [][]byte
115
+ if err := json .Unmarshal (* val .(* []byte ), & protobufs ); err != nil {
116
+ return nil , err
117
+ }
118
+
119
+ nodes := make ([]* uast.Node , len (protobufs ))
120
+
121
+ for i , v := range protobufs {
122
+ node := uast .NewNode ()
123
+ if err = node .Unmarshal (v ); err != nil {
124
+ return nil , err
125
+ }
126
+ nodes [i ] = node
127
+ }
128
+
129
+ colData [columnNames [i ]] = nodes
74
130
}
75
-
76
- colData [columnNames [i ]] = st
77
131
}
78
132
79
133
tableData = append (tableData , colData )
0 commit comments