~drizzle-trunk/drizzle/development

1712.1.1 by Monty Taylor
Merged libdrizzle directly into tree.
1
/*
2
 * Drizzle Client & Protocol Library
3
 *
4
 * Copyright (C) 2008 Eric Day (eday@oddments.org)
5
 * All rights reserved.
6
 *
1971.2.1 by kalebral at gmail
update files that did not have license or had incorrect license structure
7
 * Redistribution and use in source and binary forms, with or without
8
 * modification, are permitted provided that the following conditions are
9
 * met:
10
 *
11
 *     * Redistributions of source code must retain the above copyright
12
 * notice, this list of conditions and the following disclaimer.
13
 *
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
17
 * distribution.
18
 *
19
 *     * The names of its contributors may not be used to endorse or
20
 * promote products derived from this software without specific prior
21
 * written permission.
22
 *
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.
34
 *
1712.1.1 by Monty Taylor
Merged libdrizzle directly into tree.
35
 */
36
1971.2.1 by kalebral at gmail
update files that did not have license or had incorrect license structure
37
1712.1.1 by Monty Taylor
Merged libdrizzle directly into tree.
38
#include <errno.h>
39
#include <stdio.h>
40
#include <stdlib.h>
41
#include <string.h>
42
#include <strings.h>
43
#include <unistd.h>
44
45
#include <libdrizzle/drizzle_server.h>
46
#include <sqlite3.h>
47
48
#define SQLITE_SERVER_VERSION "SQLite Server using libdrizzle 0.1"
49
50
#define DRIZZLE_RETURN_CHECK(__ret, __function, __drizzle) \
51
{ \
52
  if ((__ret) != DRIZZLE_RETURN_OK) \
53
    DRIZZLE_RETURN_ERROR(__function, __drizzle) \
54
}
55
56
#define DRIZZLE_RETURN_ERROR(__function, __drizzle) \
57
{ \
58
  printf(__function ":%s\n", drizzle_error(__drizzle)); \
59
  return; \
60
}
61
62
#define DRIZZLE_RETURN_CHECK_VAL(__ret, __function, __drizzle) \
63
{ \
64
  if ((__ret) != DRIZZLE_RETURN_OK) \
65
  { \
66
    printf(__function ":%s\n", drizzle_error(__drizzle)); \
67
    return ret; \
68
  } \
69
}
70
71
typedef struct
72
{
73
  drizzle_st drizzle;
74
  drizzle_con_st con;
75
  drizzle_result_st result;
76
  drizzle_column_st column;
77
  sqlite3* db;
78
  bool send_columns;
79
  drizzle_verbose_t verbose;
80
  uint64_t rows;
81
} sqlite_server;
82
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);
87
88
int main(int argc, char *argv[])
89
{
90
  int c;
91
  uint32_t count= 0;
92
  const char *host= NULL;
93
  bool mysql= false;
94
  in_port_t port= 0;
95
  drizzle_return_t ret;
1929.1.35 by Stewart Smith
typo
96
  sqlite_server *server= (sqlite_server*)malloc(sizeof(sqlite_server));
1929.1.33 by Stewart Smith
fix large stack usag ein examples/sqlite_server.c:
97
  drizzle_con_st *con_listen= (drizzle_con_st*)malloc(sizeof(drizzle_con_st));
1712.1.1 by Monty Taylor
Merged libdrizzle directly into tree.
98
1929.1.34 by Stewart Smith
fix sqlite_server stack usage
99
  server->db= NULL;
100
  server->verbose= DRIZZLE_VERBOSE_NEVER;
1712.1.1 by Monty Taylor
Merged libdrizzle directly into tree.
101
102
  while((c = getopt(argc, argv, "c:h:mp:v")) != -1)
103
  {
104
    switch(c)
105
    {
106
    case 'c':
107
      count= (uint32_t)atoi(optarg);
108
      break;
109
110
    case 'h':
111
      host= optarg;
112
      break;
113
114
    case 'm':
115
      mysql= true;
116
      break;
117
118
    case 'p':
119
      port= (in_port_t)atoi(optarg);
120
      break;
121
122
    case 'v':
1992.6.2 by Monty Taylor
Cleaned up for additional gcc 4.5 warnings.
123
      switch(server->verbose)
124
      {
125
      case DRIZZLE_VERBOSE_NEVER:
126
        server->verbose= DRIZZLE_VERBOSE_FATAL;
127
        break;
128
      case DRIZZLE_VERBOSE_FATAL:
129
        server->verbose= DRIZZLE_VERBOSE_ERROR;
130
        break;
131
      case DRIZZLE_VERBOSE_ERROR:
132
        server->verbose= DRIZZLE_VERBOSE_INFO;
133
        break;
134
      case DRIZZLE_VERBOSE_INFO:
135
        server->verbose= DRIZZLE_VERBOSE_DEBUG;
136
        break;
137
      case DRIZZLE_VERBOSE_DEBUG:
138
        server->verbose= DRIZZLE_VERBOSE_CRAZY;
139
        break;
140
      case DRIZZLE_VERBOSE_CRAZY:
141
      case DRIZZLE_VERBOSE_MAX:
142
        break;
143
      }
1712.1.1 by Monty Taylor
Merged libdrizzle directly into tree.
144
      break;
145
146
    default:
147
      usage(argv[0]);
148
      return 1;
149
    }
150
  }
151
152
  if (argc != (optind + 1))
153
  {
154
    usage(argv[0]);
155
    return 1;
156
  }
157
1929.1.34 by Stewart Smith
fix sqlite_server stack usage
158
  sqlite3_open(argv[optind], &(server->db));
159
  if (server->db == NULL)
1712.1.1 by Monty Taylor
Merged libdrizzle directly into tree.
160
  {
161
    printf("sqlite3_open: could not open sqlite3 db\n");
162
    return 1;
163
  }
164
1929.1.34 by Stewart Smith
fix sqlite_server stack usage
165
  if (drizzle_create(&(server->drizzle)) == NULL)
1712.1.1 by Monty Taylor
Merged libdrizzle directly into tree.
166
  {
167
    printf("drizzle_create:NULL\n");
168
    return 1;
169
  }
170
1929.1.34 by Stewart Smith
fix sqlite_server stack usage
171
  drizzle_add_options(&(server->drizzle), DRIZZLE_FREE_OBJECTS);
172
  drizzle_set_verbose(&(server->drizzle), server->verbose);
1712.1.1 by Monty Taylor
Merged libdrizzle directly into tree.
173
1929.1.34 by Stewart Smith
fix sqlite_server stack usage
174
  if (drizzle_con_create(&(server->drizzle), con_listen) == NULL)
1712.1.1 by Monty Taylor
Merged libdrizzle directly into tree.
175
  {
176
    printf("drizzle_con_create:NULL\n");
177
    return 1;
178
  }
179
1929.1.33 by Stewart Smith
fix large stack usag ein examples/sqlite_server.c:
180
  drizzle_con_add_options(con_listen, DRIZZLE_CON_LISTEN);
181
  drizzle_con_set_tcp(con_listen, host, port);
1712.1.1 by Monty Taylor
Merged libdrizzle directly into tree.
182
183
  if (mysql)
1929.1.33 by Stewart Smith
fix large stack usag ein examples/sqlite_server.c:
184
    drizzle_con_add_options(con_listen, DRIZZLE_CON_MYSQL);
1712.1.1 by Monty Taylor
Merged libdrizzle directly into tree.
185
1929.1.33 by Stewart Smith
fix large stack usag ein examples/sqlite_server.c:
186
  if (drizzle_con_listen(con_listen) != DRIZZLE_RETURN_OK)
1712.1.1 by Monty Taylor
Merged libdrizzle directly into tree.
187
  {
1929.1.34 by Stewart Smith
fix sqlite_server stack usage
188
    printf("drizzle_con_listen:%s\n", drizzle_error(&(server->drizzle)));
1712.1.1 by Monty Taylor
Merged libdrizzle directly into tree.
189
    return 1;
190
  }
191
192
  while (1)
193
  {
1929.1.34 by Stewart Smith
fix sqlite_server stack usage
194
    (void)drizzle_con_accept(&(server->drizzle), &(server->con), &ret);
1712.1.1 by Monty Taylor
Merged libdrizzle directly into tree.
195
    if (ret != DRIZZLE_RETURN_OK)
196
    {
1929.1.34 by Stewart Smith
fix sqlite_server stack usage
197
      printf("drizzle_con_accept:%s\n", drizzle_error(&(server->drizzle)));
1712.1.1 by Monty Taylor
Merged libdrizzle directly into tree.
198
      return 1;
199
    }
200
1929.1.34 by Stewart Smith
fix sqlite_server stack usage
201
    server_run(server);
1712.1.1 by Monty Taylor
Merged libdrizzle directly into tree.
202
1929.1.34 by Stewart Smith
fix sqlite_server stack usage
203
    drizzle_con_free(&(server->con));
1712.1.1 by Monty Taylor
Merged libdrizzle directly into tree.
204
205
    if (count > 0)
206
    {
207
      count--;
208
209
      if (count == 0)
210
        break;
211
    }
212
  }
213
1929.1.33 by Stewart Smith
fix large stack usag ein examples/sqlite_server.c:
214
  drizzle_con_free(con_listen);
1929.1.34 by Stewart Smith
fix sqlite_server stack usage
215
  drizzle_free(&(server->drizzle));
216
  sqlite3_close(server->db);
1929.1.33 by Stewart Smith
fix large stack usag ein examples/sqlite_server.c:
217
  free(con_listen);
1929.1.34 by Stewart Smith
fix sqlite_server stack usage
218
  free(server);
1712.1.1 by Monty Taylor
Merged libdrizzle directly into tree.
219
220
  return 0;
221
}
222
223
static void server_run(sqlite_server *server)
224
{
225
  drizzle_return_t ret;
226
  drizzle_command_t command;
227
  uint8_t *data= NULL;
228
  size_t total;
229
  int sqlite_ret;
230
  char *sqlite_err;
231
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);
242
243
  ret= drizzle_handshake_server_write(&(server->con));
