func driverExec(t *testing.T, dc driver.Conn, query string) { st, err := dc.Prepare(query) if err != nil { t.Fatal(err) } defer func() { if err := st.Close(); err != nil && t != nil { t.Fatal(err) } }() r, err := st.Exec([]driver.Value{}) if err != nil { if t != nil { t.Fatal(err) } return } _, err = r.RowsAffected() if err != nil { if t != nil { t.Fatalf("r.RowsAffected(%q ...) failed: %v", query, err) } return } }
func ctxDriverBegin(ctx context.Context, ci driver.Conn) (driver.Tx, error) { if ciCtx, is := ci.(driver.ConnBeginContext); is { return ciCtx.BeginContext(ctx) } if ctx.Done() == context.Background().Done() { return ci.Begin() } // Check the transaction level in ctx. If set and non-default // then return an error here as the BeginContext driver value is not supported. if level, ok := driver.IsolationFromContext(ctx); ok && level != driver.IsolationLevel(LevelDefault) { return nil, errors.New("sql: driver does not support non-default isolation level") } // Check for a read-only parameter in ctx. If a read-only transaction is // requested return an error as the BeginContext driver value is not supported. if ro := driver.ReadOnlyFromContext(ctx); ro { return nil, errors.New("sql: driver does not support read-only transactions") } txi, err := ci.Begin() if err == nil { select { default: case <-ctx.Done(): txi.Rollback() return nil, ctx.Err() } } return txi, err }
func ctxDriverBegin(ctx context.Context, ci driver.Conn) (driver.Tx, error) { if ciCtx, is := ci.(driver.ConnBeginContext); is { return ciCtx.BeginContext(ctx) } if ctx.Done() == context.Background().Done() { return ci.Begin() } // Check the transaction level in ctx. If set and non-default // then return an error here as the BeginContext driver value is not supported. if level, ok := driver.IsolationFromContext(ctx); ok && level != driver.IsolationLevel(LevelDefault) { return nil, errors.New("sql: driver does not support non-default isolation level") } // Check for a read-only parameter in ctx. If a read-only transaction is // requested return an error as the BeginContext driver value is not supported. if ro := driver.ReadOnlyFromContext(ctx); ro { return nil, errors.New("sql: driver does not support read-only transactions") } type R struct { err error panic interface{} txi driver.Tx } rc := make(chan R, 1) go func() { r := R{} defer func() { if v := recover(); v != nil { r.panic = v } rc <- r }() r.txi, r.err = ci.Begin() }() select { case <-ctx.Done(): go func() { <-rc close(rc) }() return nil, ctx.Err() case r := <-rc: if r.panic != nil { panic(r.panic) } return r.txi, r.err } }
// queryConn executes a query on the given connection. // The connection gets released by the releaseConn function. func (db *DB) queryConn(ci driver.Conn, releaseConn func(error), query string, args []interface{}) (*Rows, error) { if queryer, ok := ci.(driver.Queryer); ok { dargs, err := driverArgs(nil, args) if err != nil { releaseConn(err) return nil, err } rowsi, err := queryer.Query(query, dargs) if err != driver.ErrSkip { if err != nil { releaseConn(err) return nil, err } // Note: ownership of ci passes to the *Rows, to be freed // with releaseConn. rows := &Rows{ db: db, ci: ci, releaseConn: releaseConn, rowsi: rowsi, } return rows, nil } } sti, err := ci.Prepare(query) if err != nil { releaseConn(err) return nil, err } rowsi, err := rowsiFromStatement(sti, args...) if err != nil { releaseConn(err) sti.Close() return nil, err } // Note: ownership of ci passes to the *Rows, to be freed // with releaseConn. rows := &Rows{ db: db, ci: ci, releaseConn: releaseConn, rowsi: rowsi, closeStmt: sti, } return rows, nil }
func ctxDriverPrepare(ctx context.Context, ci driver.Conn, query string) (driver.Stmt, error) { if ciCtx, is := ci.(driver.ConnPrepareContext); is { return ciCtx.PrepareContext(ctx, query) } si, err := ci.Prepare(query) if err == nil { select { default: case <-ctx.Done(): si.Close() return nil, ctx.Err() } } return si, err }
func commitTrans(dbcon driver.Conn, cmd string) error { dbstmt, e := dbcon.Prepare(cmd) if e != nil { return e } _, e = dbstmt.Exec(nil) if e != nil { return e } e = dbstmt.Close() if e != nil { return e } return nil }
// putConn adds a connection to the db's free pool. // err is optionally the last error that occurred on this connection. func (db *DB) putConn(c driver.Conn, err error) { if err == driver.ErrBadConn { // Don't reuse bad connections. return } db.mu.Lock() if putConnHook != nil { putConnHook(db, c) } if n := len(db.freeConn); !db.closed && n < db.maxIdleConns() { db.freeConn = append(db.freeConn, c) db.mu.Unlock() return } // TODO: check to see if we need this Conn for any prepared // statements which are still active? db.mu.Unlock() c.Close() }
func ctxDriverBegin(ctx context.Context, ci driver.Conn) (driver.Tx, error) { if ciCtx, is := ci.(driver.ConnBeginContext); is { return ciCtx.BeginContext(ctx) } if ctx.Done() == context.Background().Done() { return ci.Begin() } // TODO(kardianos): check the transaction level in ctx. If set and non-default // then return an error here as the BeginContext driver value is not supported. type R struct { err error panic interface{} txi driver.Tx } rc := make(chan R, 1) go func() { r := R{} defer func() { if v := recover(); v != nil { r.panic = v } rc <- r }() r.txi, r.err = ci.Begin() }() select { case <-ctx.Done(): go func() { <-rc close(rc) }() return nil, ctx.Err() case r := <-rc: if r.panic != nil { panic(r.panic) } return r.txi, r.err } }
func ctxDriverPrepare(ctx context.Context, ci driver.Conn, query string) (driver.Stmt, error) { if ciCtx, is := ci.(driver.ConnPrepareContext); is { return ciCtx.PrepareContext(ctx, query) } if ctx.Done() == context.Background().Done() { return ci.Prepare(query) } type R struct { err error panic interface{} si driver.Stmt } rc := make(chan R, 1) go func() { r := R{} defer func() { if v := recover(); v != nil { r.panic = v } rc <- r }() r.si, r.err = ci.Prepare(query) }() select { case <-ctx.Done(): go func() { <-rc close(rc) }() return nil, ctx.Err() case r := <-rc: if r.panic != nil { panic(r.panic) } return r.si, r.err } }
// putConn adds a connection to the db's free pool. // err is optionally the last error that occurred on this connection. func (db *DB) putConn(c driver.Conn, err error) { db.mu.Lock() if !db.outConn[c] { if debugGetPut { fmt.Printf("putConn(%v) DUPLICATE was: %s\n\nPREVIOUS was: %s", c, stack(), db.lastPut[c]) } panic("sql: connection returned that was never out") } if debugGetPut { db.lastPut[c] = stack() } delete(db.outConn, c) if fns, ok := db.onConnPut[c]; ok { for _, fn := range fns { fn() } delete(db.onConnPut, c) } if err == driver.ErrBadConn { // Don't reuse bad connections. db.mu.Unlock() return } if putConnHook != nil { putConnHook(db, c) } if n := len(db.freeConn); !db.closed && n < db.maxIdleConns() { db.freeConn = append(db.freeConn, c) db.mu.Unlock() return } // TODO: check to see if we need this Conn for any prepared // statements which are still active? db.mu.Unlock() c.Close() }
func (p *Proxy) Open(name string) (driver.Conn, error) { var err error var ctx interface{} var conn driver.Conn if h := p.Hooks.PostOpen; h != nil { // Setup PostOpen. This needs to be a closure like this // or otherwise changes to the `ctx` and `conn` parameters // within this Open() method does not get applied at the // time defer is fired defer func() { h(ctx, conn) }() } if h := p.Hooks.PreOpen; h != nil { if ctx, err = h(name); err != nil { return nil, err } } conn, err = p.Driver.Open(name) if err != nil { return nil, err } conn = &Conn{ Conn: conn, Proxy: p, } if hook := p.Hooks.Open; hook != nil { if err = hook(ctx, conn); err != nil { conn.Close() return nil, err } } return conn, nil }
func (db *DB) closeConn(c driver.Conn) { // TODO: check to see if we need this Conn for any prepared statements // that are active. c.Close() }