github.com/CanonicalLtd/go-sqlite3@v1.6.0/sqlite3_vtable.go (about)

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