Commit 2a5b9ead authored by gwenn's avatar gwenn

Another step toward Stmt cache support.

parent a61a41f9
...@@ -49,11 +49,10 @@ func (c *Cache) find(sql string) *Stmt { ...@@ -49,11 +49,10 @@ func (c *Cache) find(sql string) *Stmt {
return nil return nil
} }
// TODO To be called instead of Stmt#Finalize // To be called in Stmt#Finalize
func (c *Cache) release(s *Stmt) { func (c *Cache) release(s *Stmt) error {
if c.maxSize <= 0 || len(s.tail) > 0 { if c.maxSize <= 0 || len(s.tail) > 0 {
s.Finalize() return s.finalize()
return
} }
c.m.Lock() c.m.Lock()
defer c.m.Unlock() defer c.m.Unlock()
...@@ -61,9 +60,10 @@ func (c *Cache) release(s *Stmt) { ...@@ -61,9 +60,10 @@ func (c *Cache) release(s *Stmt) {
for c.l.Len() > c.maxSize { for c.l.Len() > c.maxSize {
v := c.l.Remove(c.l.Back()) v := c.l.Remove(c.l.Back())
if s, ok := v.(*Stmt); ok { if s, ok := v.(*Stmt); ok {
s.Finalize() s.finalize()
} }
} }
return nil
} }
// Finalize and free the cached prepared statements // Finalize and free the cached prepared statements
...@@ -79,7 +79,7 @@ func (c *Cache) flush() { ...@@ -79,7 +79,7 @@ func (c *Cache) flush() {
next = e.Next() next = e.Next()
v := c.l.Remove(e) v := c.l.Remove(e)
if s, ok := v.(*Stmt); ok { if s, ok := v.(*Stmt); ok {
s.Finalize() s.finalize()
} else { } else {
panic(fmt.Sprintf("unexpected element in Stmt cache: %#v", v)) panic(fmt.Sprintf("unexpected element in Stmt cache: %#v", v))
} }
......
...@@ -40,7 +40,7 @@ func (c *Conn) Databases() (map[string]string, error) { ...@@ -40,7 +40,7 @@ func (c *Conn) Databases() (map[string]string, error) {
if err != nil { if err != nil {
return nil, err return nil, err
} }
defer s.Finalize() defer s.finalize()
var databases map[string]string = make(map[string]string) var databases map[string]string = make(map[string]string)
var name, file string var name, file string
err = s.Select(func(s *Stmt) (err error) { err = s.Select(func(s *Stmt) (err error) {
...@@ -63,7 +63,7 @@ func (c *Conn) Tables() ([]string, error) { ...@@ -63,7 +63,7 @@ func (c *Conn) Tables() ([]string, error) {
if err != nil { if err != nil {
return nil, err return nil, err
} }
defer s.Finalize() defer s.finalize()
var tables []string = make([]string, 0, 20) var tables []string = make([]string, 0, 20)
err = s.Select(func(s *Stmt) (err error) { err = s.Select(func(s *Stmt) (err error) {
name, _ := s.ScanText(0) name, _ := s.ScanText(0)
...@@ -95,7 +95,7 @@ func (c *Conn) Columns(table string) ([]Column, error) { ...@@ -95,7 +95,7 @@ func (c *Conn) Columns(table string) ([]Column, error) {
if err != nil { if err != nil {
return nil, err return nil, err
} }
defer s.Finalize() defer s.finalize()
var columns []Column = make([]Column, 0, 20) var columns []Column = make([]Column, 0, 20)
err = s.Select(func(s *Stmt) (err error) { err = s.Select(func(s *Stmt) (err error) {
c := Column{} c := Column{}
...@@ -148,7 +148,7 @@ func (c *Conn) ForeignKeys(table string) (map[int]*ForeignKey, error) { ...@@ -148,7 +148,7 @@ func (c *Conn) ForeignKeys(table string) (map[int]*ForeignKey, error) {
if err != nil { if err != nil {
return nil, err return nil, err
} }
defer s.Finalize() defer s.finalize()
var fks = make(map[int]*ForeignKey) var fks = make(map[int]*ForeignKey)
var id, seq int var id, seq int
var ref, from, to string var ref, from, to string
...@@ -185,7 +185,7 @@ func (c *Conn) Indexes(table string) ([]Index, error) { ...@@ -185,7 +185,7 @@ func (c *Conn) Indexes(table string) ([]Index, error) {
if err != nil { if err != nil {
return nil, err return nil, err
} }
defer s.Finalize() defer s.finalize()
var indexes []Index = make([]Index, 0, 5) var indexes []Index = make([]Index, 0, 5)
err = s.Select(func(s *Stmt) (err error) { err = s.Select(func(s *Stmt) (err error) {
i := Index{} i := Index{}
...@@ -208,7 +208,7 @@ func (c *Conn) IndexColumns(index string) ([]Column, error) { ...@@ -208,7 +208,7 @@ func (c *Conn) IndexColumns(index string) ([]Column, error) {
if err != nil { if err != nil {
return nil, err return nil, err
} }
defer s.Finalize() defer s.finalize()
var columns []Column = make([]Column, 0, 5) var columns []Column = make([]Column, 0, 5)
err = s.Select(func(s *Stmt) (err error) { err = s.Select(func(s *Stmt) (err error) {
c := Column{} c := Column{}
......
...@@ -319,24 +319,24 @@ func (c *Conn) Exec(cmd string, args ...interface{}) error { ...@@ -319,24 +319,24 @@ func (c *Conn) Exec(cmd string, args ...interface{}) error {
} else if s.stmt == nil { } else if s.stmt == nil {
// this happens for a comment or white-space // this happens for a comment or white-space
cmd = s.tail cmd = s.tail
if err = s.Finalize(); err != nil { if err = s.finalize(); err != nil {
return err return err
} }
continue continue
} }
err = s.Exec(args...) err = s.Exec(args...)
if err != nil { if err != nil {
s.Finalize() s.finalize()
return err return err
} }
if len(s.tail) > 0 { if len(s.tail) > 0 {
if len(args) > 0 { if len(args) > 0 {
s.Finalize() s.finalize()
return c.specificError("Cannot execute multiple statements when args are specified") return c.specificError("Cannot execute multiple statements when args are specified")
} }
} }
cmd = s.tail cmd = s.tail
if err = s.Finalize(); err != nil { if err = s.finalize(); err != nil {
return err return err
} }
} }
...@@ -349,7 +349,7 @@ func (c *Conn) Exists(query string, args ...interface{}) (bool, error) { ...@@ -349,7 +349,7 @@ func (c *Conn) Exists(query string, args ...interface{}) (bool, error) {
if err != nil { if err != nil {
return false, err return false, err
} }
defer s.Finalize() defer s.finalize()
return s.Next() return s.Next()
} }
...@@ -360,7 +360,7 @@ func (c *Conn) OneValue(query string, value interface{}, args ...interface{}) er ...@@ -360,7 +360,7 @@ func (c *Conn) OneValue(query string, value interface{}, args ...interface{}) er
if err != nil { if err != nil {
return err return err
} }
defer s.Finalize() defer s.finalize()
b, err := s.Next() b, err := s.Next()
if err != nil { if err != nil {
return err return err
...@@ -445,7 +445,7 @@ func (c *Conn) exec(cmd string) error { ...@@ -445,7 +445,7 @@ func (c *Conn) exec(cmd string) error {
if err != nil { if err != nil {
return err return err
} }
defer s.Finalize() defer s.finalize()
rv := C.sqlite3_step(s.stmt) rv := C.sqlite3_step(s.stmt)
if Errno(rv) != Done { if Errno(rv) != Done {
return s.error(rv) return s.error(rv)
......
...@@ -76,8 +76,10 @@ type Stmt struct { ...@@ -76,8 +76,10 @@ type Stmt struct {
cols map[string]int // cached columns index by name cols map[string]int // cached columns index by name
bindParameterCount int bindParameterCount int
params map[string]int // cached parameter index by name params map[string]int // cached parameter index by name
// Enable type check in Scan methods // Enable type check in Scan methods (default true)
CheckTypeMismatch bool CheckTypeMismatch bool
// Tell if the stmt should be cached (default false)
Cacheable bool
} }
// Compile an SQL statement and optionally bind values. // Compile an SQL statement and optionally bind values.
...@@ -109,7 +111,7 @@ func (c *Conn) Prepare(cmd string, args ...interface{}) (*Stmt, error) { ...@@ -109,7 +111,7 @@ func (c *Conn) Prepare(cmd string, args ...interface{}) (*Stmt, error) {
if len(args) > 0 { if len(args) > 0 {
err := s.Bind(args...) err := s.Bind(args...)
if err != nil { if err != nil {
s.Finalize() s.finalize()
return nil, err return nil, err
} }
} }
...@@ -880,6 +882,12 @@ func (s *Stmt) Busy() bool { ...@@ -880,6 +882,12 @@ func (s *Stmt) Busy() bool {
// Destroy a prepared statement // Destroy a prepared statement
// (See http://sqlite.org/c3ref/finalize.html) // (See http://sqlite.org/c3ref/finalize.html)
func (s *Stmt) Finalize() error { func (s *Stmt) Finalize() error {
if s.Cacheable {
return s.c.stmtCache.release(s)
}
return s.finalize()
}
func (s *Stmt) finalize() error {
rv := C.sqlite3_finalize(s.stmt) rv := C.sqlite3_finalize(s.stmt)
if rv != C.SQLITE_OK { if rv != C.SQLITE_OK {
return s.error(rv) return s.error(rv)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment