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  }