From 618e784627e2d0c0883f92c1708de3107296a0f9 Mon Sep 17 00:00:00 2001 From: Conor Branagan Date: Sun, 11 Dec 2016 12:49:48 -0500 Subject: [vtable] Add pure Go example of GitHub repo vtable. --- _example/vtable/vtable.go | 110 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 110 insertions(+) create mode 100644 _example/vtable/vtable.go (limited to '_example/vtable/vtable.go') diff --git a/_example/vtable/vtable.go b/_example/vtable/vtable.go new file mode 100644 index 0000000..cc0f308 --- /dev/null +++ b/_example/vtable/vtable.go @@ -0,0 +1,110 @@ +package main + +import ( + "encoding/json" + "fmt" + "github.com/mattn/go-sqlite3" + "io/ioutil" + "net/http" +) + +type GithubRepo struct { + ID int `json:"id"` + FullName string `json:"full_name"` + Description string `json:"description"` + HtmlURL string `json:"html_url"` +} + +type githubModule struct { +} + +func (m githubModule) Create(c *sqlite3.SQLiteConn, args []string) (sqlite3.VTab, error) { + err := c.DeclareVTab(fmt.Sprintf(` + CREATE TABLE %s ( + id INT, + full_name TEXT, + description TEXT, + html_url TEXT + )`, args[0])) + if err != nil { + return nil, err + } + return &ghRepoTable{}, nil +} + +func (m githubModule) Connect(c *sqlite3.SQLiteConn, args []string) (sqlite3.VTab, error) { + return m.Create(c, args) +} + +func (m githubModule) DestroyModule() {} + +type ghRepoTable struct { + repos []GithubRepo +} + +func (v *ghRepoTable) Open() (sqlite3.VTabCursor, error) { + resp, err := http.Get("https://api.github.com/repositories") + if err != nil { + return nil, err + } + defer resp.Body.Close() + + body, err := ioutil.ReadAll(resp.Body) + if err != nil { + return nil, err + } + + repos := make([]GithubRepo, 0) + if err := json.Unmarshal(body, &repos); err != nil { + return nil, err + } + return &ghRepoCursor{0, repos}, nil +} + +func (v *ghRepoTable) BestIndex(cst []sqlite3.InfoConstraint, ob []sqlite3.InfoOrderBy) (*sqlite3.IndexResult, error) { + return &sqlite3.IndexResult{}, nil +} + +func (v *ghRepoTable) Disconnect() error { return nil } +func (v *ghRepoTable) Destroy() error { return nil } + +type ghRepoCursor struct { + index int + repos []GithubRepo +} + +func (vc *ghRepoCursor) Column(c *sqlite3.Context, col int) error { + switch col { + case 0: + c.ResultInt(vc.repos[vc.index].ID) + case 1: + c.ResultText(vc.repos[vc.index].FullName) + case 2: + c.ResultText(vc.repos[vc.index].Description) + case 3: + c.ResultText(vc.repos[vc.index].HtmlURL) + } + return nil +} + +func (vc *ghRepoCursor) Filter(idxNum int, idxStr string, vals []interface{}) error { + vc.index = 0 + return nil +} + +func (vc *ghRepoCursor) Next() error { + vc.index++ + return nil +} + +func (vc *ghRepoCursor) EOF() bool { + return vc.index >= len(vc.repos) +} + +func (vc *ghRepoCursor) Rowid() (int64, error) { + return int64(vc.index), nil +} + +func (vc *ghRepoCursor) Close() error { + return nil +} -- cgit v1.2.3 From 9efa963d05cac8b780d1cb3abbd8493a94f1db82 Mon Sep 17 00:00:00 2001 From: Conor Branagan Date: Sat, 4 Mar 2017 18:15:00 -0500 Subject: [vtable] Rename Context to SQLiteContext To not conflict with core "context" package naming. --- _example/vtable/vtable.go | 4 +- context.go | 103 ---------------------------------------------- sqlite_context.go | 103 ++++++++++++++++++++++++++++++++++++++++++++++ vtable.go | 4 +- vtable_test.go | 2 +- 5 files changed, 108 insertions(+), 108 deletions(-) delete mode 100644 context.go create mode 100644 sqlite_context.go (limited to '_example/vtable/vtable.go') diff --git a/_example/vtable/vtable.go b/_example/vtable/vtable.go index cc0f308..13e2624 100644 --- a/_example/vtable/vtable.go +++ b/_example/vtable/vtable.go @@ -3,7 +3,7 @@ package main import ( "encoding/json" "fmt" - "github.com/mattn/go-sqlite3" + "github.com/DataDog/go-sqlite3" "io/ioutil" "net/http" ) @@ -73,7 +73,7 @@ type ghRepoCursor struct { repos []GithubRepo } -func (vc *ghRepoCursor) Column(c *sqlite3.Context, col int) error { +func (vc *ghRepoCursor) Column(c *sqlite3.SQLiteContext, col int) error { switch col { case 0: c.ResultInt(vc.repos[vc.index].ID) diff --git a/context.go b/context.go deleted file mode 100644 index ba943da..0000000 --- a/context.go +++ /dev/null @@ -1,103 +0,0 @@ -// Copyright (C) 2014 Yasuhiro Matsumoto . -// -// Use of this source code is governed by an MIT-style -// license that can be found in the LICENSE file. - -package sqlite3 - -/* - -#ifndef USE_LIBSQLITE3 -#include -#else -#include -#endif -#include -// These wrappers are necessary because SQLITE_TRANSIENT -// is a pointer constant, and cgo doesn't translate them correctly. - -static inline void my_result_text(sqlite3_context *ctx, char *p, int np) { - sqlite3_result_text(ctx, p, np, SQLITE_TRANSIENT); -} - -static inline void my_result_blob(sqlite3_context *ctx, void *p, int np) { - sqlite3_result_blob(ctx, p, np, SQLITE_TRANSIENT); -} -*/ -import "C" - -import ( - "math" - "reflect" - "unsafe" -) - -const i64 = unsafe.Sizeof(int(0)) > 4 - -type ZeroBlobLength int32 -type Context C.sqlite3_context - -// ResultBool sets the result of an SQL function. -func (c *Context) ResultBool(b bool) { - if b { - c.ResultInt(1) - } else { - c.ResultInt(0) - } -} - -// ResultBlob sets the result of an SQL function. -// See: sqlite3_result_blob, http://sqlite.org/c3ref/result_blob.html -func (c *Context) ResultBlob(b []byte) { - if i64 && len(b) > math.MaxInt32 { - C.sqlite3_result_error_toobig((*C.sqlite3_context)(c)) - return - } - var p *byte - if len(b) > 0 { - p = &b[0] - } - C.my_result_blob((*C.sqlite3_context)(c), unsafe.Pointer(p), C.int(len(b))) -} - -// ResultDouble sets the result of an SQL function. -// See: sqlite3_result_double, http://sqlite.org/c3ref/result_blob.html -func (c *Context) ResultDouble(d float64) { - C.sqlite3_result_double((*C.sqlite3_context)(c), C.double(d)) -} - -// ResultInt sets the result of an SQL function. -// See: sqlite3_result_int, http://sqlite.org/c3ref/result_blob.html -func (c *Context) ResultInt(i int) { - if i64 && (i > math.MaxInt32 || i < math.MinInt32) { - C.sqlite3_result_int64((*C.sqlite3_context)(c), C.sqlite3_int64(i)) - } else { - C.sqlite3_result_int((*C.sqlite3_context)(c), C.int(i)) - } -} - -// ResultInt64 sets the result of an SQL function. -// See: sqlite3_result_int64, http://sqlite.org/c3ref/result_blob.html -func (c *Context) ResultInt64(i int64) { - C.sqlite3_result_int64((*C.sqlite3_context)(c), C.sqlite3_int64(i)) -} - -// ResultNull sets the result of an SQL function. -// See: sqlite3_result_null, http://sqlite.org/c3ref/result_blob.html -func (c *Context) ResultNull() { - C.sqlite3_result_null((*C.sqlite3_context)(c)) -} - -// ResultText sets the result of an SQL function. -// See: sqlite3_result_text, http://sqlite.org/c3ref/result_blob.html -func (c *Context) ResultText(s string) { - h := (*reflect.StringHeader)(unsafe.Pointer(&s)) - cs, l := (*C.char)(unsafe.Pointer(h.Data)), C.int(h.Len) - C.my_result_text((*C.sqlite3_context)(c), cs, l) -} - -// ResultZeroblob sets the result of an SQL function. -// See: sqlite3_result_zeroblob, http://sqlite.org/c3ref/result_blob.html -func (c *Context) ResultZeroblob(n ZeroBlobLength) { - C.sqlite3_result_zeroblob((*C.sqlite3_context)(c), C.int(n)) -} diff --git a/sqlite_context.go b/sqlite_context.go new file mode 100644 index 0000000..7652902 --- /dev/null +++ b/sqlite_context.go @@ -0,0 +1,103 @@ +// Copyright (C) 2014 Yasuhiro Matsumoto . +// +// Use of this source code is governed by an MIT-style +// license that can be found in the LICENSE file. + +package sqlite3 + +/* + +#ifndef USE_LIBSQLITE3 +#include +#else +#include +#endif +#include +// These wrappers are necessary because SQLITE_TRANSIENT +// is a pointer constant, and cgo doesn't translate them correctly. + +static inline void my_result_text(sqlite3_context *ctx, char *p, int np) { + sqlite3_result_text(ctx, p, np, SQLITE_TRANSIENT); +} + +static inline void my_result_blob(sqlite3_context *ctx, void *p, int np) { + sqlite3_result_blob(ctx, p, np, SQLITE_TRANSIENT); +} +*/ +import "C" + +import ( + "math" + "reflect" + "unsafe" +) + +const i64 = unsafe.Sizeof(int(0)) > 4 + +type ZeroBlobLength int32 +type SQLiteContext C.sqlite3_context + +// ResultBool sets the result of an SQL function. +func (c *SQLiteContext) ResultBool(b bool) { + if b { + c.ResultInt(1) + } else { + c.ResultInt(0) + } +} + +// ResultBlob sets the result of an SQL function. +// See: sqlite3_result_blob, http://sqlite.org/c3ref/result_blob.html +func (c *SQLiteContext) ResultBlob(b []byte) { + if i64 && len(b) > math.MaxInt32 { + C.sqlite3_result_error_toobig((*C.sqlite3_context)(c)) + return + } + var p *byte + if len(b) > 0 { + p = &b[0] + } + C.my_result_blob((*C.sqlite3_context)(c), unsafe.Pointer(p), C.int(len(b))) +} + +// ResultDouble sets the result of an SQL function. +// See: sqlite3_result_double, http://sqlite.org/c3ref/result_blob.html +func (c *SQLiteContext) ResultDouble(d float64) { + C.sqlite3_result_double((*C.sqlite3_context)(c), C.double(d)) +} + +// ResultInt sets the result of an SQL function. +// See: sqlite3_result_int, http://sqlite.org/c3ref/result_blob.html +func (c *SQLiteContext) ResultInt(i int) { + if i64 && (i > math.MaxInt32 || i < math.MinInt32) { + C.sqlite3_result_int64((*C.sqlite3_context)(c), C.sqlite3_int64(i)) + } else { + C.sqlite3_result_int((*C.sqlite3_context)(c), C.int(i)) + } +} + +// ResultInt64 sets the result of an SQL function. +// See: sqlite3_result_int64, http://sqlite.org/c3ref/result_blob.html +func (c *SQLiteContext) ResultInt64(i int64) { + C.sqlite3_result_int64((*C.sqlite3_context)(c), C.sqlite3_int64(i)) +} + +// ResultNull sets the result of an SQL function. +// See: sqlite3_result_null, http://sqlite.org/c3ref/result_blob.html +func (c *SQLiteContext) ResultNull() { + C.sqlite3_result_null((*C.sqlite3_context)(c)) +} + +// ResultText sets the result of an SQL function. +// See: sqlite3_result_text, http://sqlite.org/c3ref/result_blob.html +func (c *SQLiteContext) ResultText(s string) { + h := (*reflect.StringHeader)(unsafe.Pointer(&s)) + cs, l := (*C.char)(unsafe.Pointer(h.Data)), C.int(h.Len) + C.my_result_text((*C.sqlite3_context)(c), cs, l) +} + +// ResultZeroblob sets the result of an SQL function. +// See: sqlite3_result_zeroblob, http://sqlite.org/c3ref/result_blob.html +func (c *SQLiteContext) ResultZeroblob(n ZeroBlobLength) { + C.sqlite3_result_zeroblob((*C.sqlite3_context)(c), C.int(n)) +} diff --git a/vtable.go b/vtable.go index 907e2dc..40ce2ea 100644 --- a/vtable.go +++ b/vtable.go @@ -294,7 +294,7 @@ func goVEof(pCursor unsafe.Pointer) C.int { //export goVColumn func goVColumn(pCursor, cp unsafe.Pointer, col int) *C.char { vtc := lookupHandle(uintptr(pCursor)).(*sqliteVTabCursor) - c := (*Context)(cp) + c := (*SQLiteContext)(cp) err := vtc.vTabCursor.Column(c, col) if err != nil { return mPrintf("%s", err.Error()) @@ -349,7 +349,7 @@ type VTabCursor interface { // http://sqlite.org/vtab.html#xeof EOF() bool // http://sqlite.org/vtab.html#xcolumn - Column(c *Context, col int) error + Column(c *SQLiteContext, col int) error // http://sqlite.org/vtab.html#xrowid Rowid() (int64, error) } diff --git a/vtable_test.go b/vtable_test.go index 4c7efcb..9b97927 100644 --- a/vtable_test.go +++ b/vtable_test.go @@ -94,7 +94,7 @@ func (vc *testVTabCursor) EOF() bool { return vc.index >= len(vc.vTab.intarray) } -func (vc *testVTabCursor) Column(c *Context, col int) error { +func (vc *testVTabCursor) Column(c *SQLiteContext, col int) error { if col != 0 { return fmt.Errorf("column index out of bounds: %d", col) } -- cgit v1.2.3