github.com/dannin/go@v0.0.0-20161031215817-d35dfd405eaa/src/database/sql/ctxutil.go (about) 1 // Copyright 2016 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package sql 6 7 import ( 8 "context" 9 "database/sql/driver" 10 "errors" 11 ) 12 13 func ctxDriverPrepare(ctx context.Context, ci driver.Conn, query string) (driver.Stmt, error) { 14 if ciCtx, is := ci.(driver.ConnPrepareContext); is { 15 return ciCtx.PrepareContext(ctx, query) 16 } 17 if ctx.Done() == context.Background().Done() { 18 return ci.Prepare(query) 19 } 20 21 type R struct { 22 err error 23 panic interface{} 24 si driver.Stmt 25 } 26 27 rc := make(chan R, 1) 28 go func() { 29 r := R{} 30 defer func() { 31 if v := recover(); v != nil { 32 r.panic = v 33 } 34 rc <- r 35 }() 36 r.si, r.err = ci.Prepare(query) 37 }() 38 select { 39 case <-ctx.Done(): 40 go func() { 41 <-rc 42 close(rc) 43 }() 44 return nil, ctx.Err() 45 case r := <-rc: 46 if r.panic != nil { 47 panic(r.panic) 48 } 49 return r.si, r.err 50 } 51 } 52 53 func ctxDriverExec(ctx context.Context, execer driver.Execer, query string, nvdargs []driver.NamedValue) (driver.Result, error) { 54 if execerCtx, is := execer.(driver.ExecerContext); is { 55 return execerCtx.ExecContext(ctx, query, nvdargs) 56 } 57 dargs, err := namedValueToValue(nvdargs) 58 if err != nil { 59 return nil, err 60 } 61 if ctx.Done() == context.Background().Done() { 62 return execer.Exec(query, dargs) 63 } 64 65 type R struct { 66 err error 67 panic interface{} 68 resi driver.Result 69 } 70 71 rc := make(chan R, 1) 72 go func() { 73 r := R{} 74 defer func() { 75 if v := recover(); v != nil { 76 r.panic = v 77 } 78 rc <- r 79 }() 80 r.resi, r.err = execer.Exec(query, dargs) 81 }() 82 select { 83 case <-ctx.Done(): 84 go func() { 85 <-rc 86 close(rc) 87 }() 88 return nil, ctx.Err() 89 case r := <-rc: 90 if r.panic != nil { 91 panic(r.panic) 92 } 93 return r.resi, r.err 94 } 95 } 96 97 func ctxDriverQuery(ctx context.Context, queryer driver.Queryer, query string, nvdargs []driver.NamedValue) (driver.Rows, error) { 98 if queryerCtx, is := queryer.(driver.QueryerContext); is { 99 return queryerCtx.QueryContext(ctx, query, nvdargs) 100 } 101 dargs, err := namedValueToValue(nvdargs) 102 if err != nil { 103 return nil, err 104 } 105 if ctx.Done() == context.Background().Done() { 106 return queryer.Query(query, dargs) 107 } 108 109 type R struct { 110 err error 111 panic interface{} 112 rowsi driver.Rows 113 } 114 115 rc := make(chan R, 1) 116 go func() { 117 r := R{} 118 defer func() { 119 if v := recover(); v != nil { 120 r.panic = v 121 } 122 rc <- r 123 }() 124 r.rowsi, r.err = queryer.Query(query, dargs) 125 }() 126 select { 127 case <-ctx.Done(): 128 go func() { 129 <-rc 130 close(rc) 131 }() 132 return nil, ctx.Err() 133 case r := <-rc: 134 if r.panic != nil { 135 panic(r.panic) 136 } 137 return r.rowsi, r.err 138 } 139 } 140 141 func ctxDriverStmtExec(ctx context.Context, si driver.Stmt, nvdargs []driver.NamedValue) (driver.Result, error) { 142 if siCtx, is := si.(driver.StmtExecContext); is { 143 return siCtx.ExecContext(ctx, nvdargs) 144 } 145 dargs, err := namedValueToValue(nvdargs) 146 if err != nil { 147 return nil, err 148 } 149 if ctx.Done() == context.Background().Done() { 150 return si.Exec(dargs) 151 } 152 153 type R struct { 154 err error 155 panic interface{} 156 resi driver.Result 157 } 158 159 rc := make(chan R, 1) 160 go func() { 161 r := R{} 162 defer func() { 163 if v := recover(); v != nil { 164 r.panic = v 165 } 166 rc <- r 167 }() 168 r.resi, r.err = si.Exec(dargs) 169 }() 170 select { 171 case <-ctx.Done(): 172 go func() { 173 <-rc 174 close(rc) 175 }() 176 return nil, ctx.Err() 177 case r := <-rc: 178 if r.panic != nil { 179 panic(r.panic) 180 } 181 return r.resi, r.err 182 } 183 } 184 185 func ctxDriverStmtQuery(ctx context.Context, si driver.Stmt, nvdargs []driver.NamedValue) (driver.Rows, error) { 186 if siCtx, is := si.(driver.StmtQueryContext); is { 187 return siCtx.QueryContext(ctx, nvdargs) 188 } 189 dargs, err := namedValueToValue(nvdargs) 190 if err != nil { 191 return nil, err 192 } 193 if ctx.Done() == context.Background().Done() { 194 return si.Query(dargs) 195 } 196 197 type R struct { 198 err error 199 panic interface{} 200 rowsi driver.Rows 201 } 202 203 rc := make(chan R, 1) 204 go func() { 205 r := R{} 206 defer func() { 207 if v := recover(); v != nil { 208 r.panic = v 209 } 210 rc <- r 211 }() 212 r.rowsi, r.err = si.Query(dargs) 213 }() 214 select { 215 case <-ctx.Done(): 216 go func() { 217 <-rc 218 close(rc) 219 }() 220 return nil, ctx.Err() 221 case r := <-rc: 222 if r.panic != nil { 223 panic(r.panic) 224 } 225 return r.rowsi, r.err 226 } 227 } 228 229 var errLevelNotSupported = errors.New("sql: selected isolation level is not supported") 230 231 func ctxDriverBegin(ctx context.Context, ci driver.Conn) (driver.Tx, error) { 232 if ciCtx, is := ci.(driver.ConnBeginContext); is { 233 return ciCtx.BeginContext(ctx) 234 } 235 236 if ctx.Done() == context.Background().Done() { 237 return ci.Begin() 238 } 239 240 // Check the transaction level in ctx. If set and non-default 241 // then return an error here as the BeginContext driver value is not supported. 242 if level, ok := driver.IsolationFromContext(ctx); ok && level != driver.IsolationLevel(LevelDefault) { 243 return nil, errors.New("sql: driver does not support non-default isolation level") 244 } 245 246 // Check for a read-only parameter in ctx. If a read-only transaction is 247 // requested return an error as the BeginContext driver value is not supported. 248 if ro := driver.ReadOnlyFromContext(ctx); ro { 249 return nil, errors.New("sql: driver does not support read-only transactions") 250 } 251 252 type R struct { 253 err error 254 panic interface{} 255 txi driver.Tx 256 } 257 rc := make(chan R, 1) 258 go func() { 259 r := R{} 260 defer func() { 261 if v := recover(); v != nil { 262 r.panic = v 263 } 264 rc <- r 265 }() 266 r.txi, r.err = ci.Begin() 267 }() 268 select { 269 case <-ctx.Done(): 270 go func() { 271 <-rc 272 close(rc) 273 }() 274 return nil, ctx.Err() 275 case r := <-rc: 276 if r.panic != nil { 277 panic(r.panic) 278 } 279 return r.txi, r.err 280 } 281 } 282 283 func namedValueToValue(named []driver.NamedValue) ([]driver.Value, error) { 284 dargs := make([]driver.Value, len(named)) 285 for n, param := range named { 286 if len(param.Name) > 0 { 287 return nil, errors.New("sql: driver does not support the use of Named Parameters") 288 } 289 dargs[n] = param.Value 290 } 291 return dargs, nil 292 }