-
Notifications
You must be signed in to change notification settings - Fork 1
/
crossdb.go
125 lines (105 loc) · 3.53 KB
/
crossdb.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
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
package crossdb
// #cgo CFLAGS: -I../src
// #cgo LDFLAGS: -L. -lcrossdb
// #include <crossdb.h>
// #include <stdlib.h>
import "C"
import (
"errors"
"fmt"
"unsafe"
)
type Conn struct {
conn *C.xdb_conn_t
}
type Result struct {
res *C.xdb_res_t
}
// Open opens a new CrossDB connection
func Open(dbPath string) (*Conn, error) {
cPath := C.CString(dbPath)
defer C.free(unsafe.Pointer(cPath))
conn := C.xdb_open(cPath)
if conn == nil {
return nil, errors.New("failed to open database")
}
return &Conn{conn: conn}, nil
}
// Close closes the CrossDB connection
func (c *Conn) Close() {
C.xdb_close(c.conn)
}
// Exec executes an SQL statement
func (c *Conn) Exec(sql string) (*Result, error) {
cSQL := C.CString(sql)
defer C.free(unsafe.Pointer(cSQL))
res := C.xdb_exec(c.conn, cSQL)
if res == nil {
return nil, errors.New("failed to execute SQL")
}
if res.errcode != 0 {
errMsg := C.GoString(C.xdb_errmsg(res))
defer C.xdb_free_result(res)
return nil, fmt.Errorf("SQL error %d: %s", res.errcode, errMsg)
}
return &Result{res: res}, nil
}
// FetchRow fetches a row from the result set
func (r *Result) FetchRow() []interface{} {
row := C.xdb_fetch_row(r.res)
if row == nil {
return nil
}
colCount := int(r.res.col_count)
result := make([]interface{}, colCount)
for i := 0; i < colCount; i++ {
col := C.xdb_column_meta(C.uint64_t(r.res.col_meta), C.uint16_t(i))
switch col.col_type {
case C.XDB_TYPE_INT:
result[i] = int(C.xdb_column_int(C.uint64_t(r.res.col_meta), row, C.uint16_t(i)))
case C.XDB_TYPE_BIGINT:
result[i] = int64(C.xdb_column_int64(C.uint64_t(r.res.col_meta), row, C.uint16_t(i)))
case C.XDB_TYPE_FLOAT:
result[i] = float32(C.xdb_column_float(C.uint64_t(r.res.col_meta), row, C.uint16_t(i)))
case C.XDB_TYPE_DOUBLE:
result[i] = float64(C.xdb_column_double(C.uint64_t(r.res.col_meta), row, C.uint16_t(i)))
case C.XDB_TYPE_CHAR:
result[i] = C.GoString(C.xdb_column_str(C.uint64_t(r.res.col_meta), row, C.uint16_t(i)))
default:
result[i] = nil
}
}
return result
}
// FreeResult frees the result set
func (r *Result) FreeResult() {
C.xdb_free_result(r.res)
}
// Begin starts a new transaction
func (c *Conn) Begin() error {
ret := C.xdb_begin(c.conn)
if ret != 0 {
return errors.New("failed to begin transaction")
}
return nil
}
// Commit commits the current transaction
func (c *Conn) Commit() error {
ret := C.xdb_commit(c.conn)
if ret != 0 {
return errors.New("failed to commit transaction")
}
return nil
}
// Rollback rolls back the current transaction
func (c *Conn) Rollback() error {
ret := C.xdb_rollback(c.conn)
if ret != 0 {
return errors.New("failed to rollback transaction")
}
return nil
}
// Version returns the CrossDB version
func Version() string {
return C.GoString(C.xdb_version())
}