move reset/clear into putCachedStmt and always finalize on failure

This avoids an unnecessary reset when the cache is full, guarantees
a statement cannot enter the cache without being reset/cleared, and
fixes a leak where sqlite3_finalize was not called when reset failed.
This commit is contained in:
Yasuhiro Matsumoto
2026-04-08 13:42:26 +09:00
parent 0e58fa4d72
commit 867dcbfbdc

View File

@@ -1942,6 +1942,10 @@ func (c *SQLiteConn) putCachedStmt(s *SQLiteStmt) bool {
if c.db == nil || c.stmtCacheCount >= c.stmtCacheSize { if c.db == nil || c.stmtCacheCount >= c.stmtCacheSize {
return false return false
} }
rv := C._sqlite3_reset_clear(s.s)
if rv != C.SQLITE_ROW && rv != C.SQLITE_OK && rv != C.SQLITE_DONE {
return false
}
c.stmtCache[s.cacheKey] = append(c.stmtCache[s.cacheKey], s) c.stmtCache[s.cacheKey] = append(c.stmtCache[s.cacheKey], s)
c.stmtCacheCount++ c.stmtCacheCount++
return true return true
@@ -2116,16 +2120,8 @@ func (s *SQLiteStmt) Close() error {
if !conn.dbConnOpen() { if !conn.dbConnOpen() {
return errors.New("sqlite statement with already closed database connection") return errors.New("sqlite statement with already closed database connection")
} }
if s.cacheKey != "" { if s.cacheKey != "" && conn.putCachedStmt(s) {
rv := C._sqlite3_reset_clear(stmt) return nil
if rv != C.SQLITE_ROW && rv != C.SQLITE_OK && rv != C.SQLITE_DONE {
s.s = nil
s.c = nil
return conn.lastError()
}
if conn.putCachedStmt(s) {
return nil
}
} }
s.s = nil s.s = nil
s.c = nil s.c = nil