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.BSD file in the root source 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;
69
sqlite_server *server= (sqlite_server*)malloc(sizeof(sqlite_server));
70
drizzle_con_st *con_listen= (drizzle_con_st*)malloc(sizeof(drizzle_con_st));
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);
176
static void server_run(sqlite_server *server)
178
drizzle_return_t ret;
179
drizzle_command_t command;
185
/* Handshake packets. */
186
drizzle_con_set_protocol_version(&(server->con), 10);
187
drizzle_con_set_server_version(&(server->con), "libdrizzle+SQLite");
188
drizzle_con_set_thread_id(&(server->con), 1);
189
drizzle_con_set_scramble(&(server->con),
190
(const uint8_t *)"ABCDEFGHIJKLMNOPQRST");
191
drizzle_con_set_capabilities(&(server->con), DRIZZLE_CAPABILITIES_NONE);
192
drizzle_con_set_charset(&(server->con), 8);
193
drizzle_con_set_status(&(server->con), DRIZZLE_CON_STATUS_NONE);
194
drizzle_con_set_max_packet_size(&(server->con), DRIZZLE_MAX_PACKET_SIZE);
196
ret= drizzle_handshake_server_write(&(server->con));
197
DRIZZLE_RETURN_CHECK(ret, "drizzle_handshake_server_write",
200
ret= drizzle_handshake_client_read(&(server->con));
201
DRIZZLE_RETURN_CHECK(ret, "drizzle_handshake_client_read", &(server->drizzle))
203
if (drizzle_result_create(&(server->con), &(server->result)) == NULL)
204
DRIZZLE_RETURN_ERROR("drizzle_result_create", &(server->drizzle))
206
ret= drizzle_result_write(&(server->con), &(server->result), true);
207
DRIZZLE_RETURN_CHECK(ret, "drizzle_result_write", &(server->drizzle))
212
drizzle_result_free(&(server->result));
216
data= drizzle_con_command_buffer(&(server->con), &command, &total, &ret);
217
if (ret == DRIZZLE_RETURN_LOST_CONNECTION ||
218
(ret == DRIZZLE_RETURN_OK && command == DRIZZLE_COMMAND_QUIT))
224
DRIZZLE_RETURN_CHECK(ret, "drizzle_con_command_buffer", &(server->drizzle))
226
if (server->verbose >= DRIZZLE_VERBOSE_INFO)
228
printf("Command=%u Data=%s\n", command,
229
data == NULL ? "NULL" : (char *)data);
232
if (drizzle_result_create(&(server->con), &(server->result)) == NULL)
233
DRIZZLE_RETURN_ERROR("drizzle_result_create", &(server->drizzle))
235
if (command != DRIZZLE_COMMAND_QUERY ||
236
!strcasecmp((char *)data, "SHOW DATABASES"))
238
ret= drizzle_result_write(&(server->con), &(server->result), true);
239
DRIZZLE_RETURN_CHECK(ret, "drizzle_result_write", &(server->drizzle))
241
if (command == DRIZZLE_COMMAND_FIELD_LIST)
243
drizzle_result_set_eof(&(server->result), true);
244
ret= drizzle_result_write(&(server->con), &(server->result), true);
245
DRIZZLE_RETURN_CHECK(ret, "drizzle_result_write", &(server->drizzle))
251
if (strstr((char *)data, "@@version") != NULL)
253
ret= send_version(server);
254
if (ret != DRIZZLE_RETURN_OK)
260
server->send_columns= true;
263
if (!strcasecmp((char *)data, "SHOW TABLES"))
265
sqlite_ret= sqlite3_exec(server->db,
266
"SELECT name FROM sqlite_master WHERE type='table'",
267
row_cb, server, &sqlite_err);
271
sqlite_ret= sqlite3_exec(server->db, (char *)data, row_cb, server,
275
if (sqlite_ret != SQLITE_OK)
277
if (sqlite_err == NULL)
278
printf("sqlite3_exec failed\n");
281
drizzle_result_set_error_code(&(server->result), (uint16_t)sqlite_ret);
282
drizzle_result_set_error(&(server->result), sqlite_err);
283
ret= drizzle_result_write(&(server->con), &(server->result), true);
284
DRIZZLE_RETURN_CHECK(ret, "drizzle_result_write", &(server->drizzle))
286
printf("sqlite3_exec:%s\n", sqlite_err);
287
sqlite3_free(sqlite_err);
293
if (server->rows == 0)
295
drizzle_result_set_column_count(&(server->result), 0);
296
ret= drizzle_result_write(&(server->con), &(server->result), true);
297
DRIZZLE_RETURN_CHECK(ret, "drizzle_result_write", &(server->drizzle))
301
drizzle_result_set_eof(&(server->result), true);
302
ret= drizzle_result_write(&(server->con), &(server->result), true);
303
DRIZZLE_RETURN_CHECK(ret, "drizzle_result_write", &(server->drizzle))
308
static int row_cb(void *data, int field_count, char **fields, char **columns)
310
sqlite_server *server= (sqlite_server *)data;
311
drizzle_return_t ret;
313
size_t *sizes= (size_t*)malloc(sizeof(size_t)*8192);
315
if (server->send_columns == true)
317
server->send_columns= false;
318
drizzle_result_set_column_count(&(server->result), (uint16_t)field_count);
320
ret= drizzle_result_write(&(server->con), &(server->result), false);
321
DRIZZLE_RETURN_CHECK_VAL(ret, "drizzle_result_write", &(server->drizzle))
323
if (drizzle_column_create(&(server->result), &(server->column)) == NULL)
325
DRIZZLE_RETURN_CHECK_VAL(DRIZZLE_RETURN_MEMORY, "drizzle_column_create",
329
drizzle_column_set_catalog(&(server->column), "sqlite");
330
drizzle_column_set_db(&(server->column), "sqlite_db");
331
drizzle_column_set_table(&(server->column), "sqlite_table");
332
drizzle_column_set_orig_table(&(server->column), "sqlite_table");
333
drizzle_column_set_charset(&(server->column), 8);
334
drizzle_column_set_type(&(server->column), DRIZZLE_COLUMN_TYPE_VARCHAR);
336
for (x= 0; x < field_count; x++)
338
drizzle_column_set_size(&(server->column),
340
0 : (uint32_t)strlen(fields[x]));
341
drizzle_column_set_name(&(server->column), columns[x]);
342
drizzle_column_set_orig_name(&(server->column), columns[x]);
344
ret= drizzle_column_write(&(server->result), &(server->column));
345
DRIZZLE_RETURN_CHECK_VAL(ret, "drizzle_column_write", &(server->drizzle))
348
drizzle_column_free(&(server->column));
350
drizzle_result_set_eof(&(server->result), true);
352
ret= drizzle_result_write(&(server->con), &(server->result), false);
353
DRIZZLE_RETURN_CHECK_VAL(ret, "drizzle_result_write", &(server->drizzle))
356
for (x= 0; x < field_count; x++)
358
if (fields[x] == NULL)
361
sizes[x]= strlen(fields[x]);
364
/* This is needed for MySQL and old Drizzle protocol. */
365
drizzle_result_calc_row_size(&(server->result), (drizzle_field_t *)fields,
368
ret= drizzle_row_write(&(server->result));
369
DRIZZLE_RETURN_CHECK_VAL(ret, "drizzle_row_write", &(server->drizzle))
371
for (x= 0; x < field_count; x++)
373
ret= drizzle_field_write(&(server->result), (drizzle_field_t)fields[x],
375
DRIZZLE_RETURN_CHECK_VAL(ret, "drizzle_field_write", &(server->drizzle))
385
static drizzle_return_t send_version(sqlite_server *server)
387
drizzle_return_t ret;
388
drizzle_field_t fields[1];
391
fields[0]= (drizzle_field_t)SQLITE_SERVER_VERSION;
392
sizes[0]= strlen(SQLITE_SERVER_VERSION);
394
drizzle_result_set_column_count(&(server->result), 1);
396
ret= drizzle_result_write(&(server->con), &(server->result), false);
397
DRIZZLE_RETURN_CHECK_VAL(ret, "drizzle_result_write", &(server->drizzle))
399
if (drizzle_column_create(&(server->result), &(server->column)) == NULL)
401
DRIZZLE_RETURN_CHECK_VAL(DRIZZLE_RETURN_MEMORY, "drizzle_column_create",
405
drizzle_column_set_catalog(&(server->column), "sqlite");
406
drizzle_column_set_db(&(server->column), "sqlite_db");
407
drizzle_column_set_table(&(server->column), "sqlite_table");
408
drizzle_column_set_orig_table(&(server->column), "sqlite_table");
409
drizzle_column_set_charset(&(server->column), 8);
410
drizzle_column_set_type(&(server->column), DRIZZLE_COLUMN_TYPE_VARCHAR);
411
drizzle_column_set_size(&(server->column), (uint32_t)sizes[0]);
412
drizzle_column_set_name(&(server->column), "version");
413
drizzle_column_set_orig_name(&(server->column), "version");
415
ret= drizzle_column_write(&(server->result), &(server->column));
416
DRIZZLE_RETURN_CHECK_VAL(ret, "drizzle_column_write", &(server->drizzle))
418
drizzle_column_free(&(server->column));
420
drizzle_result_set_eof(&(server->result), true);
422
ret= drizzle_result_write(&(server->con), &(server->result), false);
423
DRIZZLE_RETURN_CHECK_VAL(ret, "drizzle_result_write", &(server->drizzle))
425
/* This is needed for MySQL and old Drizzle protocol. */
426
drizzle_result_calc_row_size(&(server->result), fields, sizes);
428
ret= drizzle_row_write(&(server->result));
429
DRIZZLE_RETURN_CHECK_VAL(ret, "drizzle_row_write", &(server->drizzle))
431
ret= drizzle_field_write(&(server->result), fields[0], sizes[0], sizes[0]);
432
DRIZZLE_RETURN_CHECK_VAL(ret, "drizzle_field_write", &(server->drizzle))
434
ret= drizzle_result_write(&(server->con), &(server->result), true);
435
DRIZZLE_RETURN_CHECK_VAL(ret, "drizzle_result_write", &(server->drizzle))
437
return DRIZZLE_RETURN_OK;
440
static void usage(char *name)
442
printf("\nusage: %s [-c <count>] [-h <host>] [-m] [-p <port>] [-v] "
443
"<sqlite3 db file>\n", name);
444
printf("\t-c <count> - Number of connections to accept before exiting\n");
445
printf("\t-h <host> - Host to listen on\n");
446
printf("\t-m - Use the MySQL protocol\n");
447
printf("\t-p <port> - Port to listen on\n");
448
printf("\t-v - Increase verbosity level\n");