~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to examples/client.c

  • Committer: Monty Taylor
  • Date: 2010-08-12 20:27:32 UTC
  • mto: (1720.1.5 build)
  • mto: This revision was merged to the branch mainline in revision 1722.
  • Revision ID: mordred@inaugust.com-20100812202732-9kzchbkvkyki4n3u
Merged libdrizzle directly into tree.

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