244
  DRIZZLE_RETURN_CHECK(ret, "drizzle_handshake_server_write",
245
                       &(server->drizzle))
246
247
  ret= drizzle_handshake_client_read(&(server->con));
248
  DRIZZLE_RETURN_CHECK(ret, "drizzle_handshake_client_read", &(server->drizzle))
249
250
  if (drizzle_result_create(&(server->con), &(server->result)) == NULL)
251
    DRIZZLE_RETURN_ERROR("drizzle_result_create", &(server->drizzle))
252
253
  ret= drizzle_result_write(&(server->con), &(server->result), true);
254
  DRIZZLE_RETURN_CHECK(ret, "drizzle_result_write", &(server->drizzle))
255
256
  /* Command loop. */
257
  while (1)
258
  {
259
    drizzle_result_free(&(server->result));
260
    if (data != NULL)
261
      free(data);
262
1992.6.2 by Monty Taylor
Cleaned up for additional gcc 4.5 warnings.
263
    data= (uint8_t *)drizzle_con_command_buffer(&(server->con), &command, &total, &ret);
1712.1.1 by Monty Taylor
Merged libdrizzle directly into tree.
264
    if (ret == DRIZZLE_RETURN_LOST_CONNECTION ||
265
        (ret == DRIZZLE_RETURN_OK && command == DRIZZLE_COMMAND_QUIT))
266
    {
267
      if (data != NULL)
268
        free(data);
269
      return;
270
    }
271
    DRIZZLE_RETURN_CHECK(ret, "drizzle_con_command_buffer", &(server->drizzle))
272
273
    if (server->verbose >= DRIZZLE_VERBOSE_INFO)
274
    {
275
      printf("Command=%u Data=%s\n", command,
276
             data == NULL ? "NULL" : (char *)data);
277
    }
278
279
    if (drizzle_result_create(&(server->con), &(server->result)) == NULL)
280
      DRIZZLE_RETURN_ERROR("drizzle_result_create", &(server->drizzle))
281
282
    if (command != DRIZZLE_COMMAND_QUERY ||
283
        !strcasecmp((char *)data, "SHOW DATABASES"))
284
    {
285
      ret= drizzle_result_write(&(server->con), &(server->result), true);
286
      DRIZZLE_RETURN_CHECK(ret, "drizzle_result_write", &(server->drizzle))
287
288
      if (command == DRIZZLE_COMMAND_FIELD_LIST)
289
      {
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))
293
      }
