@@ -3,23 +3,27 @@ package sqlds
33import (
44 "context"
55 "database/sql"
6+ "errors"
7+ "fmt"
68 "net/http"
79 "sync"
810
911 "github.com/grafana/grafana-plugin-sdk-go/backend"
1012 "github.com/grafana/grafana-plugin-sdk-go/backend/instancemgmt"
1113 "github.com/grafana/grafana-plugin-sdk-go/backend/resource/httpadapter"
1214 "github.com/grafana/grafana-plugin-sdk-go/data"
13- "github.com/pkg/errors"
1415)
1516
1617type sqldatasource struct {
17- db * sql.DB
18- c Driver
19- settings backend.DataSourceInstanceSettings
18+ Completable
19+
20+ db * sql.DB
21+ c Driver
22+
23+ driverSettings DriverSettings
24+ settings backend.DataSourceInstanceSettings
2025
2126 backend.CallResourceHandler
22- Completable
2327 CustomRoutes map [string ]func (http.ResponseWriter , * http.Request )
2428}
2529
@@ -37,7 +41,9 @@ func (ds *sqldatasource) NewDatasource(settings backend.DataSourceInstanceSettin
3741 if err != nil {
3842 return nil , err
3943 }
44+
4045 ds .CallResourceHandler = httpadapter .New (mux )
46+ ds .driverSettings = ds .c .Settings (settings )
4147
4248 return ds , nil
4349}
@@ -66,7 +72,7 @@ func (ds *sqldatasource) QueryData(ctx context.Context, req *backend.QueryDataRe
6672 // Execute each query and store the results by query RefID
6773 for _ , q := range req .Queries {
6874 go func (query backend.DataQuery ) {
69- frames , err := ds .handleQuery (query )
75+ frames , err := ds .handleQuery (ctx , query )
7076
7177 response .Set (query .RefID , backend.DataResponse {
7278 Frames : frames ,
@@ -83,7 +89,7 @@ func (ds *sqldatasource) QueryData(ctx context.Context, req *backend.QueryDataRe
8389}
8490
8591// handleQuery will call query, and attempt to reconnect if the query failed
86- func (ds * sqldatasource ) handleQuery (req backend.DataQuery ) (data.Frames , error ) {
92+ func (ds * sqldatasource ) handleQuery (ctx context. Context , req backend.DataQuery ) (data.Frames , error ) {
8793 // Convert the backend.DataQuery into a Query object
8894 q , err := GetQuery (req )
8995 if err != nil {
@@ -93,30 +99,42 @@ func (ds *sqldatasource) handleQuery(req backend.DataQuery) (data.Frames, error)
9399 // Apply supported macros to the query
94100 q .RawSQL , err = interpolate (ds .c , q )
95101 if err != nil {
96- return nil , errors . WithMessage ( err , "Could not apply macros" )
102+ return nil , fmt . Errorf ( "%s: %w" , "Could not apply macros" , err )
97103 }
98104
99105 // Apply the default FillMode, overwritting it if the query specifies it
100- fillMode := ds .c .FillMode ()
106+ fillMode := ds .driverSettings .FillMode
101107 if q .FillMissing != nil {
102108 fillMode = q .FillMissing
103109 }
104110
111+ if ds .driverSettings .Timeout != 0 {
112+ tctx , cancel := context .WithTimeout (ctx , ds .driverSettings .Timeout )
113+ defer cancel ()
114+
115+ ctx = tctx
116+ }
117+
105118 // FIXES:
106119 // * Some datasources (snowflake) expire connections or have an authentication token that expires if not used in 1 or 4 hours.
107120 // Because the datasource driver does not include an option for permanent connections, we retry the connection
108121 // if the query fails. NOTE: this does not include some errors like "ErrNoRows"
109- res , err := query (ds .db , ds .c .Converters (), fillMode , q )
122+ res , err := query (ctx , ds .db , ds .c .Converters (), fillMode , q )
110123 if err == nil {
111124 return res , nil
112125 }
113126
114- if errors .Cause (err ) == ErrorQuery {
127+ if errors .Is (err , ErrorNoResults ) {
128+ return res , nil
129+ }
130+
131+ if errors .Is (err , ErrorQuery ) {
115132 ds .db , err = ds .c .Connect (ds .settings )
116133 if err != nil {
117134 return nil , err
118135 }
119- return query (ds .db , ds .c .Converters (), fillMode , q )
136+
137+ return query (ctx , ds .db , ds .c .Converters (), fillMode , q )
120138 }
121139
122140 return nil , err
0 commit comments