#include #include #include "include.h" #include "sqlite3.h" #define SQLITE_VTAB_CREATOR_GO /******/ 0x001 #define SQLITE_VTAB_DESTROYER_GO /****/ 0x002 #define SQLITE_VTAB_UPDATER_GO /******/ 0x004 #define SQLITE_VTAB_RENAMER_GO /******/ 0x008 #define SQLITE_VTAB_OVERLOADER_GO /***/ 0x010 #define SQLITE_VTAB_CHECKER_GO /******/ 0x020 #define SQLITE_VTAB_TXN_GO /**********/ 0x040 #define SQLITE_VTAB_SAVEPOINTER_GO /**/ 0x080 #define SQLITE_VTAB_SHADOWTABS_GO /***/ 0x100 int go_vtab_create(sqlite3_module*, int argc, const char* const* argv, sqlite3_vtab**, char** pzErr); int go_vtab_connect(sqlite3_module*, int argc, const char* const* argv, sqlite3_vtab**, char** pzErr); int go_vtab_disconnect(sqlite3_vtab*); int go_vtab_destroy(sqlite3_vtab*); int go_vtab_best_index(sqlite3_vtab*, sqlite3_index_info*); int go_cur_open(sqlite3_vtab*, sqlite3_vtab_cursor**); int go_cur_close(sqlite3_vtab_cursor*); int go_cur_filter(sqlite3_vtab_cursor*, int idxNum, const char* idxStr, int argc, sqlite3_value** argv); int go_cur_next(sqlite3_vtab_cursor*); int go_cur_eof(sqlite3_vtab_cursor*); int go_cur_column(sqlite3_vtab_cursor*, sqlite3_context*, int); int go_cur_rowid(sqlite3_vtab_cursor*, sqlite3_int64* pRowid); int go_vtab_update(sqlite3_vtab*, int, sqlite3_value**, sqlite3_int64*); int go_vtab_rename(sqlite3_vtab*, const char* zNew); int go_vtab_find_function(sqlite3_vtab*, int nArg, const char* zName, go_handle* pxFunc); int go_vtab_begin(sqlite3_vtab*); int go_vtab_sync(sqlite3_vtab*); int go_vtab_commit(sqlite3_vtab*); int go_vtab_rollback(sqlite3_vtab*); int go_vtab_savepoint(sqlite3_vtab*, int); int go_vtab_release(sqlite3_vtab*, int); int go_vtab_rollback_to(sqlite3_vtab*, int); int go_vtab_integrity(sqlite3_vtab*, const char* zSchema, const char* zTabName, int mFlags, char** pzErr); struct go_module { go_handle handle; sqlite3_module base; }; struct go_vtab { go_handle handle; sqlite3_vtab base; }; struct go_cursor { go_handle handle; sqlite3_vtab_cursor base; }; static void go_mod_destroy(void* pAux) { struct go_module* mod = pAux; void* handle = mod->handle; free(mod); go_destroy(handle); } static int go_vtab_create_wrapper(sqlite3* db, void* pAux, int argc, const char* const* argv, sqlite3_vtab** ppVTab, char** pzErr) { UNUSED_PARAMETER(db); struct go_vtab* vtab = calloc(1, sizeof(struct go_vtab)); if (vtab == NULL) return SQLITE_NOMEM; *ppVTab = &vtab->base; struct go_module* mod = pAux; int rc = go_vtab_create(&mod->base, argc, argv, ppVTab, pzErr); if (rc) { if (*pzErr) *pzErr = sqlite3_mprintf("%s", *pzErr); free(vtab); } return rc; } static int go_vtab_connect_wrapper(sqlite3* db, void* pAux, int argc, const char* const* argv, sqlite3_vtab** ppVTab, char** pzErr) { UNUSED_PARAMETER(db); struct go_vtab* vtab = calloc(1, sizeof(struct go_vtab)); if (vtab == NULL) return SQLITE_NOMEM; *ppVTab = &vtab->base; struct go_module* mod = pAux; int rc = go_vtab_connect(&mod->base, argc, argv, ppVTab, pzErr); if (rc) { free(vtab); if (*pzErr) *pzErr = sqlite3_mprintf("%s", *pzErr); } return rc; } static int go_vtab_disconnect_wrapper(sqlite3_vtab* pVTab) { struct go_vtab* vtab = container_of(pVTab, struct go_vtab, base); int rc = go_vtab_disconnect(pVTab); free(vtab); return rc; } static int go_vtab_destroy_wrapper(sqlite3_vtab* pVTab) { struct go_vtab* vtab = container_of(pVTab, struct go_vtab, base); int rc = go_vtab_destroy(pVTab); free(vtab); return rc; } static int go_cur_open_wrapper(sqlite3_vtab* pVTab, sqlite3_vtab_cursor** ppCursor) { struct go_cursor* cur = calloc(1, sizeof(struct go_cursor)); if (cur == NULL) return SQLITE_NOMEM; *ppCursor = &cur->base; int rc = go_cur_open(pVTab, ppCursor); if (rc) free(cur); return rc; } static int go_cur_close_wrapper(sqlite3_vtab_cursor* pCursor) { struct go_cursor* cur = container_of(pCursor, struct go_cursor, base); int rc = go_cur_close(pCursor); free(cur); return rc; } static int go_vtab_find_function_wrapper( sqlite3_vtab* pVTab, int nArg, const char* zName, void (**pxFunc)(sqlite3_context*, int, sqlite3_value**), void** ppArg) { go_handle handle; int rc = go_vtab_find_function(pVTab, nArg, zName, &handle); if (rc) { *pxFunc = go_func_wrapper; *ppArg = handle; } return rc; } static int go_vtab_integrity_wrapper(sqlite3_vtab* pVTab, const char* zSchema, const char* zTabName, int mFlags, char** pzErr) { int rc = go_vtab_integrity(pVTab, zSchema, zTabName, mFlags, pzErr); if (rc && *pzErr) *pzErr = sqlite3_mprintf("%s", *pzErr); return rc; } static int go_vtab_shadown_name_wrapper(const char* zName) { return true; } int sqlite3_create_module_go(sqlite3* db, const char* zName, int flags, go_handle handle) { if (handle == NULL) { return sqlite3_create_module_v2(db, zName, NULL, NULL, NULL); } struct go_module* mod = malloc(sizeof(struct go_module)); if (mod == NULL) { go_destroy(handle); return SQLITE_NOMEM; } mod->handle = handle; mod->base = (sqlite3_module){ .iVersion = 4, .xConnect = go_vtab_connect_wrapper, .xDisconnect = go_vtab_disconnect_wrapper, .xBestIndex = go_vtab_best_index, .xOpen = go_cur_open_wrapper, .xClose = go_cur_close_wrapper, .xFilter = go_cur_filter, .xNext = go_cur_next, .xEof = go_cur_eof, .xColumn = go_cur_column, .xRowid = go_cur_rowid, }; if (flags & SQLITE_VTAB_CREATOR_GO) { mod->base.xCreate = go_vtab_create_wrapper; } if (flags & SQLITE_VTAB_DESTROYER_GO) { mod->base.xDestroy = go_vtab_destroy_wrapper; } if (flags & SQLITE_VTAB_UPDATER_GO) { mod->base.xUpdate = go_vtab_update; } if (flags & SQLITE_VTAB_RENAMER_GO) { mod->base.xRename = go_vtab_rename; } if (flags & SQLITE_VTAB_OVERLOADER_GO) { mod->base.xFindFunction = go_vtab_find_function_wrapper; } if (flags & SQLITE_VTAB_CHECKER_GO) { mod->base.xIntegrity = go_vtab_integrity_wrapper; } if (flags & SQLITE_VTAB_TXN_GO) { mod->base.xBegin = go_vtab_begin; mod->base.xSync = go_vtab_sync; mod->base.xCommit = go_vtab_commit; mod->base.xRollback = go_vtab_rollback; } if (flags & SQLITE_VTAB_SAVEPOINTER_GO) { mod->base.xSavepoint = go_vtab_savepoint; mod->base.xRelease = go_vtab_release; mod->base.xRollbackTo = go_vtab_rollback_to; } if (flags & SQLITE_VTAB_SHADOWTABS_GO) { mod->base.xShadowName = go_vtab_shadown_name_wrapper; } if (mod->base.xCreate && !mod->base.xDestroy) { mod->base.xDestroy = mod->base.xDisconnect; } if (mod->base.xDestroy && !mod->base.xCreate) { mod->base.xCreate = mod->base.xConnect; } return sqlite3_create_module_v2(db, zName, &mod->base, mod, go_mod_destroy); } int sqlite3_vtab_config_go(sqlite3* db, int op, int constraint) { return sqlite3_vtab_config(db, op, constraint); } static_assert(offsetof(struct sqlite3_vtab, zErrMsg) == 8, "Unexpected offset"); static_assert(offsetof(struct go_module, base) == 4, "Unexpected offset"); static_assert(offsetof(struct go_vtab, base) == 4, "Unexpected offset"); static_assert(offsetof(struct go_cursor, base) == 4, "Unexpected offset"); static_assert(sizeof(struct sqlite3_index_info) == 72, "Unexpected size"); static_assert(sizeof(struct sqlite3_index_orderby) == 8, "Unexpected size"); static_assert(sizeof(struct sqlite3_index_constraint) == 12, "Unexpected size"); static_assert(sizeof(struct sqlite3_index_constraint_usage) == 8, "Unexpected size");