forked from iamacarpet/go-sqlite3-win64
-
Notifications
You must be signed in to change notification settings - Fork 1
/
sqlite3.go
executable file
·128 lines (110 loc) · 2.89 KB
/
sqlite3.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
126
127
128
// +build windows
// Copyright (C) 2016 Samuel Melrose <[email protected]>.
//
// Based on work by Yasuhiro Matsumoto <[email protected]>
// https://github.com/mattn/go-sqlite3
//
// Use of this source code is governed by an MIT-style
// license that can be found in the LICENSE file.
package sqlite3
import (
"database/sql"
"database/sql/driver"
"fmt"
"net/url"
"runtime"
"strconv"
"strings"
"time"
)
var SQLiteWin64 = true
func init() {
if runtime.GOARCH == "386" {
SQLiteWin64 = false
}
registerDLLFunctions()
sql.Register("sqlite3", &SQLiteDriver{})
}
func Version() (libVersion string, libVersionNumber int, sourceID string) {
return sqlite3_libversion(), sqlite3_libversion_number(), sqlite3_sourceid()
}
func errorString(err Error) string {
return sqlite3_errstr(int(err.Code))
}
func (d *SQLiteDriver) Open(dsn string) (driver.Conn, error) {
if !dllRegistered {
registerDLLFunctions()
if !dllRegistered {
return nil, fmt.Errorf("sqlite library not found")
}
}
if sqlite3_threadsafe() == 0 {
return nil, fmt.Errorf("sqlite library was not compiled for thread-safe operation")
}
var loc *time.Location
txlock := "BEGIN"
busyTimeout := 5000
dsn = strings.TrimPrefix(dsn, `file:///`)
pos := strings.IndexRune(dsn, '?')
if pos >= 1 {
params, err := url.ParseQuery(dsn[pos+1:])
if err != nil {
return nil, err
}
// _loc
if val := params.Get("_loc"); val != "" {
if val == "auto" {
loc = time.Local
} else {
loc, err = time.LoadLocation(val)
if err != nil {
return nil, fmt.Errorf("Invalid _loc: %v: %v", val, err)
}
}
}
// _busy_timeout
if val := params.Get("_busy_timeout"); val != "" {
iv, err := strconv.ParseInt(val, 10, 64)
if err != nil {
return nil, fmt.Errorf("Invalid _busy_timeout: %v: %v", val, err)
}
busyTimeout = int(iv)
}
// _txlock
if val := params.Get("_txlock"); val != "" {
switch val {
case "immediate":
txlock = "BEGIN IMMEDIATE"
case "exclusive":
txlock = "BEGIN EXCLUSIVE"
case "deferred":
txlock = "BEGIN"
default:
return nil, fmt.Errorf("Invalid _txlock: %v", val)
}
}
if !strings.HasPrefix(dsn, "file:") {
dsn = dsn[:pos]
}
}
var db sqlite3
rv := sqlite3_open_v2(dsn, &db, SQLITE_OPEN_FULLMUTEX|SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE, "")
if rv != 0 {
return nil, Error{Code: ErrNo(rv)}
}
if db == sqlite3(uintptr(0)) {
return nil, fmt.Errorf("sqlite succeeded without returning a database")
}
rv = sqlite3_busy_timeout(db, busyTimeout)
if rv != SQLITE_OK {
return nil, Error{Code: ErrNo(rv)}
}
conn := &SQLiteConn{db: db, loc: loc, txlock: txlock}
if d.ConnectHook != nil {
if err := d.ConnectHook(conn); err != nil {
return nil, err
}
}
runtime.SetFinalizer(conn, (*SQLiteConn).Close)
return conn, nil
}