~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to examples/client.c

  • Committer: Stewart Smith
  • Date: 2010-02-15 03:55:09 UTC
  • mto: (1273.13.96 build)
  • mto: This revision was merged to the branch mainline in revision 1308.
  • Revision ID: stewart@flamingspork.com-20100215035509-y6sry4q4yymph2by
move SUBSTR, SUBSTRING and SUBSTR_INDEX to plugins. add parser hooks for substr being a plugin now.

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 "config.h"
39
 
 
40
 
#include <errno.h>
41
 
#include <stdbool.h>
42
 
#include <stdint.h>
43
 
#include <stdio.h>
44
 
#include <stdlib.h>
45
 
#include <string.h>
46
 
#include <unistd.h>
47
 
 
48
 
#include <libdrizzle/drizzle_client.h>
49
 
 
50
 
typedef enum
51
 
{
52
 
  CLIENT_QUERY,
53
 
  CLIENT_FIELDS,
54
 
  CLIENT_ROWS
55
 
} client_state;
56
 
 
57
 
typedef enum
58
 
{
59
 
  BUFFER_NONE,
60
 
  BUFFER_FIELD,
61
 
  BUFFER_ROW,
62
 
  BUFFER_ALL
63
 
} buffer_level;
64
 
 
65
 
typedef struct
66
 
{
67
 
  drizzle_con_st con;
68
 
  drizzle_result_st result;
69
 
  drizzle_column_st column;
70
 
  client_state state;
71
 
  uint64_t row;
72
 
} client_con_st;
73
 
 
74
 
typedef struct
75
 
{
76
 
  drizzle_st drizzle;
77
 
  bool mysql_protocol;
78
 
  client_con_st *client_con_list;
79
 
  uint32_t client_con_count;
80
 
  buffer_level level;
81
 
  char *query;
82
 
  size_t query_len;
83
 
} client_st;
84
 
 
85
 
char client_process(client_st *client, client_con_st *client_con);
86
 
void con_info(drizzle_con_st *con);
87
 
void result_info(drizzle_result_st *result);
88
 
void column_info(drizzle_column_st *column);
89
 
 
90
 
#define CLIENT_ERROR(__function, __ret, __client) { \
91
 
    printf(__function ":%d:%s\n", __ret, \
92
 
           drizzle_error(&((__client)->drizzle))); \
93
 
    exit(1); }
94
 
 
95
 
int main(int argc, char *argv[])
96
 
