~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
2244.1.1 by Monty Taylor
Split libdrizzle into 1.0 and 2.0. Applied the C++ changes to 2.0 branch.
37
#include <config.h>
1971.2.1 by kalebral at gmail
update files that did not have license or had incorrect license structure
38
1712.1.1 by Monty Taylor
Merged libdrizzle directly into tree.
39
#include <errno.h>
40
#include <stdio.h>
41
#include <stdlib.h>
42
#include <string.h>
43
#include <strings.h>
44
#include <unistd.h>
45
46
#include <libdrizzle/drizzle_server.h>
47
#include <sqlite3.h>
48
49
#define SQLITE_SERVER_VERSION "SQLite Server using libdrizzle 0.1"
50
51
#define DRIZZLE_RETURN_CHECK(__ret, __function, __drizzle) \
52
{ \
53
  if ((__ret) != DRIZZLE_RETURN_OK) \
54
    DRIZZLE_RETURN_ERROR(__function, __drizzle) \
55
}
56
57
#define DRIZZLE_RETURN_ERROR(__function, __drizzle) \
58
{ \
59
  printf(__function ":%s\n", drizzle_error(__drizzle)); \
60
  return; \
61
}
62
63
#define DRIZZLE_RETURN_CHECK_VAL(__ret, __function, __drizzle) \
64
{ \
65
  if ((__ret) != DRIZZLE_RETURN_OK) \
66
  { \
67
    printf(__function ":%s\n", drizzle_error(__drizzle)); \
68
    return ret; \
69
  } \
70
}
71
72
typedef struct
73
{
74
  drizzle_st drizzle;
75
  drizzle_con_st con;
76
  drizzle_result_st result;
77
  drizzle_column_st column;
78
  sqlite3* db;
79
  bool send_columns;
80
  drizzle_verbose_t verbose;
81
  uint64_t rows;
82
} sqlite_server;
83
84
static void server_run(sqlite_server *server);
85
static int row_cb(void *data, int field_count, char **fields, char **columns);
86
static drizzle_return_t send_version(sqlite_server *server);
87
static void usage(char *name);
88
89
int main(int argc, char *argv[])
90
{
91
  int c;
92
  uint32_t count= 0;
93
  const char *host= NULL;
94
  bool mysql= false;
95
  in_port_t port= 0;
96
  drizzle_return_t ret;
1929.1.35 by Stewart Smith
typo
97
  sqlite_server *server= (sqlite_server*)malloc(sizeof(sqlite_server));
1929.1.33 by Stewart Smith
fix large stack usag ein examples/sqlite_server.c:
98
  drizzle_con_st *con_listen= (drizzle_con_st*)malloc(sizeof(drizzle_con_st));
1712.1.1 by Monty Taylor
Merged libdrizzle directly into tree.
99
1929.1.34 by Stewart Smith
fix sqlite_server stack usage
100
  server->db= NULL;
101
  server->verbose= DRIZZLE_VERBOSE_NEVER;
1712.1.1 by Monty Taylor
Merged libdrizzle directly into tree.
102
103
  while((c = getopt(argc, argv, "c:h:mp:v")) != -1)
104
  {
105
    switch(c)
106
    {
107
    case 'c':
108
      count= (uint32_t)atoi(optarg);
109
      break;
110
111
    case 'h':
112
      host= optarg;
113
      break;
114
115
    case 'm':
116
      mysql= true;
117
      break;
118
119
    case 'p':
120
      port= (in_port_t)atoi(optarg);
121
      break;
122
123
    case 'v':
1992.6.2 by Monty Taylor
Cleaned up for additional gcc 4.5 warnings.
124
      switch(server->verbose)
125
      {
126
      case DRIZZLE_VERBOSE_NEVER:
127
        server->verbose= DRIZZLE_VERBOSE_FATAL;
128
        break;
129
      case DRIZZLE_VERBOSE_FATAL:
130
        server->verbose= DRIZZLE_VERBOSE_ERROR;
131
        break;
132
      case DRIZZLE_VERBOSE_ERROR:
133
        server->verbose= DRIZZLE_VERBOSE_INFO;
134
        break;
135
      case DRIZZLE_VERBOSE_INFO:
136
        server->verbose= DRIZZLE_VERBOSE_DEBUG;
137
        break;
138
      case DRIZZLE_VERBOSE_DEBUG:
139
        server->verbose= DRIZZLE_VERBOSE_CRAZY;
140
        break;
141
      case DRIZZLE_VERBOSE_CRAZY:
142
      case DRIZZLE_VERBOSE_MAX:
143
        break;
144
      }
1712.1.1 by Monty Taylor
Merged libdrizzle directly into tree.
145
      break;
146
147
    default:
148
      usage(argv[0]);
149
      return 1;
150
    }
151
  }
152
153
  if (argc != (optind + 1))
154
  {
155
    usage(argv[0]);
156
    return 1;
157
  }
158
1929.1.34 by Stewart Smith
fix sqlite_server stack usage
159
  sqlite3_open(argv[optind], &(server->db));
160
  if (server->db == NULL)
1712.1.1 by Monty Taylor
Merged libdrizzle directly into tree.
161
  {
162
    printf("sqlite3_open: could not open sqlite3 db\n");
163
    return 1;
164
  }
165
1929.1.34 by Stewart Smith
fix sqlite_server stack usage
166
  if (drizzle_create(&(server->drizzle)) == NULL)
1712.1.1 by Monty Taylor
Merged libdrizzle directly into tree.
167
  {
168
    printf("drizzle_create:NULL\n");
169
    return 1;
170
  }
171
1929.1.34 by Stewart Smith
fix sqlite_server stack usage
172
  drizzle_add_options(&(server->drizzle), DRIZZLE_FREE_OBJECTS);
173
  drizzle_set_verbose(&(server->drizzle), server->verbose);
1712.1.1 by Monty Taylor
Merged libdrizzle directly into tree.
174
1929.1.34 by Stewart Smith
fix sqlite_server stack usage
175
  if (drizzle_con_create(&(server->drizzle), con_listen) == NULL)
1712.1.1 by Monty Taylor
Merged libdrizzle directly into tree.
176
  {
177
    printf("drizzle_con_create:NULL\n");
178
    return 1;
179
  }
180
1929.1.33 by Stewart Smith
fix large stack usag ein examples/sqlite_server.c:
181
  drizzle_con_add_options(con_listen, DRIZZLE_CON_LISTEN);
182
  drizzle_con_set_tcp(con_listen, host, port);
1712.1.1 by Monty Taylor
Merged libdrizzle directly into tree.
183
184
  if (mysql)
1929.1.33 by Stewart Smith
fix large stack usag ein examples/sqlite_server.c:
185
    drizzle_con_add_options(con_listen, DRIZZLE_CON_MYSQL);
1712.1.1 by Monty Taylor
Merged libdrizzle directly into tree.
186
1929.1.33 by Stewart Smith
fix large stack usag ein examples/sqlite_server.c:
187
  if (drizzle_con_listen(con_listen) != DRIZZLE_RETURN_OK)
1712.1.1 by Monty Taylor
Merged libdrizzle directly into tree.
188
  {
1929.1.34 by Stewart Smith
fix sqlite_server stack usage
189
    printf("drizzle_con_listen:%s\n", drizzle_error(&(server->drizzle)));
1712.1.1 by Monty Taylor
Merged libdrizzle directly into tree.
190
    return 1;
191
  }
192
193
  while (1)
194
  {
1929.1.34 by Stewart Smith
fix sqlite_server stack usage
195
    (void)drizzle_con_accept(&(server->drizzle), &(server->con), &ret);
1712.1.1 by Monty Taylor
Merged libdrizzle directly into tree.
196
    if (ret != DRIZZLE_RETURN_OK)
197
    {
1929.1.34 by Stewart Smith
fix sqlite_server stack usage
198
      printf("drizzle_con_accept:%s\n", drizzle_error(&(server->drizzle)));
1712.1.1 by Monty Taylor
Merged libdrizzle directly into tree.
199
      return 1;
200
    }
201
1929.1.34 by Stewart Smith
fix sqlite_server stack usage
202
    server_run(server);
1712.1.1 by Monty Taylor
Merged libdrizzle directly into tree.
203
1929.1.34 by Stewart Smith
fix sqlite_server stack usage
204
    drizzle_con_free(&(server->con));
1712.1.1 by Monty Taylor
Merged libdrizzle directly into tree.
205
206
    if (count > 0)
207
    {
208
      count--;
209
210
      if (count == 0)
211
        break;
212
    }
213
  }
214
1929.1.33 by Stewart Smith
fix large stack usag ein examples/sqlite_server.c:
215
  drizzle_con_free(con_listen);
1929.1.34 by Stewart Smith
fix sqlite_server stack usage
216
  drizzle_free(&(server->drizzle));
217
  sqlite3_close(server->db);
1929.1.33 by Stewart Smith
fix large stack usag ein examples/sqlite_server.c:
218
  free(con_listen);
1929.1.34 by Stewart Smith
fix sqlite_server stack usage
219
  free(server);
1712.1.1 by Monty Taylor
Merged libdrizzle directly into tree.
220
221
  return 0;
222
}
223
224
static void server_run(sqlite_server *server)
225
{
226
  drizzle_return_t ret;
227
  drizzle_command_t command;
228
  uint8_t *data= NULL;
229
  size_t total;
230
  int sqlite_ret;
231
  char *sqlite_err;
232
233
  /* Handshake packets. */
234
  drizzle_con_set_protocol_version(&(server->con), 10);
235
  drizzle_con_set_server_version(&(server->con), "libdrizzle+SQLite");
236
  drizzle_con_set_thread_id(&(server->con), 1);
237
  drizzle_con_set_scramble(&(server->con),
238
                           (const uint8_t *)"ABCDEFGHIJKLMNOPQRST");
239
  drizzle_con_set_capabilities(&(server->con), DRIZZLE_CAPABILITIES_NONE);
240
  drizzle_con_set_charset(&(server->con), 8);
241
  drizzle_con_set_status(&(server->con), DRIZZLE_CON_STATUS_NONE);
242
  drizzle_con_set_max_packet_size(&(server->con), DRIZZLE_MAX_PACKET_SIZE);
243
244
  ret= drizzle_handshake_server_write(&(server->con));
245
  DRIZZLE_RETURN_CHECK(ret, "drizzle_handshake_server_write",
246
                       &(server->drizzle))
247
248
  ret= drizzle_handshake_client_read(&(server->con));
249
  DRIZZLE_RETURN_CHECK(ret, "drizzle_handshake_client_read", &(server->drizzle))
250
251
  if (drizzle_result_create(&(server->con), &(server->result)) == NULL)
252
    DRIZZLE_RETURN_ERROR("drizzle_result_create", &(server->drizzle))
253
254
  ret= drizzle_result_write(&(server->con), &(server->result), true);
255
  DRIZZLE_RETURN_CHECK(ret, "drizzle_result_write", &(server->drizzle))
256
257
  /* Command loop. */
258
  while (1)
259
  {
260
    drizzle_result_free(&(server->result));
2353.3.1 by Mark Atwood
fix cppcheck redundantIfDelete0 warnings. It is safe to deallocate a NULL pointer
261
    free(data);
1712.1.1 by Monty Taylor
Merged libdrizzle directly into tree.
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
    {
2353.3.1 by Mark Atwood
fix cppcheck redundantIfDelete0 warnings. It is safe to deallocate a NULL pointer
267
      free(data);
1712.1.1 by Monty Taylor
Merged libdrizzle directly into tree.
268
      return;
269
    }
270
    DRIZZLE_RETURN_CHECK(ret, "drizzle_con_command_buffer", &(server->drizzle))
271
272
    if (server->verbose >= DRIZZLE_VERBOSE_INFO)
273
    {
274
      printf("Command=%u Data=%s\n", command,
275
             data == NULL ? "NULL" : (char *)data);
276
    }
277
278
    if (drizzle_result_create(&(server->con), &(server->result)) == NULL)
279
      DRIZZLE_RETURN_ERROR("drizzle_result_create", &(server->drizzle))
280
281
    if (command != DRIZZLE_COMMAND_QUERY ||
282
        !strcasecmp((char *)data, "SHOW DATABASES"))
283
    {
284
      ret= drizzle_result_write(&(server->con), &(server->result), true);
285
      DRIZZLE_RETURN_CHECK(ret, "drizzle_result_write", &(server->drizzle))
286
287
      if (command == DRIZZLE_COMMAND_FIELD_LIST)
288
      {
289
        drizzle_result_set_eof(&(server->result), true);
290
        ret= drizzle_result_write(&(server->con), &(server->result), true);
291
        DRIZZLE_RETURN_CHECK(ret, "drizzle_result_write", &(server->drizzle))
292
      }
293
294
      continue;
295
    }
296
297
    if (strstr((char *)data, "@@version") != NULL)
298
    {
299
      ret= send_version(server);
300
      if (ret != DRIZZLE_RETURN_OK)
301
        return;
302
303
      continue;
304
    }
305
306
    server->send_columns= true;
307
    server->rows= 0;
308
309
    if (!strcasecmp((char *)data, "SHOW TABLES"))
310
    {
311
      sqlite_ret= sqlite3_exec(server->db,
312
                            "SELECT name FROM sqlite_master WHERE type='table'",
313
                               row_cb, server, &sqlite_err);
314
    }
315
    else
316
    {
317
      sqlite_ret= sqlite3_exec(server->db, (char *)data, row_cb, server,
318
                               &sqlite_err);
319
    }
320
321
    if (sqlite_ret != SQLITE_OK)
322
    {
323
      if (sqlite_err == NULL)
324
        printf("sqlite3_exec failed\n");
325
      else
326
      {
327
        drizzle_result_set_error_code(&(server->result), (uint16_t)sqlite_ret);
328
        drizzle_result_set_error(&(server->result), sqlite_err);
329
        ret= drizzle_result_write(&(server->con), &(server->result), true);
330
        DRIZZLE_RETURN_CHECK(ret, "drizzle_result_write", &(server->drizzle))
331
332
        printf("sqlite3_exec:%s\n", sqlite_err);
333
        sqlite3_free(sqlite_err);
334
      }
335
336
      return;
337
    }
338
339
    if (server->rows == 0)
340
    {
341
      drizzle_result_set_column_count(&(server->result), 0);
342
      ret= drizzle_result_write(&(server->con), &(server->result), true);
343
      DRIZZLE_RETURN_CHECK(ret, "drizzle_result_write", &(server->drizzle))
344
    }
345
    else
346
    {
347
      drizzle_result_set_eof(&(server->result), true);
348
      ret= drizzle_result_write(&(server->con), &(server->result), true);
349
      DRIZZLE_RETURN_CHECK(ret, "drizzle_result_write", &(server->drizzle))
350
    }
351
  }
352
}
353
354
static int row_cb(void *data, int field_count, char **fields, char **columns)
355
{
356
  sqlite_server *server= (sqlite_server *)data;
357
  drizzle_return_t ret;
358
  int x;
1929.1.36 by Stewart Smith
one last sqlite_server stack fix
359
  size_t *sizes= (size_t*)malloc(sizeof(size_t)*8192);
1712.1.1 by Monty Taylor
Merged libdrizzle directly into tree.
360
361
  if (server->send_columns == true)
362
  {
363
    server->send_columns= false;
364
    drizzle_result_set_column_count(&(server->result), (uint16_t)field_count);
365
366
    ret= drizzle_result_write(&(server->con), &(server->result), false);
367
    DRIZZLE_RETURN_CHECK_VAL(ret, "drizzle_result_write", &(server->drizzle))
368
369
    if (drizzle_column_create(&(server->result), &(server->column)) == NULL)
370
    {
371
      DRIZZLE_RETURN_CHECK_VAL(DRIZZLE_RETURN_MEMORY, "drizzle_column_create",
372
                               &(server->drizzle))
373
    }
374
375
    drizzle_column_set_catalog(&(server->column), "sqlite");
376
    drizzle_column_set_db(&(server->column), "sqlite_db");
377
    drizzle_column_set_table(&(server->column), "sqlite_table");
378
    drizzle_column_set_orig_table(&(server->column), "sqlite_table");
379
    drizzle_column_set_charset(&(server->column), 8);
380
    drizzle_column_set_type(&(server->column), DRIZZLE_COLUMN_TYPE_VARCHAR);
381
382
    for (x= 0; x < field_count; x++)
383
    {
384
      drizzle_column_set_size(&(server->column),
385
                              fields[x] == NULL ?
386
                              0 : (uint32_t)strlen(fields[x]));
387
      drizzle_column_set_name(&(server->column), columns[x]);
388
      drizzle_column_set_orig_name(&(server->column), columns[x]);
389
390
      ret= drizzle_column_write(&(server->result), &(server->column));
391
      DRIZZLE_RETURN_CHECK_VAL(ret, "drizzle_column_write", &(server->drizzle))
392
    }
393
394
    drizzle_column_free(&(server->column));
395
396
    drizzle_result_set_eof(&(server->result), true);
397
398
    ret= drizzle_result_write(&(server->con), &(server->result), false);
399
    DRIZZLE_RETURN_CHECK_VAL(ret, "drizzle_result_write", &(server->drizzle))
400
  }
401
402
  for (x= 0; x < field_count; x++)
403
  {
404
    if (fields[x] == NULL)
405
      sizes[x]= 0;
406
    else
407
      sizes[x]= strlen(fields[x]);
408
  }
409
410
  /* This is needed for MySQL and old Drizzle protocol. */
411
  drizzle_result_calc_row_size(&(server->result), (drizzle_field_t *)fields,
412
                               sizes);
413
414
  ret= drizzle_row_write(&(server->result));
415
  DRIZZLE_RETURN_CHECK_VAL(ret, "drizzle_row_write", &(server->drizzle))
416
417
  for (x= 0; x < field_count; x++)
418
  {
419
    ret= drizzle_field_write(&(server->result), (drizzle_field_t)fields[x],
420
                             sizes[x], sizes[x]);
421
    DRIZZLE_RETURN_CHECK_VAL(ret, "drizzle_field_write", &(server->drizzle))
422
  }
423
424
  server->rows++;
425
1929.1.36 by Stewart Smith
one last sqlite_server stack fix
426
  free(sizes);
427
1712.1.1 by Monty Taylor
Merged libdrizzle directly into tree.
428
  return 0;
429
}
430
431
static drizzle_return_t send_version(sqlite_server *server)
432
{
433
  drizzle_return_t ret;
434
  drizzle_field_t fields[1];
435
  size_t sizes[1];
436
437
  fields[0]= (drizzle_field_t)SQLITE_SERVER_VERSION;
438
  sizes[0]= strlen(SQLITE_SERVER_VERSION);
439
440
  drizzle_result_set_column_count(&(server->result), 1);
441
442
  ret= drizzle_result_write(&(server->con), &(server->result), false);
443
  DRIZZLE_RETURN_CHECK_VAL(ret, "drizzle_result_write", &(server->drizzle))
444
445
  if (drizzle_column_create(&(server->result), &(server->column)) == NULL)
446
  {
447
    DRIZZLE_RETURN_CHECK_VAL(DRIZZLE_RETURN_MEMORY, "drizzle_column_create",
448
                             &(server->drizzle))
449
  }
450
451
  drizzle_column_set_catalog(&(server->column), "sqlite");
452
  drizzle_column_set_db(&(server->column), "sqlite_db");
453
  drizzle_column_set_table(&(server->column), "sqlite_table");
454
  drizzle_column_set_orig_table(&(server->column), "sqlite_table");
455
  drizzle_column_set_charset(&(server->column), 8);
456
  drizzle_column_set_type(&(server->column), DRIZZLE_COLUMN_TYPE_VARCHAR);
457
  drizzle_column_set_size(&(server->column), (uint32_t)sizes[0]);
458
  drizzle_column_set_name(&(server->column), "version");
459
  drizzle_column_set_orig_name(&(server->column), "version");
460
461
  ret= drizzle_column_write(&(server->result), &(server->column));
462
  DRIZZLE_RETURN_CHECK_VAL(ret, "drizzle_column_write", &(server->drizzle))
463
464
  drizzle_column_free(&(server->column));
465
466
  drizzle_result_set_eof(&(server->result), true);
467
468
  ret= drizzle_result_write(&(server->con), &(server->result), false);
469
  DRIZZLE_RETURN_CHECK_VAL(ret, "drizzle_result_write", &(server->drizzle))
470
471
  /* This is needed for MySQL and old Drizzle protocol. */
472
  drizzle_result_calc_row_size(&(server->result), fields, sizes);
473
474
  ret= drizzle_row_write(&(server->result));
475
  DRIZZLE_RETURN_CHECK_VAL(ret, "drizzle_row_write", &(server->drizzle))
476
477
  ret= drizzle_field_write(&(server->result), fields[0], sizes[0], sizes[0]);
478
  DRIZZLE_RETURN_CHECK_VAL(ret, "drizzle_field_write", &(server->drizzle))
479
480
  ret= drizzle_result_write(&(server->con), &(server->result), true);
481
  DRIZZLE_RETURN_CHECK_VAL(ret, "drizzle_result_write", &(server->drizzle))
482
483
  return DRIZZLE_RETURN_OK;
484
}
485
486
static void usage(char *name)
487
{
488
  printf("\nusage: %s [-c <count>] [-h <host>] [-m] [-p <port>] [-v] "
489
         "<sqlite3 db file>\n", name);
490
  printf("\t-c <count> - Number of connections to accept before exiting\n");
491
  printf("\t-h <host>  - Host to listen on\n");
492
  printf("\t-m         - Use the MySQL protocol\n");
493
  printf("\t-p <port>  - Port to listen on\n");
494
  printf("\t-v         - Increase verbosity level\n");
495
}