Commit b5f02770 authored by gwenn's avatar gwenn

Introduce a FastExec method.

parent 9669acc1
...@@ -6,6 +6,7 @@ package sqlite_test ...@@ -6,6 +6,7 @@ package sqlite_test
import ( import (
. "github.com/gwenn/gosqlite" . "github.com/gwenn/gosqlite"
"strings"
"testing" "testing"
) )
...@@ -141,3 +142,27 @@ func BenchmarkNamedInsert(b *testing.B) { ...@@ -141,3 +142,27 @@ func BenchmarkNamedInsert(b *testing.B) {
} }
panicOnError(b, db.Commit()) panicOnError(b, db.Commit())
} }
func BenchmarkExec(b *testing.B) {
b.StopTimer()
db, err := Open(":memory:")
panicOnError(b, err)
defer db.Close()
b.StartTimer()
for i := 0; i < b.N; i++ {
panicOnError(b, db.Exec(strings.Repeat("BEGIN;ROLLBACK;", 5)))
}
}
func BenchmarkFastExec(b *testing.B) {
b.StopTimer()
db, err := Open(":memory:")
panicOnError(b, err)
defer db.Close()
b.StartTimer()
for i := 0; i < b.N; i++ {
panicOnError(b, db.FastExec(strings.Repeat("BEGIN;ROLLBACK;", 5)))
}
}
...@@ -65,7 +65,7 @@ func (c *Conn) SchemaVersion(dbName string) (int, error) { ...@@ -65,7 +65,7 @@ func (c *Conn) SchemaVersion(dbName string) (int, error) {
// Database name is optional (default is 'main'). // Database name is optional (default is 'main').
// (See http://sqlite.org/pragma.html#pragma_recursive_triggers) // (See http://sqlite.org/pragma.html#pragma_recursive_triggers)
func (c *Conn) SetRecursiveTriggers(dbName string, on bool) error { func (c *Conn) SetRecursiveTriggers(dbName string, on bool) error {
return c.exec(pragma(dbName, fmt.Sprintf("recursive_triggers=%t", on))) return c.FastExec(pragma(dbName, fmt.Sprintf("recursive_triggers=%t", on)))
} }
// JournalMode queries the current journaling mode for database. // JournalMode queries the current journaling mode for database.
...@@ -132,7 +132,7 @@ func (c *Conn) Synchronous(dbName string) (int, error) { ...@@ -132,7 +132,7 @@ func (c *Conn) Synchronous(dbName string) (int, error) {
// Database name is optional (default is 'main'). // Database name is optional (default is 'main').
// (See http://sqlite.org/pragma.html#pragma_synchronous) // (See http://sqlite.org/pragma.html#pragma_synchronous)
func (c *Conn) SetSynchronous(dbName string, mode int) error { func (c *Conn) SetSynchronous(dbName string, mode int) error {
return c.exec(pragma(dbName, fmt.Sprintf("synchronous=%d", mode))) return c.FastExec(pragma(dbName, fmt.Sprintf("synchronous=%d", mode)))
} }
// FkViolation is the description of one foreign key constraint violation. // FkViolation is the description of one foreign key constraint violation.
...@@ -200,7 +200,7 @@ func (c *Conn) QueryOnly(dbName string) (bool, error) { ...@@ -200,7 +200,7 @@ func (c *Conn) QueryOnly(dbName string) (bool, error) {
// Database name is optional (default is 'main'). // Database name is optional (default is 'main').
// (See http://sqlite.org/pragma.html#pragma_query_only) // (See http://sqlite.org/pragma.html#pragma_query_only)
func (c *Conn) SetQueryOnly(dbName string, mode bool) error { func (c *Conn) SetQueryOnly(dbName string, mode bool) error {
return c.exec(pragma(dbName, fmt.Sprintf("query_only=%t", mode))) return c.FastExec(pragma(dbName, fmt.Sprintf("query_only=%t", mode)))
} }
// ApplicationId queries the "Application ID" integer located into the database header. // ApplicationId queries the "Application ID" integer located into the database header.
...@@ -219,7 +219,7 @@ func (c *Conn) ApplicationId(dbName string) (int, error) { ...@@ -219,7 +219,7 @@ func (c *Conn) ApplicationId(dbName string) (int, error) {
// Database name is optional (default is 'main'). // Database name is optional (default is 'main').
// (See http://sqlite.org/pragma.html#pragma_application_id) // (See http://sqlite.org/pragma.html#pragma_application_id)
func (c *Conn) SetApplicationId(dbName string, id int) error { func (c *Conn) SetApplicationId(dbName string, id int) error {
return c.exec(pragma(dbName, fmt.Sprintf("application_id=%d", id))) return c.FastExec(pragma(dbName, fmt.Sprintf("application_id=%d", id)))
} }
func pragma(dbName, pragmaName string) string { func pragma(dbName, pragmaName string) string {
......
...@@ -310,7 +310,7 @@ func (c *Conn) Filename(dbName string) string { ...@@ -310,7 +310,7 @@ func (c *Conn) Filename(dbName string) string {
return C.GoString(C.sqlite3_db_filename(c.db, cname)) return C.GoString(C.sqlite3_db_filename(c.db, cname))
} }
// Exec prepares and executes one parameterized statement or many statements (separated by semi-colon). // Exec prepares and executes one or many parameterized statement(s) (separated by semi-colon).
// Don't use it with SELECT or anything that returns data. // Don't use it with SELECT or anything that returns data.
func (c *Conn) Exec(cmd string, args ...interface{}) error { func (c *Conn) Exec(cmd string, args ...interface{}) error {
for len(cmd) > 0 { for len(cmd) > 0 {
...@@ -422,11 +422,11 @@ func (c *Conn) Begin() error { ...@@ -422,11 +422,11 @@ func (c *Conn) Begin() error {
// (See http://www.sqlite.org/lang_transaction.html) // (See http://www.sqlite.org/lang_transaction.html)
func (c *Conn) BeginTransaction(t TransactionType) error { func (c *Conn) BeginTransaction(t TransactionType) error {
if t == Deferred { if t == Deferred {
return c.exec("BEGIN") return c.FastExec("BEGIN")
} else if t == Immediate { } else if t == Immediate {
return c.exec("BEGIN IMMEDIATE") return c.FastExec("BEGIN IMMEDIATE")
} else if t == Exclusive { } else if t == Exclusive {
return c.exec("BEGIN EXCLUSIVE") return c.FastExec("BEGIN EXCLUSIVE")
} }
panic(fmt.Sprintf("Unsupported transaction type: '%#v'", t)) panic(fmt.Sprintf("Unsupported transaction type: '%#v'", t))
return nil // Go 1.1 unreachable code return nil // Go 1.1 unreachable code
...@@ -435,13 +435,13 @@ func (c *Conn) BeginTransaction(t TransactionType) error { ...@@ -435,13 +435,13 @@ func (c *Conn) BeginTransaction(t TransactionType) error {
// Commit commits transaction // Commit commits transaction
func (c *Conn) Commit() error { func (c *Conn) Commit() error {
// TODO Check autocommit? // TODO Check autocommit?
return c.exec("COMMIT") return c.FastExec("COMMIT")
} }
// Rollback rollbacks transaction // Rollback rollbacks transaction
func (c *Conn) Rollback() error { func (c *Conn) Rollback() error {
// TODO Check autocommit? // TODO Check autocommit?
return c.exec("ROLLBACK") return c.FastExec("ROLLBACK")
} }
// Transaction is used to execute a function inside an SQLite database transaction. // Transaction is used to execute a function inside an SQLite database transaction.
...@@ -492,19 +492,19 @@ func (c *Conn) Transaction(t TransactionType, f func(c *Conn) error) (err error) ...@@ -492,19 +492,19 @@ func (c *Conn) Transaction(t TransactionType, f func(c *Conn) error) (err error)
// Savepoint starts a new transaction with a name. // Savepoint starts a new transaction with a name.
// (See http://sqlite.org/lang_savepoint.html) // (See http://sqlite.org/lang_savepoint.html)
func (c *Conn) Savepoint(name string) error { func (c *Conn) Savepoint(name string) error {
return c.exec(Mprintf("SAVEPOINT %Q", name)) return c.FastExec(Mprintf("SAVEPOINT %Q", name))
} }
// ReleaseSavepoint causes all savepoints back to and including the most recent savepoint with a matching name to be removed from the transaction stack. // ReleaseSavepoint causes all savepoints back to and including the most recent savepoint with a matching name to be removed from the transaction stack.
// (See http://sqlite.org/lang_savepoint.html) // (See http://sqlite.org/lang_savepoint.html)
func (c *Conn) ReleaseSavepoint(name string) error { func (c *Conn) ReleaseSavepoint(name string) error {
return c.exec(Mprintf("RELEASE %Q", name)) return c.FastExec(Mprintf("RELEASE %Q", name))
} }
// RollbackSavepoint reverts the state of the database back to what it was just before the corresponding SAVEPOINT. // RollbackSavepoint reverts the state of the database back to what it was just before the corresponding SAVEPOINT.
// (See http://sqlite.org/lang_savepoint.html) // (See http://sqlite.org/lang_savepoint.html)
func (c *Conn) RollbackSavepoint(name string) error { func (c *Conn) RollbackSavepoint(name string) error {
return c.exec(Mprintf("ROLLBACK TO SAVEPOINT %Q", name)) return c.FastExec(Mprintf("ROLLBACK TO SAVEPOINT %Q", name))
} }
func (c *Conn) exec(cmd string) error { func (c *Conn) exec(cmd string) error {
...@@ -514,12 +514,19 @@ func (c *Conn) exec(cmd string) error { ...@@ -514,12 +514,19 @@ func (c *Conn) exec(cmd string) error {
} }
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 { // this check cannot be done with sqlite3_exec
return s.error(rv, "Conn.exec(%q)", cmd) return s.error(rv, "Conn.exec(%q)", cmd)
} }
return nil return nil
} }
// FastExec executes one or many non-parameterized statement(s) (separated by semi-colon) with no control and no stmt cache.
func (c *Conn) FastExec(cmd string) error {
cmdstr := C.CString(cmd)
defer C.free(unsafe.Pointer(cmdstr))
return c.error(C.sqlite3_exec(c.db, cmdstr, nil, nil, nil))
}
// Close closes a database connection and any dangling statements. // Close closes a database connection and any dangling statements.
// (See http://sqlite.org/c3ref/close.html) // (See http://sqlite.org/c3ref/close.html)
func (c *Conn) Close() error { func (c *Conn) Close() error {
......
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