{
97
 
  client_st client;
98
 
  int c;
99
 
  char blocking= 0;
100
 
  drizzle_return_t ret;
101
 
  uint32_t x;
102
 
  int wait_for_connections= 0;
103
 
  drizzle_con_st *con;
104
 
  client_con_st *client_con;
105
 
  char *host= NULL;
106
 
  in_port_t port= 0;
107
 
  char *user= NULL;
108
 
  char *password= NULL;
109
 
  char *db= NULL;
110
 
 
111
 
  memset(&client, 0, sizeof(client_st));
112
 
 
113
 
  /* Use one connection by default. */
114
 
  client.client_con_count= 1;
115
 
 
116
 
  while ((c = getopt(argc, argv, "bB:c:d:h:Hmp:P:u:")) != -1)
117
 
  {
118
 
    switch(c)
119
 
    {
120
 
    case 'b':
121
 
      blocking= 1;
122
 
      break;
123
 
 
124
 
    case 'B':
125
 
      if (!strcasecmp(optarg, "none"))
126
 
        client.level= BUFFER_NONE;
127
 
      else if (!strcasecmp(optarg, "field"))
128
 
        client.level= BUFFER_FIELD;
129
 
      else if (!strcasecmp(optarg, "row"))
130
 
        client.level= BUFFER_ROW;
131
 
      else if (!strcasecmp(optarg, "all"))
132
 
        client.level= BUFFER_ALL;
133
 
      else
134
 
      {
135
 
        printf("Invalid buffer level: %s\n", optarg);
136
 
        exit(0);
137
 
      }
138
 
      break;
139
 
 
140
 
    case 'c':
141
 
      client.client_con_count= (uint32_t)atoi(optarg);
142
 
      break;
143
 
 
144
 
    case 'd':
145
 
      db= optarg;
146
 
      break;
147
 
 
148
 
    case 'h':
149
 
      host= optarg;
150
 
      break;
151
 
 
152
 
    case 'm':
153
 
      client.mysql_protocol= true;
154
 
      break;
155
 
 
156
 
    case 'p':
157
 
      password= optarg;
158
 
      break;
159
 
 
160
 
    case 'P':
161
 
      port= (in_port_t)atoi(optarg);
162
 
      break;
163
 
 
164
 
    case 'u':
165
 
      user= optarg;
166
 
      break;
167
 
 
168
 
    case 'H':
169
 
    default:
170
 
      printf("\nUsage: %s [options] [query]\n", argv[0]);
171
 
      printf("\t-b            - Use blocking sockets\n");
172
 
      printf("\t-B <level>    - Use buffer <level>, options are:\n");
173
 
      printf("\t                none - Don't buffer anything (default)\n");
174
 
      printf("\t                field - Only buffer individual fields\n");
175
 
      printf("\t                row - Only buffer individual rows\n");
176
 
      printf("\t                all - Buffer entire result\n");
177
 
      printf("\t-c <cons>     - Create <cons> connections\n");
178
 
      printf("\t-d <db>       - Use <db> for the connection\n");
179
 
      printf("\t-h <host>     - Connect to <host>\n");
180
 
      printf("\t-H            - Print this help menu\n");
181
 
      printf("\t-m            - Use MySQL protocol\n");
182
 
      printf("\t-p <password> - Use <password> for authentication\n");
183
 
      printf("\t-P <port>     - Connect to <port>\n");
184
 
      printf("\t-u <user>     - Use <user> for authentication\n");
185
 
      exit(0);
186
 
    }
187
 
  }
188
 
 
189
 
  if (argc != optind)
190
 
  {
191
 
    client.query= argv[optind];
192
 
    client.query_len= strlen(client.query);
193
 
  }
194
 
 
195
 
  if (client.client_con_count > 0)
196
 
  {
197
 
    client.client_con_list= calloc(client.client_con_count,
198
 
                                   sizeof(client_con_st));
199
 
    if (client.client_con_list == NULL)
200
 
    {
201
 
      printf("calloc:%d\n", errno);
202
 
      exit(1);
203
 
    }
204
 
  }
205
 
 
206
 
  /* This may fail if there is other initialization that fails. See docs. */
207
 
  if (drizzle_create(&(client.drizzle)) == NULL)
208
 
  {
209
 
    printf("drizzle_create failed\n");
210
 
    exit(1);
211
 
  }
212
 
 
213
 
  if (blocking == 0)
214
 
    drizzle_add_options(&(client.drizzle), DRIZZLE_NON_BLOCKING);
215
 
 
216
 
  /* Start all connections, and if in non-blocking mode, return as soon as the
217
 
     connection would block. In blocking mode, this completes the entire
218
 
     connection/query/result. */
219
 
  for (x= 0; x < client.client_con_count; x++)
220
 
  {
221
 
    /* This may fail if there is other initialization that fails. See docs. */
222
 
    con= drizzle_con_add_tcp(&(client.drizzle),
223
 
                              &(client.client_con_list[x].con),
224
 
                              host, port, user, password, db,
225
 
                              client.mysql_protocol ? DRIZZLE_CON_MYSQL : 0);
226
 
    if (con == NULL)
227
 
      CLIENT_ERROR("drizzle_con_add_tcp", 0, &client);
228
 
    drizzle_con_set_context(&(client.client_con_list[x].con),
229
 
                            &(client.client_con_list[x]));
230
 
 
231
 
    if (client_process(&client, &(client.client_con_list[x])) == 1)
232
 
      wait_for_connections++;
233
 
  }
234
 
 
235
 
  /* If in non-blocking mode, continue to process connections as they become
236
 
     ready. Loop exits when all connections have completed. */
237
 
  while (wait_for_connections != 0)
238
 
  {
239
 
    ret= drizzle_con_wait(&(client.drizzle));
240
 
    if (ret != DRIZZLE_RETURN_OK)
241
 
      CLIENT_ERROR("drizzle_con_wait", ret, &client);
242
 
 
243
 
    while ((con= drizzle_con_ready(&(client.drizzle))) != NULL)
244
 
    {
245
 
      client_con= (client_con_st *)drizzle_con_context(con);
246
 
 
247
 
      if (client_process(&client, client_con) == 0)
248
 
        wait_for_connections--;
249
 
    }
250
 
  }
251
 
 
252
 
  for (x= 0; x < client.client_con_count; x++)
253
 
    drizzle_con_free(&(client.client_con_list[x].con));
254
 
 
255
 
  drizzle_free(&(client.drizzle));
256
 
 
257
 
  if (client.client_con_list != NULL)
258
 
    free(client.client_con_list);
259
 
 
260
 
  return 0;
261
 
}
262
 
 
263
 
char client_process(client_st *client, client_con_st *client_con)
264
 
