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