sqlite3_opt_vtable.go 18 KB

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