-
Notifications
You must be signed in to change notification settings - Fork 3
/
connection.go
114 lines (103 loc) · 3.5 KB
/
connection.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
package sqlite3_js //nolint:golint
import (
"context"
"database/sql/driver"
"fmt"
"strings"
"sync"
"syscall/js"
)
// SqliteJsConn implements driver.Conn.
type SqliteJsConn struct {
JsDb js.Value // sql.js SQL.Database : https://sql-js.github.io/sql.js/documentation/class/Database.html
mu *sync.Mutex
}
// Prepare creates a prepared statement for later queries or executions. Multiple
// queries or executions may be run concurrently from the returned statement. The
// caller must call the statement's Close method when the statement is no longer
// needed.
func (conn *SqliteJsConn) Prepare(query string) (stmt driver.Stmt, err error) {
defer protect("Prepare", func(e error) { err = e })
return &SqliteJsStmt{
c: conn,
js: conn.JsDb.Call("prepare", query),
}, nil
}
// Close returns the connection to the connection pool. All operations after a
// Close will return with ErrConnDone. Close is safe to call concurrently with
// other operations and will block until all other operations finish. It may be
// useful to first cancel any used context and then call close directly after.
func (conn SqliteJsConn) Close() error {
// TODO
return nil
}
func (conn *SqliteJsConn) Exec(query string, args []driver.Value) (result driver.Result, err error) {
defer protect("Exec", func(e error) { err = e })
query = strings.TrimRight(query, ";")
if strings.Contains(query, ";") {
if len(args) != 0 {
return nil, fmt.Errorf("cannot exec multiple statements with placeholders, query: %s nargs=%d", query, len(args))
}
jsVal, err := jsTryCatch(func() js.Value {
return conn.JsDb.Call("exec", query)
})
if err != nil {
return nil, err
}
return &SqliteJsResult{
js: jsVal,
changes: 0,
id: 0,
}, nil
}
list := make([]namedValue, len(args))
for i, v := range args {
list[i] = namedValue{
Ordinal: i + 1,
Value: v,
}
}
return conn.exec(context.Background(), query, list)
}
func (conn *SqliteJsConn) exec(ctx context.Context, query string, args []namedValue) (driver.Result, error) {
// FIXME: we removed tbe ability to handle 'tails' - is this a problem?
s, err := conn.Prepare(query)
if err != nil {
return nil, err
}
var res driver.Result
res, err = s.(*SqliteJsStmt).exec(ctx, args)
s.Close()
return res, err
}
// Transactions
// Begin starts a transaction. The default isolation level is dependent on the driver.
func (conn *SqliteJsConn) Begin() (driver.Tx, error) {
return conn.begin(context.Background())
}
// BeginTx starts and returns a new transaction.
// If the context is canceled by the user the sql package will
// call Tx.Rollback before discarding and closing the connection.
//
// This must check opts.Isolation to determine if there is a set
// isolation level. If the driver does not support a non-default
// level and one is set or if there is a non-default isolation level
// that is not supported, an error must be returned.
//
// This must also check opts.ReadOnly to determine if the read-only
// value is true to either set the read-only transaction property if supported
// or return an error if it is not supported.
func (conn *SqliteJsConn) BeginTx(ctx context.Context, opts driver.TxOptions) (driver.Tx, error) {
return conn.begin(ctx)
}
func (conn *SqliteJsConn) begin(ctx context.Context) (driver.Tx, error) { //nolint:unparam
/*
if conn.disableTxns {
fmt.Println("Ignoring BEGIN, txns disabled")
return &SqliteJsTx{c: conn}, nil
}
if _, err := conn.exec(ctx, "BEGIN", nil); err != nil {
return nil, err
} */
return &SqliteJsTx{c: conn}, nil
}