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
c699a930
Commit
c699a930
authored
Nov 03, 2012
by
gwenn
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Small step toward Virtual table support
parent
24e630f3
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
140 additions
and
41 deletions
+140
-41
vtab.c
vtab.c
+27
-3
vtab.go
vtab.go
+78
-36
vtab_test.go
vtab_test.go
+35
-2
No files found.
vtab.c
View file @
c699a930
...
@@ -39,11 +39,12 @@ static int cXConnect(sqlite3 *db, void *pAux, int argc, const char *const*argv,
...
@@ -39,11 +39,12 @@ static int cXConnect(sqlite3 *db, void *pAux, int argc, const char *const*argv,
}
}
static
int
cXBestIndex
(
sqlite3_vtab
*
pVTab
,
sqlite3_index_info
*
info
)
{
static
int
cXBestIndex
(
sqlite3_vtab
*
pVTab
,
sqlite3_index_info
*
info
)
{
// TODO
return
SQLITE_OK
;
return
SQLITE_OK
;
}
}
static
int
cXRelease
(
sqlite3_vtab
*
pVTab
,
int
isDestroy
)
{
static
int
cXRelease
(
sqlite3_vtab
*
pVTab
,
int
isDestroy
)
{
char
*
pzErr
=
go
M
Release
(((
goVTab
*
)
pVTab
)
->
vTab
,
isDestroy
);
char
*
pzErr
=
go
V
Release
(((
goVTab
*
)
pVTab
)
->
vTab
,
isDestroy
);
if
(
pzErr
)
{
if
(
pzErr
)
{
if
(
pVTab
->
zErrMsg
)
if
(
pVTab
->
zErrMsg
)
sqlite3_free
(
pVTab
->
zErrMsg
);
sqlite3_free
(
pVTab
->
zErrMsg
);
...
@@ -63,11 +64,34 @@ static int cXDestroy(sqlite3_vtab *pVTab) {
...
@@ -63,11 +64,34 @@ static int cXDestroy(sqlite3_vtab *pVTab) {
return
cXRelease
(
pVTab
,
1
);
return
cXRelease
(
pVTab
,
1
);
}
}
typedef
struct
goVTabCursor
goVTabCursor
;
struct
goVTabCursor
{
sqlite3_vtab_cursor
base
;
void
*
vTabCursor
;
};
static
int
cXOpen
(
sqlite3_vtab
*
pVTab
,
sqlite3_vtab_cursor
**
ppCursor
)
{
static
int
cXOpen
(
sqlite3_vtab
*
pVTab
,
sqlite3_vtab_cursor
**
ppCursor
)
{
return
0
;
void
*
vTabCursor
=
goVOpen
(((
goVTab
*
)
pVTab
)
->
vTab
,
&
(
pVTab
->
zErrMsg
));
goVTabCursor
*
pCursor
=
(
goVTabCursor
*
)
sqlite3_malloc
(
sizeof
(
goVTabCursor
));
if
(
!
pCursor
)
{
return
SQLITE_NOMEM
;
}
memset
(
pCursor
,
0
,
sizeof
(
goVTabCursor
));
pCursor
->
vTabCursor
=
vTabCursor
;
*
ppCursor
=
(
sqlite3_vtab_cursor
*
)
pCursor
;
return
SQLITE_OK
;
}
}
static
int
cXClose
(
sqlite3_vtab_cursor
*
pCursor
)
{
static
int
cXClose
(
sqlite3_vtab_cursor
*
pCursor
)
{
return
0
;
char
*
pzErr
=
goVClose
(((
goVTabCursor
*
)
pCursor
)
->
vTabCursor
);
if
(
pzErr
)
{
if
(
pCursor
->
pVtab
->
zErrMsg
)
sqlite3_free
(
pCursor
->
pVtab
->
zErrMsg
);
pCursor
->
pVtab
->
zErrMsg
=
pzErr
;
return
SQLITE_ERROR
;
}
sqlite3_free
(
pCursor
);
return
SQLITE_OK
;
}
}
static
int
cXFilter
(
sqlite3_vtab_cursor
*
pCursor
,
int
idxNum
,
const
char
*
idxStr
,
int
argc
,
sqlite3_value
**
argv
)
{
static
int
cXFilter
(
sqlite3_vtab_cursor
*
pCursor
,
int
idxNum
,
const
char
*
idxStr
,
int
argc
,
sqlite3_value
**
argv
)
{
return
0
;
return
0
;
...
...
vtab.go
View file @
c699a930
...
@@ -17,15 +17,28 @@ import (
...
@@ -17,15 +17,28 @@ import (
"unsafe"
"unsafe"
)
)
type
sqliteModule
struct
{
c
*
Conn
name
string
module
Module
vts
map
[
*
sqliteVTab
]
bool
}
type
sqliteVTab
struct
{
type
sqliteVTab
struct
{
c
*
Conn
// TODO Useful?
module
*
sqliteModule
vTab
VTab
vTab
VTab
vtcs
map
[
*
sqliteVTabCursor
]
bool
}
type
sqliteVTabCursor
struct
{
vTab
*
sqliteVTab
vTabCursor
VTabCursor
}
}
//export goMInit
//export goMInit
func
goMInit
(
db
,
pClientData
unsafe
.
Pointer
,
argc
int
,
argv
**
C
.
char
,
pzErr
**
C
.
char
,
isCreate
int
)
unsafe
.
Pointer
{
func
goMInit
(
db
,
pClientData
unsafe
.
Pointer
,
argc
int
,
argv
**
C
.
char
,
pzErr
**
C
.
char
,
isCreate
int
)
unsafe
.
Pointer
{
ud
m
:=
(
*
sqliteModule
)(
pClientData
)
m
:=
(
*
sqliteModule
)(
pClientData
)
if
ud
m
.
c
.
db
!=
(
*
C
.
sqlite3
)(
db
)
{
if
m
.
c
.
db
!=
(
*
C
.
sqlite3
)(
db
)
{
*
pzErr
=
mPrintf
(
"%s"
,
"Inconsistent db handles"
)
*
pzErr
=
mPrintf
(
"%s"
,
"Inconsistent db handles"
)
return
nil
return
nil
}
}
...
@@ -39,45 +52,84 @@ func goMInit(db, pClientData unsafe.Pointer, argc int, argv **C.char, pzErr **C.
...
@@ -39,45 +52,84 @@ func goMInit(db, pClientData unsafe.Pointer, argc int, argv **C.char, pzErr **C.
var
vTab
VTab
var
vTab
VTab
var
err
error
var
err
error
if
isCreate
==
1
{
if
isCreate
==
1
{
vTab
,
err
=
udm
.
module
.
Create
(
ud
m
.
c
,
args
)
vTab
,
err
=
m
.
module
.
Create
(
m
.
c
,
args
)
}
else
{
}
else
{
vTab
,
err
=
udm
.
module
.
Connect
(
ud
m
.
c
,
args
)
vTab
,
err
=
m
.
module
.
Connect
(
m
.
c
,
args
)
}
}
if
err
!=
nil
{
if
err
!=
nil
{
*
pzErr
=
mPrintf
(
"%s"
,
err
.
Error
())
*
pzErr
=
mPrintf
(
"%s"
,
err
.
Error
())
return
nil
return
nil
}
}
udt
:=
&
sqliteVTab
{
udm
.
c
,
vTab
}
vt
:=
&
sqliteVTab
{
m
,
vTab
,
nil
}
// prevents 'vt' from being gced
if
m
.
vts
==
nil
{
m
.
vts
=
make
(
map
[
*
sqliteVTab
]
bool
)
}
m
.
vts
[
vt
]
=
true
*
pzErr
=
nil
*
pzErr
=
nil
return
unsafe
.
Pointer
(
ud
t
)
return
unsafe
.
Pointer
(
v
t
)
}
}
//export go
M
Release
//export go
V
Release
func
go
M
Release
(
pVTab
unsafe
.
Pointer
,
isDestroy
int
)
*
C
.
char
{
func
go
V
Release
(
pVTab
unsafe
.
Pointer
,
isDestroy
int
)
*
C
.
char
{
ud
t
:=
(
*
sqliteVTab
)(
pVTab
)
v
t
:=
(
*
sqliteVTab
)(
pVTab
)
var
err
error
var
err
error
if
isDestroy
==
1
{
if
isDestroy
==
1
{
err
=
ud
t
.
vTab
.
Destroy
()
err
=
v
t
.
vTab
.
Destroy
()
}
else
{
}
else
{
err
=
ud
t
.
vTab
.
Disconnect
()
err
=
v
t
.
vTab
.
Disconnect
()
}
}
if
err
!=
nil
{
if
err
!=
nil
{
return
mPrintf
(
"%s"
,
err
.
Error
())
return
mPrintf
(
"%s"
,
err
.
Error
())
}
}
// TODO Check vt.vtcs is empty
vt
.
vtcs
=
nil
delete
(
vt
.
module
.
vts
,
vt
)
return
nil
}
//export goVOpen
func
goVOpen
(
pVTab
unsafe
.
Pointer
,
pzErr
**
C
.
char
)
unsafe
.
Pointer
{
vt
:=
(
*
sqliteVTab
)(
pVTab
)
vTabCursor
,
err
:=
vt
.
vTab
.
Open
()
if
err
!=
nil
{
*
pzErr
=
mPrintf
(
"%s"
,
err
.
Error
())
return
nil
}
// prevents 'vt' from being gced
vtc
:=
&
sqliteVTabCursor
{
vt
,
vTabCursor
}
if
vt
.
vtcs
==
nil
{
vt
.
vtcs
=
make
(
map
[
*
sqliteVTabCursor
]
bool
)
}
vt
.
vtcs
[
vtc
]
=
true
*
pzErr
=
nil
return
unsafe
.
Pointer
(
vtc
)
}
//export goVClose
func
goVClose
(
pCursor
unsafe
.
Pointer
)
*
C
.
char
{
vtc
:=
(
*
sqliteVTabCursor
)(
pCursor
)
err
:=
vtc
.
vTabCursor
.
Close
()
if
err
!=
nil
{
return
mPrintf
(
"%s"
,
err
.
Error
())
}
delete
(
vtc
.
vTab
.
vtcs
,
vtc
)
return
nil
return
nil
}
}
//export goMDestroy
//export goMDestroy
func
goMDestroy
(
pClientData
unsafe
.
Pointer
)
{
func
goMDestroy
(
pClientData
unsafe
.
Pointer
)
{
udm
:=
(
*
sqliteModule
)(
pClientData
)
m
:=
(
*
sqliteModule
)(
pClientData
)
udm
.
module
.
Destroy
()
m
.
module
.
Destroy
()
delete
(
udm
.
c
.
modules
,
udm
.
name
)
// TODO Check m.vts is empty
m
.
vts
=
nil
delete
(
m
.
c
.
modules
,
m
.
name
)
}
}
//export goXNext
//export goXNext
func
goXNext
(
c
ursor
unsafe
.
Pointer
)
C
.
int
{
func
goXNext
(
pC
ursor
unsafe
.
Pointer
)
C
.
int
{
//
c := (*VTableCursor)(c
ursor)
//
vtc := (*sqliteVTabCursor)(pC
ursor)
return
0
return
0
}
}
...
@@ -124,10 +176,6 @@ type VTabCursor interface {
...
@@ -124,10 +176,6 @@ type VTabCursor interface {
Rowid
()
(
int64
,
error
)
// See http://sqlite.org/vtab.html#xrowid
Rowid
()
(
int64
,
error
)
// See http://sqlite.org/vtab.html#xrowid
}
}
type
vTabCursor
struct
{
base
*
C
.
sqlite3_vtab_cursor
}
// DeclareVTab declares the Schema of a virtual table.
// DeclareVTab declares the Schema of a virtual table.
// (See http://sqlite.org/c3ref/declare_vtab.html)
// (See http://sqlite.org/c3ref/declare_vtab.html)
func
(
c
*
Conn
)
DeclareVTab
(
sql
string
)
error
{
func
(
c
*
Conn
)
DeclareVTab
(
sql
string
)
error
{
...
@@ -136,19 +184,13 @@ func (c *Conn) DeclareVTab(sql string) error {
...
@@ -136,19 +184,13 @@ func (c *Conn) DeclareVTab(sql string) error {
return
c
.
error
(
C
.
sqlite3_declare_vtab
(
c
.
db
,
zSQL
))
return
c
.
error
(
C
.
sqlite3_declare_vtab
(
c
.
db
,
zSQL
))
}
}
type
sqliteModule
struct
{
c
*
Conn
name
string
module
Module
}
// CreateModule registers a virtual table implementation.
// CreateModule registers a virtual table implementation.
// (See http://sqlite.org/c3ref/create_module.html)
// (See http://sqlite.org/c3ref/create_module.html)
func
(
c
*
Conn
)
CreateModule
(
moduleName
string
,
module
Module
)
error
{
func
(
c
*
Conn
)
CreateModule
(
moduleName
string
,
module
Module
)
error
{
mname
:=
C
.
CString
(
moduleName
)
mname
:=
C
.
CString
(
moduleName
)
defer
C
.
free
(
unsafe
.
Pointer
(
mname
))
defer
C
.
free
(
unsafe
.
Pointer
(
mname
))
// To make sure it is not gced, keep a reference in the connection.
// To make sure it is not gced, keep a reference in the connection.
udm
:=
&
sqliteModule
{
c
,
moduleName
,
module
}
udm
:=
&
sqliteModule
{
c
,
moduleName
,
module
,
nil
}
if
len
(
c
.
modules
)
==
0
{
if
len
(
c
.
modules
)
==
0
{
c
.
modules
=
make
(
map
[
string
]
*
sqliteModule
)
c
.
modules
=
make
(
map
[
string
]
*
sqliteModule
)
}
}
...
@@ -168,15 +210,15 @@ CreateModule( int sqlite3_create_module_v2(
...
@@ -168,15 +210,15 @@ CreateModule( int sqlite3_create_module_v2(
goModule sqlite3_module {
goModule sqlite3_module {
|- int iVersion
|- int iVersion
x
|- int (*xCreate)(sqlite3*, void *pAux, int argc, char **argv, sqlite3_vtab **ppVTab,
goMInit
|- int (*xCreate)(sqlite3*, void *pAux, int argc, char **argv, sqlite3_vtab **ppVTab,
char **pzErr)
char **pzErr)
x
|- int (*xConnect)(sqlite3*, void *pAux, int argc, char **argv, sqlite3_vtab **ppVTab,
goMInit
|- int (*xConnect)(sqlite3*, void *pAux, int argc, char **argv, sqlite3_vtab **ppVTab,
char **pzErr)
char **pzErr)
x |- int (*xBestIndex)(sqlite3_vtab *pVTab, sqlite3_index_info*)
x |- int (*xBestIndex)(sqlite3_vtab *pVTab, sqlite3_index_info*)
x
|- int (*xDisconnect)(sqlite3_vtab *pVTab)
goVRelease
|- int (*xDisconnect)(sqlite3_vtab *pVTab)
x
|- int (*xDestroy)(sqlite3_vtab *pVTab)
goVRelease
|- int (*xDestroy)(sqlite3_vtab *pVTab)
x
|- int (*xOpen)(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor)
goVOpen
|- int (*xOpen)(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor)
x
|- int (*xClose)(sqlite3_vtab_cursor*)
goVClose
|- int (*xClose)(sqlite3_vtab_cursor*)
x |- int (*xFilter)(sqlite3_vtab_cursor*, int idxNum, const char *idxStr, int argc,
x |- int (*xFilter)(sqlite3_vtab_cursor*, int idxNum, const char *idxStr, int argc,
sqlite3_value **argv)
sqlite3_value **argv)
x |- int (*xNext)(sqlite3_vtab_cursor*)
x |- int (*xNext)(sqlite3_vtab_cursor*)
...
@@ -201,7 +243,7 @@ o \- int (*xRollbackTo)(sqlite3_vtab *pVTab,
...
@@ -201,7 +243,7 @@ o \- int (*xRollbackTo)(sqlite3_vtab *pVTab,
\- const char *zCreateTable
\- const char *zCreateTable
)
)
?
sqlite3_vtab { (Created by xCreate/xConnect)
sqliteVTab
sqlite3_vtab { (Created by xCreate/xConnect)
|- const sqlite3_module *pModule
|- const sqlite3_module *pModule
|- int nRef
|- int nRef
|- char *zErrMsg
|- char *zErrMsg
...
...
vtab_test.go
View file @
c699a930
...
@@ -16,6 +16,9 @@ type testModule struct {
...
@@ -16,6 +16,9 @@ type testModule struct {
type
testVTab
struct
{
type
testVTab
struct
{
}
}
type
testVTabCursor
struct
{
}
func
(
m
testModule
)
Create
(
c
*
Conn
,
args
[]
string
)
(
VTab
,
error
)
{
func
(
m
testModule
)
Create
(
c
*
Conn
,
args
[]
string
)
(
VTab
,
error
)
{
//println("testVTab.Create")
//println("testVTab.Create")
assert
(
m
.
t
,
"Six arguments expected"
,
len
(
args
)
==
6
)
assert
(
m
.
t
,
"Six arguments expected"
,
len
(
args
)
==
6
)
...
@@ -50,8 +53,33 @@ func (v testVTab) Destroy() error {
...
@@ -50,8 +53,33 @@ func (v testVTab) Destroy() error {
return
nil
return
nil
}
}
func
(
v
testVTab
)
Open
()
(
VTabCursor
,
error
)
{
func
(
v
testVTab
)
Open
()
(
VTabCursor
,
error
)
{
println
(
"testVTab.Open"
)
//println("testVTab.Open")
return
nil
,
nil
return
testVTabCursor
{},
nil
}
func
(
v
testVTabCursor
)
Close
()
error
{
//println("testVTabCursor.Close")
return
nil
}
func
(
v
testVTabCursor
)
Filter
(
idxNum
int
,
idxStr
string
/*, int argc, sqlite3_value **argv*/
)
error
{
println
(
"testVTabCursor.Filter"
)
return
nil
}
func
(
v
testVTabCursor
)
Next
()
error
{
println
(
"testVTabCursor.Next"
)
return
nil
}
func
(
v
testVTabCursor
)
Eof
()
bool
{
println
(
"testVTabCursor.Eof"
)
return
true
}
func
(
v
testVTabCursor
)
Column
(
c
*
Context
,
col
int
)
error
{
println
(
"testVTabCursor.Column"
)
return
nil
}
func
(
v
testVTabCursor
)
Rowid
()
(
int64
,
error
)
{
println
(
"testVTabCursor.Rowid"
)
return
1
,
nil
}
}
func
TestCreateModule
(
t
*
testing
.
T
)
{
func
TestCreateModule
(
t
*
testing
.
T
)
{
...
@@ -61,6 +89,11 @@ func TestCreateModule(t *testing.T) {
...
@@ -61,6 +89,11 @@ func TestCreateModule(t *testing.T) {
checkNoError
(
t
,
err
,
"couldn't create module: %s"
)
checkNoError
(
t
,
err
,
"couldn't create module: %s"
)
err
=
db
.
Exec
(
"CREATE VIRTUAL TABLE vtab USING test('1', 2, three)"
)
err
=
db
.
Exec
(
"CREATE VIRTUAL TABLE vtab USING test('1', 2, three)"
)
checkNoError
(
t
,
err
,
"couldn't create virtual table: %s"
)
checkNoError
(
t
,
err
,
"couldn't create virtual table: %s"
)
var
value
*
string
err
=
db
.
OneValue
(
"SELECT * from vtab"
,
&
value
)
checkNoError
(
t
,
err
,
"couldn't select from virtual table: %s"
)
//assert(t, "Not null value expected", value != nil)
//assertEquals(t, "Expected '%s' but got '%s'", "test", *value)
err
=
db
.
Exec
(
"DROP TABLE vtab"
)
err
=
db
.
Exec
(
"DROP TABLE vtab"
)
checkNoError
(
t
,
err
,
"couldn't drop virtual table: %s"
)
checkNoError
(
t
,
err
,
"couldn't drop virtual table: %s"
)
}
}
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