27 #include <drizzled/module/module.h>
28 #include <drizzled/module/context.h>
29 #include <drizzled/plugin/plugin.h>
30 #include <drizzled/plugin.h>
31 #include <drizzled/plugin/daemon.h>
32 #include <drizzled/sys_var.h>
33 #include <drizzled/gettext.h>
34 #include <drizzled/error.h>
35 #include <drizzled/session.h>
36 #include <drizzled/internal/my_sys.h>
37 #include <drizzled/internal/m_string.h>
40 #include <boost/program_options.hpp>
42 #include <drizzled/constrained_value.h>
45 #include <drizzled/execute.h>
46 #include <drizzled/sql/result_set.h>
48 #include <drizzled/plugin/listen.h>
49 #include <drizzled/plugin/client.h>
50 #include <drizzled/catalog/local.h>
52 #include <drizzled/pthread_globals.h>
53 #include <boost/bind.hpp>
56 #include <drizzled/version.h>
57 #include <plugin/json_server/json/json.h>
59 namespace po= boost::program_options;
60 using namespace drizzled;
63 namespace drizzle_plugin
70 static in_port_t getPort(
void)
75 extern "C" void process_request(
struct evhttp_request *req,
void* );
76 extern "C" void process_root_request(
struct evhttp_request *req,
void* );
77 extern "C" void process_api01_version_req(
struct evhttp_request *req,
void* );
78 extern "C" void process_api01_sql_req(
struct evhttp_request *req,
void* );
80 extern "C" void process_request(
struct evhttp_request *req,
void* )
82 struct evbuffer *buf = evbuffer_new();
83 if (buf == NULL)
return;
84 evbuffer_add_printf(buf,
"Requested: %s\n", evhttp_request_uri(req));
85 evhttp_send_reply(req, HTTP_OK,
"OK", buf);
88 extern "C" void process_root_request(
struct evhttp_request *req,
void* )
90 struct evbuffer *buf = evbuffer_new();
91 if (buf == NULL)
return;
95 output.append(
"<html><head><title>JSON DATABASE interface demo</title></head>"
97 "<script lang=\"javascript\">"
98 "function to_table(obj) {"
99 " var str = '<table>';"
100 "for (var r=0; r< obj.length; r++) {"
102 " for (var c=0; c < obj[r].length; c++) {"
103 " str+= '<td>' + obj[r][c] + '</td>';"
110 "function run_query()\n"
112 "var url = document.getElementById(\"baseurl\").innerHTML;\n"
113 "var query= document.getElementById(\"query\").value;\n"
114 "var xmlHttp = new XMLHttpRequest();\n"
115 "xmlHttp.onreadystatechange = function () {\n"
116 "if (xmlHttp.readyState == 4 && xmlHttp.status == 200) {\n"
117 "var info = eval ( \"(\" + xmlHttp.responseText + \")\" );\n"
118 "document.getElementById( \"resultset\").innerHTML= to_table(info.result_set);\n"
121 "xmlHttp.open(\"POST\", url + \"/0.1/sql\", true);"
122 "xmlHttp.send(query);"
125 "function update_version()\n"
126 "{drizzle_version(document.getElementById(\"baseurl\").innerHTML);}\n\n"
127 "function drizzle_version($url)"
129 "var xmlHttp = new XMLHttpRequest();\n"
130 "xmlHttp.onreadystatechange = function () {\n"
131 "if (xmlHttp.readyState == 4 && xmlHttp.status == 200) {\n"
132 "var info = eval ( \"(\" + xmlHttp.responseText + \")\" );\n"
133 "document.getElementById( \"drizzleversion\").innerHTML= info.version;\n"
136 "xmlHttp.open(\"GET\", $url + \"/0.1/version\", true);"
137 "xmlHttp.send(null);"
140 "<p>Drizzle Server at: <a id=\"baseurl\">http://localhost:8765</a></p>"
141 "<p>Drizzle server version: <a id=\"drizzleversion\"></a></p>"
142 "<p><textarea rows=\"3\" cols=\"40\" id=\"query\">"
143 "SELECT * from DATA_DICTIONARY.GLOBAL_STATUS;"
145 "<button type=\"button\" onclick=\"run_query();\">Execute Query</button>"
146 "<div id=\"resultset\"/>"
147 "<script lang=\"javascript\">update_version(); run_query();</script>"
150 evbuffer_add(buf, output.c_str(), output.length());
151 evhttp_send_reply(req, HTTP_OK,
"OK", buf);
154 extern "C" void process_api01_version_req(
struct evhttp_request *req,
void* )
156 struct evbuffer *buf = evbuffer_new();
157 if (buf == NULL)
return;
160 root[
"version"]= ::drizzled::version();
163 std::string output= writer.
write(root);
165 evbuffer_add(buf, output.c_str(), output.length());
166 evhttp_send_reply(req, HTTP_OK,
"OK", buf);
169 extern "C" void process_api01_sql_req(
struct evhttp_request *req,
void* )
171 struct evbuffer *buf = evbuffer_new();
172 if (buf == NULL)
return;
178 l= evbuffer_remove(req->input_buffer, buffer, 1024);
179 input.append(buffer, l);
183 drizzled::catalog::local());
184 drizzled::identifier::user::mptr user_id= identifier::User::make_shared();
185 user_id->setUser(
"");
186 _session->setUser(user_id);
187 _session->set_schema(
"test");
194 execute.run(input, result_set);
197 drizzled::error_t err= exception.getErrorCode();
200 root[
"sqlstate"]= exception.getSQLState();
202 if ((err != drizzled::EE_OK) && (err != drizzled::ER_EMPTY_QUERY))
204 root[
"error_message"]= exception.getErrorMessage();
205 root[
"error_code"]= exception.getErrorCode();
208 while (result_set.next())
211 for (
size_t x= 0; x < result_set.getMetaData().getColumnCount(); x++)
213 if (not result_set.isNull(x))
215 json_row[x]= result_set.getString(x);
218 root[
"result_set"].
append(json_row);
221 root[
"query"]= input;
224 std::string output= writer.
write(root);
226 evbuffer_add(buf, output.c_str(), output.length());
227 evhttp_send_reply(req, HTTP_OK,
"OK", buf);
230 static void shutdown_event(
int fd,
short,
void *arg)
232 struct event_base *base= (
struct event_base *)arg;
233 event_base_loopbreak(base);
238 static void run(
struct event_base *base)
240 internal::my_thread_init();
242 event_base_dispatch(base);
249 drizzled::thread_ptr json_thread;
251 struct evhttp *httpd;
252 struct event_base *base;
254 struct event wakeup_event;
266 if (pipe(wakeup_fd) < 0)
273 if ((returned_flags= fcntl(wakeup_fd[0], F_GETFL, 0)) < 0)
275 sql_perror(
"fcntl:F_GETFL");
279 if (fcntl(wakeup_fd[0], F_SETFL, returned_flags | O_NONBLOCK) < 0)
282 sql_perror(
"F_SETFL");
286 if ((base= event_init()) == NULL)
288 sql_perror(
"event_init()");
292 if ((httpd= evhttp_new(base)) == NULL)
294 sql_perror(
"evhttp_new()");
299 if ((evhttp_bind_socket(httpd,
"0.0.0.0", getPort())) == -1)
301 sql_perror(
"evhttp_bind_socket()");
305 evhttp_set_cb(httpd,
"/", process_root_request, NULL);
306 evhttp_set_cb(httpd,
"/0.1/version", process_api01_version_req, NULL);
307 evhttp_set_cb(httpd,
"/0.1/sql", process_api01_sql_req, NULL);
308 evhttp_set_gencb(httpd, process_request, NULL);
310 event_set(&wakeup_event, wakeup_fd[0], EV_READ | EV_PERSIST, shutdown_event, base);
311 event_base_set(base, &wakeup_event);
312 if (event_add(&wakeup_event, NULL) < 0)
314 sql_perror(
"event_add");
318 json_thread.reset(
new boost::thread((boost::bind(&run, base))));
331 if ((write(wakeup_fd[1], &buffer, 1)) == 1)
335 event_base_free(base);
347 if (server and not server->init())
352 return bool(server) ? 0 : 1;
358 po::value<port_constraint>(&port)->default_value(8086),
359 _(
"Port number to use for connection or 0 for default (port 8086) "));
365 DRIZZLE_DECLARE_PLUGIN
371 N_(
"JSON HTTP interface"),
373 drizzle_plugin::json_server::json_server_init,
375 drizzle_plugin::json_server::init_options
377 DRIZZLE_DECLARE_PLUGIN_END;