Commit f687a5d8 authored by gwenn's avatar gwenn

Add transaction related methods.

parent 83fee886
......@@ -290,6 +290,39 @@ func (c *Conn) GetAutocommit() bool {
return C.sqlite3_get_autocommit(c.db) != 0
}
type TransactionType int
const (
DEFERRED TransactionType = 0
IMMEDIATE TransactionType = 1
EXCLUSIVE TransactionType = 2
)
func (c *Conn) Begin() os.Error {
return c.BeginTransaction(DEFERRED)
}
func (c *Conn) BeginTransaction(t TransactionType) os.Error {
if t == DEFERRED {
return c.Exec("BEGIN")
} else if t == IMMEDIATE {
return c.Exec("BEGIN IMMEDIATE")
} else if t == EXCLUSIVE {
return c.Exec("BEGIN EXCLUSIVE")
}
panic(fmt.Sprintf("Unsupported transaction type: '%#v'", t))
return nil
}
func (c *Conn) Commit() os.Error {
// TODO Check autocommit?
return c.Exec("COMMIT")
}
func (c *Conn) Rollback() os.Error {
// TODO Check autocommit?
return c.Exec("ROLLBACK")
}
// Prepared Statement (sqlite3_stmt)
type Stmt struct {
c *Conn
......@@ -525,7 +558,7 @@ func (s *Stmt) ColumnIndex(name string) (int, os.Error) {
}
// Set nullable to false to skip NULL type test.
// Returns true when nullable is true and field is null.
// Returns true when nullable is true and column is null.
// Calls sqlite3_column_count, sqlite3_column_name and sqlite3_column_(blob|double|int|int64|text) depending on args type.
// http://sqlite.org/c3ref/column_blob.html
func (s *Stmt) NamedScanColumn(name string, value interface{}, nullable bool) (bool, os.Error) {
......@@ -539,7 +572,7 @@ func (s *Stmt) NamedScanColumn(name string, value interface{}, nullable bool) (b
// The leftmost column is number 0.
// Index starts at 0.
// Set nullable to false to skip NULL type test.
// Returns true when nullable is true and field is null.
// Returns true when nullable is true and column is null.
// Calls sqlite3_column_(blob|double|int|int64|text) depending on args type.
// http://sqlite.org/c3ref/column_blob.html
func (s *Stmt) ScanColumn(index int, value interface{}, nullable bool) (bool, os.Error) {
......
......@@ -95,6 +95,20 @@ func TestCreateTable(t *testing.T) {
createTable(db, t)
}
func TestTransaction(t *testing.T) {
db := open(t)
defer db.Close()
if err := db.Begin(); err != nil {
t.Fatalf("Error while beginning transaction: %s", err)
}
if err := db.Begin(); err == nil {
t.Fatalf("Error expected (transaction cannot be nested)")
}
if err := db.Commit(); err != nil {
t.Fatalf("Error while commiting transaction: %s", err)
}
}
func TestExists(t *testing.T) {
db := open(t)
defer db.Close()
......@@ -118,6 +132,7 @@ func TestInsert(t *testing.T) {
db := open(t)
defer db.Close()
createTable(db, t)
db.Begin()
for i := 0; i < 1000; i++ {
ierr := db.Exec("INSERT INTO test (float_num, int_num, a_string) VALUES (?, ?, ?)", float64(i)*float64(3.14), i, "hello")
if ierr != nil {
......@@ -128,6 +143,9 @@ func TestInsert(t *testing.T) {
t.Errorf("insert error: %d <> 1", c)
}
}
if err := db.Commit(); err != nil {
t.Fatalf("Error: %s", err)
}
lastId := db.LastInsertRowid()
if lastId != 1000 {
......@@ -180,6 +198,7 @@ func TestInsertWithStatement(t *testing.T) {
t.Errorf("bind parameter count error: %d <> 3", paramCount)
}
db.Begin()
for i := 0; i < 1000; i++ {
ierr := s.Exec(float64(i)*float64(3.14), i, "hello")
if ierr != nil {
......@@ -191,6 +210,9 @@ func TestInsertWithStatement(t *testing.T) {
}
}
s.Finalize()
if err := db.Commit(); err != nil {
t.Fatalf("Error: %s", err)
}
cs, _ := db.Prepare("SELECT COUNT(*) FROM test")
defer cs.Finalize()
......@@ -466,12 +488,14 @@ func BenchmarkScan(b *testing.B) {
defer db.Close()
db.Exec("DROP TABLE IF EXISTS test")
db.Exec("CREATE TABLE test (id INTEGER PRIMARY KEY AUTOINCREMENT, float_num REAL, int_num INTEGER, a_string TEXT)")
db.Begin()
s, _ := db.Prepare("INSERT INTO test (float_num, int_num, a_string) VALUES (?, ?, ?)")
for i := 0; i < 1000; i++ {
s.Exec(float64(i)*float64(3.14), i, "hello")
}
s.Finalize()
db.Commit()
b.StartTimer()
for i := 0; i < b.N; i++ {
......@@ -499,12 +523,14 @@ func BenchmarkNamedScan(b *testing.B) {
defer db.Close()
db.Exec("DROP TABLE IF EXISTS test")
db.Exec("CREATE TABLE test (id INTEGER PRIMARY KEY AUTOINCREMENT, float_num REAL, int_num INTEGER, a_string TEXT)")
db.Begin()
s, _ := db.Prepare("INSERT INTO test (float_num, int_num, a_string) VALUES (?, ?, ?)")
for i := 0; i < 1000; i++ {
s.Exec(float64(i)*float64(3.14), i, "hello")
}
s.Finalize()
db.Commit()
b.StartTimer()
for i := 0; i < b.N; i++ {
......@@ -536,7 +562,9 @@ func BenchmarkInsert(b *testing.B) {
" VALUES (?, ?, ?)")
defer s.Finalize()
db.Begin()
for i := 0; i < b.N; i++ {
s.Exec(float64(i)*float64(3.14), i, "hello")
}
db.Commit()
}
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