1package squirrel 2 3import ( 4 "database/sql" 5 "sync" 6) 7 8// Prepareer is the interface that wraps the Prepare method. 9// 10// Prepare executes the given query as implemented by database/sql.Prepare. 11type Preparer interface { 12 Prepare(query string) (*sql.Stmt, error) 13} 14 15// DBProxy groups the Execer, Queryer, QueryRower, and Preparer interfaces. 16type DBProxy interface { 17 Execer 18 Queryer 19 QueryRower 20 Preparer 21} 22 23// NOTE: NewStmtCacher is defined in stmtcacher_ctx.go (Go >= 1.8) or stmtcacher_noctx.go (Go < 1.8). 24 25type stmtCacher struct { 26 prep Preparer 27 cache map[string]*sql.Stmt 28 mu sync.Mutex 29} 30 31func (sc *stmtCacher) Prepare(query string) (*sql.Stmt, error) { 32 sc.mu.Lock() 33 defer sc.mu.Unlock() 34 stmt, ok := sc.cache[query] 35 if ok { 36 return stmt, nil 37 } 38 stmt, err := sc.prep.Prepare(query) 39 if err == nil { 40 sc.cache[query] = stmt 41 } 42 return stmt, err 43} 44 45func (sc *stmtCacher) Exec(query string, args ...interface{}) (res sql.Result, err error) { 46 stmt, err := sc.Prepare(query) 47 if err != nil { 48 return 49 } 50 return stmt.Exec(args...) 51} 52 53func (sc *stmtCacher) Query(query string, args ...interface{}) (rows *sql.Rows, err error) { 54 stmt, err := sc.Prepare(query) 55 if err != nil { 56 return 57 } 58 return stmt.Query(args...) 59} 60 61func (sc *stmtCacher) QueryRow(query string, args ...interface{}) RowScanner { 62 stmt, err := sc.Prepare(query) 63 if err != nil { 64 return &Row{err: err} 65 } 66 return stmt.QueryRow(args...) 67} 68 69type DBProxyBeginner interface { 70 DBProxy 71 Begin() (*sql.Tx, error) 72} 73 74type stmtCacheProxy struct { 75 DBProxy 76 db *sql.DB 77} 78 79func NewStmtCacheProxy(db *sql.DB) DBProxyBeginner { 80 return &stmtCacheProxy{DBProxy: NewStmtCacher(db), db: db} 81} 82 83func (sp *stmtCacheProxy) Begin() (*sql.Tx, error) { 84 return sp.db.Begin() 85} 86