Skip to content

Instantly share code, notes, and snippets.

@little-brother
Last active May 7, 2021 16:09
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/35d9cec9c018489449141fe925bacd42 to your computer and use it in GitHub Desktop.
Save little-brother/35d9cec9c018489449141fe925bacd42 to your computer and use it in GitHub Desktop.
SQLite non-table-valued virtual table example
// gcc -shared vtab.c -o vtab.dll -s -static
// create virtual table t using vtab(4); -- 4 is a column count
#include "sqlite3ext.h"
SQLITE_EXTENSION_INIT1
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
typedef struct vtab_vtab vtab_vtab;
struct vtab_vtab {
sqlite3_vtab base;
int colCount;
};
static int vtabCreate(sqlite3 *db, void *pAux, int argc, const char *const*argv, sqlite3_vtab **ppVtab, char **pzErr);
static int vtabConnect(sqlite3 *db, void *pAux, int argc, const char *const*argv, sqlite3_vtab **ppVtab, char **pzErr) {
vtab_vtab *pNew;
int colCount = argc >= 4 ? atoi(argv[3]) : 0;
if (colCount <= 0)
return SQLITE_ERROR;
char query[255 + colCount * 10];
sprintf(query, "create table x(");
for (int i = 0; i < colCount; i++) {
char colName[255];
sprintf(colName, "%scol%i", i > 0 ? ", " : "", i);
strcat(query, colName);
}
strcat(query, ")");
int rc = sqlite3_declare_vtab(db, query);
if (rc == SQLITE_OK) {
pNew = sqlite3_malloc(sizeof(*pNew));
*ppVtab = (sqlite3_vtab*)pNew;
if (pNew == 0)
return SQLITE_NOMEM;
memset(pNew, 0, sizeof(*pNew));
pNew->colCount = colCount;
}
return rc;
}
static int vtabCreate(sqlite3 *db, void *pAux, int argc, const char *const*argv, sqlite3_vtab **ppVtab, char **pzErr) {
return vtabConnect(db, pAux, argc, argv, ppVtab, pzErr);
}
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;
int isEof;
};
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++;
pCur->isEof = pCur->iRowid > 10;
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, pow(10, colNo) + 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 */ vtabCreate,
/* xConnect */ vtabConnect,
/* xBestIndex */ vtabBestIndex,
/* xDisconnect */ vtabDisconnect,
/* xDestroy */ vtabDisconnect,
/* 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) {
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