1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586 |
- package sqladapter
-
- import (
- "database/sql"
- "errors"
- "sync"
- "sync/atomic"
- )
-
- var (
- activeStatements int64
- )
-
- // Stmt represents a *sql.Stmt that is cached and provides the
- // OnPurge method to allow it to clean after itself.
- type Stmt struct {
- *sql.Stmt
-
- query string
- mu sync.Mutex
-
- count int64
- dead bool
- }
-
- // NewStatement creates an returns an opened statement
- func NewStatement(stmt *sql.Stmt, query string) *Stmt {
- s := &Stmt{
- Stmt: stmt,
- query: query,
- }
- atomic.AddInt64(&activeStatements, 1)
- return s
- }
-
- // Open marks the statement as in-use
- func (c *Stmt) Open() (*Stmt, error) {
- c.mu.Lock()
- defer c.mu.Unlock()
-
- if c.dead {
- return nil, errors.New("statement is dead")
- }
-
- c.count++
- return c, nil
- }
-
- // Close closes the underlying statement if no other go-routine is using it.
- func (c *Stmt) Close() error {
- c.mu.Lock()
- defer c.mu.Unlock()
-
- c.count--
-
- return c.checkClose()
- }
-
- func (c *Stmt) checkClose() error {
- if c.dead && c.count == 0 {
- // Statement is dead and we can close it for real.
- err := c.Stmt.Close()
- if err != nil {
- return err
- }
- // Reduce active statements counter.
- atomic.AddInt64(&activeStatements, -1)
- }
- return nil
- }
-
- // OnPurge marks the statement as ready to be cleaned up.
- func (c *Stmt) OnPurge() {
- c.mu.Lock()
- defer c.mu.Unlock()
-
- c.dead = true
- c.checkClose()
- }
-
- // NumActiveStatements returns the global number of prepared statements in use
- // at any point.
- func NumActiveStatements() int64 {
- return atomic.LoadInt64(&activeStatements)
- }
|