github.com/ncruces/go-sqlite3@v0.15.1-0.20240520133447-53eef1510ff0/sqlite3/vtab.c (about) 1 #include <stddef.h> 2 3 #include "include.h" 4 #include "sqlite3.h" 5 6 #define SQLITE_VTAB_CREATOR_GO /******/ 0x01 7 #define SQLITE_VTAB_DESTROYER_GO /****/ 0x02 8 #define SQLITE_VTAB_UPDATER_GO /******/ 0x04 9 #define SQLITE_VTAB_RENAMER_GO /******/ 0x08 10 #define SQLITE_VTAB_OVERLOADER_GO /***/ 0x10 11 #define SQLITE_VTAB_CHECKER_GO /******/ 0x20 12 #define SQLITE_VTAB_TXN_GO /**********/ 0x40 13 #define SQLITE_VTAB_SAVEPOINTER_GO /**/ 0x80 14 15 int go_vtab_create(sqlite3_module *, int argc, const char *const *argv, 16 sqlite3_vtab **, char **pzErr); 17 int go_vtab_connect(sqlite3_module *, int argc, const char *const *argv, 18 sqlite3_vtab **, char **pzErr); 19 20 int go_vtab_disconnect(sqlite3_vtab *); 21 int go_vtab_destroy(sqlite3_vtab *); 22 int go_vtab_best_index(sqlite3_vtab *, sqlite3_index_info *); 23 int go_cur_open(sqlite3_vtab *, sqlite3_vtab_cursor **); 24 25 int go_cur_close(sqlite3_vtab_cursor *); 26 int go_cur_filter(sqlite3_vtab_cursor *, int idxNum, const char *idxStr, 27 int argc, sqlite3_value **argv); 28 int go_cur_next(sqlite3_vtab_cursor *); 29 int go_cur_eof(sqlite3_vtab_cursor *); 30 int go_cur_column(sqlite3_vtab_cursor *, sqlite3_context *, int); 31 int go_cur_rowid(sqlite3_vtab_cursor *, sqlite3_int64 *pRowid); 32 33 int go_vtab_update(sqlite3_vtab *, int, sqlite3_value **, sqlite3_int64 *); 34 int go_vtab_rename(sqlite3_vtab *, const char *zNew); 35 int go_vtab_find_function(sqlite3_vtab *, int nArg, const char *zName, 36 go_handle *pxFunc); 37 38 int go_vtab_begin(sqlite3_vtab *); 39 int go_vtab_sync(sqlite3_vtab *); 40 int go_vtab_commit(sqlite3_vtab *); 41 int go_vtab_rollback(sqlite3_vtab *); 42 43 int go_vtab_savepoint(sqlite3_vtab *, int); 44 int go_vtab_release(sqlite3_vtab *, int); 45 int go_vtab_rollback_to(sqlite3_vtab *, int); 46 47 int go_vtab_integrity(sqlite3_vtab *, const char *zSchema, const char *zTabName, 48 int mFlags, char **pzErr); 49 50 struct go_module { 51 go_handle handle; 52 sqlite3_module base; 53 }; 54 55 struct go_vtab { 56 go_handle handle; 57 sqlite3_vtab base; 58 }; 59 60 struct go_cursor { 61 go_handle handle; 62 sqlite3_vtab_cursor base; 63 }; 64 65 static void go_mod_destroy(void *pAux) { 66 struct go_module *mod = pAux; 67 void *handle = mod->handle; 68 free(mod); 69 go_destroy(handle); 70 } 71 72 static int go_vtab_create_wrapper(sqlite3 *db, void *pAux, int argc, 73 const char *const *argv, 74 sqlite3_vtab **ppVTab, char **pzErr) { 75 struct go_vtab *vtab = calloc(1, sizeof(struct go_vtab)); 76 if (vtab == NULL) return SQLITE_NOMEM; 77 *ppVTab = &vtab->base; 78 79 struct go_module *mod = pAux; 80 int rc = go_vtab_create(&mod->base, argc, argv, ppVTab, pzErr); 81 if (rc) { 82 if (*pzErr) *pzErr = sqlite3_mprintf("%s", *pzErr); 83 free(vtab); 84 } 85 return rc; 86 } 87 88 static int go_vtab_connect_wrapper(sqlite3 *db, void *pAux, int argc, 89 const char *const *argv, 90 sqlite3_vtab **ppVTab, char **pzErr) { 91 struct go_vtab *vtab = calloc(1, sizeof(struct go_vtab)); 92 if (vtab == NULL) return SQLITE_NOMEM; 93 *ppVTab = &vtab->base; 94 95 struct go_module *mod = pAux; 96 int rc = go_vtab_connect(&mod->base, argc, argv, ppVTab, pzErr); 97 if (rc) { 98 free(vtab); 99 if (*pzErr) *pzErr = sqlite3_mprintf("%s", *pzErr); 100 } 101 return rc; 102 } 103 104 static int go_vtab_disconnect_wrapper(sqlite3_vtab *pVTab) { 105 struct go_vtab *vtab = container_of(pVTab, struct go_vtab, base); 106 int rc = go_vtab_disconnect(pVTab); 107 free(vtab); 108 return rc; 109 } 110 111 static int go_vtab_destroy_wrapper(sqlite3_vtab *pVTab) { 112 struct go_vtab *vtab = container_of(pVTab, struct go_vtab, base); 113 int rc = go_vtab_destroy(pVTab); 114 free(vtab); 115 return rc; 116 } 117 118 static int go_cur_open_wrapper(sqlite3_vtab *pVTab, 119 sqlite3_vtab_cursor **ppCursor) { 120 struct go_cursor *cur = calloc(1, sizeof(struct go_cursor)); 121 if (cur == NULL) return SQLITE_NOMEM; 122 *ppCursor = &cur->base; 123 124 int rc = go_cur_open(pVTab, ppCursor); 125 if (rc) free(cur); 126 return rc; 127 } 128 129 static int go_cur_close_wrapper(sqlite3_vtab_cursor *pCursor) { 130 struct go_cursor *cur = container_of(pCursor, struct go_cursor, base); 131 int rc = go_cur_close(pCursor); 132 free(cur); 133 return rc; 134 } 135 136 static int go_vtab_find_function_wrapper( 137 sqlite3_vtab *pVTab, int nArg, const char *zName, 138 void (**pxFunc)(sqlite3_context *, int, sqlite3_value **), void **ppArg) { 139 go_handle handle; 140 int rc = go_vtab_find_function(pVTab, nArg, zName, &handle); 141 if (rc) { 142 *pxFunc = go_func_wrapper; 143 *ppArg = handle; 144 } 145 return rc; 146 } 147 148 static int go_vtab_integrity_wrapper(sqlite3_vtab *pVTab, const char *zSchema, 149 const char *zTabName, int mFlags, 150 char **pzErr) { 151 int rc = go_vtab_integrity(pVTab, zSchema, zTabName, mFlags, pzErr); 152 if (rc && *pzErr) *pzErr = sqlite3_mprintf("%s", *pzErr); 153 return rc; 154 } 155 156 int sqlite3_create_module_go(sqlite3 *db, const char *zName, int flags, 157 go_handle handle) { 158 struct go_module *mod = malloc(sizeof(struct go_module)); 159 if (mod == NULL) { 160 go_destroy(handle); 161 return SQLITE_NOMEM; 162 } 163 164 mod->handle = handle; 165 mod->base = (sqlite3_module){ 166 .iVersion = 4, 167 .xConnect = go_vtab_connect_wrapper, 168 .xDisconnect = go_vtab_disconnect_wrapper, 169 .xBestIndex = go_vtab_best_index, 170 .xOpen = go_cur_open_wrapper, 171 .xClose = go_cur_close_wrapper, 172 .xFilter = go_cur_filter, 173 .xNext = go_cur_next, 174 .xEof = go_cur_eof, 175 .xColumn = go_cur_column, 176 .xRowid = go_cur_rowid, 177 }; 178 if (flags & SQLITE_VTAB_CREATOR_GO) { 179 mod->base.xCreate = go_vtab_create_wrapper; 180 } 181 if (flags & SQLITE_VTAB_DESTROYER_GO) { 182 mod->base.xDestroy = go_vtab_destroy_wrapper; 183 } 184 if (flags & SQLITE_VTAB_UPDATER_GO) { 185 mod->base.xUpdate = go_vtab_update; 186 } 187 if (flags & SQLITE_VTAB_RENAMER_GO) { 188 mod->base.xRename = go_vtab_rename; 189 } 190 if (flags & SQLITE_VTAB_OVERLOADER_GO) { 191 mod->base.xFindFunction = go_vtab_find_function_wrapper; 192 } 193 if (flags & SQLITE_VTAB_CHECKER_GO) { 194 mod->base.xIntegrity = go_vtab_integrity_wrapper; 195 } 196 if (flags & SQLITE_VTAB_TXN_GO) { 197 mod->base.xBegin = go_vtab_begin; 198 mod->base.xSync = go_vtab_sync; 199 mod->base.xCommit = go_vtab_commit; 200 mod->base.xRollback = go_vtab_rollback; 201 } 202 if (flags & SQLITE_VTAB_SAVEPOINTER_GO) { 203 mod->base.xSavepoint = go_vtab_savepoint; 204 mod->base.xRelease = go_vtab_release; 205 mod->base.xRollbackTo = go_vtab_rollback_to; 206 } 207 if (mod->base.xCreate && !mod->base.xDestroy) { 208 mod->base.xDestroy = mod->base.xDisconnect; 209 } 210 if (mod->base.xDestroy && !mod->base.xCreate) { 211 mod->base.xCreate = mod->base.xConnect; 212 } 213 214 return sqlite3_create_module_v2(db, zName, &mod->base, mod, go_mod_destroy); 215 } 216 217 int sqlite3_vtab_config_go(sqlite3 *db, int op, int constraint) { 218 return sqlite3_vtab_config(db, op, constraint); 219 } 220 221 static_assert(offsetof(struct sqlite3_vtab, zErrMsg) == 8, "Unexpected offset"); 222 static_assert(offsetof(struct go_module, base) == 4, "Unexpected offset"); 223 static_assert(offsetof(struct go_vtab, base) == 4, "Unexpected offset"); 224 static_assert(offsetof(struct go_cursor, base) == 4, "Unexpected offset"); 225 static_assert(sizeof(struct sqlite3_index_info) == 72, "Unexpected size"); 226 static_assert(sizeof(struct sqlite3_index_orderby) == 8, "Unexpected size"); 227 static_assert(sizeof(struct sqlite3_index_constraint) == 12, "Unexpected size"); 228 static_assert(sizeof(struct sqlite3_index_constraint_usage) == 8, 229 "Unexpected size");