{
265
 
  drizzle_return_t ret;
266
 
  drizzle_column_st *column;
267
 
  size_t offset= 0;
268
 
  size_t length;
269
 
  size_t total;
270
 
  drizzle_field_t field;
271
 
  drizzle_row_t row;
272
 
  size_t *field_sizes;
273
 
  uint16_t x;
274
 
 
275
 
  switch (client_con->state)
276
 
  {
277
 
  case CLIENT_QUERY:
278
 
    if (client->query == NULL)
279
 
      break;
280
 
 
281
 
    /* This may fail if some allocation fails, but it will set ret. */
282
 
    (void)drizzle_query(&(client_con->con), &(client_con->result),
283
 
                        client->query, client->query_len, &ret);
284
 
    if (ret == DRIZZLE_RETURN_IO_WAIT)
285
 
      return 1;
286
 
    else if (ret != DRIZZLE_RETURN_OK)
287
 
      CLIENT_ERROR("drizzle_query", ret, client);
288
 
 
289
 
    result_info(&(client_con->result));
290
 
 
291
 
    if (drizzle_result_column_count(&(client_con->result)) == 0)
292
 
      break;
293
 
 
294
 
    client_con->state= CLIENT_FIELDS;
295
 
 
296
 
  case CLIENT_FIELDS:
297
 
    if (client->level == BUFFER_ALL)
298
 
    {
299
 
      ret= drizzle_result_buffer(&(client_con->result));
300
 
      if (ret == DRIZZLE_RETURN_IO_WAIT)
301
 
        return 1;
302
 
      else if (ret != DRIZZLE_RETURN_OK)
303
 
        CLIENT_ERROR("drizzle_result_buffer", ret, client);
304
 
 
305
 
      while ((column= drizzle_column_next(&(client_con->result))) != NULL)
306
 
        column_info(column);
307
 
    }
308
 
    else
309
 
    {
310
 
      while (1)
311
 
      {
312
 
        column= drizzle_column_read(&(client_con->result),
313
 
                                    &(client_con->column), &ret);
314
 
        if (ret == DRIZZLE_RETURN_IO_WAIT)
315
 
          return 1;
316
 
        else if (ret != DRIZZLE_RETURN_OK)
317
 
          CLIENT_ERROR("drizzle_column_read", ret, client);
318
 
 
319
 
        if (column == NULL)
320
 
          break;
321
 
 
322
 
        column_info(column);
323
 
        drizzle_column_free(column);
324
 
      }
325
 
    }
326
 
 
327
 
    client_con->state= CLIENT_ROWS;
328
 
 
329
 
  case CLIENT_ROWS:
330
 
    if (client->level == BUFFER_ALL)
331
 
    {
332
 
      /* Everything has been buffered, just loop through and print. */
333
 
      while ((row= drizzle_row_next(&(client_con->result))) != NULL)
334
 
      {
335
 
        field_sizes= drizzle_row_field_sizes(&(client_con->result));
336
 
 
337
 
        printf("Row: %" PRId64 "\n",
338
 
               drizzle_row_current(&(client_con->result)));
339
 
 
340
 
        for (x= 0; x < drizzle_result_column_count(&(client_con->result)); x++)
341
 
        {
342
 
          if (row[x] == NULL)
343
 
            printf("     (NULL)\n");
344
 
          else
345
 
          {
346
 
            printf("     (%zd) %.*s\n", field_sizes[x], (int32_t)field_sizes[x],
347
 
                   row[x]);
348
 
          }
349
 
        }
350
 
 
351
 
        printf("\n");
352
 
      }
353
 
 
354
 
      drizzle_result_free(&(client_con->result));
355
 
      break;
356
 
    }
357
 
 
358
 
    while (1)
359
 
    {
360
 
      if (client->level == BUFFER_NONE || client->level == BUFFER_FIELD)
361
 
      {
362
 
        /* Still need to read a row at a time, and then each field. */
363
 
        if (client_con->row == 0)
364
 
        {
365
 
          client_con->row= drizzle_row_read(&(client_con->result), &ret);
366
 
          if (ret == DRIZZLE_RETURN_IO_WAIT)
367
 
          {
368
 
            client_con->row= 0;
369
 
            return 1;
370
 
          }
371
 
          else if (ret != DRIZZLE_RETURN_OK)
372
 
            CLIENT_ERROR("drizzle_row", ret, client);
373
 
 
374
 
          if (client_con->row == 0)
375
 
          {
376
 
            drizzle_result_free(&(client_con->result));
377
 
            break;
378
 
          }
379
 
 
380
 
          printf("Row: %" PRId64 "\n", client_con->row);
381
 
        }
382
 
 
383
 
        while (1)
384
 
        {
385
 
          if (client->level == BUFFER_FIELD)
386
 
          {
387
 
            /* Since an entire field is buffered, we don't need to worry about
388
 
               partial reads. */
389
 
            field= drizzle_field_buffer(&(client_con->result), &total, &ret);
390
 
            length= total;
391
 
          }
392
 
          else
393
 
          {
394
 
            field= drizzle_field_read(&(client_con->result), &offset, &length,
395
 
                                      &total, &ret);
396
 
          }
397
 
 
398
 
          if (ret == DRIZZLE_RETURN_IO_WAIT)
399
 
            return 1;
400
 
          else if (ret == DRIZZLE_RETURN_ROW_END)
401
 
            break;
402
 
          else if (ret != DRIZZLE_RETURN_OK)
403
 
            CLIENT_ERROR("drizzle_field_read", ret, client);
404
 
 
405
 
          if (field == NULL)
406
 
            printf("     (NULL)");
407
 
          else if (offset > 0)
408
 
            printf("%.*s", (int32_t)length, field);
409
 
          else
410
 
            printf("     (%zd) %.*s", total, (int32_t)length, field);
411
 
 
412
 
          if (offset + length == total)
413
 
            printf("\n");
414
 
 
415
 
          /* If we buffered the entire field, be sure to free it. */
416
 
          if (client->level == BUFFER_FIELD)
417
 
            drizzle_field_free(field);
418
 
        }
419
 
 
420
 
        client_con->row= 0;
421
 
        printf("\n");
422
 
      }
423
 
      else if (client->level == BUFFER_ROW)
424
 
      {
425
 
        /* The entire row will be buffered here, so no need to worry about
426
 
           partial reads. */
427
 
        row = drizzle_row_buffer(&(client_con->result), &ret);
428
 
        if (ret == DRIZZLE_RETURN_IO_WAIT)
429
 
          return 1;
430
 
        else if (ret != DRIZZLE_RETURN_OK)
431
 
          CLIENT_ERROR("drizzle_row", ret, client);
432
 
 
433
 
        /* This marks the end of rows. */
434
 
        if (row == NULL)
435
 
          break;
436
 
 
437
 
        field_sizes= drizzle_row_field_sizes(&(client_con->result));
438
 
 
439
 
        printf("Row: %" PRId64 "\n",
440
 
               drizzle_row_current(&(client_con->result)));
441
 
 
442
 
        for (x= 0; x < drizzle_result_column_count(&(client_con->result)); x++)
443
 
        {
444
 
          if (row[x] == NULL)
445
 
            printf("     (NULL)\n");
446
 
          else
447
 
          {
448
 
            printf("     (%zd) %.*s\n", field_sizes[x], (int32_t)field_sizes[x],
449
 
                   row[x]);
450
 
          }
451
 
        }
452
 
 
453
 
        drizzle_row_free(&(client_con->result), row);
454
 
        printf("\n");
455
 
      }
456
 
    }
457
 
 
458
 
    drizzle_result_free(&(client_con->result));
459
 
    break;
460
 
 
461
 
  default:
462
 
    /* This should be impossible. */
463
 
    return 1;
464
 
  }
465
 
 
466
 
  return 0;
467
 
}
468
 
 
469
 
