sqlite3_opt_vtable.go 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709
  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. // See https://sqlite.org/vtab.html#eponymous_only_virtual_tables
  193. static sqlite3_module goModuleEponymousOnly = {
  194. 0, // iVersion
  195. 0, // xCreate - create a table, which here is null
  196. cXConnect, // xConnect - connect to an existing table
  197. cXBestIndex, // xBestIndex - Determine search strategy
  198. cXDisconnect, // xDisconnect - Disconnect from a table
  199. cXDestroy, // xDestroy - Drop a table
  200. cXOpen, // xOpen - open a cursor
  201. cXClose, // xClose - close a cursor
  202. cXFilter, // xFilter - configure scan constraints
  203. cXNext, // xNext - advance a cursor
  204. cXEof, // xEof
  205. cXColumn, // xColumn - read data
  206. cXRowid, // xRowid - read data
  207. cXUpdate, // xUpdate - write data
  208. // Not implemented
  209. 0, // xBegin - begin transaction
  210. 0, // xSync - sync transaction
  211. 0, // xCommit - commit transaction
  212. 0, // xRollback - rollback transaction
  213. 0, // xFindFunction - function overloading
  214. 0, // xRename - rename the table
  215. 0, // xSavepoint
  216. 0, // xRelease
  217. 0 // xRollbackTo
  218. };
  219. void goMDestroy(void*);
  220. static int _sqlite3_create_module(sqlite3 *db, const char *zName, uintptr_t pClientData) {
  221. return sqlite3_create_module_v2(db, zName, &goModule, (void*) pClientData, goMDestroy);
  222. }
  223. static int _sqlite3_create_module_eponymous_only(sqlite3 *db, const char *zName, uintptr_t pClientData) {
  224. return sqlite3_create_module_v2(db, zName, &goModuleEponymousOnly, (void*) pClientData, goMDestroy);
  225. }
  226. */
  227. import "C"
  228. import (
  229. "fmt"
  230. "math"
  231. "reflect"
  232. "unsafe"
  233. )
  234. type sqliteModule struct {
  235. c *SQLiteConn
  236. name string
  237. module Module
  238. }
  239. type sqliteVTab struct {
  240. module *sqliteModule
  241. vTab VTab
  242. }
  243. type sqliteVTabCursor struct {
  244. vTab *sqliteVTab
  245. vTabCursor VTabCursor
  246. }
  247. // Op is type of operations.
  248. type Op uint8
  249. // Op mean identity of operations.
  250. const (
  251. OpEQ Op = 2
  252. OpGT = 4
  253. OpLE = 8
  254. OpLT = 16
  255. OpGE = 32
  256. OpMATCH = 64
  257. OpLIKE = 65 /* 3.10.0 and later only */
  258. OpGLOB = 66 /* 3.10.0 and later only */
  259. OpREGEXP = 67 /* 3.10.0 and later only */
  260. OpScanUnique = 1 /* Scan visits at most 1 row */
  261. )
  262. // InfoConstraint give information of constraint.
  263. type InfoConstraint struct {
  264. Column int
  265. Op Op
  266. Usable bool
  267. }
  268. // InfoOrderBy give information of order-by.
  269. type InfoOrderBy struct {
  270. Column int
  271. Desc bool
  272. }
  273. func constraints(info *C.sqlite3_index_info) []InfoConstraint {
  274. slice := *(*[]C.struct_sqlite3_index_constraint)(unsafe.Pointer(&reflect.SliceHeader{
  275. Data: uintptr(unsafe.Pointer(info.aConstraint)),
  276. Len: int(info.nConstraint),
  277. Cap: int(info.nConstraint),
  278. }))
  279. cst := make([]InfoConstraint, 0, len(slice))
  280. for _, c := range slice {
  281. var usable bool
  282. if c.usable > 0 {
  283. usable = true
  284. }
  285. cst = append(cst, InfoConstraint{
  286. Column: int(c.iColumn),
  287. Op: Op(c.op),
  288. Usable: usable,
  289. })
  290. }
  291. return cst
  292. }
  293. func orderBys(info *C.sqlite3_index_info) []InfoOrderBy {
  294. slice := *(*[]C.struct_sqlite3_index_orderby)(unsafe.Pointer(&reflect.SliceHeader{
  295. Data: uintptr(unsafe.Pointer(info.aOrderBy)),
  296. Len: int(info.nOrderBy),
  297. Cap: int(info.nOrderBy),
  298. }))
  299. ob := make([]InfoOrderBy, 0, len(slice))
  300. for _, c := range slice {
  301. var desc bool
  302. if c.desc > 0 {
  303. desc = true
  304. }
  305. ob = append(ob, InfoOrderBy{
  306. Column: int(c.iColumn),
  307. Desc: desc,
  308. })
  309. }
  310. return ob
  311. }
  312. // IndexResult is a Go struct representation of what eventually ends up in the
  313. // output fields for `sqlite3_index_info`
  314. // See: https://www.sqlite.org/c3ref/index_info.html
  315. type IndexResult struct {
  316. Used []bool // aConstraintUsage
  317. IdxNum int
  318. IdxStr string
  319. AlreadyOrdered bool // orderByConsumed
  320. EstimatedCost float64
  321. EstimatedRows float64
  322. }
  323. // mPrintf is a utility wrapper around sqlite3_mprintf
  324. func mPrintf(format, arg string) *C.char {
  325. cf := C.CString(format)
  326. defer C.free(unsafe.Pointer(cf))
  327. ca := C.CString(arg)
  328. defer C.free(unsafe.Pointer(ca))
  329. return C._sqlite3_mprintf(cf, ca)
  330. }
  331. //export goMInit
  332. func goMInit(db, pClientData unsafe.Pointer, argc C.int, argv **C.char, pzErr **C.char, isCreate C.int) C.uintptr_t {
  333. m := lookupHandle(pClientData).(*sqliteModule)
  334. if m.c.db != (*C.sqlite3)(db) {
  335. *pzErr = mPrintf("%s", "Inconsistent db handles")
  336. return 0
  337. }
  338. args := make([]string, argc)
  339. var A []*C.char
  340. slice := reflect.SliceHeader{Data: uintptr(unsafe.Pointer(argv)), Len: int(argc), Cap: int(argc)}
  341. a := reflect.NewAt(reflect.TypeOf(A), unsafe.Pointer(&slice)).Elem().Interface()
  342. for i, s := range a.([]*C.char) {
  343. args[i] = C.GoString(s)
  344. }
  345. var vTab VTab
  346. var err error
  347. if isCreate == 1 {
  348. vTab, err = m.module.Create(m.c, args)
  349. } else {
  350. vTab, err = m.module.Connect(m.c, args)
  351. }
  352. if err != nil {
  353. *pzErr = mPrintf("%s", err.Error())
  354. return 0
  355. }
  356. vt := sqliteVTab{m, vTab}
  357. *pzErr = nil
  358. return C.uintptr_t(uintptr(newHandle(m.c, &vt)))
  359. }
  360. //export goVRelease
  361. func goVRelease(pVTab unsafe.Pointer, isDestroy C.int) *C.char {
  362. vt := lookupHandle(pVTab).(*sqliteVTab)
  363. var err error
  364. if isDestroy == 1 {
  365. err = vt.vTab.Destroy()
  366. } else {
  367. err = vt.vTab.Disconnect()
  368. }
  369. if err != nil {
  370. return mPrintf("%s", err.Error())
  371. }
  372. return nil
  373. }
  374. //export goVOpen
  375. func goVOpen(pVTab unsafe.Pointer, pzErr **C.char) C.uintptr_t {
  376. vt := lookupHandle(pVTab).(*sqliteVTab)
  377. vTabCursor, err := vt.vTab.Open()
  378. if err != nil {
  379. *pzErr = mPrintf("%s", err.Error())
  380. return 0
  381. }
  382. vtc := sqliteVTabCursor{vt, vTabCursor}
  383. *pzErr = nil
  384. return C.uintptr_t(uintptr(newHandle(vt.module.c, &vtc)))
  385. }
  386. //export goVBestIndex
  387. func goVBestIndex(pVTab unsafe.Pointer, icp unsafe.Pointer) *C.char {
  388. vt := lookupHandle(pVTab).(*sqliteVTab)
  389. info := (*C.sqlite3_index_info)(icp)
  390. csts := constraints(info)
  391. res, err := vt.vTab.BestIndex(csts, orderBys(info))
  392. if err != nil {
  393. return mPrintf("%s", err.Error())
  394. }
  395. if len(res.Used) != len(csts) {
  396. return mPrintf("Result.Used != expected value", "")
  397. }
  398. // Get a pointer to constraint_usage struct so we can update in place.
  399. slice := *(*[]C.struct_sqlite3_index_constraint_usage)(unsafe.Pointer(&reflect.SliceHeader{
  400. Data: uintptr(unsafe.Pointer(info.aConstraintUsage)),
  401. Len: int(info.nConstraint),
  402. Cap: int(info.nConstraint),
  403. }))
  404. index := 1
  405. for i := range slice {
  406. if res.Used[i] {
  407. slice[i].argvIndex = C.int(index)
  408. slice[i].omit = C.uchar(1)
  409. index++
  410. }
  411. }
  412. info.idxNum = C.int(res.IdxNum)
  413. idxStr := C.CString(res.IdxStr)
  414. defer C.free(unsafe.Pointer(idxStr))
  415. info.idxStr = idxStr
  416. info.needToFreeIdxStr = C.int(0)
  417. if res.AlreadyOrdered {
  418. info.orderByConsumed = C.int(1)
  419. }
  420. info.estimatedCost = C.double(res.EstimatedCost)
  421. info.estimatedRows = C.sqlite3_int64(res.EstimatedRows)
  422. return nil
  423. }
  424. //export goVClose
  425. func goVClose(pCursor unsafe.Pointer) *C.char {
  426. vtc := lookupHandle(pCursor).(*sqliteVTabCursor)
  427. err := vtc.vTabCursor.Close()
  428. if err != nil {
  429. return mPrintf("%s", err.Error())
  430. }
  431. return nil
  432. }
  433. //export goMDestroy
  434. func goMDestroy(pClientData unsafe.Pointer) {
  435. m := lookupHandle(pClientData).(*sqliteModule)
  436. m.module.DestroyModule()
  437. }
  438. //export goVFilter
  439. func goVFilter(pCursor unsafe.Pointer, idxNum C.int, idxName *C.char, argc C.int, argv **C.sqlite3_value) *C.char {
  440. vtc := lookupHandle(pCursor).(*sqliteVTabCursor)
  441. args := (*[(math.MaxInt32 - 1) / unsafe.Sizeof((*C.sqlite3_value)(nil))]*C.sqlite3_value)(unsafe.Pointer(argv))[:argc:argc]
  442. vals := make([]interface{}, 0, argc)
  443. for _, v := range args {
  444. conv, err := callbackArgGeneric(v)
  445. if err != nil {
  446. return mPrintf("%s", err.Error())
  447. }
  448. vals = append(vals, conv.Interface())
  449. }
  450. err := vtc.vTabCursor.Filter(int(idxNum), C.GoString(idxName), vals)
  451. if err != nil {
  452. return mPrintf("%s", err.Error())
  453. }
  454. return nil
  455. }
  456. //export goVNext
  457. func goVNext(pCursor unsafe.Pointer) *C.char {
  458. vtc := lookupHandle(pCursor).(*sqliteVTabCursor)
  459. err := vtc.vTabCursor.Next()
  460. if err != nil {
  461. return mPrintf("%s", err.Error())
  462. }
  463. return nil
  464. }
  465. //export goVEof
  466. func goVEof(pCursor unsafe.Pointer) C.int {
  467. vtc := lookupHandle(pCursor).(*sqliteVTabCursor)
  468. err := vtc.vTabCursor.EOF()
  469. if err {
  470. return 1
  471. }
  472. return 0
  473. }
  474. //export goVColumn
  475. func goVColumn(pCursor, cp unsafe.Pointer, col C.int) *C.char {
  476. vtc := lookupHandle(pCursor).(*sqliteVTabCursor)
  477. c := (*SQLiteContext)(cp)
  478. err := vtc.vTabCursor.Column(c, int(col))
  479. if err != nil {
  480. return mPrintf("%s", err.Error())
  481. }
  482. return nil
  483. }
  484. //export goVRowid
  485. func goVRowid(pCursor unsafe.Pointer, pRowid *C.sqlite3_int64) *C.char {
  486. vtc := lookupHandle(pCursor).(*sqliteVTabCursor)
  487. rowid, err := vtc.vTabCursor.Rowid()
  488. if err != nil {
  489. return mPrintf("%s", err.Error())
  490. }
  491. *pRowid = C.sqlite3_int64(rowid)
  492. return nil
  493. }
  494. //export goVUpdate
  495. func goVUpdate(pVTab unsafe.Pointer, argc C.int, argv **C.sqlite3_value, pRowid *C.sqlite3_int64) *C.char {
  496. vt := lookupHandle(pVTab).(*sqliteVTab)
  497. var tname string
  498. if n, ok := vt.vTab.(interface {
  499. TableName() string
  500. }); ok {
  501. tname = n.TableName() + " "
  502. }
  503. err := fmt.Errorf("virtual %s table %sis read-only", vt.module.name, tname)
  504. if v, ok := vt.vTab.(VTabUpdater); ok {
  505. // convert argv
  506. args := (*[(math.MaxInt32 - 1) / unsafe.Sizeof((*C.sqlite3_value)(nil))]*C.sqlite3_value)(unsafe.Pointer(argv))[:argc:argc]
  507. vals := make([]interface{}, 0, argc)
  508. for _, v := range args {
  509. conv, err := callbackArgGeneric(v)
  510. if err != nil {
  511. return mPrintf("%s", err.Error())
  512. }
  513. // work around for SQLITE_NULL
  514. x := conv.Interface()
  515. if z, ok := x.([]byte); ok && z == nil {
  516. x = nil
  517. }
  518. vals = append(vals, x)
  519. }
  520. switch {
  521. case argc == 1:
  522. err = v.Delete(vals[0])
  523. case argc > 1 && vals[0] == nil:
  524. var id int64
  525. id, err = v.Insert(vals[1], vals[2:])
  526. if err == nil {
  527. *pRowid = C.sqlite3_int64(id)
  528. }
  529. case argc > 1:
  530. err = v.Update(vals[1], vals[2:])
  531. }
  532. }
  533. if err != nil {
  534. return mPrintf("%s", err.Error())
  535. }
  536. return nil
  537. }
  538. // Module is a "virtual table module", it defines the implementation of a
  539. // virtual tables. See: http://sqlite.org/c3ref/module.html
  540. type Module interface {
  541. // http://sqlite.org/vtab.html#xcreate
  542. Create(c *SQLiteConn, args []string) (VTab, error)
  543. // http://sqlite.org/vtab.html#xconnect
  544. Connect(c *SQLiteConn, args []string) (VTab, error)
  545. // http://sqlite.org/c3ref/create_module.html
  546. DestroyModule()
  547. }
  548. // EponymousOnlyModule is a "virtual table module" (as above), but
  549. // for defining "eponymous only" virtual tables See: https://sqlite.org/vtab.html#eponymous_only_virtual_tables
  550. type EponymousOnlyModule interface {
  551. Module
  552. EponymousOnlyModule()
  553. }
  554. // VTab describes a particular instance of the virtual table.
  555. // See: http://sqlite.org/c3ref/vtab.html
  556. type VTab interface {
  557. // http://sqlite.org/vtab.html#xbestindex
  558. BestIndex([]InfoConstraint, []InfoOrderBy) (*IndexResult, error)
  559. // http://sqlite.org/vtab.html#xdisconnect
  560. Disconnect() error
  561. // http://sqlite.org/vtab.html#sqlite3_module.xDestroy
  562. Destroy() error
  563. // http://sqlite.org/vtab.html#xopen
  564. Open() (VTabCursor, error)
  565. }
  566. // VTabUpdater is a type that allows a VTab to be inserted, updated, or
  567. // deleted.
  568. // See: https://sqlite.org/vtab.html#xupdate
  569. type VTabUpdater interface {
  570. Delete(interface{}) error
  571. Insert(interface{}, []interface{}) (int64, error)
  572. Update(interface{}, []interface{}) error
  573. }
  574. // VTabCursor describes cursors that point into the virtual table and are used
  575. // to loop through the virtual table. See: http://sqlite.org/c3ref/vtab_cursor.html
  576. type VTabCursor interface {
  577. // http://sqlite.org/vtab.html#xclose
  578. Close() error
  579. // http://sqlite.org/vtab.html#xfilter
  580. Filter(idxNum int, idxStr string, vals []interface{}) error
  581. // http://sqlite.org/vtab.html#xnext
  582. Next() error
  583. // http://sqlite.org/vtab.html#xeof
  584. EOF() bool
  585. // http://sqlite.org/vtab.html#xcolumn
  586. Column(c *SQLiteContext, col int) error
  587. // http://sqlite.org/vtab.html#xrowid
  588. Rowid() (int64, error)
  589. }
  590. // DeclareVTab declares the Schema of a virtual table.
  591. // See: http://sqlite.org/c3ref/declare_vtab.html
  592. func (c *SQLiteConn) DeclareVTab(sql string) error {
  593. zSQL := C.CString(sql)
  594. defer C.free(unsafe.Pointer(zSQL))
  595. rv := C.sqlite3_declare_vtab(c.db, zSQL)
  596. if rv != C.SQLITE_OK {
  597. return c.lastError()
  598. }
  599. return nil
  600. }
  601. // CreateModule registers a virtual table implementation.
  602. // See: http://sqlite.org/c3ref/create_module.html
  603. func (c *SQLiteConn) CreateModule(moduleName string, module Module) error {
  604. mname := C.CString(moduleName)
  605. defer C.free(unsafe.Pointer(mname))
  606. udm := sqliteModule{c, moduleName, module}
  607. switch module.(type) {
  608. case EponymousOnlyModule:
  609. rv := C._sqlite3_create_module_eponymous_only(c.db, mname, C.uintptr_t(uintptr(newHandle(c, &udm))))
  610. if rv != C.SQLITE_OK {
  611. return c.lastError()
  612. }
  613. return nil
  614. case Module:
  615. rv := C._sqlite3_create_module(c.db, mname, C.uintptr_t(uintptr(newHandle(c, &udm))))
  616. if rv != C.SQLITE_OK {
  617. return c.lastError()
  618. }
  619. return nil
  620. }
  621. return nil
  622. }