sqlite3_opt_vtable.go 20 KB

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