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
c38edfad
Commit
c38edfad
authored
Apr 03, 2014
by
gwenn
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
First draft of an "intarrayFirst draft of an "intarray""
parent
53988358
Changes
2
Show whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
218 additions
and
0 deletions
+218
-0
intarray.go
intarray.go
+162
-0
intarray_test.go
intarray_test.go
+56
-0
No files found.
intarray.go
0 → 100644
View file @
c38edfad
// Copyright 2010 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build all
package
sqlite
import
"fmt"
// This is the Go-language interface definition for the "intarray" or
// integer array virtual table for SQLite.
//
// The intarray virtual table is designed to facilitate using an
// aray of integers as the right-hand side of an IN operator. So
// instead of doing a prepared statement like this:
//
// SELECT * FROM table WHERE x IN (?,?,?,...,?);
//
// And then binding indivdual integers to each of ? slots, a Go-language
// application can create an intarray object (named "ex1" in the following
// example), prepare a statement like this:
//
// SELECT * FROM table WHERE x IN ex1;
//
// Then bind an ordinary Go slice of integer values to the ex1 object
// to run the statement.
//
// USAGE:
//
// One or more intarray objects can be created as follows:
//
// var p1, p2, p3 IntArray
// p1, err = db.CreateIntArray("ex1")
// p2, err = db.CreateIntArray("ex2")
// p3, err = db.CreateIntArray("ex3")
//
// Each call to CreateIntArray() generates a new virtual table
// module and a singleton of that virtual table module in the TEMP
// database. Both the module and the virtual table instance use the
// name given by the second parameter. The virtual tables can then be
// used in prepared statements:
//
// SELECT * FROM t1, t2, t3
// WHERE t1.x IN ex1
// AND t2.y IN ex2
// AND t3.z IN ex3;
//
// Each integer array is initially empty. New arrays can be bound to
// an integer array as follows:
//
// p1.Bind([]int64{ 1, 2, 3, 4 })
// p2.Bind([]int64{ 5, 6, 7, 8, 9, 10, 11 })
// a3 := make([]int64, 100)
// // Fill in content of a3
// p3.Bind(a3)
//
// A single intarray object can be rebound multiple times. But do not
// attempt to change the bindings of an intarray while it is in the middle
// of a query.
//
// The application must not change the intarray values while an intarray is in
// the middle of a query.
//
// The intarray object is automatically destroyed when its corresponding
// virtual table is dropped. Since the virtual tables are created in the
// TEMP database, they are automatically dropped when the database connection
// closes so the application does not normally need to take any special
// action to free the intarray objects (except if connections are pooled...).
type
IntArray
interface
{
Bind
(
elements
[]
int64
)
}
type
intArray
struct
{
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
(
v
*
intArray
)
BestIndex
()
error
{
return
nil
}
func
(
v
*
intArray
)
Disconnect
()
error
{
return
nil
}
func
(
v
*
intArray
)
Destroy
()
error
{
return
nil
}
func
(
v
*
intArray
)
Open
()
(
VTabCursor
,
error
)
{
return
&
intArrayVTabCursor
{
v
,
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.
//
// Each intarray object corresponds to a virtual table in the TEMP table
// with the specified name.
//
// Destroy the intarray object by dropping the virtual table. If not done
// explicitly by the application, the virtual table will be dropped implicitly
// by the system when the database connection is closed.
func
(
c
*
Conn
)
CreateIntArray
(
name
string
)
(
IntArray
,
error
)
{
module
:=
new
(
intArray
)
if
err
:=
c
.
CreateModule
(
name
,
module
);
err
!=
nil
{
return
nil
,
err
}
name
=
escapeQuote
(
name
)
if
err
:=
c
.
FastExec
(
fmt
.
Sprintf
(
"CREATE VIRTUAL TABLE temp.%s USING %s"
,
name
,
name
));
err
!=
nil
{
return
nil
,
err
}
return
module
,
nil
}
// Bind a new array of integers to a specific intarray object.
//
// The array of integers bound must be unchanged for the duration of
// any query against the corresponding virtual table. If the integer
// array does change or is deallocated undefined behavior will result.
func
(
ia
*
intArray
)
Bind
(
elements
[]
int64
)
{
ia
.
content
=
elements
}
intarray_test.go
0 → 100644
View file @
c38edfad
// Copyright 2010 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build all
package
sqlite_test
import
(
"github.com/bmizerany/assert"
.
"github.com/gwenn/gosqlite"
"testing"
)
func
TestIntArrayModule
(
t
*
testing
.
T
)
{
db
:=
open
(
t
)
defer
checkClose
(
db
,
t
)
err
:=
db
.
FastExec
(
`CREATE TABLE t1 (x INT);
INSERT INTO t1 VALUES (1), (3);
CREATE TABLE t2 (y INT);
INSERT INTO t2 VALUES (11);
CREATE TABLE t3 (z INT);
INSERT INTO t3 VALUES (-5);`
)
assert
.
T
(
t
,
err
==
nil
)
var
p1
,
p2
,
p3
IntArray
p1
,
err
=
db
.
CreateIntArray
(
"ex1"
)
assert
.
T
(
t
,
err
==
nil
)
p2
,
err
=
db
.
CreateIntArray
(
"ex2"
)
assert
.
T
(
t
,
err
==
nil
)
p3
,
err
=
db
.
CreateIntArray
(
"ex3"
)
assert
.
T
(
t
,
err
==
nil
)
s
,
err
:=
db
.
Prepare
(
`SELECT * FROM t1, t2, t3
WHERE t1.x IN ex1
AND t2.y IN ex2
AND t3.z IN ex3`
)
assert
.
T
(
t
,
err
==
nil
)
defer
checkFinalize
(
s
,
t
)
p1
.
Bind
([]
int64
{
1
,
2
,
3
,
4
})
p2
.
Bind
([]
int64
{
5
,
6
,
7
,
8
,
9
,
10
,
11
})
// Fill in content of a3
p3
.
Bind
([]
int64
{
-
1
,
-
5
,
-
10
})
var
i1
,
i2
,
i3
int64
for
checkStep
(
t
,
s
)
{
err
=
s
.
Scan
(
&
i1
,
&
i2
,
&
i3
)
assert
.
T
(
t
,
err
==
nil
)
assert
.
T
(
t
,
i1
==
1
||
i1
==
3
)
assert
.
T
(
t
,
i2
==
11
)
assert
.
T
(
t
,
i3
==
-
5
)
}
}
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