294
295
      continue;
296
    }
297
298
    if (strstr((char *)data, "@@version") != NULL)
299
    {
300
      ret= send_version(server);
301
      if (ret != DRIZZLE_RETURN_OK)
302
        return;
303
304
      continue;
305
    }
306
307
    server->send_columns= true;
308
    server->rows= 0;
309
310
    if (!strcasecmp((char *)data, "SHOW TABLES"))
311
    {
312
      sqlite_ret= sqlite3_exec(server->db,
313
                            "SELECT name FROM sqlite_master WHERE type='table'",
314
                               row_cb, server, &sqlite_err);
315
    }
316
    else
317
    {
318
      sqlite_ret= sqlite3_exec(server->db, (char *)data, row_cb, server,
319
                               &sqlite_err);
320
    }
321
322
    if (sqlite_ret != SQLITE_OK)
323
    {
324
      if (sqlite_err == NULL)
325
        printf("sqlite3_exec failed\n");
326
      else
327
      {
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))
332
333
        printf("sqlite3_exec:%s\n", sqlite_err);
334
        sqlite3_free(sqlite_err);
335
      }
336
337
      return;
338
    }
339
340
    if (server->rows == 0)
341
    {
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))
345
    }
346
    else
347
    {
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))
351
    }
352
  }
