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  }