Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
G
gosqlite
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
gosqlite
Commits
67fc1ed7
Commit
67fc1ed7
authored
Jul 17, 2011
by
gwenn
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Customize to my needs.
parent
8e81aa1b
Changes
5
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
423 additions
and
365 deletions
+423
-365
.gitignore
.gitignore
+4
-12
Makefile
Makefile
+2
-8
README
README
+9
-7
sqlite.go
sqlite.go
+289
-214
sqlite_test.go
sqlite_test.go
+119
-124
No files found.
.gitignore
View file @
67fc1ed7
*.6
*.[568ao]
*.8
[568a].out
*.swp
_testmain.go
*~
_obj
_obj
*.o
*.out
*.cgo*
_test
_test
cgo_*
*.swp
_cgo_*
_testmain.go
Makefile
View file @
67fc1ed7
...
@@ -4,15 +4,9 @@
...
@@ -4,15 +4,9 @@
include
$(GOROOT)/src/Make.inc
include
$(GOROOT)/src/Make.inc
TARG
=
f
sqlite
TARG
=
github.com/gwenn/
sqlite
CGOFILES
=
\
CGOFILES
=
\
fsqlite.go
sqlite.go
ifeq
($(GOOS),darwin)
CGO_LDFLAGS
=
/usr/lib/libsqlite3.0.dylib
else
CGO_LDFLAGS
=
-lsqlite3
endif
include
$(GOROOT)/src/Make.pkg
include
$(GOROOT)/src/Make.pkg
README
View file @
67fc1ed7
This is based on Russ Cox's original gosqlite package:
Yet another SQLite binding based on:
- original [Russ Cox's][http://code.google.com/p/gosqlite/] implementation,
- the [Patrick Crosby's][https://github.com/patrickxb/fgosqlite/] fork.
http://code.google.com/p/gosqlite/
Conn#Exec handles multiple statements (separated by semicolons) properly.
Stmt#Exec is renamed in Stmt#Bind and a new Stmt#Exec method is introduced to #Bind and #Step.
I added Scan2 and Exec2 which use sqlite api calls to get/bind values instead of the
Stmt#Bind uses native sqlite3_bind_x methods and failed if unsupported type.
original which basically converted everything to strings
.
Stmt#Next returns a (bool, os.Error) couple like Reader#Read. But its use in for loop becomes inelegant..
.
Stmt#Scan uses native sqlite3_column_x methods.
S
can2 and Exec2 are significantly faster. See the benchmarks in fgosqlite_test.go
.
S
tmt#NamedScan is added. It's compliant with [go-dbi][https://github.com/thomaslee/go-dbi/] API but I think its signature should be improved/modified
.
sqlite.go
View file @
67fc1ed7
This diff is collapsed.
Click to expand it.
sqlite_test.go
View file @
67fc1ed7
package
f
sqlite
package
sqlite
import
(
import
(
"testing"
"testing"
"fmt
"
"os
"
)
)
func
TestOpen
(
t
*
testing
.
T
)
{
func
open
(
t
*
testing
.
T
)
*
Conn
{
db
,
err
:=
Open
(
"
/tmp/test.db
"
)
db
,
err
:=
Open
(
""
)
if
err
!=
nil
{
if
err
!=
nil
{
t
.
Error
f
(
"couldn't open database file: %s"
,
err
)
t
.
Fatal
f
(
"couldn't open database file: %s"
,
err
)
}
}
if
db
==
nil
{
if
db
==
nil
{
t
.
Error
(
"opened database is nil"
)
t
.
Fatal
(
"opened database is nil"
)
}
}
db
.
Close
()
return
db
}
}
func
TestCreateTable
(
t
*
testing
.
T
)
{
func
createTable
(
db
*
Conn
,
t
*
testing
.
T
)
{
db
,
err
:=
Open
(
"/tmp/test.db"
)
err
:=
db
.
Exec
(
"DROP TABLE IF EXISTS test;"
+
db
.
Exec
(
"DROP TABLE test"
)
"CREATE TABLE test (id INTEGER PRIMARY KEY AUTOINCREMENT,"
+
err
=
db
.
Exec
(
"CREATE TABLE test (id INTEGER PRIMARY KEY AUTOINCREMENT, float_num REAL, int_num INTEGER, a_string TEXT)
"
)
" float_num REAL, int_num INTEGER, a_string TEXT); -- bim
"
)
if
err
!=
nil
{
if
err
!=
nil
{
t
.
Error
f
(
"error creating table: %s"
,
err
)
t
.
Fatal
f
(
"error creating table: %s"
,
err
)
}
}
}
}
type
OutRow
struct
{
func
TestOpen
(
t
*
testing
.
T
)
{
Key
int64
db
:=
open
(
t
)
FloatNum
float64
db
.
Close
()
IntNum
int64
}
AString
string
func
TestCreateTable
(
t
*
testing
.
T
)
{
db
:=
open
(
t
)
defer
db
.
Close
()
createTable
(
db
,
t
)
}
}
func
TestInsert
(
t
*
testing
.
T
)
{
func
TestInsert
(
t
*
testing
.
T
)
{
db
,
_
:=
Open
(
"/tmp/test.db"
)
db
:=
open
(
t
)
d
b
.
Exec
(
"DROP TABLE test"
)
d
efer
db
.
Close
(
)
db
.
Exec
(
"CREATE TABLE test (id INTEGER PRIMARY KEY AUTOINCREMENT, float_num REAL, int_num INTEGER, a_string TEXT)"
)
createTable
(
db
,
t
)
for
i
:=
0
;
i
<
1000
;
i
++
{
for
i
:=
0
;
i
<
1000
;
i
++
{
ierr
:=
db
.
Exec
(
"INSERT INTO test (float_num, int_num, a_string) VALUES (?, ?, ?)"
,
float64
(
i
)
*
float64
(
3.14
),
i
,
"hello"
)
ierr
:=
db
.
Exec
(
"INSERT INTO test (float_num, int_num, a_string) VALUES (?, ?, ?)"
,
float64
(
i
)
*
float64
(
3.14
),
i
,
"hello"
)
if
ierr
!=
nil
{
if
ierr
!=
nil
{
t
.
Errorf
(
"insert error: %s"
,
ierr
)
t
.
Fatalf
(
"insert error: %s"
,
ierr
)
}
c
:=
db
.
Changes
()
if
c
!=
1
{
t
.
Errorf
(
"insert error: %d <> 1"
,
c
)
}
}
}
}
cs
,
_
:=
db
.
Prepare
(
"SELECT COUNT(*) FROM test"
)
cs
,
_
:=
db
.
Prepare
(
"SELECT COUNT(*) FROM test"
)
cs
.
Exec
()
defer
cs
.
Finalize
()
if
!
cs
.
Next
()
{
if
ok
,
err
:=
cs
.
Next
();
!
ok
{
t
.
Error
(
"no result for count"
)
if
err
!=
nil
{
t
.
Fatalf
(
"error preparing count: %s"
,
err
)
}
t
.
Fatal
(
"no result for count"
)
}
}
var
i
int
var
i
int
err
:=
cs
.
Scan
(
&
i
)
err
:=
cs
.
Scan
(
&
i
)
if
err
!=
nil
{
if
err
!=
nil
{
t
.
Error
f
(
"error scanning count: %s"
,
err
)
t
.
Fatal
f
(
"error scanning count: %s"
,
err
)
}
}
if
i
!=
1000
{
if
i
!=
1000
{
t
.
Errorf
(
"count should be 1000, but it is %d"
,
i
)
t
.
Errorf
(
"count should be 1000, but it is %d"
,
i
)
...
@@ -59,169 +70,153 @@ func TestInsert(t *testing.T) {
...
@@ -59,169 +70,153 @@ func TestInsert(t *testing.T) {
}
}
func
TestInsertWithStatement
(
t
*
testing
.
T
)
{
func
TestInsertWithStatement
(
t
*
testing
.
T
)
{
db
,
_
:=
Open
(
"/tmp/test_is.db"
)
db
:=
open
(
t
)
d
b
.
Exec
(
"DROP TABLE test"
)
d
efer
db
.
Close
(
)
db
.
Exec
(
"CREATE TABLE test (id INTEGER PRIMARY KEY AUTOINCREMENT, float_num REAL, int_num INTEGER, a_string TEXT)"
)
createTable
(
db
,
t
)
s
,
serr
:=
db
.
Prepare
(
"INSERT INTO test (float_num, int_num, a_string) VALUES (?, ?, ?)"
)
s
,
serr
:=
db
.
Prepare
(
"INSERT INTO test (float_num, int_num, a_string) VALUES (?, ?, ?)"
)
if
serr
!=
nil
{
if
serr
!=
nil
{
t
.
Error
f
(
"prepare error: %s"
,
serr
)
t
.
Fatal
f
(
"prepare error: %s"
,
serr
)
}
}
if
s
==
nil
{
if
s
==
nil
{
t
.
Error
(
"statement is nil"
)
t
.
Fatal
(
"statement is nil"
)
}
}
defer
s
.
Finalize
()
for
i
:=
0
;
i
<
1000
;
i
++
{
for
i
:=
0
;
i
<
1000
;
i
++
{
ierr
:=
s
.
Exec
(
float64
(
i
)
*
float64
(
3.14
),
i
,
"hello"
)
ierr
:=
s
.
Exec
(
float64
(
i
)
*
float64
(
3.14
),
i
,
"hello"
)
if
ierr
!=
nil
{
if
ierr
!=
nil
{
t
.
Error
f
(
"insert error: %s"
,
ierr
)
t
.
Fatal
f
(
"insert error: %s"
,
ierr
)
}
}
s
.
Next
()
c
:=
db
.
Changes
()
}
if
c
!=
1
{
s
.
Finalize
()
t
.
Errorf
(
"insert error: %d <> 1"
,
c
)
cs
,
_
:=
db
.
Prepare
(
"SELECT COUNT(*) FROM test"
)
cs
.
Exec
()
if
!
cs
.
Next
()
{
t
.
Error
(
"no result for count"
)
}
var
i
int
err
:=
cs
.
Scan
(
&
i
)
if
err
!=
nil
{
t
.
Errorf
(
"error scanning count: %s"
,
err
)
}
if
i
!=
1000
{
t
.
Errorf
(
"count should be 1000, but it is %d"
,
i
)
}
}
func
TestInsertWithStatement2
(
t
*
testing
.
T
)
{
db
,
_
:=
Open
(
"/tmp/test_is2.db"
)
db
.
Exec
(
"DROP TABLE test"
)
db
.
Exec
(
"CREATE TABLE test (id INTEGER PRIMARY KEY AUTOINCREMENT, float_num REAL, int_num INTEGER, a_string TEXT)"
)
s
,
serr
:=
db
.
Prepare
(
"INSERT INTO test (float_num, int_num, a_string) VALUES (?, ?, ?)"
)
if
serr
!=
nil
{
t
.
Errorf
(
"prepare error: %s"
,
serr
)
}
if
s
==
nil
{
t
.
Error
(
"statement is nil"
)
}
for
i
:=
0
;
i
<
1000
;
i
++
{
ierr
:=
s
.
Exec2
(
float64
(
i
)
*
float64
(
3.14
),
i
,
"hello"
)
if
ierr
!=
nil
{
t
.
Errorf
(
"insert error: %s"
,
ierr
)
}
}
s
.
Next
()
}
}
s
.
Finalize
()
cs
,
_
:=
db
.
Prepare
(
"SELECT COUNT(*) FROM test"
)
cs
,
_
:=
db
.
Prepare
(
"SELECT COUNT(*) FROM test"
)
cs
.
Exec
()
defer
cs
.
Finalize
()
if
!
cs
.
Next
()
{
if
ok
,
_
:=
cs
.
Next
();
!
ok
{
t
.
Error
(
"no result for count"
)
t
.
Fatal
(
"no result for count"
)
}
}
var
i
int
var
i
int
err
:=
cs
.
Scan
(
&
i
)
err
:=
cs
.
Scan
(
&
i
)
if
err
!=
nil
{
if
err
!=
nil
{
t
.
Error
f
(
"error scanning count: %s"
,
err
)
t
.
Fatal
f
(
"error scanning count: %s"
,
err
)
}
}
if
i
!=
1000
{
if
i
!=
1000
{
t
.
Errorf
(
"count should be 1000, but it is %d"
,
i
)
t
.
Errorf
(
"count should be 1000, but it is %d"
,
i
)
}
}
rs
,
_
:=
db
.
Prepare
(
"SELECT float_num, int_num, a_string FROM test ORDER BY int_num LIMIT 10
"
)
rs
,
_
:=
db
.
Prepare
(
"SELECT float_num, int_num, a_string FROM test ORDER BY int_num LIMIT 2
"
)
var
fnum
float64
var
fnum
float64
var
inum
int64
var
inum
int64
var
sstr
string
var
sstr
string
for
rs
.
Next
()
{
if
ok
,
_
:=
rs
.
Next
();
ok
{
rs
.
Scan
(
&
fnum
,
&
inum
,
&
sstr
)
rs
.
Scan
(
&
fnum
,
&
inum
,
&
sstr
)
fmt
.
Printf
(
"fnum = %f, inum = %d, sstre = %s
\n
"
,
fnum
,
inum
,
sstr
)
if
fnum
!=
0
{
}
t
.
Errorf
(
"Expected 0 <> %f
\n
"
,
fnum
)
}
if
inum
!=
0
{
t
.
Errorf
(
"Expected 0 <> %d
\n
"
,
inum
)
}
if
sstr
!=
"hello"
{
t
.
Errorf
(
"Expected 'hello' <> %s
\n
"
,
sstr
)
}
}
if
ok
,
_
:=
rs
.
Next
();
ok
{
var
fnum
float64
var
inum
int64
var
sstr
string
rs
.
NamedScan
(
"a_string"
,
&
sstr
,
"float_num"
,
&
fnum
,
"int_num"
,
&
inum
)
if
fnum
!=
3.14
{
t
.
Errorf
(
"Expected 3.14 <> %f
\n
"
,
fnum
)
}
if
inum
!=
1
{
t
.
Errorf
(
"Expected 1 <> %d
\n
"
,
inum
)
}
if
sstr
!=
"hello"
{
t
.
Errorf
(
"Expected 'hello' <> %s
\n
"
,
sstr
)
}
}
}
}
func
BenchmarkScan
(
b
*
testing
.
B
)
{
func
BenchmarkScan
(
b
*
testing
.
B
)
{
b
.
StopTimer
()
b
.
StopTimer
()
db
,
_
:=
Open
(
"/tmp/test_bs.db"
)
db
,
_
:=
Open
(
""
)
db
.
Exec
(
"DROP TABLE test"
)
defer
db
.
Close
()
db
.
Exec
(
"DROP TABLE IF EXISTS test"
)
db
.
Exec
(
"CREATE TABLE test (id INTEGER PRIMARY KEY AUTOINCREMENT, float_num REAL, int_num INTEGER, a_string TEXT)"
)
db
.
Exec
(
"CREATE TABLE test (id INTEGER PRIMARY KEY AUTOINCREMENT, float_num REAL, int_num INTEGER, a_string TEXT)"
)
s
,
_
:=
db
.
Prepare
(
"INSERT INTO test (float_num, int_num, a_string) VALUES (?, ?, ?)"
)
s
,
_
:=
db
.
Prepare
(
"INSERT INTO test (float_num, int_num, a_string) VALUES (?, ?, ?)"
)
for
i
:=
0
;
i
<
1000
;
i
++
{
for
i
:=
0
;
i
<
1000
;
i
++
{
s
.
Exec
(
float64
(
i
)
*
float64
(
3.14
),
i
,
"hello"
)
s
.
Exec
(
float64
(
i
)
*
float64
(
3.14
),
i
,
"hello"
)
s
.
Next
()
}
}
s
.
Finalize
()
s
.
Finalize
()
b
.
StartTimer
()
b
.
StartTimer
()
for
i
:=
0
;
i
<
b
.
N
;
i
++
{
for
i
:=
0
;
i
<
b
.
N
;
i
++
{
cs
,
_
:=
db
.
Prepare
(
"SELECT float_num, int_num, a_string FROM test"
)
cs
,
_
:=
db
.
Prepare
(
"SELECT float_num, int_num, a_string FROM test"
)
var
fnum
float64
cs
.
Exec
()
var
inum
int64
var
sstr
string
var
fnum
float64
var
inum
int64
var
sstr
string
for
cs
.
Next
()
{
var
ok
bool
var
err
os
.
Error
for
ok
,
err
=
cs
.
Next
();
ok
;
ok
,
err
=
cs
.
Next
()
{
cs
.
Scan
(
&
fnum
,
&
inum
,
&
sstr
)
cs
.
Scan
(
&
fnum
,
&
inum
,
&
sstr
)
}
}
if
err
!=
nil
{
panic
(
err
)
}
cs
.
Finalize
()
}
}
}
}
func
Benchmark
Scan2
(
b
*
testing
.
B
)
{
func
Benchmark
NamedScan
(
b
*
testing
.
B
)
{
b
.
StopTimer
()
b
.
StopTimer
()
db
,
_
:=
Open
(
"/tmp/test_bs2.db"
)
db
,
_
:=
Open
(
""
)
db
.
Exec
(
"DROP TABLE test"
)
defer
db
.
Close
()
db
.
Exec
(
"DROP TABLE IF EXISTS test"
)
db
.
Exec
(
"CREATE TABLE test (id INTEGER PRIMARY KEY AUTOINCREMENT, float_num REAL, int_num INTEGER, a_string TEXT)"
)
db
.
Exec
(
"CREATE TABLE test (id INTEGER PRIMARY KEY AUTOINCREMENT, float_num REAL, int_num INTEGER, a_string TEXT)"
)
s
,
_
:=
db
.
Prepare
(
"INSERT INTO test (float_num, int_num, a_string) VALUES (?, ?, ?)"
)
s
,
_
:=
db
.
Prepare
(
"INSERT INTO test (float_num, int_num, a_string) VALUES (?, ?, ?)"
)
for
i
:=
0
;
i
<
1000
;
i
++
{
for
i
:=
0
;
i
<
1000
;
i
++
{
s
.
Exec
(
float64
(
i
)
*
float64
(
3.14
),
i
,
"hello"
)
s
.
Exec
(
float64
(
i
)
*
float64
(
3.14
),
i
,
"hello"
)
s
.
Next
()
}
}
s
.
Finalize
()
s
.
Finalize
()
b
.
StartTimer
()
b
.
StartTimer
()
for
i
:=
0
;
i
<
b
.
N
;
i
++
{
for
i
:=
0
;
i
<
b
.
N
;
i
++
{
cs
,
_
:=
db
.
Prepare
(
"SELECT float_num, int_num, a_string FROM test"
)
cs
,
_
:=
db
.
Prepare
(
"SELECT float_num, int_num, a_string FROM test"
)
cs
.
Exec
()
var
fnum
float64
var
fnum
float64
var
inum
int64
var
inum
int64
var
sstr
string
var
sstr
string
for
cs
.
Next
()
{
var
ok
bool
cs
.
Scan2
(
&
fnum
,
&
inum
,
&
sstr
)
var
err
os
.
Error
for
ok
,
err
=
cs
.
Next
();
ok
;
ok
,
err
=
cs
.
Next
()
{
cs
.
NamedScan
(
"float_num"
,
&
fnum
,
"int_num"
,
&
inum
,
"a_string"
,
&
sstr
)
}
if
err
!=
nil
{
panic
(
err
)
}
}
cs
.
Finalize
()
}
}
}
}
func
BenchmarkInsert
(
b
*
testing
.
B
)
{
func
BenchmarkInsert
(
b
*
testing
.
B
)
{
db
,
_
:=
Open
(
"/tmp/test_bi.db"
)
db
,
_
:=
Open
(
""
)
db
.
Exec
(
"DROP TABLE test"
)
defer
db
.
Close
()
db
.
Exec
(
"CREATE TABLE test (id INTEGER PRIMARY KEY AUTOINCREMENT, float_num REAL, int_num INTEGER, a_string TEXT)"
)
db
.
Exec
(
"DROP TABLE IF EXISTS test"
)
s
,
_
:=
db
.
Prepare
(
"INSERT INTO test (float_num, int_num, a_string) VALUES (?, ?, ?)"
)
db
.
Exec
(
"CREATE TABLE test (id INTEGER PRIMARY KEY AUTOINCREMENT,"
+
" float_num REAL, int_num INTEGER, a_string TEXT)"
)
// for x := 0; x < b.N; x++ {
s
,
_
:=
db
.
Prepare
(
"INSERT INTO test (float_num, int_num, a_string)"
+
for
i
:=
0
;
i
<
b
.
N
;
i
++
{
" VALUES (?, ?, ?)"
)
s
.
Exec
(
float64
(
i
)
*
float64
(
3.14
),
i
,
"hello"
)
defer
s
.
Finalize
()
s
.
Next
()
}
// }
s
.
Finalize
()
}
func
BenchmarkInsert2
(
b
*
testing
.
B
)
{
db
,
_
:=
Open
(
"/tmp/test_bi2.db"
)
db
.
Exec
(
"DROP TABLE test"
)
db
.
Exec
(
"CREATE TABLE test (id INTEGER PRIMARY KEY AUTOINCREMENT, float_num REAL, int_num INTEGER, a_string TEXT)"
)
s
,
_
:=
db
.
Prepare
(
"INSERT INTO test (float_num, int_num, a_string) VALUES (?, ?, ?)"
)
// for x := 0; x < b.N; x++ {
for
i
:=
0
;
i
<
b
.
N
;
i
++
{
for
i
:=
0
;
i
<
b
.
N
;
i
++
{
s
.
Exec
(
float64
(
i
)
*
float64
(
3.14
),
i
,
"hello"
)
s
.
Exec2
(
float64
(
i
)
*
float64
(
3.14
),
i
,
"hello"
)
}
s
.
Next
()
}
// }
s
.
Finalize
()
}
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment