libdrizzle Public API Documentation

sqlite_server.c
Go to the documentation of this file.
1/*
2 * Drizzle Client & Protocol Library
3 *
4 * Copyright (C) 2008 Eric Day (eday@oddments.org)
5 * All rights reserved.
6 *
7 * Use and distribution licensed under the BSD license. See
8 * the COPYING file in this directory for full text.
9 */
10
11#include <errno.h>
12#include <stdio.h>
13#include <stdlib.h>
14#include <string.h>
15#include <strings.h>
16#include <unistd.h>
17
19#include <sqlite3.h>
20
21#define SQLITE_SERVER_VERSION "SQLite Server using libdrizzle 0.1"
22
23#define DRIZZLE_RETURN_CHECK(__ret, __function, __drizzle) \
24{ \
25 if ((__ret) != DRIZZLE_RETURN_OK) \
26 DRIZZLE_RETURN_ERROR(__function, __drizzle) \
27}
28
29#define DRIZZLE_RETURN_ERROR(__function, __drizzle) \
30{ \
31 printf(__function ":%s\n", drizzle_error(__drizzle)); \
32 return; \
33}
34
35#define DRIZZLE_RETURN_CHECK_VAL(__ret, __function, __drizzle) \
36{ \
37 if ((__ret) != DRIZZLE_RETURN_OK) \
38 { \
39 printf(__function ":%s\n", drizzle_error(__drizzle)); \
40 return ret; \
41 } \
42}
43
55
56static void server_run(sqlite_server *server);
57static int row_cb(void *data, int field_count, char **fields, char **columns);
59static void usage(char *name);
60
61int main(int argc, char *argv[])
62{
63 int c;
64 uint32_t count= 0;
65 const char *host= NULL;
66 bool mysql= false;
67 in_port_t port= 0;
70 drizzle_con_st con_listen;
71
72 server.db= NULL;
74
75 while((c = getopt(argc, argv, "c:h:mp:v")) != -1)
76 {
77 switch(c)
78 {
79 case 'c':
80 count= (uint32_t)atoi(optarg);
81 break;
82
83 case 'h':
84 host= optarg;
85 break;
86
87 case 'm':
88 mysql= true;
89 break;
90
91 case 'p':
92 port= (in_port_t)atoi(optarg);
93 break;
94
95 case 'v':
96 server.verbose++;
97 break;
98
99 default:
100 usage(argv[0]);
101 return 1;
102 }
103 }
104
105 if (argc != (optind + 1))
106 {
107 usage(argv[0]);
108 return 1;
109 }
110
111 sqlite3_open(argv[optind], &(server.db));
112 if (server.db == NULL)
113 {
114 printf("sqlite3_open: could not open sqlite3 db\n");
115 return 1;
116 }
117
118 if (drizzle_create(&server.drizzle) == NULL)
119 {
120 printf("drizzle_create:NULL\n");
121 return 1;
122 }
123
125 drizzle_set_verbose(&server.drizzle, server.verbose);
126
127 if (drizzle_con_create(&server.drizzle, &con_listen) == NULL)
128 {
129 printf("drizzle_con_create:NULL\n");
130 return 1;
131 }
132
134 drizzle_con_set_tcp(&con_listen, host, port);
135
136 if (mysql)
138
139 if (drizzle_con_listen(&con_listen) != DRIZZLE_RETURN_OK)
140 {
141 printf("drizzle_con_listen:%s\n", drizzle_error(&server.drizzle));
142 return 1;
143 }
144
145 while (1)
146 {
147 (void)drizzle_con_accept(&server.drizzle, &server.con, &ret);
148 if (ret != DRIZZLE_RETURN_OK)
149 {
150 printf("drizzle_con_accept:%s\n", drizzle_error(&server.drizzle));
151 return 1;
152 }
153
155
157
158 if (count > 0)
159 {
160 count--;
161
162 if (count == 0)
163 break;
164 }
165 }
166
167 drizzle_con_free(&con_listen);
168 drizzle_free(&server.drizzle);
169 sqlite3_close(server.db);
170
171 return 0;
172}
173
175{
177 drizzle_command_t command;
178 uint8_t *data= NULL;
179 size_t total;
180 int sqlite_ret;
181 char *sqlite_err;
182
183 /* Handshake packets. */
185 drizzle_con_set_server_version(&(server->con), "libdrizzle+SQLite");
188 (const uint8_t *)"ABCDEFGHIJKLMNOPQRST");
193
195 DRIZZLE_RETURN_CHECK(ret, "drizzle_handshake_server_write",
196 &(server->drizzle))
197
199 DRIZZLE_RETURN_CHECK(ret, "drizzle_handshake_client_read", &(server->drizzle))
200
201 if (drizzle_result_create(&(server->con), &(server->result)) == NULL)
202 DRIZZLE_RETURN_ERROR("drizzle_result_create", &(server->drizzle))
203
204 ret= drizzle_result_write(&(server->con), &(server->result), true);
205 DRIZZLE_RETURN_CHECK(ret, "drizzle_result_write", &(server->drizzle))
206
207 /* Command loop. */
208 while (1)
209 {
210 drizzle_result_free(&(server->result));
211 if (data != NULL)
212 free(data);
213
214 data= drizzle_con_command_buffer(&(server->con), &command, &total, &ret);
216 (ret == DRIZZLE_RETURN_OK && command == DRIZZLE_COMMAND_QUIT))
217 {
218 if (data != NULL)
219 free(data);
220 return;
221 }
222 DRIZZLE_RETURN_CHECK(ret, "drizzle_con_command_buffer", &(server->drizzle))
223
224 if (server->verbose >= DRIZZLE_VERBOSE_INFO)
225 {
226 printf("Command=%u Data=%s\n", command,
227 data == NULL ? "NULL" : (char *)data);
228 }
229
230 if (drizzle_result_create(&(server->con), &(server->result)) == NULL)
231 DRIZZLE_RETURN_ERROR("drizzle_result_create", &(server->drizzle))
232
233 if (command != DRIZZLE_COMMAND_QUERY ||
234 !strcasecmp((char *)data, "SHOW DATABASES"))
235 {
236 ret= drizzle_result_write(&(server->con), &(server->result), true);
237 DRIZZLE_RETURN_CHECK(ret, "drizzle_result_write", &(server->drizzle))
238
239 if (command == DRIZZLE_COMMAND_FIELD_LIST)
240 {
241 drizzle_result_set_eof(&(server->result), true);
242 ret= drizzle_result_write(&(server->con), &(server->result), true);
243 DRIZZLE_RETURN_CHECK(ret, "drizzle_result_write", &(server->drizzle))
244 }
245
246 continue;
247 }
248
249 if (strstr((char *)data, "@@version") != NULL)
250 {
251 ret= send_version(server);
252 if (ret != DRIZZLE_RETURN_OK)
253 return;
254
255 continue;
256 }
257
258 server->send_columns= true;
259 server->rows= 0;
260
261 if (!strcasecmp((char *)data, "SHOW TABLES"))
262 {
263 sqlite_ret= sqlite3_exec(server->db,
264 "SELECT name FROM sqlite_master WHERE type='table'",
265 row_cb, server, &sqlite_err);
266 }
267 else
268 {
269 sqlite_ret= sqlite3_exec(server->db, (char *)data, row_cb, server,
270 &sqlite_err);
271 }
272
273 if (sqlite_ret != SQLITE_OK)
274 {
275 if (sqlite_err == NULL)
276 printf("sqlite3_exec failed\n");
277 else
278 {
279 drizzle_result_set_error_code(&(server->result), (uint16_t)sqlite_ret);
280 drizzle_result_set_error(&(server->result), sqlite_err);
281 ret= drizzle_result_write(&(server->con), &(server->result), true);
282 DRIZZLE_RETURN_CHECK(ret, "drizzle_result_write", &(server->drizzle))
283
284 printf("sqlite3_exec:%s\n", sqlite_err);
285 sqlite3_free(sqlite_err);
286 }
287
288 return;
289 }
290
291 if (server->rows == 0)
292 {
294 ret= drizzle_result_write(&(server->con), &(server->result), true);
295 DRIZZLE_RETURN_CHECK(ret, "drizzle_result_write", &(server->drizzle))
296 }
297 else
298 {
299 drizzle_result_set_eof(&(server->result), true);
300 ret= drizzle_result_write(&(server->con), &(server->result), true);
301 DRIZZLE_RETURN_CHECK(ret, "drizzle_result_write", &(server->drizzle))
302 }
303 }
304}
305
306static int row_cb(void *data, int field_count, char **fields, char **columns)
307{
310 int x;
311 size_t sizes[8192];
312
313 if (server->send_columns == true)
314 {
315 server->send_columns= false;
316 drizzle_result_set_column_count(&(server->result), (uint16_t)field_count);
317
318 ret= drizzle_result_write(&(server->con), &(server->result), false);
319 DRIZZLE_RETURN_CHECK_VAL(ret, "drizzle_result_write", &(server->drizzle))
320
321 if (drizzle_column_create(&(server->result), &(server->column)) == NULL)
322 {
323 DRIZZLE_RETURN_CHECK_VAL(DRIZZLE_RETURN_MEMORY, "drizzle_column_create",
324 &(server->drizzle))
325 }
326
327 drizzle_column_set_catalog(&(server->column), "sqlite");
328 drizzle_column_set_db(&(server->column), "sqlite_db");
329 drizzle_column_set_table(&(server->column), "sqlite_table");
330 drizzle_column_set_orig_table(&(server->column), "sqlite_table");
331 drizzle_column_set_charset(&(server->column), 8);
333
334 for (x= 0; x < field_count; x++)
335 {
337 fields[x] == NULL ?
338 0 : (uint32_t)strlen(fields[x]));
339 drizzle_column_set_name(&(server->column), columns[x]);
340 drizzle_column_set_orig_name(&(server->column), columns[x]);
341
342 ret= drizzle_column_write(&(server->result), &(server->column));
343 DRIZZLE_RETURN_CHECK_VAL(ret, "drizzle_column_write", &(server->drizzle))
344 }
345
346 drizzle_column_free(&(server->column));
347
348 drizzle_result_set_eof(&(server->result), true);
349
350 ret= drizzle_result_write(&(server->con), &(server->result), false);
351 DRIZZLE_RETURN_CHECK_VAL(ret, "drizzle_result_write", &(server->drizzle))
352 }
353
354 for (x= 0; x < field_count; x++)
355 {
356 if (fields[x] == NULL)
357 sizes[x]= 0;
358 else
359 sizes[x]= strlen(fields[x]);
360 }
361
362 /* This is needed for MySQL and old Drizzle protocol. */
364 sizes);
365
366 ret= drizzle_row_write(&(server->result));
367 DRIZZLE_RETURN_CHECK_VAL(ret, "drizzle_row_write", &(server->drizzle))
368
369 for (x= 0; x < field_count; x++)
370 {
371 ret= drizzle_field_write(&(server->result), (drizzle_field_t)fields[x],
372 sizes[x], sizes[x]);
373 DRIZZLE_RETURN_CHECK_VAL(ret, "drizzle_field_write", &(server->drizzle))
374 }
375
376 server->rows++;
377
378 return 0;
379}
380
382{
384 drizzle_field_t fields[1];
385 size_t sizes[1];
386
388 sizes[0]= strlen(SQLITE_SERVER_VERSION);
389
391
392 ret= drizzle_result_write(&(server->con), &(server->result), false);
393 DRIZZLE_RETURN_CHECK_VAL(ret, "drizzle_result_write", &(server->drizzle))
394
395 if (drizzle_column_create(&(server->result), &(server->column)) == NULL)
396 {
397 DRIZZLE_RETURN_CHECK_VAL(DRIZZLE_RETURN_MEMORY, "drizzle_column_create",
398 &(server->drizzle))
399 }
400
401 drizzle_column_set_catalog(&(server->column), "sqlite");
402 drizzle_column_set_db(&(server->column), "sqlite_db");
403 drizzle_column_set_table(&(server->column), "sqlite_table");
404 drizzle_column_set_orig_table(&(server->column), "sqlite_table");
405 drizzle_column_set_charset(&(server->column), 8);
407 drizzle_column_set_size(&(server->column), (uint32_t)sizes[0]);
408 drizzle_column_set_name(&(server->column), "version");
409 drizzle_column_set_orig_name(&(server->column), "version");
410
411 ret= drizzle_column_write(&(server->result), &(server->column));
412 DRIZZLE_RETURN_CHECK_VAL(ret, "drizzle_column_write", &(server->drizzle))
413
414 drizzle_column_free(&(server->column));
415
416 drizzle_result_set_eof(&(server->result), true);
417
418 ret= drizzle_result_write(&(server->con), &(server->result), false);
419 DRIZZLE_RETURN_CHECK_VAL(ret, "drizzle_result_write", &(server->drizzle))
420
421 /* This is needed for MySQL and old Drizzle protocol. */
422 drizzle_result_calc_row_size(&(server->result), fields, sizes);
423
424 ret= drizzle_row_write(&(server->result));
425 DRIZZLE_RETURN_CHECK_VAL(ret, "drizzle_row_write", &(server->drizzle))
426
427 ret= drizzle_field_write(&(server->result), fields[0], sizes[0], sizes[0]);
428 DRIZZLE_RETURN_CHECK_VAL(ret, "drizzle_field_write", &(server->drizzle))
429
430 ret= drizzle_result_write(&(server->con), &(server->result), true);
431 DRIZZLE_RETURN_CHECK_VAL(ret, "drizzle_result_write", &(server->drizzle))
432
433 return DRIZZLE_RETURN_OK;
434}
435
436static void usage(char *name)
437{
438 printf("\nusage: %s [-c <count>] [-h <host>] [-m] [-p <port>] [-v] "
439 "<sqlite3 db file>\n", name);
440 printf("\t-c <count> - Number of connections to accept before exiting\n");
441 printf("\t-h <host> - Host to listen on\n");
442 printf("\t-m - Use the MySQL protocol\n");
443 printf("\t-p <port> - Port to listen on\n");
444 printf("\t-v - Increase verbosity level\n");
445}
drizzle_command_t
Definition constants.h:214
@ DRIZZLE_COMMAND_FIELD_LIST
Definition constants.h:219
@ DRIZZLE_COMMAND_QUIT
Definition constants.h:216
@ DRIZZLE_COMMAND_QUERY
Definition constants.h:218
Drizzle Declarations for Servers.
void drizzle_column_set_orig_table(drizzle_column_st *column, const char *orig_table)
void drizzle_column_set_charset(drizzle_column_st *column, drizzle_charset_t charset)
void drizzle_column_set_size(drizzle_column_st *column, uint32_t size)
drizzle_return_t drizzle_column_write(drizzle_result_st *result, drizzle_column_st *column)
void drizzle_column_set_db(drizzle_column_st *column, const char *db)
void drizzle_column_set_type(drizzle_column_st *column, drizzle_column_type_t type)
void drizzle_column_set_name(drizzle_column_st *column, const char *name)
void drizzle_column_set_table(drizzle_column_st *column, const char *table)
void drizzle_column_set_catalog(drizzle_column_st *column, const char *catalog)
void drizzle_column_set_orig_name(drizzle_column_st *column, const char *orig_name)
void drizzle_column_free(drizzle_column_st *column)
drizzle_column_st * drizzle_column_create(drizzle_result_st *result, drizzle_column_st *column)
@ DRIZZLE_COLUMN_TYPE_VARCHAR
Definition constants.h:330
void drizzle_con_set_status(drizzle_con_st *con, drizzle_con_status_t status)
void drizzle_con_set_server_version(drizzle_con_st *con, const char *server_version)
void drizzle_con_set_scramble(drizzle_con_st *con, const uint8_t *scramble)
drizzle_return_t drizzle_con_listen(drizzle_con_st *con)
void drizzle_con_set_max_packet_size(drizzle_con_st *con, uint32_t max_packet_size)
void drizzle_con_set_capabilities(drizzle_con_st *con, drizzle_capabilities_t capabilities)
void drizzle_con_set_charset(drizzle_con_st *con, drizzle_charset_t charset)
void * drizzle_con_command_buffer(drizzle_con_st *con, drizzle_command_t *command, size_t *total, drizzle_return_t *ret_ptr)
void drizzle_con_set_thread_id(drizzle_con_st *con, uint32_t thread_id)
void drizzle_con_set_protocol_version(drizzle_con_st *con, uint8_t protocol_version)
void drizzle_con_set_tcp(drizzle_con_st *con, const char *host, in_port_t port)
void drizzle_con_add_options(drizzle_con_st *con, drizzle_con_options_t options)
@ DRIZZLE_CON_STATUS_NONE
Definition constants.h:161
@ DRIZZLE_CAPABILITIES_NONE
Definition constants.h:180
@ DRIZZLE_CON_LISTEN
Definition constants.h:141
@ DRIZZLE_CON_MYSQL
Definition constants.h:135
#define DRIZZLE_MAX_PACKET_SIZE
Definition constants.h:54
drizzle_return_t
Definition constants.h:69
drizzle_verbose_t
Definition constants.h:102
@ DRIZZLE_RETURN_OK
Definition constants.h:70
@ DRIZZLE_RETURN_LOST_CONNECTION
Definition constants.h:90
@ DRIZZLE_RETURN_MEMORY
Definition constants.h:74
@ DRIZZLE_VERBOSE_NEVER
Definition constants.h:103
@ DRIZZLE_VERBOSE_INFO
Definition constants.h:106
drizzle_return_t drizzle_field_write(drizzle_result_st *result, const drizzle_field_t field, size_t size, size_t total)
drizzle_return_t drizzle_handshake_client_read(drizzle_con_st *con)
drizzle_return_t drizzle_handshake_server_write(drizzle_con_st *con)
void drizzle_result_set_error(drizzle_result_st *result, const char *error)
void drizzle_result_set_error_code(drizzle_result_st *result, uint16_t error_code)
void drizzle_result_set_eof(drizzle_result_st *result, bool eof)
drizzle_return_t drizzle_result_write(drizzle_con_st *con, drizzle_result_st *result, bool flush)
void drizzle_result_calc_row_size(drizzle_result_st *result, const drizzle_field_t *field, const size_t *size)
void drizzle_result_set_column_count(drizzle_result_st *result, uint16_t column_count)
drizzle_result_st * drizzle_result_create(drizzle_con_st *con, drizzle_result_st *result)
void drizzle_result_free(drizzle_result_st *result)
drizzle_return_t drizzle_row_write(drizzle_result_st *result)
drizzle_con_st * drizzle_con_accept(drizzle_st *drizzle, drizzle_con_st *con, drizzle_return_t *ret_ptr)
struct drizzle_result_st drizzle_result_st
Definition constants.h:410
char * drizzle_field_t
Definition constants.h:412
struct drizzle_con_st drizzle_con_st
Definition constants.h:408
struct drizzle_st drizzle_st
Definition constants.h:405
struct drizzle_column_st drizzle_column_st
Definition constants.h:411
drizzle_con_st * drizzle_con_create(drizzle_st *drizzle, drizzle_con_st *con)
const char * drizzle_error(const drizzle_st *drizzle)
void drizzle_set_verbose(drizzle_st *drizzle, drizzle_verbose_t verbose)
void drizzle_free(drizzle_st *drizzle)
void drizzle_add_options(drizzle_st *drizzle, drizzle_options_t options)
drizzle_st * drizzle_create(drizzle_st *drizzle)
void drizzle_con_free(drizzle_con_st *con)
@ DRIZZLE_FREE_OBJECTS
Definition constants.h:123
static void server(drizzle_st *drizzle, drizzle_con_st *con, drizzle_result_st *result, drizzle_column_st *column)
Definition server.c:142
#define DRIZZLE_RETURN_CHECK(__ret, __function, __drizzle)
int main(int argc, char *argv[])
static int row_cb(void *data, int field_count, char **fields, char **columns)
#define DRIZZLE_RETURN_CHECK_VAL(__ret, __function, __drizzle)
static void usage(char *name)
#define DRIZZLE_RETURN_ERROR(__function, __drizzle)
#define SQLITE_SERVER_VERSION
static void server_run(sqlite_server *server)
static drizzle_return_t send_version(sqlite_server *server)
drizzle_st drizzle
drizzle_verbose_t verbose
drizzle_con_st con
drizzle_result_st result
drizzle_column_st column