github.com/insionng/yougam@v0.0.0-20170714101924-2bc18d833463/libraries/mattn/go-sqlite3/_example/mod_vtable/sqlite3_mod_vtable.cc (about)

     1  #include <string>
     2  #include <sstream>
     3  #include <sqlite3-binding.h>
     4  #include <sqlite3ext.h>
     5  #include <curl/curl.h>
     6  #include "picojson.h"
     7  
     8  #ifdef _WIN32
     9  # define EXPORT __declspec(dllexport)
    10  #else
    11  # define EXPORT
    12  #endif
    13  
    14  SQLITE_EXTENSION_INIT1;
    15  
    16  typedef struct {
    17    char* data;   // response data from server
    18    size_t size;  // response size of data
    19  } MEMFILE;
    20  
    21  MEMFILE*
    22  memfopen() {
    23    MEMFILE* mf = (MEMFILE*) malloc(sizeof(MEMFILE));
    24    if (mf) {
    25      mf->data = NULL;
    26      mf->size = 0;
    27    }
    28    return mf;
    29  }
    30  
    31  void
    32  memfclose(MEMFILE* mf) {
    33    if (mf->data) free(mf->data);
    34    free(mf);
    35  }
    36  
    37  size_t
    38  memfwrite(char* ptr, size_t size, size_t nmemb, void* stream) {
    39    MEMFILE* mf = (MEMFILE*) stream;
    40    int block = size * nmemb;
    41    if (!mf) return block; // through
    42    if (!mf->data)
    43      mf->data = (char*) malloc(block);
    44    else
    45      mf->data = (char*) realloc(mf->data, mf->size + block);
    46    if (mf->data) {
    47      memcpy(mf->data + mf->size, ptr, block);
    48      mf->size += block;
    49    }
    50    return block;
    51  }
    52  
    53  char*
    54  memfstrdup(MEMFILE* mf) {
    55    char* buf;
    56    if (mf->size == 0) return NULL;
    57    buf = (char*) malloc(mf->size + 1);
    58    memcpy(buf, mf->data, mf->size);
    59    buf[mf->size] = 0;
    60    return buf;
    61  }
    62  
    63  static int
    64  my_connect(sqlite3 *db, void *pAux, int argc, const char * const *argv, sqlite3_vtab **ppVTab, char **c) {
    65    std::stringstream ss;
    66    ss << "CREATE TABLE " << argv[0]
    67      << "(id int, full_name text, description text, html_url text)";
    68    int rc = sqlite3_declare_vtab(db, ss.str().c_str());
    69    *ppVTab = (sqlite3_vtab *) sqlite3_malloc(sizeof(sqlite3_vtab));
    70    memset(*ppVTab, 0, sizeof(sqlite3_vtab));
    71    return rc;
    72  }
    73  
    74  static int
    75  my_create(sqlite3 *db, void *pAux, int argc, const char * const * argv, sqlite3_vtab **ppVTab, char **c) {
    76    return my_connect(db, pAux, argc, argv, ppVTab, c);
    77  }
    78  
    79  static int my_disconnect(sqlite3_vtab *pVTab) {
    80    sqlite3_free(pVTab);
    81    return SQLITE_OK;
    82  }
    83  
    84  static int
    85  my_destroy(sqlite3_vtab *pVTab) {
    86    sqlite3_free(pVTab);
    87    return SQLITE_OK;
    88  }
    89  
    90  typedef struct {
    91    sqlite3_vtab_cursor base;
    92    int index;
    93    picojson::value* rows;
    94  } cursor;
    95  
    96  static int
    97  my_open(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor) {
    98    MEMFILE* mf;
    99    CURL* curl;
   100    char* json;
   101    CURLcode res = CURLE_OK;
   102    char error[CURL_ERROR_SIZE] = {0};
   103    char* cert_file = getenv("SSL_CERT_FILE");
   104  
   105    mf = memfopen();
   106    curl = curl_easy_init();
   107    curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 1);
   108    curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 2);
   109    curl_easy_setopt(curl, CURLOPT_USERAGENT, "curl/7.29.0");
   110    curl_easy_setopt(curl, CURLOPT_URL, "https://api.github.com/repositories");
   111    if (cert_file)
   112      curl_easy_setopt(curl, CURLOPT_CAINFO, cert_file);
   113    curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1);
   114    curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, error);
   115    curl_easy_setopt(curl, CURLOPT_WRITEDATA, mf);
   116    curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, memfwrite);
   117    res = curl_easy_perform(curl);
   118    curl_easy_cleanup(curl);
   119    if (res != CURLE_OK) {
   120      std::cerr << error << std::endl;
   121      return SQLITE_FAIL;
   122    }
   123  
   124    picojson::value* v = new picojson::value;
   125    std::string err;
   126    picojson::parse(*v, mf->data, mf->data + mf->size, &err);
   127    memfclose(mf);
   128  
   129    if (!err.empty()) {
   130      delete v;
   131      std::cerr << err << std::endl;
   132      return SQLITE_FAIL;
   133    }
   134  
   135    cursor *c = (cursor *)sqlite3_malloc(sizeof(cursor));
   136    c->rows = v;
   137    c->index = 0;
   138    *ppCursor = &c->base;
   139    return SQLITE_OK;
   140  }
   141  
   142  static int
   143  my_close(cursor *c) {
   144    delete c->rows;
   145    sqlite3_free(c);
   146    return SQLITE_OK;
   147  }
   148  
   149  static int
   150  my_filter(cursor *c, int idxNum, const char *idxStr, int argc, sqlite3_value **argv) {
   151    c->index = 0;
   152    return SQLITE_OK;
   153  }
   154  
   155  static int
   156  my_next(cursor *c) {
   157    c->index++;
   158    return SQLITE_OK;
   159  }
   160  
   161  static int
   162  my_eof(cursor *c) {
   163    return c->index >= c->rows->get<picojson::array>().size() ? 1 : 0;
   164  }
   165  
   166  static int
   167  my_column(cursor *c, sqlite3_context *ctxt, int i) {
   168    picojson::value v = c->rows->get<picojson::array>()[c->index];
   169    picojson::object row = v.get<picojson::object>();
   170    const char* p = NULL;
   171    switch (i) {
   172    case 0:
   173      p = row["id"].to_str().c_str();
   174      break;
   175    case 1:
   176      p = row["full_name"].to_str().c_str();
   177      break;
   178    case 2:
   179      p = row["description"].to_str().c_str();
   180      break;
   181    case 3:
   182      p = row["html_url"].to_str().c_str();
   183      break;
   184    }
   185    sqlite3_result_text(ctxt, strdup(p), strlen(p), free);
   186    return SQLITE_OK;
   187  }
   188  
   189  static int
   190  my_rowid(cursor *c, sqlite3_int64 *pRowid) {
   191    *pRowid = c->index;
   192    return SQLITE_OK;
   193  }
   194  
   195  static int
   196  my_bestindex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo) {
   197    return SQLITE_OK;
   198  }
   199  
   200  static const sqlite3_module module = {
   201    0,
   202    my_create,
   203    my_connect,
   204    my_bestindex,
   205    my_disconnect,
   206    my_destroy,
   207    my_open,
   208    (int (*)(sqlite3_vtab_cursor *)) my_close,
   209    (int (*)(sqlite3_vtab_cursor *, int, char const *, int, sqlite3_value **)) my_filter,
   210    (int (*)(sqlite3_vtab_cursor *)) my_next,
   211    (int (*)(sqlite3_vtab_cursor *)) my_eof,
   212    (int (*)(sqlite3_vtab_cursor *, sqlite3_context *, int)) my_column,
   213    (int (*)(sqlite3_vtab_cursor *, sqlite3_int64 *)) my_rowid,
   214    NULL, // my_update
   215    NULL, // my_begin
   216    NULL, // my_sync
   217    NULL, // my_commit
   218    NULL, // my_rollback
   219    NULL, // my_findfunction
   220    NULL, // my_rename
   221  };
   222  
   223  static void
   224  destructor(void *arg) {
   225    return;
   226  }
   227  
   228  
   229  extern "C" {
   230  
   231  EXPORT int
   232  sqlite3_extension_init(sqlite3 *db, char **errmsg, const sqlite3_api_routines *api) {
   233    SQLITE_EXTENSION_INIT2(api);
   234    sqlite3_create_module_v2(db, "github", &module, NULL, destructor);
   235    return 0;
   236  }
   237  
   238  }