Source file src/database/sql/ctxutil.go

     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  func ctxDriverBegin(ctx context.Context, opts *TxOptions, ci driver.Conn) (driver.Tx, error) {
    98  	if ciCtx, is := ci.(driver.ConnBeginTx); is {
    99  		dopts := driver.TxOptions{}
   100  		if opts != nil {
   101  			dopts.Isolation = driver.IsolationLevel(opts.Isolation)
   102  			dopts.ReadOnly = opts.ReadOnly
   103  		}
   104  		return ciCtx.BeginTx(ctx, dopts)
   105  	}
   106  
   107  	if opts != nil {
   108  		// Check the transaction level. If the transaction level is non-default
   109  		// then return an error here as the BeginTx driver value is not supported.
   110  		if opts.Isolation != LevelDefault {
   111  			return nil, errors.New("sql: driver does not support non-default isolation level")
   112  		}
   113  
   114  		// If a read-only transaction is requested return an error as the
   115  		// BeginTx driver value is not supported.
   116  		if opts.ReadOnly {
   117  			return nil, errors.New("sql: driver does not support read-only transactions")
   118  		}
   119  	}
   120  
   121  	if ctx.Done() == nil {
   122  		return ci.Begin()
   123  	}
   124  
   125  	txi, err := ci.Begin()
   126  	if err == nil {
   127  		select {
   128  		default:
   129  		case <-ctx.Done():
   130  			txi.Rollback()
   131  			return nil, ctx.Err()
   132  		}
   133  	}
   134  	return txi, err
   135  }
   136  
   137  func namedValueToValue(named []driver.NamedValue) ([]driver.Value, error) {
   138  	dargs := make([]driver.Value, len(named))
   139  	for n, param := range named {
   140  		if len(param.Name) > 0 {
   141  			return nil, errors.New("sql: driver does not support the use of Named Parameters")
   142  		}
   143  		dargs[n] = param.Value
   144  	}
   145  	return dargs, nil
   146  }
   147  

View as plain text