void con_info(drizzle_con_st *con)
470
 
{
471
 
  printf("Connected: protocol_version=%u\n"
472
 
         "                    version=%s\n"
473
 
         "                  thread_id=%u\n"
474
 
         "               capabilities=%u\n"
475
 
         "                   language=%u\n"
476
 
         "                     status=%u\n\n",
477
 
         drizzle_con_protocol_version(con), drizzle_con_server_version(con),
478
 
         drizzle_con_thread_id(con), drizzle_con_capabilities(con),
479
 
         drizzle_con_charset(con), drizzle_con_status(con));
480
 
}
481
 
 
482
 
void result_info(drizzle_result_st *result)
483
 
{
484
 
  printf("Result:     row_count=%" PRId64 "\n"
485
 
         "            insert_id=%" PRId64 "\n"
486
 
         "        warning_count=%u\n"
487
 
         "         column_count=%u\n"
488
 
         "        affected_rows=%" PRId64 "\n\n",
489
 
         drizzle_result_row_count(result),
490
 
         drizzle_result_insert_id(result),
491
 
         drizzle_result_warning_count(result),
492
 
         drizzle_result_column_count(result),
493
 
         drizzle_result_affected_rows(result));
494
 
}
495
 
 
496
 
void column_info(drizzle_column_st *column)
497
 
{
498
 
  printf("Field:   catalog=%s\n"
499
 
         "              db=%s\n"
500
 
         "           table=%s\n"
501
 
         "       org_table=%s\n"
502
 
         "            name=%s\n"
503
 
         "        org_name=%s\n"
504
 
         "         charset=%u\n"
505
 
         "            size=%u\n"
506
 
         "        max_size=%zu\n"
507
 
         "            type=%u\n"
508
 
         "           flags=%u\n\n",
509
 
         drizzle_column_catalog(column), drizzle_column_db(column),
510
 
         drizzle_column_table(column), drizzle_column_orig_table(column),
511
 
         drizzle_column_name(column), drizzle_column_orig_name(column),
512
 
         drizzle_column_charset(column), drizzle_column_size(column),
513
 
         drizzle_column_max_size(column), drizzle_column_type(column),
514
 
         drizzle_column_flags(column));
515
 
}