Skip to content

Commit 3e97a4c

Browse files
committed
Merge pull request #1 from mattn/master
Bring master up-to-date
2 parents 1704ea5 + c5aee96 commit 3e97a4c

29 files changed

+84344
-42940
lines changed

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
*.db
2+
*.exe
3+
*.dll

.travis.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,6 @@ go:
44
before_install:
55
- go get github.com/axw/gocov/gocov
66
- go get github.com/mattn/goveralls
7-
- go get code.google.com/p/go.tools/cmd/cover
7+
- go get golang.org/x/tools/cmd/cover
88
script:
99
- $HOME/gopath/bin/goveralls -repotoken 3qJVUE0iQwqnCbmNcDsjYu1nh4J4KIFXx

LICENSE

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
The MIT License (MIT)
2+
3+
Copyright (c) 2014 Yasuhiro Matsumoto
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

README.md

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
go-sqlite3
22
==========
33

4-
[![Build Status](https://travis-ci.org/mattn/go-sqlite3.png?branch=master)](https://travis-ci.org/mattn/go-sqlite3)
5-
[![Coverage Status](https://coveralls.io/repos/mattn/go-sqlite3/badge.png?branch=master)](https://coveralls.io/r/mattn/go-sqlite3?branch=master)
4+
[![Build Status](https://travis-ci.org/mattn/go-sqlite3.svg?branch=master)](https://travis-ci.org/mattn/go-sqlite3)
5+
[![Coverage Status](https://coveralls.io/repos/mattn/go-sqlite3/badge.svg?branch=master)](https://coveralls.io/r/mattn/go-sqlite3?branch=master)
6+
[![GoDoc](https://godoc.org/github.com/mattn/go-sqlite3?status.svg)](http://godoc.org/github.com/mattn/go-sqlite3)
67

78
Description
89
-----------
@@ -16,6 +17,10 @@ This package can be installed with the go get command:
1617

1718
go get github.com/mattn/go-sqlite3
1819

20+
_go-sqlite3_ is *cgo* package.
21+
If you want to build your app using go-sqlite3, you need gcc.
22+
However, if you install _go-sqlite3_ with `go install github.com/mattn/go-sqlite3`, you don't need gcc to build your app anymore.
23+
1924
Documentation
2025
-------------
2126

@@ -26,6 +31,14 @@ Examples can be found under the `./_example` directory
2631
FAQ
2732
---
2833

34+
* Want to build go-sqlite3 with libsqlite3 on my linux.
35+
36+
Use `go build --tags "libsqlite3 linux"`
37+
38+
* Want to build go-sqlite3 with icu extension.
39+
40+
Use `go build --tags "icu"`
41+
2942
* Can't build go-sqlite3 on windows 64bit.
3043

3144
> Probably, you are using go 1.0, go1.0 has a problem when it comes to compiling/linking on windows 64bit.
@@ -36,7 +49,27 @@ FAQ
3649
> You can pass some arguments into the connection string, for example, a URI.
3750
> See: https://github.com/mattn/go-sqlite3/issues/39
3851
52+
* Do you want cross compiling? mingw on Linux or Mac?
53+
54+
> See: https://github.com/mattn/go-sqlite3/issues/106
55+
> See also: http://www.limitlessfx.com/cross-compile-golang-app-for-windows-from-linux.html
56+
57+
* Want to get time.Time with current locale
58+
59+
Use `loc=auto` in SQLite3 filename schema like `file:foo.db?loc=auto`.
60+
3961
License
4062
-------
4163

4264
MIT: http://mattn.mit-license.org/2012
65+
66+
sqlite3-binding.c, sqlite3-binding.h, sqlite3ext.h
67+
68+
The -binding suffix was added to avoid build failures under gccgo.
69+
70+
In this repository, those files are amalgamation code that copied from SQLite3. The license of those codes are depend on the license of SQLite3.
71+
72+
Author
73+
------
74+
75+
Yasuhiro Matsumoto (a.k.a mattn)

_example/custom_func/main.go

Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
package main
2+
3+
import (
4+
"database/sql"
5+
"fmt"
6+
"log"
7+
"math"
8+
"math/rand"
9+
10+
sqlite "github.com/mattn/go-sqlite3"
11+
)
12+
13+
// Computes x^y
14+
func pow(x, y int64) int64 {
15+
return int64(math.Pow(float64(x), float64(y)))
16+
}
17+
18+
// Computes the bitwise exclusive-or of all its arguments
19+
func xor(xs ...int64) int64 {
20+
var ret int64
21+
for _, x := range xs {
22+
ret ^= x
23+
}
24+
return ret
25+
}
26+
27+
// Returns a random number. It's actually deterministic here because
28+
// we don't seed the RNG, but it's an example of a non-pure function
29+
// from SQLite's POV.
30+
func getrand() int64 {
31+
return rand.Int63()
32+
}
33+
34+
// Computes the standard deviation of a GROUPed BY set of values
35+
type stddev struct {
36+
xs []int64
37+
// Running average calculation
38+
sum int64
39+
n int64
40+
}
41+
42+
func newStddev() *stddev { return &stddev{} }
43+
44+
func (s *stddev) Step(x int64) {
45+
s.xs = append(s.xs, x)
46+
s.sum += x
47+
s.n++
48+
}
49+
50+
func (s *stddev) Done() float64 {
51+
mean := float64(s.sum) / float64(s.n)
52+
var sqDiff []float64
53+
for _, x := range s.xs {
54+
sqDiff = append(sqDiff, math.Pow(float64(x)-mean, 2))
55+
}
56+
var dev float64
57+
for _, x := range sqDiff {
58+
dev += x
59+
}
60+
dev /= float64(len(sqDiff))
61+
return math.Sqrt(dev)
62+
}
63+
64+
func main() {
65+
sql.Register("sqlite3_custom", &sqlite.SQLiteDriver{
66+
ConnectHook: func(conn *sqlite.SQLiteConn) error {
67+
if err := conn.RegisterFunc("pow", pow, true); err != nil {
68+
return err
69+
}
70+
if err := conn.RegisterFunc("xor", xor, true); err != nil {
71+
return err
72+
}
73+
if err := conn.RegisterFunc("rand", getrand, false); err != nil {
74+
return err
75+
}
76+
if err := conn.RegisterAggregator("stddev", newStddev, true); err != nil {
77+
return err
78+
}
79+
return nil
80+
},
81+
})
82+
83+
db, err := sql.Open("sqlite3_custom", ":memory:")
84+
if err != nil {
85+
log.Fatal("Failed to open database:", err)
86+
}
87+
defer db.Close()
88+
89+
var i int64
90+
err = db.QueryRow("SELECT pow(2,3)").Scan(&i)
91+
if err != nil {
92+
log.Fatal("POW query error:", err)
93+
}
94+
fmt.Println("pow(2,3) =", i) // 8
95+
96+
err = db.QueryRow("SELECT xor(1,2,3,4,5,6)").Scan(&i)
97+
if err != nil {
98+
log.Fatal("XOR query error:", err)
99+
}
100+
fmt.Println("xor(1,2,3,4,5) =", i) // 7
101+
102+
err = db.QueryRow("SELECT rand()").Scan(&i)
103+
if err != nil {
104+
log.Fatal("RAND query error:", err)
105+
}
106+
fmt.Println("rand() =", i) // pseudorandom
107+
108+
_, err = db.Exec("create table foo (department integer, profits integer)")
109+
if err != nil {
110+
log.Fatal("Failed to create table:", err)
111+
}
112+
_, err = db.Exec("insert into foo values (1, 10), (1, 20), (1, 45), (2, 42), (2, 115)")
113+
if err != nil {
114+
log.Fatal("Failed to insert records:", err)
115+
}
116+
117+
rows, err := db.Query("select department, stddev(profits) from foo group by department")
118+
if err != nil {
119+
log.Fatal("STDDEV query error:", err)
120+
}
121+
defer rows.Close()
122+
for rows.Next() {
123+
var dept int64
124+
var dev float64
125+
if err := rows.Scan(&dept, &dev); err != nil {
126+
log.Fatal(err)
127+
}
128+
fmt.Printf("dept=%d stddev=%f\n", dept, dev)
129+
}
130+
if err := rows.Err(); err != nil {
131+
log.Fatal(err)
132+
}
133+
}

_example/hook/hook.go

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,12 @@ import (
1010
func main() {
1111
sqlite3conn := []*sqlite3.SQLiteConn{}
1212
sql.Register("sqlite3_with_hook_example",
13-
&sqlite3.SQLiteDriver{
14-
ConnectHook: func(conn *sqlite3.SQLiteConn) error {
15-
sqlite3conn = append(sqlite3conn, conn)
16-
return nil
17-
},
18-
})
13+
&sqlite3.SQLiteDriver{
14+
ConnectHook: func(conn *sqlite3.SQLiteConn) error {
15+
sqlite3conn = append(sqlite3conn, conn)
16+
return nil
17+
},
18+
})
1919
os.Remove("./foo.db")
2020
os.Remove("./bar.db")
2121

@@ -54,7 +54,7 @@ func main() {
5454
log.Fatal(err)
5555
}
5656

57-
bk.Step(-1)
57+
_, err = bk.Step(-1)
5858
if err != nil {
5959
log.Fatal(err)
6060
}

_example/mod_vtable/sqlite3_mod_vtable.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
#include <string>
22
#include <sstream>
3-
#include <sqlite3.h>
3+
#include <sqlite3-binding.h>
44
#include <sqlite3ext.h>
55
#include <curl/curl.h>
66
#include "picojson.h"

_example/simple/simple.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,6 @@ func main() {
5555
rows.Scan(&id, &name)
5656
fmt.Println(id, name)
5757
}
58-
rows.Close()
5958

6059
stmt, err = db.Prepare("select name from foo where id = ?")
6160
if err != nil {

backup.go

Lines changed: 24 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,34 @@
1+
// Copyright (C) 2014 Yasuhiro Matsumoto <[email protected]>.
2+
//
3+
// Use of this source code is governed by an MIT-style
4+
// license that can be found in the LICENSE file.
5+
16
package sqlite3
27

38
/*
4-
#include <sqlite3.h>
9+
#include <sqlite3-binding.h>
510
#include <stdlib.h>
611
*/
712
import "C"
813
import (
14+
"runtime"
915
"unsafe"
1016
)
1117

12-
type Backup struct {
18+
type SQLiteBackup struct {
1319
b *C.sqlite3_backup
1420
}
1521

16-
func (c *SQLiteConn) Backup(dest string, conn *SQLiteConn, src string) (*Backup, error) {
22+
func (c *SQLiteConn) Backup(dest string, conn *SQLiteConn, src string) (*SQLiteBackup, error) {
1723
destptr := C.CString(dest)
1824
defer C.free(unsafe.Pointer(destptr))
1925
srcptr := C.CString(src)
2026
defer C.free(unsafe.Pointer(srcptr))
2127

2228
if b := C.sqlite3_backup_init(c.db, destptr, conn.db, srcptr); b != nil {
23-
return &Backup{b: b}, nil
29+
bb := &SQLiteBackup{b: b}
30+
runtime.SetFinalizer(bb, (*SQLiteBackup).Finish)
31+
return bb, nil
2432
}
2533
return nil, c.lastError()
2634
}
@@ -29,28 +37,34 @@ func (c *SQLiteConn) Backup(dest string, conn *SQLiteConn, src string) (*Backup,
2937
// This function returns a boolean indicating if the backup is done and
3038
// an error signalling any other error. Done is returned if the underlying C
3139
// function returns SQLITE_DONE (Code 101)
32-
func (b *Backup) Step(p int) (bool, error) {
40+
func (b *SQLiteBackup) Step(p int) (bool, error) {
3341
ret := C.sqlite3_backup_step(b.b, C.int(p))
34-
if ret == 101 {
42+
if ret == C.SQLITE_DONE {
3543
return true, nil
36-
} else if ret != 0 {
44+
} else if ret != 0 && ret != C.SQLITE_LOCKED && ret != C.SQLITE_BUSY {
3745
return false, Error{Code: ErrNo(ret)}
3846
}
3947
return false, nil
4048
}
4149

42-
func (b *Backup) Remaining() int {
50+
func (b *SQLiteBackup) Remaining() int {
4351
return int(C.sqlite3_backup_remaining(b.b))
4452
}
4553

46-
func (b *Backup) PageCount() int {
54+
func (b *SQLiteBackup) PageCount() int {
4755
return int(C.sqlite3_backup_pagecount(b.b))
4856
}
4957

50-
func (b *Backup) Finish() error {
58+
func (b *SQLiteBackup) Finish() error {
59+
return b.Close()
60+
}
61+
62+
func (b *SQLiteBackup) Close() error {
5163
ret := C.sqlite3_backup_finish(b.b)
5264
if ret != 0 {
5365
return Error{Code: ErrNo(ret)}
5466
}
67+
b.b = nil
68+
runtime.SetFinalizer(b, nil)
5569
return nil
5670
}

0 commit comments

Comments
 (0)