Skip to content

Commit f5f7752

Browse files
committed
Kill queries also after the rows start streaming
Signed-off-by: Carlos Martín <[email protected]>
1 parent 56c5ce4 commit f5f7752

File tree

1 file changed

+42
-28
lines changed

1 file changed

+42
-28
lines changed

server/handler/query.go

Lines changed: 42 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -53,36 +53,37 @@ func genericVals(colTypes []string) []interface{} {
5353
// the rows as JSON
5454
func Query(db service.SQLDB) RequestProcessFunc {
5555
return func(r *http.Request) (*serializer.Response, error) {
56-
var queryRequest queryRequest
56+
var queryReq queryRequest
5757
body, err := ioutil.ReadAll(r.Body)
5858
if err != nil {
5959
return nil, err
6060
}
6161

62-
err = json.Unmarshal(body, &queryRequest)
63-
if err != nil || queryRequest.Query == "" {
62+
err = json.Unmarshal(body, &queryReq)
63+
if err != nil || queryReq.Query == "" {
6464
return nil, serializer.NewHTTPError(http.StatusBadRequest,
6565
`Bad Request. Expected body: { "query": "SQL statement", "limit": 1234 }`)
6666
}
6767

68-
query, limitSet := addLimit(queryRequest.Query, queryRequest.Limit)
69-
7068
// go-sql-driver/mysql QueryContext stops waiting for the query results on
7169
// context cancel, but it does not actually cancel the query on the server
7270

7371
c := make(chan error, 1)
7472

75-
var rows *sql.Rows
7673
conn, err := db.Conn(r.Context())
74+
if err != nil {
75+
return nil, fmt.Errorf("failed to get a DB connection: %s", err)
76+
}
7777
defer conn.Close()
7878

79-
connID, err := getConnID(r, conn)
79+
connID, err := getConnID(conn)
8080
if err != nil {
8181
return nil, fmt.Errorf("failed to get connection id: %s", err)
8282
}
8383

84+
var resp *serializer.Response
8485
go func() {
85-
rows, err = conn.QueryContext(r.Context(), query)
86+
resp, err = queryContext(r.Context(), conn, queryReq)
8687
c <- err
8788
}()
8889

@@ -103,40 +104,53 @@ func Query(db service.SQLDB) RequestProcessFunc {
103104
return nil, dbError(err)
104105
}
105106

106-
defer rows.Close()
107+
return resp, nil
108+
}
109+
}
107110

108-
columnNames, columnTypes, err := columnsInfo(rows)
109-
if err != nil {
110-
return nil, err
111-
}
111+
func queryContext(ctx context.Context, conn *sql.Conn, queryReq queryRequest) (*serializer.Response, error) {
112+
query, limitSet := addLimit(queryReq.Query, queryReq.Limit)
112113

113-
columnValsPtr := genericVals(columnTypes)
114+
var rows *sql.Rows
114115

115-
tableData := make([]map[string]interface{}, 0)
116+
rows, err := conn.QueryContext(ctx, query)
117+
if err != nil {
118+
return nil, err
119+
}
116120

117-
for rows.Next() {
118-
if err := rows.Scan(columnValsPtr...); err != nil {
119-
return nil, err
120-
}
121+
defer rows.Close()
121122

122-
colData, err := columnsData(columnNames, columnTypes, columnValsPtr)
123-
if err != nil {
124-
return nil, err
125-
}
123+
columnNames, columnTypes, err := columnsInfo(rows)
124+
if err != nil {
125+
return nil, err
126+
}
127+
128+
columnValsPtr := genericVals(columnTypes)
129+
130+
tableData := make([]map[string]interface{}, 0)
126131

127-
tableData = append(tableData, colData)
132+
for rows.Next() {
133+
if err := rows.Scan(columnValsPtr...); err != nil {
134+
return nil, err
128135
}
129136

130-
if err := rows.Err(); err != nil {
137+
colData, err := columnsData(columnNames, columnTypes, columnValsPtr)
138+
if err != nil {
131139
return nil, err
132140
}
133141

134-
return serializer.NewQueryResponse(
135-
tableData, columnNames, columnTypes, limitSet, queryRequest.Limit), nil
142+
tableData = append(tableData, colData)
136143
}
144+
145+
if err := rows.Err(); err != nil {
146+
return nil, err
147+
}
148+
149+
return serializer.NewQueryResponse(
150+
tableData, columnNames, columnTypes, limitSet, queryReq.Limit), nil
137151
}
138152

139-
func getConnID(r *http.Request, conn *sql.Conn) (uint32, error) {
153+
func getConnID(conn *sql.Conn) (uint32, error) {
140154
const connIDQuery = "SELECT CONNECTION_ID()"
141155
var connID uint32
142156

0 commit comments

Comments
 (0)