~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to examples/sqlite_server.c

  • Committer: Prafulla Tekawade
  • Date: 2010-07-13 16:07:35 UTC
  • mto: (1662.1.4 rollup)
  • mto: This revision was merged to the branch mainline in revision 1664.
  • Revision ID: prafulla_t@users.sourceforge.net-20100713160735-2fsdtrm3azayuyu1
This bug is simillar to mysql bug 36133
http://bugs.mysql.com/bug.php?id=36133

Taking changes from that fix.

  - The problem was that the range optimizer evaluated constant expressions, 
    and among them it would try to evaluate IN-subquery predicates slated for
    handling with materialization strategy. However, these predicates require
    that parent_join->setup_subquery_materialization() is invoked before one
    attempts to evaluate them.
  
  - Fixed by making the range optimizer not to evaluate expressions that have
    item->is_expensive() == TRUE (these are materialization subqueries and 
    stored function calls). This should also resolve the problem that EXPLAIN 
    may be too long. 
    This change cuts off some opportunities for range optimizer, but this is 
    the price we're willing to pay for separation of query optimization and
    execution. 

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
 
 * 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
 
 *
35
 
 */
36
 
 
37
 
 
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;
96
 
  sqlite_server *server= (sqlite_server*)malloc(sizeof(sqlite_server));
97
 
  drizzle_con_st *con_listen= (drizzle_con_st*)malloc(sizeof(drizzle_con_st));
98
 
 
99
 
  server->db= NULL;
100
 
  server->verbose= DRIZZLE_VERBOSE_NEVER;
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':
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
 
      }
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
 
 
158
 
  sqlite3_open(argv[optind], &(server->db));
159
 
  if (server->db == NULL)
160
 
  {
161
 
    printf("sqlite3_open: could not open sqlite3 db\n");
162
 
    return 1;
163
 
  }
164
 
 
165
 
  if (drizzle_create(&(server->drizzle)) == NULL)
166
 
  {
167
 
    printf("drizzle_create:NULL\n");
168
 
    return 1;
169
 
  }
170
 
 
171
 
  drizzle_add_options(&(server->drizzle), DRIZZLE_FREE_OBJECTS);
172
 
  drizzle_set_verbose(&(server->drizzle), server->verbose);
173
 
 
174
 
  if (drizzle_con_create(&(server->drizzle), con_listen) == NULL)
175
 
  {
176
 
    printf("drizzle_con_create:NULL\n");
177
 
    return 1;
178
 
  }
179
 
 
180
 
  drizzle_con_add_options(con_listen, DRIZZLE_CON_LISTEN);
181
 
  drizzle_con_set_tcp(con_listen, host, port);
182
 
 
183
 
  if (mysql)
184
 
    drizzle_con_add_options(con_listen, DRIZZLE_CON_MYSQL);
185
 
 
186
 
  if (drizzle_con_listen(con_listen) != DRIZZLE_RETURN_OK)
187
 
  {
188
 
    printf("drizzle_con_listen:%s\n", drizzle_error(&(server->drizzle)));
189
 
    return 1;
190
 
  }
191
 
 
192
 
  while (1)
193
 
  {
194
 
    (void)drizzle_con_accept(&(server->drizzle), &(server->con), &ret);
195
 
    if (ret != DRIZZLE_RETURN_OK)
196
 
    {
197
 
      printf("drizzle_con_accept:%s\n", drizzle_error(&(server->drizzle)));
198
 
      return 1;
199
 
    }
200
 
 
201
 
    server_run(server);
202
 
 
203
 
    drizzle_con_free(&(server->con));
204
 
 
205
 
    if (count > 0)
206
 
    {
207
 
      count--;
208
 
 
209
 
      if (count == 0)
210
 
        break;
211
 
    }
212
 
  }
213
 
 
214
 
  drizzle_con_free(con_listen);
215
 
  drizzle_free(&(server->drizzle));
216
 
  sqlite3_close(server->db);
217
 
  free(con_listen);
218
 
  free(server);
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
 
 
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))
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;
360
 
  size_t *sizes= (size_t*)malloc(sizeof(size_t)*8192);
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
 
 
427
 
  free(sizes);
428
 
 
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
 
}