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
3940be47
Commit
3940be47
authored
Jun 23, 2014
by
gwenn
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Replace Go intarray by original C.
parent
220759b9
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
38 additions
and
68 deletions
+38
-68
intarray.go
intarray.go
+32
-64
intarray_test.go
intarray_test.go
+6
-4
No files found.
intarray.go
View file @
3940be47
...
@@ -4,16 +4,28 @@
...
@@ -4,16 +4,28 @@
package
sqlite
package
sqlite
/*
#include <sqlite3.h>
#include <stdlib.h>
// An sqlite3_intarray is an abstract type to stores an instance of an integer array.
typedef struct sqlite3_intarray sqlite3_intarray;
int sqlite3_intarray_bind(sqlite3_intarray *pIntArray, int nElements, sqlite3_int64 *aElements, void (*xFree)(void*));
int sqlite3_intarray_create(sqlite3 *db, const char *zName, sqlite3_intarray **ppReturn);
*/
import
"C"
import
(
import
(
"errors"
"errors"
"fmt"
"fmt"
"unsafe"
)
)
// IntArray is the Go-language interface definition for the "intarray" or
// IntArray is the Go-language interface definition for the "intarray" or
// integer array virtual table for SQLite.
// integer array virtual table for SQLite.
//
//
// The intarray virtual table is designed to facilitate using an
// The intarray virtual table is designed to facilitate using an
// aray of integers as the right-hand side of an IN operator. So
// ar
r
ay of integers as the right-hand side of an IN operator. So
// instead of doing a prepared statement like this:
// instead of doing a prepared statement like this:
//
//
// SELECT * FROM table WHERE x IN (?,?,?,...,?);
// SELECT * FROM table WHERE x IN (?,?,?,...,?);
...
@@ -75,67 +87,11 @@ type IntArray interface {
...
@@ -75,67 +87,11 @@ type IntArray interface {
type
intArray
struct
{
type
intArray
struct
{
c
*
Conn
c
*
Conn
ia
*
C
.
sqlite3_intarray
name
string
name
string
content
[]
int64
content
[]
int64
}
}
func
(
m
*
intArray
)
Create
(
c
*
Conn
,
args
[]
string
)
(
VTab
,
error
)
{
err
:=
c
.
DeclareVTab
(
"CREATE TABLE x(value INTEGER PRIMARY KEY)"
)
if
err
!=
nil
{
return
nil
,
err
}
return
m
,
nil
}
func
(
m
*
intArray
)
Connect
(
c
*
Conn
,
args
[]
string
)
(
VTab
,
error
)
{
return
m
.
Create
(
c
,
args
)
}
func
(
m
*
intArray
)
DestroyModule
()
{
}
func
(
m
*
intArray
)
BestIndex
()
error
{
return
nil
}
func
(
m
*
intArray
)
Disconnect
()
error
{
return
nil
}
func
(
m
*
intArray
)
Destroy
()
error
{
return
nil
}
func
(
m
*
intArray
)
Open
()
(
VTabCursor
,
error
)
{
return
&
intArrayVTabCursor
{
m
,
0
},
nil
}
type
intArrayVTabCursor
struct
{
vTab
*
intArray
i
int
/* Current cursor position */
}
func
(
vc
*
intArrayVTabCursor
)
Close
()
error
{
return
nil
}
func
(
vc
*
intArrayVTabCursor
)
Filter
()
error
{
vc
.
i
=
0
return
nil
}
func
(
vc
*
intArrayVTabCursor
)
Next
()
error
{
vc
.
i
++
return
nil
}
func
(
vc
*
intArrayVTabCursor
)
EOF
()
bool
{
return
vc
.
i
>=
len
(
vc
.
vTab
.
content
)
}
func
(
vc
*
intArrayVTabCursor
)
Column
(
c
*
Context
,
col
int
)
error
{
if
col
!=
0
{
return
fmt
.
Errorf
(
"column index out of bounds: %d"
,
col
)
}
c
.
ResultInt64
(
vc
.
vTab
.
content
[
vc
.
i
])
return
nil
}
func
(
vc
*
intArrayVTabCursor
)
Rowid
()
(
int64
,
error
)
{
return
int64
(
vc
.
i
),
nil
}
// CreateIntArray create a specific instance of an intarray object.
// CreateIntArray create a specific instance of an intarray object.
//
//
// Each intarray object corresponds to a virtual table in the TEMP table
// Each intarray object corresponds to a virtual table in the TEMP table
...
@@ -145,14 +101,17 @@ func (vc *intArrayVTabCursor) Rowid() (int64, error) {
...
@@ -145,14 +101,17 @@ func (vc *intArrayVTabCursor) Rowid() (int64, error) {
// explicitly by the application, the virtual table will be dropped implicitly
// explicitly by the application, the virtual table will be dropped implicitly
// by the system when the database connection is closed.
// by the system when the database connection is closed.
func
(
c
*
Conn
)
CreateIntArray
(
name
string
)
(
IntArray
,
error
)
{
func
(
c
*
Conn
)
CreateIntArray
(
name
string
)
(
IntArray
,
error
)
{
module
:=
&
intArray
{
c
:
c
,
name
:
name
}
var
ia
*
C
.
sqlite3_intarray
if
err
:=
c
.
CreateModule
(
name
,
module
);
err
!=
nil
{
cname
:=
C
.
CString
(
name
)
return
nil
,
err
defer
C
.
free
(
unsafe
.
Pointer
(
cname
))
rv
:=
C
.
sqlite3_intarray_create
(
c
.
db
,
cname
,
&
ia
)
if
rv
!=
C
.
SQLITE_OK
{
return
nil
,
Errno
(
rv
)
}
}
name
=
escapeQuote
(
name
)
if
ia
==
nil
{
if
err
:=
c
.
FastExec
(
fmt
.
Sprintf
(
`CREATE VIRTUAL TABLE temp."%s" USING "%s"`
,
name
,
name
));
err
!=
nil
{
return
nil
,
errors
.
New
(
"sqlite succeeded without returning an intarray"
)
return
nil
,
err
}
}
module
:=
&
intArray
{
c
:
c
,
ia
:
ia
,
name
:
name
}
return
module
,
nil
return
module
,
nil
}
}
...
@@ -162,7 +121,15 @@ func (c *Conn) CreateIntArray(name string) (IntArray, error) {
...
@@ -162,7 +121,15 @@ func (c *Conn) CreateIntArray(name string) (IntArray, error) {
// any query against the corresponding virtual table. If the integer
// any query against the corresponding virtual table. If the integer
// array does change or is deallocated undefined behavior will result.
// array does change or is deallocated undefined behavior will result.
func
(
m
*
intArray
)
Bind
(
elements
[]
int64
)
{
func
(
m
*
intArray
)
Bind
(
elements
[]
int64
)
{
if
m
.
ia
==
nil
{
return
}
m
.
content
=
elements
m
.
content
=
elements
var
p
*
int64
if
len
(
elements
)
>
0
{
p
=
&
elements
[
0
]
}
C
.
sqlite3_intarray_bind
(
m
.
ia
,
C
.
int
(
len
(
elements
)),
(
*
C
.
sqlite3_int64
)(
unsafe
.
Pointer
(
p
)),
nil
)
}
}
// Drop underlying virtual table.
// Drop underlying virtual table.
...
@@ -178,5 +145,6 @@ func (m *intArray) Drop() error {
...
@@ -178,5 +145,6 @@ func (m *intArray) Drop() error {
return
err
return
err
}
}
m
.
c
=
nil
m
.
c
=
nil
m
.
ia
=
nil
return
nil
return
nil
}
}
intarray_test.go
View file @
3940be47
...
@@ -78,6 +78,8 @@ func TestIntArrayModule(t *testing.T) {
...
@@ -78,6 +78,8 @@ func TestIntArrayModule(t *testing.T) {
checkNoError
(
t
,
p3
.
Drop
(),
"%s"
)
checkNoError
(
t
,
p3
.
Drop
(),
"%s"
)
}
}
const
INTARRAY_SIZE
=
100
func
BenchmarkNoIntArray
(
b
*
testing
.
B
)
{
func
BenchmarkNoIntArray
(
b
*
testing
.
B
)
{
b
.
StopTimer
()
b
.
StopTimer
()
db
,
err
:=
Open
(
":memory:"
)
db
,
err
:=
Open
(
":memory:"
)
...
@@ -85,14 +87,14 @@ func BenchmarkNoIntArray(b *testing.B) {
...
@@ -85,14 +87,14 @@ func BenchmarkNoIntArray(b *testing.B) {
defer
db
.
Close
()
defer
db
.
Close
()
panicOnError
(
b
,
db
.
Exec
(
"CREATE TABLE rand (r INT)"
))
panicOnError
(
b
,
db
.
Exec
(
"CREATE TABLE rand (r INT)"
))
values
:=
rand
.
Perm
(
1000
)
values
:=
rand
.
Perm
(
INTARRAY_SIZE
)
for
_
,
v
:=
range
values
{
for
_
,
v
:=
range
values
{
panicOnError
(
b
,
db
.
Exec
(
"INSERT INTO rand (r) VALUES (?)"
,
v
))
panicOnError
(
b
,
db
.
Exec
(
"INSERT INTO rand (r) VALUES (?)"
,
v
))
}
}
b
.
StartTimer
()
b
.
StartTimer
()
for
i
:=
0
;
i
<
b
.
N
;
i
++
{
for
i
:=
0
;
i
<
b
.
N
;
i
++
{
l
:=
rand
.
Intn
(
999
)
+
1
// at least one value
l
:=
rand
.
Intn
(
INTARRAY_SIZE
-
1
)
+
1
// at least one value
sql
:=
fmt
.
Sprintf
(
"SELECT * FROM rand WHERE r IN (?%s)"
,
strings
.
Repeat
(
", ?"
,
l
-
1
))
sql
:=
fmt
.
Sprintf
(
"SELECT * FROM rand WHERE r IN (?%s)"
,
strings
.
Repeat
(
", ?"
,
l
-
1
))
s
,
err
:=
db
.
Prepare
(
sql
)
s
,
err
:=
db
.
Prepare
(
sql
)
panicOnError
(
b
,
err
)
panicOnError
(
b
,
err
)
...
@@ -120,7 +122,7 @@ func BenchmarkIntArray(b *testing.B) {
...
@@ -120,7 +122,7 @@ func BenchmarkIntArray(b *testing.B) {
defer
db
.
Close
()
defer
db
.
Close
()
panicOnError
(
b
,
db
.
Exec
(
"CREATE TABLE rand (r INT)"
))
panicOnError
(
b
,
db
.
Exec
(
"CREATE TABLE rand (r INT)"
))
perms
:=
rand
.
Perm
(
1000
)
perms
:=
rand
.
Perm
(
INTARRAY_SIZE
)
values
:=
make
([]
int64
,
len
(
perms
))
values
:=
make
([]
int64
,
len
(
perms
))
for
i
,
v
:=
range
perms
{
for
i
,
v
:=
range
perms
{
panicOnError
(
b
,
db
.
Exec
(
"INSERT INTO rand (r) VALUES (?)"
,
v
))
panicOnError
(
b
,
db
.
Exec
(
"INSERT INTO rand (r) VALUES (?)"
,
v
))
...
@@ -137,7 +139,7 @@ func BenchmarkIntArray(b *testing.B) {
...
@@ -137,7 +139,7 @@ func BenchmarkIntArray(b *testing.B) {
defer
s
.
Finalize
()
defer
s
.
Finalize
()
for
i
:=
0
;
i
<
b
.
N
;
i
++
{
for
i
:=
0
;
i
<
b
.
N
;
i
++
{
l
:=
rand
.
Intn
(
999
)
+
1
// at least one value
l
:=
rand
.
Intn
(
INTARRAY_SIZE
-
1
)
+
1
// at least one value
p
.
Bind
(
values
[
0
:
l
])
p
.
Bind
(
values
[
0
:
l
])
nr
:=
0
nr
:=
0
err
=
s
.
Select
(
func
(
s
*
Stmt
)
error
{
err
=
s
.
Select
(
func
(
s
*
Stmt
)
error
{
...
...
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