353
}
354
355
static int row_cb(void *data, int field_count, char **fields, char **columns)
356
{
357
  sqlite_server *server= (sqlite_server *)data;
358
  drizzle_return_t ret;
359
  int x;
1929.1.36 by Stewart Smith
one last sqlite_server stack fix
360
  size_t *sizes= (size_t*)malloc(sizeof(size_t)*8192);
1712.1.1 by Monty Taylor
Merged libdrizzle directly into tree.
361
362
  if (server->send_columns == true)
363
  {
364
    server->send_columns= false;
365
    drizzle_result_set_column_count(&(server->result), (uint16_t)field_count);
366
367
    ret= drizzle_result_write(&(server->con), &(server->result), false);
368
    DRIZZLE_RETURN_CHECK_VAL(ret, "drizzle_result_write", &(server->drizzle))
369
370
    if (drizzle_column_create(&(server->result), &(server->column)) == NULL)
371
    {
372
      DRIZZLE_RETURN_CHECK_VAL(DRIZZLE_RETURN_MEMORY, "drizzle_column_create",
373
                               &(server->drizzle))
374
    }
375
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);
382
383
    for (x= 0; x < field_count; x++)
384
    {
385
      drizzle_column_set_size(&(server->column),
386
                              fields[x] == NULL ?
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]);
390
391
      ret= drizzle_column_write(&(server->result), &(server->column));
392
      DRIZZLE_RETURN_CHECK_VAL(ret, "drizzle_column_write", &(server->drizzle))
393
    }
