mirror of
				https://github.com/go-gitea/gitea.git
				synced 2025-11-03 08:02:36 +09:00 
			
		
		
		
	
		
			
				
	
	
		
			129 lines
		
	
	
		
			2.5 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			129 lines
		
	
	
		
			2.5 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
// +build go1.8
 | 
						|
 | 
						|
package pq
 | 
						|
 | 
						|
import (
 | 
						|
	"context"
 | 
						|
	"database/sql"
 | 
						|
	"database/sql/driver"
 | 
						|
	"fmt"
 | 
						|
	"io"
 | 
						|
	"io/ioutil"
 | 
						|
)
 | 
						|
 | 
						|
// Implement the "QueryerContext" interface
 | 
						|
func (cn *conn) QueryContext(ctx context.Context, query string, args []driver.NamedValue) (driver.Rows, error) {
 | 
						|
	list := make([]driver.Value, len(args))
 | 
						|
	for i, nv := range args {
 | 
						|
		list[i] = nv.Value
 | 
						|
	}
 | 
						|
	finish := cn.watchCancel(ctx)
 | 
						|
	r, err := cn.query(query, list)
 | 
						|
	if err != nil {
 | 
						|
		if finish != nil {
 | 
						|
			finish()
 | 
						|
		}
 | 
						|
		return nil, err
 | 
						|
	}
 | 
						|
	r.finish = finish
 | 
						|
	return r, nil
 | 
						|
}
 | 
						|
 | 
						|
// Implement the "ExecerContext" interface
 | 
						|
func (cn *conn) ExecContext(ctx context.Context, query string, args []driver.NamedValue) (driver.Result, error) {
 | 
						|
	list := make([]driver.Value, len(args))
 | 
						|
	for i, nv := range args {
 | 
						|
		list[i] = nv.Value
 | 
						|
	}
 | 
						|
 | 
						|
	if finish := cn.watchCancel(ctx); finish != nil {
 | 
						|
		defer finish()
 | 
						|
	}
 | 
						|
 | 
						|
	return cn.Exec(query, list)
 | 
						|
}
 | 
						|
 | 
						|
// Implement the "ConnBeginTx" interface
 | 
						|
func (cn *conn) BeginTx(ctx context.Context, opts driver.TxOptions) (driver.Tx, error) {
 | 
						|
	var mode string
 | 
						|
 | 
						|
	switch sql.IsolationLevel(opts.Isolation) {
 | 
						|
	case sql.LevelDefault:
 | 
						|
		// Don't touch mode: use the server's default
 | 
						|
	case sql.LevelReadUncommitted:
 | 
						|
		mode = " ISOLATION LEVEL READ UNCOMMITTED"
 | 
						|
	case sql.LevelReadCommitted:
 | 
						|
		mode = " ISOLATION LEVEL READ COMMITTED"
 | 
						|
	case sql.LevelRepeatableRead:
 | 
						|
		mode = " ISOLATION LEVEL REPEATABLE READ"
 | 
						|
	case sql.LevelSerializable:
 | 
						|
		mode = " ISOLATION LEVEL SERIALIZABLE"
 | 
						|
	default:
 | 
						|
		return nil, fmt.Errorf("pq: isolation level not supported: %d", opts.Isolation)
 | 
						|
	}
 | 
						|
 | 
						|
	if opts.ReadOnly {
 | 
						|
		mode += " READ ONLY"
 | 
						|
	} else {
 | 
						|
		mode += " READ WRITE"
 | 
						|
	}
 | 
						|
 | 
						|
	tx, err := cn.begin(mode)
 | 
						|
	if err != nil {
 | 
						|
		return nil, err
 | 
						|
	}
 | 
						|
	cn.txnFinish = cn.watchCancel(ctx)
 | 
						|
	return tx, nil
 | 
						|
}
 | 
						|
 | 
						|
func (cn *conn) watchCancel(ctx context.Context) func() {
 | 
						|
	if done := ctx.Done(); done != nil {
 | 
						|
		finished := make(chan struct{})
 | 
						|
		go func() {
 | 
						|
			select {
 | 
						|
			case <-done:
 | 
						|
				_ = cn.cancel()
 | 
						|
				finished <- struct{}{}
 | 
						|
			case <-finished:
 | 
						|
			}
 | 
						|
		}()
 | 
						|
		return func() {
 | 
						|
			select {
 | 
						|
			case <-finished:
 | 
						|
			case finished <- struct{}{}:
 | 
						|
			}
 | 
						|
		}
 | 
						|
	}
 | 
						|
	return nil
 | 
						|
}
 | 
						|
 | 
						|
func (cn *conn) cancel() error {
 | 
						|
	c, err := dial(cn.dialer, cn.opts)
 | 
						|
	if err != nil {
 | 
						|
		return err
 | 
						|
	}
 | 
						|
	defer c.Close()
 | 
						|
 | 
						|
	{
 | 
						|
		can := conn{
 | 
						|
			c: c,
 | 
						|
		}
 | 
						|
		can.ssl(cn.opts)
 | 
						|
 | 
						|
		w := can.writeBuf(0)
 | 
						|
		w.int32(80877102) // cancel request code
 | 
						|
		w.int32(cn.processID)
 | 
						|
		w.int32(cn.secretKey)
 | 
						|
 | 
						|
		if err := can.sendStartupPacket(w); err != nil {
 | 
						|
			return err
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	// Read until EOF to ensure that the server received the cancel.
 | 
						|
	{
 | 
						|
		_, err := io.Copy(ioutil.Discard, c)
 | 
						|
		return err
 | 
						|
	}
 | 
						|
}
 |