2
* Drizzle Client & Protocol Library
4
* Copyright (C) 2008 Eric Day (eday@oddments.org)
7
* Use and distribution licensed under the BSD license. See
8
* the COPYING file in this directory for full text.
18
#include <libdrizzle/drizzle_server.h>
21
#define SQLITE_SERVER_VERSION "SQLite Server using libdrizzle 0.1"
23
#define DRIZZLE_RETURN_CHECK(__ret, __function, __drizzle) \
25
if ((__ret) != DRIZZLE_RETURN_OK) \
26
DRIZZLE_RETURN_ERROR(__function, __drizzle) \
29
#define DRIZZLE_RETURN_ERROR(__function, __drizzle) \
31
printf(__function ":%s\n", drizzle_error(__drizzle)); \
35
#define DRIZZLE_RETURN_CHECK_VAL(__ret, __function, __drizzle) \
37
if ((__ret) != DRIZZLE_RETURN_OK) \
39
printf(__function ":%s\n", drizzle_error(__drizzle)); \
48
drizzle_result_st result;
49
drizzle_column_st column;
52
drizzle_verbose_t verbose;
56
static void server_run(sqlite_server *server);
57
static int row_cb(void *data, int field_count, char **fields, char **columns);
58
static drizzle_return_t send_version(sqlite_server *server);
59
static void usage(char *name);
61
int main(int argc, char *argv[])
65
const char *host= NULL;
70
drizzle_con_st con_listen;
73
server.verbose= DRIZZLE_VERBOSE_NEVER;
75
while((c = getopt(argc, argv, "c:h:mp:v")) != -1)
80
count= (uint32_t)atoi(optarg);
92
port= (in_port_t)atoi(optarg);
105
if (argc != (optind + 1))
111
sqlite3_open(argv[optind], &(server.db));
112
if (server.db == NULL)
114
printf("sqlite3_open: could not open sqlite3 db\n");
118
if (drizzle_create(&server.drizzle) == NULL)
120
printf("drizzle_create:NULL\n");
124
drizzle_add_options(&server.drizzle, DRIZZLE_FREE_OBJECTS);
125
drizzle_set_verbose(&server.drizzle, server.verbose);
127
if (drizzle_con_create(&server.drizzle, &con_listen) == NULL)
129
printf("drizzle_con_create:NULL\n");
133
drizzle_con_add_options(&con_listen, DRIZZLE_CON_LISTEN);
134
drizzle_con_set_tcp(&con_listen, host, port);
137
drizzle_con_add_options(&con_listen, DRIZZLE_CON_MYSQL);
139
if (drizzle_con_listen(&con_listen) != DRIZZLE_RETURN_OK)
141
printf("drizzle_con_listen:%s\n", drizzle_error(&server.drizzle));
147
(void)drizzle_con_accept(&server.drizzle, &server.con, &ret);
148
if (ret != DRIZZLE_RETURN_OK)
150
printf("drizzle_con_accept:%s\n", drizzle_error(&server.drizzle));
156
drizzle_con_free(&server.con);
167
drizzle_con_free(&con_listen);
168
drizzle_free(&server.drizzle);
169
sqlite3_close(server.db);
174
static void server_run(sqlite_server *server)
176
drizzle_return_t ret;
177
drizzle_command_t command;
183
/* Handshake packets. */
184
drizzle_con_set_protocol_version(&(server->con), 10);
185
drizzle_con_set_server_version(&(server->con), "libdrizzle+SQLite");
186
drizzle_con_set_thread_id(&(server->con), 1);
187
drizzle_con_set_scramble(&(server->con),
188
(const uint8_t *)"ABCDEFGHIJKLMNOPQRST");
189
drizzle_con_set_capabilities(&(server->con), DRIZZLE_CAPABILITIES_NONE);
190
drizzle_con_set_charset(&(server->con), 8);
191
drizzle_con_set_status(&(server->con), DRIZZLE_CON_STATUS_NONE);
192
drizzle_con_set_max_packet_size(&(server->con), DRIZZLE_MAX_PACKET_SIZE);
194
ret= drizzle_handshake_server_write(&(server->con));
195
DRIZZLE_RETURN_CHECK(ret, "drizzle_handshake_server_write",
198
ret= drizzle_handshake_client_read(&(server->con));
199
DRIZZLE_RETURN_CHECK(ret, "drizzle_handshake_client_read", &(server->drizzle))
201
if (drizzle_result_create(&(server->con), &(server->result)) == NULL)
202
DRIZZLE_RETURN_ERROR("drizzle_result_create", &(server->drizzle))
204
ret= drizzle_result_write(&(server->con), &(server->result), true);
205
DRIZZLE_RETURN_CHECK(ret, "drizzle_result_write", &(server->drizzle))
210
drizzle_result_free(&(server->result));
214
data= drizzle_con_command_buffer(&(server->con), &command, &total, &ret);
215
if (ret == DRIZZLE_RETURN_LOST_CONNECTION ||
216
(ret == DRIZZLE_RETURN_OK && command == DRIZZLE_COMMAND_QUIT))
222
DRIZZLE_RETURN_CHECK(ret, "drizzle_con_command_buffer", &(server->drizzle))
224
if (server->verbose >= DRIZZLE_VERBOSE_INFO)
226
printf("Command=%u Data=%s\n", command,
227
data == NULL ? "NULL" : (char *)data);
230
if (drizzle_result_create(&(server->con), &(server->result)) == NULL)
231
DRIZZLE_RETURN_ERROR("drizzle_result_create", &(server->drizzle))
233
if (command != DRIZZLE_COMMAND_QUERY ||
234
!strcasecmp((char *)data, "SHOW DATABASES"))
236
ret= drizzle_result_write(&(server->con), &(server->result), true);
237
DRIZZLE_RETURN_CHECK(ret, "drizzle_result_write", &(server->drizzle))
239
if (command == DRIZZLE_COMMAND_FIELD_LIST)
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))
249
if (strstr((char *)data, "@@version") != NULL)
251
ret= send_version(server);
252
if (ret != DRIZZLE_RETURN_OK)
258
server->send_columns= true;
261
if (!strcasecmp((char *)data, "SHOW TABLES"))
263
sqlite_ret= sqlite3_exec(server->db,
264
"SELECT name FROM sqlite_master WHERE type='table'",
265
row_cb, server, &sqlite_err);
269
sqlite_ret= sqlite3_exec(server->db, (char *)data, row_cb, server,
273
if (sqlite_ret != SQLITE_OK)
275
if (sqlite_err == NULL)
276
printf("sqlite3_exec failed\n");
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))
284
printf("sqlite3_exec:%s\n", sqlite_err);
285
sqlite3_free(sqlite_err);
291
if (server->rows == 0)
293
drizzle_result_set_column_count(&(server->result), 0);
294
ret= drizzle_result_write(&(server->con), &(server->result), true);
295
DRIZZLE_RETURN_CHECK(ret, "drizzle_result_write", &(server->drizzle))
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))
306
static int row_cb(void *data, int field_count, char **fields, char **columns)
308
sqlite_server *server= (sqlite_server *)data;
309
drizzle_return_t ret;
313
if (server->send_columns == true)
315
server->send_columns= false;
316
drizzle_result_set_column_count(&(server->result), (uint16_t)field_count);
318
ret= drizzle_result_write(&(server->con), &(server->result), false);
319
DRIZZLE_RETURN_CHECK_VAL(ret, "drizzle_result_write", &(server->drizzle))
321
if (drizzle_column_create(&(server->result), &(server->column)) == NULL)
323
DRIZZLE_RETURN_CHECK_VAL(DRIZZLE_RETURN_MEMORY, "drizzle_column_create",
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);
332
drizzle_column_set_type(&(server->column), DRIZZLE_COLUMN_TYPE_VARCHAR);
334
for (x= 0; x < field_count; x++)
336
drizzle_column_set_size(&(server->column),
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]);
342
ret= drizzle_column_write(&(server->result), &(server->column));
343
DRIZZLE_RETURN_CHECK_VAL(ret, "drizzle_column_write", &(server->drizzle))
346
drizzle_column_free(&(server->column));
348
drizzle_result_set_eof(&(server->result), true);
350
ret= drizzle_result_write(&(server->con), &(server->result), false);
351
DRIZZLE_RETURN_CHECK_VAL(ret, "drizzle_result_write", &(server->drizzle))
354
for (x= 0; x < field_count; x++)
356
if (fields[x] == NULL)
359
sizes[x]= strlen(fields[x]);
362
/* This is needed for MySQL and old Drizzle protocol. */
363
drizzle_result_calc_row_size(&(server->result), (drizzle_field_t *)fields,
366
ret= drizzle_row_write(&(server->result));
367
DRIZZLE_RETURN_CHECK_VAL(ret, "drizzle_row_write", &(server->drizzle))
369
for (x= 0; x < field_count; x++)
371
ret= drizzle_field_write(&(server->result), (drizzle_field_t)fields[x],
373
DRIZZLE_RETURN_CHECK_VAL(ret, "drizzle_field_write", &(server->drizzle))
381
static drizzle_return_t send_version(sqlite_server *server)
383
drizzle_return_t ret;
384
drizzle_field_t fields[1];
387
fields[0]= (drizzle_field_t)SQLITE_SERVER_VERSION;
388
sizes[0]= strlen(SQLITE_SERVER_VERSION);
390
drizzle_result_set_column_count(&(server->result), 1);
392
ret= drizzle_result_write(&(server->con), &(server->result), false);
393
DRIZZLE_RETURN_CHECK_VAL(ret, "drizzle_result_write", &(server->drizzle))
395
if (drizzle_column_create(&(server->result), &(server->column)) == NULL)
397
DRIZZLE_RETURN_CHECK_VAL(DRIZZLE_RETURN_MEMORY, "drizzle_column_create",
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);
406
drizzle_column_set_type(&(server->column), DRIZZLE_COLUMN_TYPE_VARCHAR);
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");
411
ret= drizzle_column_write(&(server->result), &(server->column));
412
DRIZZLE_RETURN_CHECK_VAL(ret, "drizzle_column_write", &(server->drizzle))
414
drizzle_column_free(&(server->column));
416
drizzle_result_set_eof(&(server->result), true);
418
ret= drizzle_result_write(&(server->con), &(server->result), false);
419
DRIZZLE_RETURN_CHECK_VAL(ret, "drizzle_result_write", &(server->drizzle))
421
/* This is needed for MySQL and old Drizzle protocol. */
422
drizzle_result_calc_row_size(&(server->result), fields, sizes);
424
ret= drizzle_row_write(&(server->result));
425
DRIZZLE_RETURN_CHECK_VAL(ret, "drizzle_row_write", &(server->drizzle))
427
ret= drizzle_field_write(&(server->result), fields[0], sizes[0], sizes[0]);
428
DRIZZLE_RETURN_CHECK_VAL(ret, "drizzle_field_write", &(server->drizzle))
430
ret= drizzle_result_write(&(server->con), &(server->result), true);
431
DRIZZLE_RETURN_CHECK_VAL(ret, "drizzle_result_write", &(server->drizzle))
433
return DRIZZLE_RETURN_OK;
436
static void usage(char *name)
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");