Skip to content

Instantly share code, notes, and snippets.

@little-brother
Last active May 7, 2021 15:34
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save little-brother/dc60dfd1667d8248adcb4359ed5489ef to your computer and use it in GitHub Desktop.
Save little-brother/dc60dfd1667d8248adcb4359ed5489ef to your computer and use it in GitHub Desktop.
SQLite minimal virtual table example
// gcc -shared vtab.c -o vtab.dll -s -static
#include "sqlite3ext.h"
SQLITE_EXTENSION_INIT1
#include <string.h>
typedef struct vtab_vtab vtab_vtab;
struct vtab_vtab {
sqlite3_vtab base;
};
static int vtabConnect(sqlite3 *db, void *pAux, int argc, const char *const*argv, sqlite3_vtab **ppVtab, char **pzErr) {
vtab_vtab *pNew;
int rc = sqlite3_declare_vtab(db, "CREATE TABLE x(a, b)");
if (rc == SQLITE_OK) {
pNew = sqlite3_malloc(sizeof(*pNew));
*ppVtab = (sqlite3_vtab*)pNew;
if (pNew == 0)
return SQLITE_NOMEM;
memset(pNew, 0, sizeof(*pNew));
}
return rc;
}
static int vtabDisconnect(sqlite3_vtab *pVtab){
vtab_vtab *p = (vtab_vtab*)pVtab;
sqlite3_free(p);
return SQLITE_OK;
}
static int vtabBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo) {
pIdxInfo->estimatedCost = (double)10;
pIdxInfo->estimatedRows = 10;
return SQLITE_OK;
}
typedef struct vtab_cursor vtab_cursor;
struct vtab_cursor {
sqlite3_vtab_cursor base;
sqlite3_int64 iRowid;
};
static int vtabOpen(sqlite3_vtab *p, sqlite3_vtab_cursor **ppCursor) {
vtab_cursor *pCur;
pCur = sqlite3_malloc( sizeof(*pCur) );
if (pCur == 0)
return SQLITE_NOMEM;
memset(pCur, 0, sizeof(*pCur));
*ppCursor = &pCur->base;
return SQLITE_OK;
}
static int vtabClose(sqlite3_vtab_cursor *cur){
vtab_cursor *pCur = (vtab_cursor*)cur;
sqlite3_free(pCur);
return SQLITE_OK;
}
static int vtabNext(sqlite3_vtab_cursor *cur) {
vtab_cursor *pCur = (vtab_cursor*)cur;
pCur->iRowid++;
return SQLITE_OK;
}
static int vtabColumn(sqlite3_vtab_cursor *cur, sqlite3_context *ctx, int colNo){
vtab_cursor *pCur = (vtab_cursor*)cur;
sqlite3_result_int(ctx, (colNo == 0 ? 1000 : 2000) + pCur->iRowid);
return SQLITE_OK;
}
static int vtabEof(sqlite3_vtab_cursor *cur){
vtab_cursor *pCur = (vtab_cursor*)cur;
return pCur->iRowid >= 10;
}
static int vtabFilter(sqlite3_vtab_cursor *pVtabCursor, int idxNum, const char *idxStr, int argc, sqlite3_value **argv) {
vtab_cursor *pCur = (vtab_cursor *)pVtabCursor;
pCur->iRowid = 1;
return SQLITE_OK;
}
static int vtabRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid) {
vtab_cursor *pCur = (vtab_cursor*)cur;
*pRowid = pCur->iRowid;
return SQLITE_OK;
}
static sqlite3_module vtabModule = {
/* iVersion */ 0,
/* xCreate */ 0,
/* xConnect */ vtabConnect,
/* xBestIndex */ vtabBestIndex,
/* xDisconnect */ vtabDisconnect,
/* xDestroy */ 0,
/* xOpen */ vtabOpen,
/* xClose */ vtabClose,
/* xFilter */ vtabFilter,
/* xNext */ vtabNext,
/* xEof */ vtabEof,
/* xColumn */ vtabColumn,
/* xRowid */ vtabRowid,
/* xUpdate */ 0,
/* xBegin */ 0,
/* xSync */ 0,
/* xCommit */ 0,
/* xRollback */ 0,
/* xFindMethod */ 0,
/* xRename */ 0,
/* xSavepoint */ 0,
/* xRelease */ 0,
/* xRollbackTo */ 0,
/* xShadowName */ 0
};
#ifdef _WIN32
__declspec(dllexport)
#endif
int sqlite3_vtab_init(sqlite3 *db, char **pzErrMsg, const sqlite3_api_routines *pApi) {
int rc = SQLITE_OK;
SQLITE_EXTENSION_INIT2(pApi);
return sqlite3_create_module(db, "vtab", &vtabModule, 0);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment