sqlite3_opt_vtable.go 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721
  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. info.idxStr = (*C.char)(C.sqlite3_malloc(C.int(len(res.IdxStr) + 1)))
  414. if info.idxStr == nil {
  415. // C.malloc and C.CString ordinarily do this for you. See https://golang.org/cmd/cgo/
  416. panic("out of memory")
  417. }
  418. info.needToFreeIdxStr = C.int(1)
  419. idxStr := *(*[]byte)(unsafe.Pointer(&reflect.SliceHeader{
  420. Data: uintptr(unsafe.Pointer(info.idxStr)),
  421. Len: len(res.IdxStr) + 1,
  422. Cap: len(res.IdxStr) + 1,
  423. }))
  424. copy(idxStr, res.IdxStr)
  425. idxStr[len(idxStr)-1] = 0 // null-terminated string
  426. if res.AlreadyOrdered {
  427. info.orderByConsumed = C.int(1)
  428. }
  429. info.estimatedCost = C.double(res.EstimatedCost)
  430. info.estimatedRows = C.sqlite3_int64(res.EstimatedRows)
  431. return nil
  432. }
  433. //export goVClose
  434. func goVClose(pCursor unsafe.Pointer) *C.char {
  435. vtc := lookupHandle(pCursor).(*sqliteVTabCursor)
  436. err := vtc.vTabCursor.Close()
  437. if err != nil {
  438. return mPrintf("%s", err.Error())
  439. }
  440. return nil
  441. }
  442. //export goMDestroy
  443. func goMDestroy(pClientData unsafe.Pointer) {
  444. m := lookupHandle(pClientData).(*sqliteModule)
  445. m.module.DestroyModule()
  446. }
  447. //export goVFilter
  448. func goVFilter(pCursor unsafe.Pointer, idxNum C.int, idxName *C.char, argc C.int, argv **C.sqlite3_value) *C.char {
  449. vtc := lookupHandle(pCursor).(*sqliteVTabCursor)
  450. args := (*[(math.MaxInt32 - 1) / unsafe.Sizeof((*C.sqlite3_value)(nil))]*C.sqlite3_value)(unsafe.Pointer(argv))[:argc:argc]
  451. vals := make([]interface{}, 0, argc)
  452. for _, v := range args {
  453. conv, err := callbackArgGeneric(v)
  454. if err != nil {
  455. return mPrintf("%s", err.Error())
  456. }
  457. vals = append(vals, conv.Interface())
  458. }
  459. err := vtc.vTabCursor.Filter(int(idxNum), C.GoString(idxName), vals)
  460. if err != nil {
  461. return mPrintf("%s", err.Error())
  462. }
  463. return nil
  464. }
  465. //export goVNext
  466. func goVNext(pCursor unsafe.Pointer) *C.char {
  467. vtc := lookupHandle(pCursor).(*sqliteVTabCursor)
  468. err := vtc.vTabCursor.Next()
  469. if err != nil {
  470. return mPrintf("%s", err.Error())
  471. }
  472. return nil
  473. }
  474. //export goVEof
  475. func goVEof(pCursor unsafe.Pointer) C.int {
  476. vtc := lookupHandle(pCursor).(*sqliteVTabCursor)
  477. err := vtc.vTabCursor.EOF()
  478. if err {
  479. return 1
  480. }
  481. return 0
  482. }
  483. //export goVColumn
  484. func goVColumn(pCursor, cp unsafe.Pointer, col C.int) *C.char {
  485. vtc := lookupHandle(pCursor).(*sqliteVTabCursor)
  486. c := (*SQLiteContext)(cp)
  487. err := vtc.vTabCursor.Column(c, int(col))
  488. if err != nil {
  489. return mPrintf("%s", err.Error())
  490. }
  491. return nil
  492. }
  493. //export goVRowid
  494. func goVRowid(pCursor unsafe.Pointer, pRowid *C.sqlite3_int64) *C.char {
  495. vtc := lookupHandle(pCursor).(*sqliteVTabCursor)
  496. rowid, err := vtc.vTabCursor.Rowid()
  497. if err != nil {
  498. return mPrintf("%s", err.Error())
  499. }
  500. *pRowid = C.sqlite3_int64(rowid)
  501. return nil
  502. }
  503. //export goVUpdate
  504. func goVUpdate(pVTab unsafe.Pointer, argc C.int, argv **C.sqlite3_value, pRowid *C.sqlite3_int64) *C.char {
  505. vt := lookupHandle(pVTab).(*sqliteVTab)
  506. var tname string
  507. if n, ok := vt.vTab.(interface {
  508. TableName() string
  509. }); ok {
  510. tname = n.TableName() + " "
  511. }
  512. err := fmt.Errorf("virtual %s table %sis read-only", vt.module.name, tname)
  513. if v, ok := vt.vTab.(VTabUpdater); ok {
  514. // convert argv
  515. args := (*[(math.MaxInt32 - 1) / unsafe.Sizeof((*C.sqlite3_value)(nil))]*C.sqlite3_value)(unsafe.Pointer(argv))[:argc:argc]
  516. vals := make([]interface{}, 0, argc)
  517. for _, v := range args {
  518. conv, err := callbackArgGeneric(v)
  519. if err != nil {
  520. return mPrintf("%s", err.Error())
  521. }
  522. // work around for SQLITE_NULL
  523. x := conv.Interface()
  524. if z, ok := x.([]byte); ok && z == nil {
  525. x = nil
  526. }
  527. vals = append(vals, x)
  528. }
  529. switch {
  530. case argc == 1:
  531. err = v.Delete(vals[0])
  532. case argc > 1 && vals[0] == nil:
  533. var id int64
  534. id, err = v.Insert(vals[1], vals[2:])
  535. if err == nil {
  536. *pRowid = C.sqlite3_int64(id)
  537. }
  538. case argc > 1:
  539. err = v.Update(vals[1], vals[2:])
  540. }
  541. }
  542. if err != nil {
  543. return mPrintf("%s", err.Error())
  544. }
  545. return nil
  546. }
  547. // Module is a "virtual table module", it defines the implementation of a
  548. // virtual tables. See: http://sqlite.org/c3ref/module.html
  549. type Module interface {
  550. // http://sqlite.org/vtab.html#xcreate
  551. Create(c *SQLiteConn, args []string) (VTab, error)
  552. // http://sqlite.org/vtab.html#xconnect
  553. Connect(c *SQLiteConn, args []string) (VTab, error)
  554. // http://sqlite.org/c3ref/create_module.html
  555. DestroyModule()
  556. }
  557. // EponymousOnlyModule is a "virtual table module" (as above), but
  558. // for defining "eponymous only" virtual tables See: https://sqlite.org/vtab.html#eponymous_only_virtual_tables
  559. type EponymousOnlyModule interface {
  560. Module
  561. EponymousOnlyModule()
  562. }
  563. // VTab describes a particular instance of the virtual table.
  564. // See: http://sqlite.org/c3ref/vtab.html
  565. type VTab interface {
  566. // http://sqlite.org/vtab.html#xbestindex
  567. BestIndex([]InfoConstraint, []InfoOrderBy) (*IndexResult, error)
  568. // http://sqlite.org/vtab.html#xdisconnect
  569. Disconnect() error
  570. // http://sqlite.org/vtab.html#sqlite3_module.xDestroy
  571. Destroy() error
  572. // http://sqlite.org/vtab.html#xopen
  573. Open() (VTabCursor, error)
  574. }
  575. // VTabUpdater is a type that allows a VTab to be inserted, updated, or
  576. // deleted.
  577. // See: https://sqlite.org/vtab.html#xupdate
  578. type VTabUpdater interface {
  579. Delete(interface{}) error
  580. Insert(interface{}, []interface{}) (int64, error)
  581. Update(interface{}, []interface{}) error
  582. }
  583. // VTabCursor describes cursors that point into the virtual table and are used
  584. // to loop through the virtual table. See: http://sqlite.org/c3ref/vtab_cursor.html
  585. type VTabCursor interface {
  586. // http://sqlite.org/vtab.html#xclose
  587. Close() error
  588. // http://sqlite.org/vtab.html#xfilter
  589. Filter(idxNum int, idxStr string, vals []interface{}) error
  590. // http://sqlite.org/vtab.html#xnext
  591. Next() error
  592. // http://sqlite.org/vtab.html#xeof
  593. EOF() bool
  594. // http://sqlite.org/vtab.html#xcolumn
  595. Column(c *SQLiteContext, col int) error
  596. // http://sqlite.org/vtab.html#xrowid
  597. Rowid() (int64, error)
  598. }
  599. // DeclareVTab declares the Schema of a virtual table.
  600. // See: http://sqlite.org/c3ref/declare_vtab.html
  601. func (c *SQLiteConn) DeclareVTab(sql string) error {
  602. zSQL := C.CString(sql)
  603. defer C.free(unsafe.Pointer(zSQL))
  604. rv := C.sqlite3_declare_vtab(c.db, zSQL)
  605. if rv != C.SQLITE_OK {
  606. return c.lastError()
  607. }
  608. return nil
  609. }
  610. // CreateModule registers a virtual table implementation.
  611. // See: http://sqlite.org/c3ref/create_module.html
  612. func (c *SQLiteConn) CreateModule(moduleName string, module Module) error {
  613. mname := C.CString(moduleName)
  614. defer C.free(unsafe.Pointer(mname))
  615. udm := sqliteModule{c, moduleName, module}
  616. switch module.(type) {
  617. case EponymousOnlyModule:
  618. rv := C._sqlite3_create_module_eponymous_only(c.db, mname, C.uintptr_t(uintptr(newHandle(c, &udm))))
  619. if rv != C.SQLITE_OK {
  620. return c.lastError()
  621. }
  622. return nil
  623. case Module:
  624. rv := C._sqlite3_create_module(c.db, mname, C.uintptr_t(uintptr(newHandle(c, &udm))))
  625. if rv != C.SQLITE_OK {
  626. return c.lastError()
  627. }
  628. return nil
  629. }
  630. return nil
  631. }