394
395
    drizzle_column_free(&(server->column));
396
397
    drizzle_result_set_eof(&(server->result), true);
398
399
    ret= drizzle_result_write(&(server->con), &(server->result), false);
400
    DRIZZLE_RETURN_CHECK_VAL(ret, "drizzle_result_write", &(server->drizzle))
401
  }
402
403
  for (x= 0; x < field_count; x++)
404
  {
405
    if (fields[x] == NULL)
406
      sizes[x]= 0;
407
    else
408
      sizes[x]= strlen(fields[x]);
409
  }
410
411
  /* This is needed for MySQL and old Drizzle protocol. */
412
  drizzle_result_calc_row_size(&(server->result), (drizzle_field_t *)fields,
413
                               sizes);
414
415
  ret= drizzle_row_write(&(server->result));
416
  DRIZZLE_RETURN_CHECK_VAL(ret, "drizzle_row_write", &(server->drizzle))
417
418
  for (x= 0; x < field_count; x++)
419
  {
420
    ret= drizzle_field_write(&(server->result), (drizzle_field_t)fields[x],
421
                             sizes[x], sizes[x]);
422
    DRIZZLE_RETURN_CHECK_VAL(ret, "drizzle_field_write", &(server->drizzle))
423
  }
424
425
  server->rows++;
426
1929.1.36 by Stewart Smith
one last sqlite_server stack fix
427
  free(sizes);
428
1712.1.1 by Monty Taylor
Merged libdrizzle directly into tree.
429
  return 0;
430
}
431
432
static drizzle_return_t send_version(sqlite_server *server)
433
{
434
  drizzle_return_t ret;
435
  drizzle_field_t fields[1];
436
  size_t sizes[1];
437
438
  fields[0]= (drizzle_field_t)SQLITE_SERVER_VERSION;
439
  sizes[0]= strlen(SQLITE_SERVER_VERSION);
440
441
  drizzle_result_set_column_count(&(server->result), 1);
442
443
  ret= drizzle_result_write(&(server->con), &(server->result), false);
444
  DRIZZLE_RETURN_CHECK_VAL(ret, "drizzle_result_write", &(server->drizzle))
445
446
  if (drizzle_column_create(&(server->result), &(server->column)) == NULL)
447
  {
448
    DRIZZLE_RETURN_CHECK_VAL(DRIZZLE_RETURN_MEMORY, "drizzle_column_create",
449
                             &(server->drizzle))
450
  }
451
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");
461
462
  ret= drizzle_column_write(&(server->result), &(server->column));
463
  DRIZZLE_RETURN_CHECK_VAL(ret, "drizzle_column_write", &(server->drizzle))
464
465
  drizzle_column_free(&(server->column));
466
467
  drizzle_result_set_eof(&(server->result), true);
468
469
  ret= drizzle_result_write(&(server->con), &(server->result), false);
470
  DRIZZLE_RETURN_CHECK_VAL(ret, "drizzle_result_write", &(server->drizzle))
471
472
  /* This is needed for MySQL and old Drizzle protocol. */
473
  drizzle_result_calc_row_size(&(server->result), fields, sizes);
474
475
  ret= drizzle_row_write(&(server->result));
476
  DRIZZLE_RETURN_CHECK_VAL(ret, "drizzle_row_write", &(server->drizzle))
477
478
  ret= drizzle_field_write(&(server->result), fields[0], sizes[0], sizes[0]);
479
  DRIZZLE_RETURN_CHECK_VAL(ret, "drizzle_field_write", &(server->drizzle))
480
481
  ret= drizzle_result_write(&(server->con), &(server->result), true);
482
  DRIZZLE_RETURN_CHECK_VAL(ret, "drizzle_result_write", &(server->drizzle))
483
484
  return DRIZZLE_RETURN_OK;
485
}
486
487
static void usage(char *name)
488
{
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");
496
}