~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to examples/sqlite_server.c

code clean move Item_func_num1 and Item_func_connection_id to functions directory

Show diffs side-by-side

added added

removed removed

Lines of Context:
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
 
 
18
 
#include <libdrizzle/drizzle_server.h>
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
 
 
44
 
typedef struct
45
 
{
46
 
  drizzle_st drizzle;
47
 
  drizzle_con_st con;
48
 
  drizzle_result_st result;
49
 
  drizzle_column_st column;
50
 
  sqlite3* db;
51
 
  bool send_columns;
52
 
  drizzle_verbose_t verbose;
53
 
  uint64_t rows;
54
 
} sqlite_server;
55
 
 
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);
60
 
 
61
 
int 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;
68
 
  drizzle_return_t ret;
69
 
  sqlite_server server;
70
 
  drizzle_con_st con_listen;
71
 
 
72
 
  server.db= NULL;
73
 
  server.verbose= DRIZZLE_VERBOSE_NEVER;
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
 
 
124
 
  drizzle_add_options(&server.drizzle, DRIZZLE_FREE_OBJECTS);
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
 
 
133
 
  drizzle_con_add_options(&con_listen, DRIZZLE_CON_LISTEN);
134
 
  drizzle_con_set_tcp(&con_listen, host, port);
135
 
 
136
 
  if (mysql)
137
 
    drizzle_con_add_options(&con_listen, DRIZZLE_CON_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
 
 
154
 
    server_run(&server);
155
 
 
156
 
    drizzle_con_free(&server.con);
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
 
 
174
 
static void server_run(sqlite_server *server)
175
 
{
176
 
  drizzle_return_t ret;
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. */
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);
193
 
 
194
 
  ret= drizzle_handshake_server_write(&(server->con));
195
 
  DRIZZLE_RETURN_CHECK(ret, "drizzle_handshake_server_write",
196
 
                       &(server->drizzle))
197
 
 
198
 
  ret= drizzle_handshake_client_read(&(server->con));
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);
215
 
    if (ret == DRIZZLE_RETURN_LOST_CONNECTION ||
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
 
    {
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))
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
 
 
306
 
static int row_cb(void *data, int field_count, char **fields, char **columns)
307
 
{
308
 
  sqlite_server *server= (sqlite_server *)data;
309
 
  drizzle_return_t ret;
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);
332
 
    drizzle_column_set_type(&(server->column), DRIZZLE_COLUMN_TYPE_VARCHAR);
333
 
 
334
 
    for (x= 0; x < field_count; x++)
335
 
    {
336
 
      drizzle_column_set_size(&(server->column),
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. */
363
 
  drizzle_result_calc_row_size(&(server->result), (drizzle_field_t *)fields,
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
 
 
381
 
static drizzle_return_t send_version(sqlite_server *server)
382
 
{
383
 
  drizzle_return_t ret;
384
 
  drizzle_field_t fields[1];
385
 
  size_t sizes[1];
386
 
 
387
 
  fields[0]= (drizzle_field_t)SQLITE_SERVER_VERSION;
388
 
  sizes[0]= strlen(SQLITE_SERVER_VERSION);
389
 
 
390
 
  drizzle_result_set_column_count(&(server->result), 1);
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);
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");
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
 
 
436
 
static 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
 
}