OSDN Git Service

add sqlite vendor (#48)
[bytom/vapor.git] / vendor / github.com / mattn / go-sqlite3 / _example / mod_vtable / sqlite3_mod_vtable.cc
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 }