2
* Drizzle Client & Protocol Library
4
* Copyright (C) 2008 Eric Day (eday@oddments.org)
7
* Redistribution and use in source and binary forms, with or without
8
* modification, are permitted provided that the following conditions are
11
* * Redistributions of source code must retain the above copyright
12
* notice, this list of conditions and the following disclaimer.
14
* * Redistributions in binary form must reproduce the above
15
* copyright notice, this list of conditions and the following disclaimer
16
* in the documentation and/or other materials provided with the
19
* * The names of its contributors may not be used to endorse or
20
* promote products derived from this software without specific prior
23
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
26
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
27
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
28
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
29
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
30
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
31
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
33
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
45
#include <libdrizzle/drizzle_server.h>
48
#define SQLITE_SERVER_VERSION "SQLite Server using libdrizzle 0.1"
50
#define DRIZZLE_RETURN_CHECK(__ret, __function, __drizzle) \
52
if ((__ret) != DRIZZLE_RETURN_OK) \
53
DRIZZLE_RETURN_ERROR(__function, __drizzle) \
56
#define DRIZZLE_RETURN_ERROR(__function, __drizzle) \
58
printf(__function ":%s\n", drizzle_error(__drizzle)); \
62
#define DRIZZLE_RETURN_CHECK_VAL(__ret, __function, __drizzle) \
64
if ((__ret) != DRIZZLE_RETURN_OK) \
66
printf(__function ":%s\n", drizzle_error(__drizzle)); \
75
drizzle_result_st result;
76
drizzle_column_st column;
79
drizzle_verbose_t verbose;
83
static void server_run(sqlite_server *server);
84
static int row_cb(void *data, int field_count, char **fields, char **columns);
85
static drizzle_return_t send_version(sqlite_server *server);
86
static void usage(char *name);
88
int main(int argc, char *argv[])
92
const char *host= NULL;
96
sqlite_server *server= (sqlite_server*)malloc(sizeof(sqlite_server));
97
drizzle_con_st *con_listen= (drizzle_con_st*)malloc(sizeof(drizzle_con_st));
100
server->verbose= DRIZZLE_VERBOSE_NEVER;
102
while((c = getopt(argc, argv, "c:h:mp:v")) != -1)
107
count= (uint32_t)atoi(optarg);
119
port= (in_port_t)atoi(optarg);
123
switch(server->verbose)
125
case DRIZZLE_VERBOSE_NEVER:
126
server->verbose= DRIZZLE_VERBOSE_FATAL;
128
case DRIZZLE_VERBOSE_FATAL:
129
server->verbose= DRIZZLE_VERBOSE_ERROR;
131
case DRIZZLE_VERBOSE_ERROR:
132
server->verbose= DRIZZLE_VERBOSE_INFO;
134
case DRIZZLE_VERBOSE_INFO:
135
server->verbose= DRIZZLE_VERBOSE_DEBUG;
137
case DRIZZLE_VERBOSE_DEBUG:
138
server->verbose= DRIZZLE_VERBOSE_CRAZY;
140
case DRIZZLE_VERBOSE_CRAZY:
141
case DRIZZLE_VERBOSE_MAX:
152
if (argc != (optind + 1))
158
sqlite3_open(argv[optind], &(server->db));
159
if (server->db == NULL)
161
printf("sqlite3_open: could not open sqlite3 db\n");
165
if (drizzle_create(&(server->drizzle)) == NULL)
167
printf("drizzle_create:NULL\n");
171
drizzle_add_options(&(server->drizzle), DRIZZLE_FREE_OBJECTS);
172
drizzle_set_verbose(&(server->drizzle), server->verbose);
174
if (drizzle_con_create(&(server->drizzle), con_listen) == NULL)
176
printf("drizzle_con_create:NULL\n");
180
drizzle_con_add_options(con_listen, DRIZZLE_CON_LISTEN);
181
drizzle_con_set_tcp(con_listen, host, port);
184
drizzle_con_add_options(con_listen, DRIZZLE_CON_MYSQL);
186
if (drizzle_con_listen(con_listen) != DRIZZLE_RETURN_OK)
188
printf("drizzle_con_listen:%s\n", drizzle_error(&(server->drizzle)));
194
(void)drizzle_con_accept(&(server->drizzle), &(server->con), &ret);
195
if (ret != DRIZZLE_RETURN_OK)
197
printf("drizzle_con_accept:%s\n", drizzle_error(&(server->drizzle)));
203
drizzle_con_free(&(server->con));
214
drizzle_con_free(con_listen);
215
drizzle_free(&(server->drizzle));
216
sqlite3_close(server->db);
223
static void server_run(sqlite_server *server)
225
drizzle_return_t ret;
226
drizzle_command_t command;
232
/* Handshake packets. */
233
drizzle_con_set_protocol_version(&(server->con), 10);
234
drizzle_con_set_server_version(&(server->con), "libdrizzle+SQLite");
235
drizzle_con_set_thread_id(&(server->con), 1);
236
drizzle_con_set_scramble(&(server->con),
237
(const uint8_t *)"ABCDEFGHIJKLMNOPQRST");
238
drizzle_con_set_capabilities(&(server->con), DRIZZLE_CAPABILITIES_NONE);
239
drizzle_con_set_charset(&(server->con), 8);
240
drizzle_con_set_status(&(server->con), DRIZZLE_CON_STATUS_NONE);
241
drizzle_con_set_max_packet_size(&(server->con), DRIZZLE_MAX_PACKET_SIZE);
243
ret= drizzle_handshake_server_write(&(server->con));
244
DRIZZLE_RETURN_CHECK(ret, "drizzle_handshake_server_write",
247
ret= drizzle_handshake_client_read(&(server->con));
248
DRIZZLE_RETURN_CHECK(ret, "drizzle_handshake_client_read", &(server->drizzle))
250
if (drizzle_result_create(&(server->con), &(server->result)) == NULL)
251
DRIZZLE_RETURN_ERROR("drizzle_result_create", &(server->drizzle))
253
ret= drizzle_result_write(&(server->con), &(server->result), true);
254
DRIZZLE_RETURN_CHECK(ret, "drizzle_result_write", &(server->drizzle))
259
drizzle_result_free(&(server->result));
263
data= (uint8_t *)drizzle_con_command_buffer(&(server->con), &command, &total, &ret);
264
if (ret == DRIZZLE_RETURN_LOST_CONNECTION ||
265
(ret == DRIZZLE_RETURN_OK && command == DRIZZLE_COMMAND_QUIT))
271
DRIZZLE_RETURN_CHECK(ret, "drizzle_con_command_buffer", &(server->drizzle))
273
if (server->verbose >= DRIZZLE_VERBOSE_INFO)
275
printf("Command=%u Data=%s\n", command,
276
data == NULL ? "NULL" : (char *)data);
279
if (drizzle_result_create(&(server->con), &(server->result)) == NULL)
280
DRIZZLE_RETURN_ERROR("drizzle_result_create", &(server->drizzle))
282
if (command != DRIZZLE_COMMAND_QUERY ||
283
!strcasecmp((char *)data, "SHOW DATABASES"))
285
ret= drizzle_result_write(&(server->con), &(server->result), true);
286
DRIZZLE_RETURN_CHECK(ret, "drizzle_result_write", &(server->drizzle))
288
if (command == DRIZZLE_COMMAND_FIELD_LIST)
290
drizzle_result_set_eof(&(server->result), true);
291
ret= drizzle_result_write(&(server->con), &(server->result), true);
292
DRIZZLE_RETURN_CHECK(ret, "drizzle_result_write", &(server->drizzle))
298
if (strstr((char *)data, "@@version") != NULL)
300
ret= send_version(server);
301
if (ret != DRIZZLE_RETURN_OK)
307
server->send_columns= true;
310
if (!strcasecmp((char *)data, "SHOW TABLES"))
312
sqlite_ret= sqlite3_exec(server->db,
313
"SELECT name FROM sqlite_master WHERE type='table'",
314
row_cb, server, &sqlite_err);
318
sqlite_ret= sqlite3_exec(server->db, (char *)data, row_cb, server,
322
if (sqlite_ret != SQLITE_OK)
324
if (sqlite_err == NULL)
325
printf("sqlite3_exec failed\n");
328
drizzle_result_set_error_code(&(server->result), (uint16_t)sqlite_ret);
329
drizzle_result_set_error(&(server->result), sqlite_err);
330
ret= drizzle_result_write(&(server->con), &(server->result), true);
331
DRIZZLE_RETURN_CHECK(ret, "drizzle_result_write", &(server->drizzle))
333
printf("sqlite3_exec:%s\n", sqlite_err);
334
sqlite3_free(sqlite_err);
340
if (server->rows == 0)
342
drizzle_result_set_column_count(&(server->result), 0);
343
ret= drizzle_result_write(&(server->con), &(server->result), true);
344
DRIZZLE_RETURN_CHECK(ret, "drizzle_result_write", &(server->drizzle))
348
drizzle_result_set_eof(&(server->result), true);
349
ret= drizzle_result_write(&(server->con), &(server->result), true);
350
DRIZZLE_RETURN_CHECK(ret, "drizzle_result_write", &(server->drizzle))
355
static int row_cb(void *data, int field_count, char **fields, char **columns)
357
sqlite_server *server= (sqlite_server *)data;
358
drizzle_return_t ret;
360
size_t *sizes= (size_t*)malloc(sizeof(size_t)*8192);
362
if (server->send_columns == true)
364
server->send_columns= false;
365
drizzle_result_set_column_count(&(server->result), (uint16_t)field_count);
367
ret= drizzle_result_write(&(server->con), &(server->result), false);
368
DRIZZLE_RETURN_CHECK_VAL(ret, "drizzle_result_write", &(server->drizzle))
370
if (drizzle_column_create(&(server->result), &(server->column)) == NULL)
372
DRIZZLE_RETURN_CHECK_VAL(DRIZZLE_RETURN_MEMORY, "drizzle_column_create",
376
drizzle_column_set_catalog(&(server->column), "sqlite");
377
drizzle_column_set_db(&(server->column), "sqlite_db");
378
drizzle_column_set_table(&(server->column), "sqlite_table");
379
drizzle_column_set_orig_table(&(server->column), "sqlite_table");
380
drizzle_column_set_charset(&(server->column), 8);
381
drizzle_column_set_type(&(server->column), DRIZZLE_COLUMN_TYPE_VARCHAR);
383
for (x= 0; x < field_count; x++)
385
drizzle_column_set_size(&(server->column),
387
0 : (uint32_t)strlen(fields[x]));
388
drizzle_column_set_name(&(server->column), columns[x]);
389
drizzle_column_set_orig_name(&(server->column), columns[x]);
391
ret= drizzle_column_write(&(server->result), &(server->column));
392
DRIZZLE_RETURN_CHECK_VAL(ret, "drizzle_column_write", &(server->drizzle))
395
drizzle_column_free(&(server->column));
397
drizzle_result_set_eof(&(server->result), true);
399
ret= drizzle_result_write(&(server->con), &(server->result), false);
400
DRIZZLE_RETURN_CHECK_VAL(ret, "drizzle_result_write", &(server->drizzle))
403
for (x= 0; x < field_count; x++)
405
if (fields[x] == NULL)
408
sizes[x]= strlen(fields[x]);
411
/* This is needed for MySQL and old Drizzle protocol. */
412
drizzle_result_calc_row_size(&(server->result), (drizzle_field_t *)fields,
415
ret= drizzle_row_write(&(server->result));
416
DRIZZLE_RETURN_CHECK_VAL(ret, "drizzle_row_write", &(server->drizzle))
418
for (x= 0; x < field_count; x++)
420
ret= drizzle_field_write(&(server->result), (drizzle_field_t)fields[x],
422
DRIZZLE_RETURN_CHECK_VAL(ret, "drizzle_field_write", &(server->drizzle))
432
static drizzle_return_t send_version(sqlite_server *server)
434
drizzle_return_t ret;
435
drizzle_field_t fields[1];
438
fields[0]= (drizzle_field_t)SQLITE_SERVER_VERSION;
439
sizes[0]= strlen(SQLITE_SERVER_VERSION);
441
drizzle_result_set_column_count(&(server->result), 1);
443
ret= drizzle_result_write(&(server->con), &(server->result), false);
444
DRIZZLE_RETURN_CHECK_VAL(ret, "drizzle_result_write", &(server->drizzle))
446
if (drizzle_column_create(&(server->result), &(server->column)) == NULL)
448
DRIZZLE_RETURN_CHECK_VAL(DRIZZLE_RETURN_MEMORY, "drizzle_column_create",
452
drizzle_column_set_catalog(&(server->column), "sqlite");
453
drizzle_column_set_db(&(server->column), "sqlite_db");
454
drizzle_column_set_table(&(server->column), "sqlite_table");
455
drizzle_column_set_orig_table(&(server->column), "sqlite_table");
456
drizzle_column_set_charset(&(server->column), 8);
457
drizzle_column_set_type(&(server->column), DRIZZLE_COLUMN_TYPE_VARCHAR);
458
drizzle_column_set_size(&(server->column), (uint32_t)sizes[0]);
459
drizzle_column_set_name(&(server->column), "version");
460
drizzle_column_set_orig_name(&(server->column), "version");
462
ret= drizzle_column_write(&(server->result), &(server->column));
463
DRIZZLE_RETURN_CHECK_VAL(ret, "drizzle_column_write", &(server->drizzle))
465
drizzle_column_free(&(server->column));
467
drizzle_result_set_eof(&(server->result), true);
469
ret= drizzle_result_write(&(server->con), &(server->result), false);
470
DRIZZLE_RETURN_CHECK_VAL(ret, "drizzle_result_write", &(server->drizzle))
472
/* This is needed for MySQL and old Drizzle protocol. */
473
drizzle_result_calc_row_size(&(server->result), fields, sizes);
475
ret= drizzle_row_write(&(server->result));
476
DRIZZLE_RETURN_CHECK_VAL(ret, "drizzle_row_write", &(server->drizzle))
478
ret= drizzle_field_write(&(server->result), fields[0], sizes[0], sizes[0]);
479
DRIZZLE_RETURN_CHECK_VAL(ret, "drizzle_field_write", &(server->drizzle))
481
ret= drizzle_result_write(&(server->con), &(server->result), true);
482
DRIZZLE_RETURN_CHECK_VAL(ret, "drizzle_result_write", &(server->drizzle))
484
return DRIZZLE_RETURN_OK;
487
static void usage(char *name)
489
printf("\nusage: %s [-c <count>] [-h <host>] [-m] [-p <port>] [-v] "
490
"<sqlite3 db file>\n", name);
491
printf("\t-c <count> - Number of connections to accept before exiting\n");
492
printf("\t-h <host> - Host to listen on\n");
493
printf("\t-m - Use the MySQL protocol\n");
494
printf("\t-p <port> - Port to listen on\n");
495
printf("\t-v - Increase verbosity level\n");