sqlite3_vtable.go 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646
  1. // Copyright (C) 2014 Yasuhiro Matsumoto <mattn.jp@gmail.com>.
  2. //
  3. // Use of this source code is governed by an MIT-style
  4. // license that can be found in the LICENSE file.
  5. // +build vtable
  6. package sqlite3
  7. /*
  8. #cgo CFLAGS: -std=gnu99
  9. #cgo CFLAGS: -DSQLITE_ENABLE_RTREE -DSQLITE_THREADSAFE
  10. #cgo CFLAGS: -DSQLITE_ENABLE_FTS3 -DSQLITE_ENABLE_FTS3_PARENTHESIS -DSQLITE_ENABLE_FTS4_UNICODE61
  11. #cgo CFLAGS: -DSQLITE_TRACE_SIZE_LIMIT=15
  12. #cgo CFLAGS: -DSQLITE_ENABLE_COLUMN_METADATA=1
  13. #cgo CFLAGS: -Wno-deprecated-declarations
  14. #ifndef USE_LIBSQLITE3
  15. #include <sqlite3-binding.h>
  16. #else
  17. #include <sqlite3.h>
  18. #endif
  19. #include <stdlib.h>
  20. #include <stdint.h>
  21. #include <memory.h>
  22. static inline char *_sqlite3_mprintf(char *zFormat, char *arg) {
  23. return sqlite3_mprintf(zFormat, arg);
  24. }
  25. typedef struct goVTab goVTab;
  26. struct goVTab {
  27. sqlite3_vtab base;
  28. void *vTab;
  29. };
  30. uintptr_t goMInit(void *db, void *pAux, int argc, char **argv, char **pzErr, int isCreate);
  31. static int cXInit(sqlite3 *db, void *pAux, int argc, const char *const*argv, sqlite3_vtab **ppVTab, char **pzErr, int isCreate) {
  32. void *vTab = (void *)goMInit(db, pAux, argc, (char**)argv, pzErr, isCreate);
  33. if (!vTab || *pzErr) {
  34. return SQLITE_ERROR;
  35. }
  36. goVTab *pvTab = (goVTab *)sqlite3_malloc(sizeof(goVTab));
  37. if (!pvTab) {
  38. *pzErr = sqlite3_mprintf("%s", "Out of memory");
  39. return SQLITE_NOMEM;
  40. }
  41. memset(pvTab, 0, sizeof(goVTab));
  42. pvTab->vTab = vTab;
  43. *ppVTab = (sqlite3_vtab *)pvTab;
  44. *pzErr = 0;
  45. return SQLITE_OK;
  46. }
  47. static inline int cXCreate(sqlite3 *db, void *pAux, int argc, const char *const*argv, sqlite3_vtab **ppVTab, char **pzErr) {
  48. return cXInit(db, pAux, argc, argv, ppVTab, pzErr, 1);
  49. }
  50. static inline int cXConnect(sqlite3 *db, void *pAux, int argc, const char *const*argv, sqlite3_vtab **ppVTab, char **pzErr) {
  51. return cXInit(db, pAux, argc, argv, ppVTab, pzErr, 0);
  52. }
  53. char* goVBestIndex(void *pVTab, void *icp);
  54. static inline int cXBestIndex(sqlite3_vtab *pVTab, sqlite3_index_info *info) {
  55. char *pzErr = goVBestIndex(((goVTab*)pVTab)->vTab, info);
  56. if (pzErr) {
  57. if (pVTab->zErrMsg)
  58. sqlite3_free(pVTab->zErrMsg);
  59. pVTab->zErrMsg = pzErr;
  60. return SQLITE_ERROR;
  61. }
  62. return SQLITE_OK;
  63. }
  64. char* goVRelease(void *pVTab, int isDestroy);
  65. static int cXRelease(sqlite3_vtab *pVTab, int isDestroy) {
  66. char *pzErr = goVRelease(((goVTab*)pVTab)->vTab, isDestroy);
  67. if (pzErr) {
  68. if (pVTab->zErrMsg)
  69. sqlite3_free(pVTab->zErrMsg);
  70. pVTab->zErrMsg = pzErr;
  71. return SQLITE_ERROR;
  72. }
  73. if (pVTab->zErrMsg)
  74. sqlite3_free(pVTab->zErrMsg);
  75. sqlite3_free(pVTab);
  76. return SQLITE_OK;
  77. }
  78. static inline int cXDisconnect(sqlite3_vtab *pVTab) {
  79. return cXRelease(pVTab, 0);
  80. }
  81. static inline int cXDestroy(sqlite3_vtab *pVTab) {
  82. return cXRelease(pVTab, 1);
  83. }
  84. typedef struct goVTabCursor goVTabCursor;
  85. struct goVTabCursor {
  86. sqlite3_vtab_cursor base;
  87. void *vTabCursor;
  88. };
  89. uintptr_t goVOpen(void *pVTab, char **pzErr);
  90. static int cXOpen(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor) {
  91. void *vTabCursor = (void *)goVOpen(((goVTab*)pVTab)->vTab, &(pVTab->zErrMsg));
  92. goVTabCursor *pCursor = (goVTabCursor *)sqlite3_malloc(sizeof(goVTabCursor));
  93. if (!pCursor) {
  94. return SQLITE_NOMEM;
  95. }
  96. memset(pCursor, 0, sizeof(goVTabCursor));
  97. pCursor->vTabCursor = vTabCursor;
  98. *ppCursor = (sqlite3_vtab_cursor *)pCursor;
  99. return SQLITE_OK;
  100. }
  101. static int setErrMsg(sqlite3_vtab_cursor *pCursor, char *pzErr) {
  102. if (pCursor->pVtab->zErrMsg)
  103. sqlite3_free(pCursor->pVtab->zErrMsg);
  104. pCursor->pVtab->zErrMsg = pzErr;
  105. return SQLITE_ERROR;
  106. }
  107. char* goVClose(void *pCursor);
  108. static int cXClose(sqlite3_vtab_cursor *pCursor) {
  109. char *pzErr = goVClose(((goVTabCursor*)pCursor)->vTabCursor);
  110. if (pzErr) {
  111. return setErrMsg(pCursor, pzErr);
  112. }
  113. sqlite3_free(pCursor);
  114. return SQLITE_OK;
  115. }
  116. char* goVFilter(void *pCursor, int idxNum, char* idxName, int argc, sqlite3_value **argv);
  117. static int cXFilter(sqlite3_vtab_cursor *pCursor, int idxNum, const char *idxStr, int argc, sqlite3_value **argv) {
  118. char *pzErr = goVFilter(((goVTabCursor*)pCursor)->vTabCursor, idxNum, (char*)idxStr, argc, argv);
  119. if (pzErr) {
  120. return setErrMsg(pCursor, pzErr);
  121. }
  122. return SQLITE_OK;
  123. }
  124. char* goVNext(void *pCursor);
  125. static int cXNext(sqlite3_vtab_cursor *pCursor) {
  126. char *pzErr = goVNext(((goVTabCursor*)pCursor)->vTabCursor);
  127. if (pzErr) {
  128. return setErrMsg(pCursor, pzErr);
  129. }
  130. return SQLITE_OK;
  131. }
  132. int goVEof(void *pCursor);
  133. static inline int cXEof(sqlite3_vtab_cursor *pCursor) {
  134. return goVEof(((goVTabCursor*)pCursor)->vTabCursor);
  135. }
  136. char* goVColumn(void *pCursor, void *cp, int col);
  137. static int cXColumn(sqlite3_vtab_cursor *pCursor, sqlite3_context *ctx, int i) {
  138. char *pzErr = goVColumn(((goVTabCursor*)pCursor)->vTabCursor, ctx, i);
  139. if (pzErr) {
  140. return setErrMsg(pCursor, pzErr);
  141. }
  142. return SQLITE_OK;
  143. }
  144. char* goVRowid(void *pCursor, sqlite3_int64 *pRowid);
  145. static int cXRowid(sqlite3_vtab_cursor *pCursor, sqlite3_int64 *pRowid) {
  146. char *pzErr = goVRowid(((goVTabCursor*)pCursor)->vTabCursor, pRowid);
  147. if (pzErr) {
  148. return setErrMsg(pCursor, pzErr);
  149. }
  150. return SQLITE_OK;
  151. }
  152. char* goVUpdate(void *pVTab, int argc, sqlite3_value **argv, sqlite3_int64 *pRowid);
  153. static int cXUpdate(sqlite3_vtab *pVTab, int argc, sqlite3_value **argv, sqlite3_int64 *pRowid) {
  154. char *pzErr = goVUpdate(((goVTab*)pVTab)->vTab, argc, argv, pRowid);
  155. if (pzErr) {
  156. if (pVTab->zErrMsg)
  157. sqlite3_free(pVTab->zErrMsg);
  158. pVTab->zErrMsg = pzErr;
  159. return SQLITE_ERROR;
  160. }
  161. return SQLITE_OK;
  162. }
  163. static sqlite3_module goModule = {
  164. 0, // iVersion
  165. cXCreate, // xCreate - create a table
  166. cXConnect, // xConnect - connect to an existing table
  167. cXBestIndex, // xBestIndex - Determine search strategy
  168. cXDisconnect, // xDisconnect - Disconnect from a table
  169. cXDestroy, // xDestroy - Drop a table
  170. cXOpen, // xOpen - open a cursor
  171. cXClose, // xClose - close a cursor
  172. cXFilter, // xFilter - configure scan constraints
  173. cXNext, // xNext - advance a cursor
  174. cXEof, // xEof
  175. cXColumn, // xColumn - read data
  176. cXRowid, // xRowid - read data
  177. cXUpdate, // xUpdate - write data
  178. // Not implemented
  179. 0, // xBegin - begin transaction
  180. 0, // xSync - sync transaction
  181. 0, // xCommit - commit transaction
  182. 0, // xRollback - rollback transaction
  183. 0, // xFindFunction - function overloading
  184. 0, // xRename - rename the table
  185. 0, // xSavepoint
  186. 0, // xRelease
  187. 0 // xRollbackTo
  188. };
  189. void goMDestroy(void*);
  190. static int _sqlite3_create_module(sqlite3 *db, const char *zName, uintptr_t pClientData) {
  191. return sqlite3_create_module_v2(db, zName, &goModule, (void*) pClientData, goMDestroy);
  192. }
  193. */
  194. import "C"
  195. import (
  196. "fmt"
  197. "math"
  198. "reflect"
  199. "unsafe"
  200. )
  201. type sqliteModule struct {
  202. c *SQLiteConn
  203. name string
  204. module Module
  205. }
  206. type sqliteVTab struct {
  207. module *sqliteModule
  208. vTab VTab
  209. }
  210. type sqliteVTabCursor struct {
  211. vTab *sqliteVTab
  212. vTabCursor VTabCursor
  213. }
  214. // Op is type of operations.
  215. type Op uint8
  216. // Op mean identity of operations.
  217. const (
  218. OpEQ Op = 2
  219. OpGT = 4
  220. OpLE = 8
  221. OpLT = 16
  222. OpGE = 32
  223. OpMATCH = 64
  224. OpLIKE = 65 /* 3.10.0 and later only */
  225. OpGLOB = 66 /* 3.10.0 and later only */
  226. OpREGEXP = 67 /* 3.10.0 and later only */
  227. OpScanUnique = 1 /* Scan visits at most 1 row */
  228. )
  229. // InfoConstraint give information of constraint.
  230. type InfoConstraint struct {
  231. Column int
  232. Op Op
  233. Usable bool
  234. }
  235. // InfoOrderBy give information of order-by.
  236. type InfoOrderBy struct {
  237. Column int
  238. Desc bool
  239. }
  240. func constraints(info *C.sqlite3_index_info) []InfoConstraint {
  241. l := info.nConstraint
  242. slice := (*[1 << 30]C.struct_sqlite3_index_constraint)(unsafe.Pointer(info.aConstraint))[:l:l]
  243. cst := make([]InfoConstraint, 0, l)
  244. for _, c := range slice {
  245. var usable bool
  246. if c.usable > 0 {
  247. usable = true
  248. }
  249. cst = append(cst, InfoConstraint{
  250. Column: int(c.iColumn),
  251. Op: Op(c.op),
  252. Usable: usable,
  253. })
  254. }
  255. return cst
  256. }
  257. func orderBys(info *C.sqlite3_index_info) []InfoOrderBy {
  258. l := info.nOrderBy
  259. slice := (*[1 << 30]C.struct_sqlite3_index_orderby)(unsafe.Pointer(info.aOrderBy))[:l:l]
  260. ob := make([]InfoOrderBy, 0, l)
  261. for _, c := range slice {
  262. var desc bool
  263. if c.desc > 0 {
  264. desc = true
  265. }
  266. ob = append(ob, InfoOrderBy{
  267. Column: int(c.iColumn),
  268. Desc: desc,
  269. })
  270. }
  271. return ob
  272. }
  273. // IndexResult is a Go struct representation of what eventually ends up in the
  274. // output fields for `sqlite3_index_info`
  275. // See: https://www.sqlite.org/c3ref/index_info.html
  276. type IndexResult struct {
  277. Used []bool // aConstraintUsage
  278. IdxNum int
  279. IdxStr string
  280. AlreadyOrdered bool // orderByConsumed
  281. EstimatedCost float64
  282. EstimatedRows float64
  283. }
  284. // mPrintf is a utility wrapper around sqlite3_mprintf
  285. func mPrintf(format, arg string) *C.char {
  286. cf := C.CString(format)
  287. defer C.free(unsafe.Pointer(cf))
  288. ca := C.CString(arg)
  289. defer C.free(unsafe.Pointer(ca))
  290. return C._sqlite3_mprintf(cf, ca)
  291. }
  292. //export goMInit
  293. func goMInit(db, pClientData unsafe.Pointer, argc C.int, argv **C.char, pzErr **C.char, isCreate C.int) C.uintptr_t {
  294. m := lookupHandle(uintptr(pClientData)).(*sqliteModule)
  295. if m.c.db != (*C.sqlite3)(db) {
  296. *pzErr = mPrintf("%s", "Inconsistent db handles")
  297. return 0
  298. }
  299. args := make([]string, argc)
  300. var A []*C.char
  301. slice := reflect.SliceHeader{Data: uintptr(unsafe.Pointer(argv)), Len: int(argc), Cap: int(argc)}
  302. a := reflect.NewAt(reflect.TypeOf(A), unsafe.Pointer(&slice)).Elem().Interface()
  303. for i, s := range a.([]*C.char) {
  304. args[i] = C.GoString(s)
  305. }
  306. var vTab VTab
  307. var err error
  308. if isCreate == 1 {
  309. vTab, err = m.module.Create(m.c, args)
  310. } else {
  311. vTab, err = m.module.Connect(m.c, args)
  312. }
  313. if err != nil {
  314. *pzErr = mPrintf("%s", err.Error())
  315. return 0
  316. }
  317. vt := sqliteVTab{m, vTab}
  318. *pzErr = nil
  319. return C.uintptr_t(newHandle(m.c, &vt))
  320. }
  321. //export goVRelease
  322. func goVRelease(pVTab unsafe.Pointer, isDestroy C.int) *C.char {
  323. vt := lookupHandle(uintptr(pVTab)).(*sqliteVTab)
  324. var err error
  325. if isDestroy == 1 {
  326. err = vt.vTab.Destroy()
  327. } else {
  328. err = vt.vTab.Disconnect()
  329. }
  330. if err != nil {
  331. return mPrintf("%s", err.Error())
  332. }
  333. return nil
  334. }
  335. //export goVOpen
  336. func goVOpen(pVTab unsafe.Pointer, pzErr **C.char) C.uintptr_t {
  337. vt := lookupHandle(uintptr(pVTab)).(*sqliteVTab)
  338. vTabCursor, err := vt.vTab.Open()
  339. if err != nil {
  340. *pzErr = mPrintf("%s", err.Error())
  341. return 0
  342. }
  343. vtc := sqliteVTabCursor{vt, vTabCursor}
  344. *pzErr = nil
  345. return C.uintptr_t(newHandle(vt.module.c, &vtc))
  346. }
  347. //export goVBestIndex
  348. func goVBestIndex(pVTab unsafe.Pointer, icp unsafe.Pointer) *C.char {
  349. vt := lookupHandle(uintptr(pVTab)).(*sqliteVTab)
  350. info := (*C.sqlite3_index_info)(icp)
  351. csts := constraints(info)
  352. res, err := vt.vTab.BestIndex(csts, orderBys(info))
  353. if err != nil {
  354. return mPrintf("%s", err.Error())
  355. }
  356. if len(res.Used) != len(csts) {
  357. return mPrintf("Result.Used != expected value", "")
  358. }
  359. // Get a pointer to constraint_usage struct so we can update in place.
  360. l := info.nConstraint
  361. s := (*[1 << 30]C.struct_sqlite3_index_constraint_usage)(unsafe.Pointer(info.aConstraintUsage))[:l:l]
  362. index := 1
  363. for i := C.int(0); i < info.nConstraint; i++ {
  364. if res.Used[i] {
  365. s[i].argvIndex = C.int(index)
  366. s[i].omit = C.uchar(1)
  367. index++
  368. }
  369. }
  370. info.idxNum = C.int(res.IdxNum)
  371. idxStr := C.CString(res.IdxStr)
  372. defer C.free(unsafe.Pointer(idxStr))
  373. info.idxStr = idxStr
  374. info.needToFreeIdxStr = C.int(0)
  375. if res.AlreadyOrdered {
  376. info.orderByConsumed = C.int(1)
  377. }
  378. info.estimatedCost = C.double(res.EstimatedCost)
  379. info.estimatedRows = C.sqlite3_int64(res.EstimatedRows)
  380. return nil
  381. }
  382. //export goVClose
  383. func goVClose(pCursor unsafe.Pointer) *C.char {
  384. vtc := lookupHandle(uintptr(pCursor)).(*sqliteVTabCursor)
  385. err := vtc.vTabCursor.Close()
  386. if err != nil {
  387. return mPrintf("%s", err.Error())
  388. }
  389. return nil
  390. }
  391. //export goMDestroy
  392. func goMDestroy(pClientData unsafe.Pointer) {
  393. m := lookupHandle(uintptr(pClientData)).(*sqliteModule)
  394. m.module.DestroyModule()
  395. }
  396. //export goVFilter
  397. func goVFilter(pCursor unsafe.Pointer, idxNum C.int, idxName *C.char, argc C.int, argv **C.sqlite3_value) *C.char {
  398. vtc := lookupHandle(uintptr(pCursor)).(*sqliteVTabCursor)
  399. args := (*[(math.MaxInt32 - 1) / unsafe.Sizeof((*C.sqlite3_value)(nil))]*C.sqlite3_value)(unsafe.Pointer(argv))[:argc:argc]
  400. vals := make([]interface{}, 0, argc)
  401. for _, v := range args {
  402. conv, err := callbackArgGeneric(v)
  403. if err != nil {
  404. return mPrintf("%s", err.Error())
  405. }
  406. vals = append(vals, conv.Interface())
  407. }
  408. err := vtc.vTabCursor.Filter(int(idxNum), C.GoString(idxName), vals)
  409. if err != nil {
  410. return mPrintf("%s", err.Error())
  411. }
  412. return nil
  413. }
  414. //export goVNext
  415. func goVNext(pCursor unsafe.Pointer) *C.char {
  416. vtc := lookupHandle(uintptr(pCursor)).(*sqliteVTabCursor)
  417. err := vtc.vTabCursor.Next()
  418. if err != nil {
  419. return mPrintf("%s", err.Error())
  420. }
  421. return nil
  422. }
  423. //export goVEof
  424. func goVEof(pCursor unsafe.Pointer) C.int {
  425. vtc := lookupHandle(uintptr(pCursor)).(*sqliteVTabCursor)
  426. err := vtc.vTabCursor.EOF()
  427. if err {
  428. return 1
  429. }
  430. return 0
  431. }
  432. //export goVColumn
  433. func goVColumn(pCursor, cp unsafe.Pointer, col C.int) *C.char {
  434. vtc := lookupHandle(uintptr(pCursor)).(*sqliteVTabCursor)
  435. c := (*SQLiteContext)(cp)
  436. err := vtc.vTabCursor.Column(c, int(col))
  437. if err != nil {
  438. return mPrintf("%s", err.Error())
  439. }
  440. return nil
  441. }
  442. //export goVRowid
  443. func goVRowid(pCursor unsafe.Pointer, pRowid *C.sqlite3_int64) *C.char {
  444. vtc := lookupHandle(uintptr(pCursor)).(*sqliteVTabCursor)
  445. rowid, err := vtc.vTabCursor.Rowid()
  446. if err != nil {
  447. return mPrintf("%s", err.Error())
  448. }
  449. *pRowid = C.sqlite3_int64(rowid)
  450. return nil
  451. }
  452. //export goVUpdate
  453. func goVUpdate(pVTab unsafe.Pointer, argc C.int, argv **C.sqlite3_value, pRowid *C.sqlite3_int64) *C.char {
  454. vt := lookupHandle(uintptr(pVTab)).(*sqliteVTab)
  455. var tname string
  456. if n, ok := vt.vTab.(interface {
  457. TableName() string
  458. }); ok {
  459. tname = n.TableName() + " "
  460. }
  461. err := fmt.Errorf("virtual %s table %sis read-only", vt.module.name, tname)
  462. if v, ok := vt.vTab.(VTabUpdater); ok {
  463. // convert argv
  464. args := (*[(math.MaxInt32 - 1) / unsafe.Sizeof((*C.sqlite3_value)(nil))]*C.sqlite3_value)(unsafe.Pointer(argv))[:argc:argc]
  465. vals := make([]interface{}, 0, argc)
  466. for _, v := range args {
  467. conv, err := callbackArgGeneric(v)
  468. if err != nil {
  469. return mPrintf("%s", err.Error())
  470. }
  471. // work around for SQLITE_NULL
  472. x := conv.Interface()
  473. if z, ok := x.([]byte); ok && z == nil {
  474. x = nil
  475. }
  476. vals = append(vals, x)
  477. }
  478. switch {
  479. case argc == 1:
  480. err = v.Delete(vals[0])
  481. case argc > 1 && vals[0] == nil:
  482. var id int64
  483. id, err = v.Insert(vals[1], vals[2:])
  484. if err == nil {
  485. *pRowid = C.sqlite3_int64(id)
  486. }
  487. case argc > 1:
  488. err = v.Update(vals[1], vals[2:])
  489. }
  490. }
  491. if err != nil {
  492. return mPrintf("%s", err.Error())
  493. }
  494. return nil
  495. }
  496. // Module is a "virtual table module", it defines the implementation of a
  497. // virtual tables. See: http://sqlite.org/c3ref/module.html
  498. type Module interface {
  499. // http://sqlite.org/vtab.html#xcreate
  500. Create(c *SQLiteConn, args []string) (VTab, error)
  501. // http://sqlite.org/vtab.html#xconnect
  502. Connect(c *SQLiteConn, args []string) (VTab, error)
  503. // http://sqlite.org/c3ref/create_module.html
  504. DestroyModule()
  505. }
  506. // VTab describes a particular instance of the virtual table.
  507. // See: http://sqlite.org/c3ref/vtab.html
  508. type VTab interface {
  509. // http://sqlite.org/vtab.html#xbestindex
  510. BestIndex([]InfoConstraint, []InfoOrderBy) (*IndexResult, error)
  511. // http://sqlite.org/vtab.html#xdisconnect
  512. Disconnect() error
  513. // http://sqlite.org/vtab.html#sqlite3_module.xDestroy
  514. Destroy() error
  515. // http://sqlite.org/vtab.html#xopen
  516. Open() (VTabCursor, error)
  517. }
  518. // VTabUpdater is a type that allows a VTab to be inserted, updated, or
  519. // deleted.
  520. // See: https://sqlite.org/vtab.html#xupdate
  521. type VTabUpdater interface {
  522. Delete(interface{}) error
  523. Insert(interface{}, []interface{}) (int64, error)
  524. Update(interface{}, []interface{}) error
  525. }
  526. // VTabCursor describes cursors that point into the virtual table and are used
  527. // to loop through the virtual table. See: http://sqlite.org/c3ref/vtab_cursor.html
  528. type VTabCursor interface {
  529. // http://sqlite.org/vtab.html#xclose
  530. Close() error
  531. // http://sqlite.org/vtab.html#xfilter
  532. Filter(idxNum int, idxStr string, vals []interface{}) error
  533. // http://sqlite.org/vtab.html#xnext
  534. Next() error
  535. // http://sqlite.org/vtab.html#xeof
  536. EOF() bool
  537. // http://sqlite.org/vtab.html#xcolumn
  538. Column(c *SQLiteContext, col int) error
  539. // http://sqlite.org/vtab.html#xrowid
  540. Rowid() (int64, error)
  541. }
  542. // DeclareVTab declares the Schema of a virtual table.
  543. // See: http://sqlite.org/c3ref/declare_vtab.html
  544. func (c *SQLiteConn) DeclareVTab(sql string) error {
  545. zSQL := C.CString(sql)
  546. defer C.free(unsafe.Pointer(zSQL))
  547. rv := C.sqlite3_declare_vtab(c.db, zSQL)
  548. if rv != C.SQLITE_OK {
  549. return c.lastError()
  550. }
  551. return nil
  552. }
  553. // CreateModule registers a virtual table implementation.
  554. // See: http://sqlite.org/c3ref/create_module.html
  555. func (c *SQLiteConn) CreateModule(moduleName string, module Module) error {
  556. mname := C.CString(moduleName)
  557. defer C.free(unsafe.Pointer(mname))
  558. udm := sqliteModule{c, moduleName, module}
  559. rv := C._sqlite3_create_module(c.db, mname, C.uintptr_t(newHandle(c, &udm)))
  560. if rv != C.SQLITE_OK {
  561. return c.lastError()
  562. }
  563. return nil
  564. }