forked from mdcnz/sqlanywhere
/
txn.go
82 lines (68 loc) · 2.03 KB
/
txn.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
package sqlanywhere
//#include <driver.c>
import "C"
import (
"database/sql"
"database/sql/driver"
"fmt"
"log"
)
type tx struct {
con *connection
opts driver.TxOptions
lastIsolation driverIsolationLevel
}
type driverIsolationLevel string
const (
levelReadUncommitted driverIsolationLevel = "0"
levelReadCommitted = "1"
levelRepeatableRead = "2"
levelSerializable = "3"
levelSnapshot = "snapshot"
levelStatementSnapshot = "statement-snapshot"
levelReadOnlyStatementSnapshot = "readonly-statement-snapshot"
)
//TODO set snapshot isolation level, see: http://dcx.sap.com/1200/en/dbusage/transact-s-3847634.html
var isolationLevels = map[sql.IsolationLevel]driverIsolationLevel{
sql.LevelDefault: levelReadUncommitted,
sql.LevelReadUncommitted: levelReadUncommitted,
sql.LevelReadCommitted: levelReadCommitted,
// sql.LevelWriteCommitted
sql.LevelRepeatableRead: levelRepeatableRead,
sql.LevelSnapshot: levelSnapshot,
sql.LevelSerializable: levelSerializable,
// sql.LevelLinearizable
}
func (t *tx) Commit() error {
defer t.restoreIsolationLevel()
if C.sqlany_commit(t.con.ptr) == 0 {
return t.con.lasterr("did not commit")
}
return nil
}
func (t *tx) Rollback() error {
defer func() {
if err := t.restoreIsolationLevel(); err != nil {
log.Println("error during restore in rollback", err)
}
}()
var err error
if err := t.con.lasterr("last err"); err != nil {
panic(err)
}
if C.sqlany_rollback(t.con.ptr) == 0 {
err = t.con.lasterr("did not rollback")
if err != nil {
log.Println("error during rollback", err)
}
return err
}
return err
}
func (t *tx) restoreIsolationLevel() error {
err := t.con.execImmediate("SET TEMPORARY OPTION isolation_level = " + string(t.lastIsolation))
if err != nil {
return fmt.Errorf("did not set isolation level: %v", err)
}
return nil
}