github.com/rakyll/go@v0.0.0-20170216000551-64c02460d703/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 si, err := ci.Prepare(query) 18 if err == nil { 19 select { 20 default: 21 case <-ctx.Done(): 22 si.Close() 23 return nil, ctx.Err() 24 } 25 } 26 return si, err 27 } 28 29 func ctxDriverExec(ctx context.Context, execer driver.Execer, query string, nvdargs []driver.NamedValue) (driver.Result, error) { 30 if execerCtx, is := execer.(driver.ExecerContext); is { 31 return execerCtx.ExecContext(ctx, query, nvdargs) 32 } 33 dargs, err := namedValueToValue(nvdargs) 34 if err != nil { 35 return nil, err 36 } 37 38 select { 39 default: 40 case <-ctx.Done(): 41 return nil, ctx.Err() 42 } 43 return execer.Exec(query, dargs) 44 } 45 46 func ctxDriverQuery(ctx context.Context, queryer driver.Queryer, query string, nvdargs []driver.NamedValue) (driver.Rows, error) { 47 if queryerCtx, is := queryer.(driver.QueryerContext); is { 48 ret, err := queryerCtx.QueryContext(ctx, query, nvdargs) 49 return ret, err 50 } 51 dargs, err := namedValueToValue(nvdargs) 52 if err != nil { 53 return nil, err 54 } 55 56 select { 57 default: 58 case <-ctx.Done(): 59 return nil, ctx.Err() 60 } 61 return queryer.Query(query, dargs) 62 } 63 64 func ctxDriverStmtExec(ctx context.Context, si driver.Stmt, nvdargs []driver.NamedValue) (driver.Result, error) { 65 if siCtx, is := si.(driver.StmtExecContext); is { 66 return siCtx.ExecContext(ctx, nvdargs) 67 } 68 dargs, err := namedValueToValue(nvdargs) 69 if err != nil { 70 return nil, err 71 } 72 73 select { 74 default: 75 case <-ctx.Done(): 76 return nil, ctx.Err() 77 } 78 return si.Exec(dargs) 79 } 80 81 func ctxDriverStmtQuery(ctx context.Context, si driver.Stmt, nvdargs []driver.NamedValue) (driver.Rows, error) { 82 if siCtx, is := si.(driver.StmtQueryContext); is { 83 return siCtx.QueryContext(ctx, nvdargs) 84 } 85 dargs, err := namedValueToValue(nvdargs) 86 if err != nil { 87 return nil, err 88 } 89 90 select { 91 default: 92 case <-ctx.Done(): 93 return nil, ctx.Err() 94 } 95 return si.Query(dargs) 96 } 97 98 var errLevelNotSupported = errors.New("sql: selected isolation level is not supported") 99 100 func ctxDriverBegin(ctx context.Context, opts *TxOptions, ci driver.Conn) (driver.Tx, error) { 101 if ciCtx, is := ci.(driver.ConnBeginTx); is { 102 dopts := driver.TxOptions{} 103 if opts != nil { 104 dopts.Isolation = driver.IsolationLevel(opts.Isolation) 105 dopts.ReadOnly = opts.ReadOnly 106 } 107 return ciCtx.BeginTx(ctx, dopts) 108 } 109 110 if ctx.Done() == context.Background().Done() { 111 return ci.Begin() 112 } 113 114 if opts != nil { 115 // Check the transaction level. If the transaction level is non-default 116 // then return an error here as the BeginTx driver value is not supported. 117 if opts.Isolation != LevelDefault { 118 return nil, errors.New("sql: driver does not support non-default isolation level") 119 } 120 121 // If a read-only transaction is requested return an error as the 122 // BeginTx driver value is not supported. 123 if opts.ReadOnly { 124 return nil, errors.New("sql: driver does not support read-only transactions") 125 } 126 } 127 128 txi, err := ci.Begin() 129 if err == nil { 130 select { 131 default: 132 case <-ctx.Done(): 133 txi.Rollback() 134 return nil, ctx.Err() 135 } 136 } 137 return txi, err 138 } 139 140 func namedValueToValue(named []driver.NamedValue) ([]driver.Value, error) { 141 dargs := make([]driver.Value, len(named)) 142 for n, param := range named { 143 if len(param.Name) > 0 { 144 return nil, errors.New("sql: driver does not support the use of Named Parameters") 145 } 146 dargs[n] = param.Value 147 } 148 return dargs, nil 149 }