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");