@@ -126,19 +126,22 @@ func (c *conn) ExecContext(ctx context.Context, query string, args []driver.Name
126
126
}
127
127
resp , err := c .client .GetResultSetMetadata (ctx , & req )
128
128
if err != nil {
129
- return nil , dbsqlerrint .NewDriverError (ctx , "Error performing staging operation" , err )
129
+ return nil , dbsqlerrint .NewDriverError (ctx , "error performing staging operation" , err )
130
130
}
131
131
isStagingOperation = * resp .IsStagingOperation
132
132
}
133
133
if isStagingOperation {
134
134
if len (driverctx .StagingPathsFromContext (ctx )) != 0 {
135
135
row , err := rows .NewRows (c .id , corrId , exStmtResp .OperationHandle , c .client , c .cfg , exStmtResp .DirectResults )
136
136
if err != nil {
137
- return nil , dbsqlerrint .NewDriverError (ctx , "Error reading row." , err )
137
+ return nil , dbsqlerrint .NewDriverError (ctx , "error reading row." , err )
138
+ }
139
+ err = c .ExecStagingOperation (ctx , row )
140
+ if err != nil {
141
+ return nil , err
138
142
}
139
- return c .ExecStagingOperation (ctx , row )
140
143
} else {
141
- return nil , dbsqlerrint .NewDriverError (ctx , "Staging ctx must be provided." , nil )
144
+ return nil , dbsqlerrint .NewDriverError (ctx , "staging ctx must be provided." , nil )
142
145
}
143
146
}
144
147
@@ -174,39 +177,40 @@ func Succeeded(response *http.Response) bool {
174
177
return false
175
178
}
176
179
177
- func (c * conn ) HandleStagingPut (ctx context.Context , presignedUrl string , headers map [string ]string , localFile string ) (driver. Result , error ) {
180
+ func (c * conn ) HandleStagingPut (ctx context.Context , presignedUrl string , headers map [string ]string , localFile string ) dbsqlerr. DBError {
178
181
if localFile == "" {
179
- return nil , dbsqlerrint .NewDriverError (ctx , "cannot perform PUT without specifying a local_file" , nil )
182
+ return dbsqlerrint .NewDriverError (ctx , "cannot perform PUT without specifying a local_file" , nil )
180
183
}
181
184
client := & http.Client {}
182
185
183
186
dat , err := os .ReadFile (localFile )
184
187
185
- req , _ := http .NewRequest ("PUT" , presignedUrl , bytes .NewReader (dat ))
186
-
187
188
if err != nil {
188
- return nil , err
189
+ return dbsqlerrint . NewDriverError ( ctx , "error reading local file" , err )
189
190
}
191
+
192
+ req , _ := http .NewRequest ("PUT" , presignedUrl , bytes .NewReader (dat ))
193
+
190
194
for k , v := range headers {
191
195
req .Header .Set (k , v )
192
196
}
193
197
res , err := client .Do (req )
194
198
if err != nil {
195
- return nil , err
199
+ return dbsqlerrint . NewDriverError ( ctx , "error sending http request" , err )
196
200
}
197
201
defer res .Body .Close ()
198
202
content , err := io .ReadAll (res .Body )
199
203
200
204
if err != nil || ! Succeeded (res ) {
201
- return nil , dbsqlerrint .NewDriverError (ctx , fmt .Sprintf ("staging operation over HTTP was unsuccessful: %d-%s, nil " , res .StatusCode , content ), nil )
205
+ return dbsqlerrint .NewDriverError (ctx , fmt .Sprintf ("staging operation over HTTP was unsuccessful: %d-%s" , res .StatusCode , content ), nil )
202
206
}
203
- return driver . ResultNoRows , nil
207
+ return nil
204
208
205
209
}
206
210
207
- func (c * conn ) HandleStagingGet (ctx context.Context , presignedUrl string , headers map [string ]string , localFile string ) (driver. Result , error ) {
211
+ func (c * conn ) HandleStagingGet (ctx context.Context , presignedUrl string , headers map [string ]string , localFile string ) dbsqlerr. DBError {
208
212
if localFile == "" {
209
- return nil , fmt . Errorf ( "cannot perform GET without specifying a local_file" )
213
+ return dbsqlerrint . NewDriverError ( ctx , "cannot perform GET without specifying a local_file" , nil )
210
214
}
211
215
client := & http.Client {}
212
216
req , _ := http .NewRequest ("GET" , presignedUrl , nil )
@@ -216,41 +220,40 @@ func (c *conn) HandleStagingGet(ctx context.Context, presignedUrl string, header
216
220
}
217
221
res , err := client .Do (req )
218
222
if err != nil {
219
- return nil , err
223
+ return dbsqlerrint . NewDriverError ( ctx , "error sending http request" , err )
220
224
}
221
225
defer res .Body .Close ()
222
226
content , err := io .ReadAll (res .Body )
223
227
224
228
if err != nil || ! Succeeded (res ) {
225
- return nil , dbsqlerrint .NewDriverError (ctx , fmt .Sprintf ("staging operation over HTTP was unsuccessful: %d-%s, nil " , res .StatusCode , content ), nil )
229
+ return dbsqlerrint .NewDriverError (ctx , fmt .Sprintf ("staging operation over HTTP was unsuccessful: %d-%s" , res .StatusCode , content ), nil )
226
230
}
227
231
228
232
err = os .WriteFile (localFile , content , 0644 ) //nolint:gosec
229
233
if err != nil {
230
- return nil , err
234
+ return dbsqlerrint . NewDriverError ( ctx , "error writing local file" , err )
231
235
}
232
- return driver .ResultNoRows , nil
233
-
236
+ return nil
234
237
}
235
238
236
- func (c * conn ) HandleStagingDelete (ctx context.Context , presignedUrl string , headers map [string ]string ) (driver. Result , error ) {
239
+ func (c * conn ) HandleStagingDelete (ctx context.Context , presignedUrl string , headers map [string ]string ) dbsqlerr. DBError {
237
240
client := & http.Client {}
238
241
req , _ := http .NewRequest ("DELETE" , presignedUrl , nil )
239
242
for k , v := range headers {
240
243
req .Header .Set (k , v )
241
244
}
242
245
res , err := client .Do (req )
243
246
if err != nil {
244
- return nil , err
247
+ return dbsqlerrint . NewDriverError ( ctx , "error sending http request" , err )
245
248
}
246
249
defer res .Body .Close ()
247
250
content , err := io .ReadAll (res .Body )
248
251
249
252
if err != nil || ! Succeeded (res ) {
250
- return nil , dbsqlerrint .NewDriverError (ctx , fmt .Sprintf ("staging operation over HTTP was unsuccessful: %d-%s, nil" , res .StatusCode , content ), nil )
253
+ return dbsqlerrint .NewDriverError (ctx , fmt .Sprintf ("staging operation over HTTP was unsuccessful: %d-%s, nil" , res .StatusCode , content ), nil )
251
254
}
252
255
253
- return driver . ResultNoRows , nil
256
+ return nil
254
257
}
255
258
256
259
func localPathIsAllowed (stagingAllowedLocalPaths []string , localFile string ) bool {
@@ -278,29 +281,29 @@ func localPathIsAllowed(stagingAllowedLocalPaths []string, localFile string) boo
278
281
279
282
func (c * conn ) ExecStagingOperation (
280
283
ctx context.Context ,
281
- row driver.Rows ) (driver. Result , error ) {
284
+ row driver.Rows ) dbsqlerr. DBError {
282
285
283
286
var sqlRow []driver.Value
284
287
colNames := row .Columns ()
285
288
sqlRow = make ([]driver.Value , len (colNames ))
286
289
err := row .Next (sqlRow )
287
290
if err != nil {
288
- return nil , dbsqlerrint .NewDriverError (ctx , "Error fetching staging operation results" , err )
291
+ return dbsqlerrint .NewDriverError (ctx , "error fetching staging operation results" , err )
289
292
}
290
293
var stringValues []string = make ([]string , 4 )
291
294
for i := range stringValues {
292
295
if s , ok := sqlRow [i ].(string ); ok {
293
296
stringValues [i ] = s
294
297
} else {
295
- return nil , dbsqlerrint .NewDriverError (ctx , "Received unexpected response from the server." , nil )
298
+ return dbsqlerrint .NewDriverError (ctx , "received unexpected response from the server." , nil )
296
299
}
297
300
}
298
301
operation := stringValues [0 ]
299
302
presignedUrl := stringValues [1 ]
300
303
headersByteArr := []byte (stringValues [2 ])
301
304
var headers map [string ]string
302
305
if err := json .Unmarshal (headersByteArr , & headers ); err != nil {
303
- return nil , err
306
+ return dbsqlerrint . NewDriverError ( ctx , "error parsing server response." , nil )
304
307
}
305
308
localFile := stringValues [3 ]
306
309
stagingAllowedLocalPaths := driverctx .StagingPathsFromContext (ctx )
@@ -309,18 +312,18 @@ func (c *conn) ExecStagingOperation(
309
312
if localPathIsAllowed (stagingAllowedLocalPaths , localFile ) {
310
313
return c .HandleStagingPut (ctx , presignedUrl , headers , localFile )
311
314
} else {
312
- return nil , dbsqlerrint .NewDriverError (ctx , "local file operations are restricted to paths within the configured stagingAllowedLocalPath" , nil )
315
+ return dbsqlerrint .NewDriverError (ctx , "local file operations are restricted to paths within the configured stagingAllowedLocalPath" , nil )
313
316
}
314
317
case "GET" :
315
318
if localPathIsAllowed (stagingAllowedLocalPaths , localFile ) {
316
319
return c .HandleStagingGet (ctx , presignedUrl , headers , localFile )
317
320
} else {
318
- return nil , dbsqlerrint .NewDriverError (ctx , "local file operations are restricted to paths within the configured stagingAllowedLocalPath" , nil )
321
+ return dbsqlerrint .NewDriverError (ctx , "local file operations are restricted to paths within the configured stagingAllowedLocalPath" , nil )
319
322
}
320
323
case "DELETE" :
321
324
return c .HandleStagingDelete (ctx , presignedUrl , headers )
322
325
default :
323
- return nil , dbsqlerrint .NewDriverError (ctx , fmt .Sprintf ("operation %s is not supported. Supported operations are GET, PUT, and REMOVE" , operation ), nil )
326
+ return dbsqlerrint .NewDriverError (ctx , fmt .Sprintf ("operation %s is not supported. Supported operations are GET, PUT, and REMOVE" , operation ), nil )
324
327
}
325
328
}
326
329
0 commit comments