~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
2173.2.1 by Monty Taylor
Fixes incorrect usage of include
38
#include <config.h>
1712.1.1 by Monty Taylor
Merged libdrizzle directly into tree.
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
  {
1992.6.2 by Monty Taylor
Cleaned up for additional gcc 4.5 warnings.
197
    client.client_con_list= (client_con_st *)calloc(client.client_con_count,
198
                                                    sizeof(client_con_st));
1712.1.1 by Monty Taylor
Merged libdrizzle directly into tree.
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,
1992.6.2 by Monty Taylor
Cleaned up for additional gcc 4.5 warnings.
225
                              client.mysql_protocol
226
                              ? DRIZZLE_CON_MYSQL
227
                              : DRIZZLE_CON_NONE);
1712.1.1 by Monty Taylor
Merged libdrizzle directly into tree.
228
    if (con == NULL)
229
      CLIENT_ERROR("drizzle_con_add_tcp", 0, &client);
230
    drizzle_con_set_context(&(client.client_con_list[x].con),
231
                            &(client.client_con_list[x]));
232
233
    if (client_process(&client, &(client.client_con_list[x])) == 1)
234
      wait_for_connections++;
235
  }
236
237
  /* If in non-blocking mode, continue to process connections as they become
238
     ready. Loop exits when all connections have completed. */
239
  while (wait_for_connections != 0)
240
  {
241
    ret= drizzle_con_wait(&(client.drizzle));
242
    if (ret != DRIZZLE_RETURN_OK)
243
      CLIENT_ERROR("drizzle_con_wait", ret, &client);
244
245
    while ((con= drizzle_con_ready(&(client.drizzle))) != NULL)
246
    {
247
      client_con= (client_con_st *)drizzle_con_context(con);
248
249
      if (client_process(&client, client_con) == 0)
250
        wait_for_connections--;
251
    }
252
  }
253
254
  for (x= 0; x < client.client_con_count; x++)
255
    drizzle_con_free(&(client.client_con_list[x].con));
256
257
  drizzle_free(&(client.drizzle));
258
2353.3.1 by Mark Atwood
fix cppcheck redundantIfDelete0 warnings. It is safe to deallocate a NULL pointer
259
  free(client.client_con_list);
1712.1.1 by Monty Taylor
Merged libdrizzle directly into tree.
260
261
  return 0;
262
}
263
264
char client_process(client_st *client, client_con_st *client_con)
265
{
266
  drizzle_return_t ret;
267
  drizzle_column_st *column;
268
  size_t offset= 0;
269
  size_t length;
270
  size_t total;
271
  drizzle_field_t field;
272
  drizzle_row_t row;
273
  size_t *field_sizes;
274
  uint16_t x;
275
276
  switch (client_con->state)
277
  {
278
  case CLIENT_QUERY:
279
    if (client->query == NULL)
280
      break;
281
282
    /* This may fail if some allocation fails, but it will set ret. */
283
    (void)drizzle_query(&(client_con->con), &(client_con->result),
284
                        client->query, client->query_len, &ret);
285
    if (ret == DRIZZLE_RETURN_IO_WAIT)
286
      return 1;
287
    else if (ret != DRIZZLE_RETURN_OK)
288
      CLIENT_ERROR("drizzle_query", ret, client);
289
290
    result_info(&(client_con->result));
291
292
    if (drizzle_result_column_count(&(client_con->result)) == 0)
293
      break;
294
295
    client_con->state= CLIENT_FIELDS;
296
297
  case CLIENT_FIELDS:
298
    if (client->level == BUFFER_ALL)
299
    {
300
      ret= drizzle_result_buffer(&(client_con->result));
301
      if (ret == DRIZZLE_RETURN_IO_WAIT)
302
        return 1;
303
      else if (ret != DRIZZLE_RETURN_OK)
304
        CLIENT_ERROR("drizzle_result_buffer", ret, client);
305
306
      while ((column= drizzle_column_next(&(client_con->result))) != NULL)
307
        column_info(column);
308
    }
309
    else
310
    {
311
      while (1)
312
      {
313
        column= drizzle_column_read(&(client_con->result),
314
                                    &(client_con->column), &ret);
315
        if (ret == DRIZZLE_RETURN_IO_WAIT)
316
          return 1;
317
        else if (ret != DRIZZLE_RETURN_OK)
318
          CLIENT_ERROR("drizzle_column_read", ret, client);
319
320
        if (column == NULL)
321
          break;
322
323
        column_info(column);
324
        drizzle_column_free(column);
325
      }
326
    }
327
328
    client_con->state= CLIENT_ROWS;
329
330
  case CLIENT_ROWS:
331
    if (client->level == BUFFER_ALL)
332
    {
333
      /* Everything has been buffered, just loop through and print. */
334
      while ((row= drizzle_row_next(&(client_con->result))) != NULL)
335
      {
336
        field_sizes= drizzle_row_field_sizes(&(client_con->result));
337
338
        printf("Row: %" PRId64 "\n",
339
               drizzle_row_current(&(client_con->result)));
340
341
        for (x= 0; x < drizzle_result_column_count(&(client_con->result)); x++)
342
        {
343
          if (row[x] == NULL)
344
            printf("     (NULL)\n");
345
          else
346
          {
2244.1.1 by Monty Taylor
Split libdrizzle into 1.0 and 2.0. Applied the C++ changes to 2.0 branch.
347
            printf("     (%"PRIu64") %.*s\n", static_cast<uint64_t>(field_sizes[x]), (int32_t)field_sizes[x],
1712.1.1 by Monty Taylor
Merged libdrizzle directly into tree.
348
                   row[x]);
349
          }
350
        }
351
352
        printf("\n");
353
      }
354
355
      drizzle_result_free(&(client_con->result));
356
      break;
357
    }
358
359
    while (1)
360
    {
361
      if (client->level == BUFFER_NONE || client->level == BUFFER_FIELD)
362
      {
363
        /* Still need to read a row at a time, and then each field. */
364
        if (client_con->row == 0)
365
        {
366
          client_con->row= drizzle_row_read(&(client_con->result), &ret);
367
          if (ret == DRIZZLE_RETURN_IO_WAIT)
368
          {
369
            client_con->row= 0;
370
            return 1;
371
          }
372
          else if (ret != DRIZZLE_RETURN_OK)
373
            CLIENT_ERROR("drizzle_row", ret, client);
374
375
          if (client_con->row == 0)
376
          {
377
            drizzle_result_free(&(client_con->result));
378
            break;
379
          }
380
381
          printf("Row: %" PRId64 "\n", client_con->row);
382
        }
383
384
        while (1)
385
        {
386
          if (client->level == BUFFER_FIELD)
387
          {
388
            /* Since an entire field is buffered, we don't need to worry about
389
               partial reads. */
390
            field= drizzle_field_buffer(&(client_con->result), &total, &ret);
391
            length= total;
392
          }
393
          else
394
          {
395
            field= drizzle_field_read(&(client_con->result), &offset, &length,
396
                                      &total, &ret);
397
          }
398
399
          if (ret == DRIZZLE_RETURN_IO_WAIT)
400
            return 1;
401
          else if (ret == DRIZZLE_RETURN_ROW_END)
402
            break;
403
          else if (ret != DRIZZLE_RETURN_OK)
404
            CLIENT_ERROR("drizzle_field_read", ret, client);
405
406
          if (field == NULL)
407
            printf("     (NULL)");
408
          else if (offset > 0)
409
            printf("%.*s", (int32_t)length, field);
410
          else
2244.1.1 by Monty Taylor
Split libdrizzle into 1.0 and 2.0. Applied the C++ changes to 2.0 branch.
411
            printf("     (%" PRIu64 " %.*s", (uint64_t)total,
412
			    (int32_t)length, field);
1712.1.1 by Monty Taylor
Merged libdrizzle directly into tree.
413
414
          if (offset + length == total)
415
            printf("\n");
416
417
          /* If we buffered the entire field, be sure to free it. */
418
          if (client->level == BUFFER_FIELD)
419
            drizzle_field_free(field);
420
        }
421
422
        client_con->row= 0;
423
        printf("\n");
424
      }
425
      else if (client->level == BUFFER_ROW)
426
      {
427
        /* The entire row will be buffered here, so no need to worry about
428
           partial reads. */
429
        row = drizzle_row_buffer(&(client_con->result), &ret);
430
        if (ret == DRIZZLE_RETURN_IO_WAIT)
431
          return 1;
432
        else if (ret != DRIZZLE_RETURN_OK)
433
          CLIENT_ERROR("drizzle_row", ret, client);
434
435
        /* This marks the end of rows. */
436
        if (row == NULL)
437
          break;
438
439
        field_sizes= drizzle_row_field_sizes(&(client_con->result));
440
441
        printf("Row: %" PRId64 "\n",
2244.1.1 by Monty Taylor
Split libdrizzle into 1.0 and 2.0. Applied the C++ changes to 2.0 branch.
442
               static_cast<uint64_t>(drizzle_row_current(&(client_con->result))));
1712.1.1 by Monty Taylor
Merged libdrizzle directly into tree.
443
444
        for (x= 0; x < drizzle_result_column_count(&(client_con->result)); x++)
445
        {
446
          if (row[x] == NULL)
447
            printf("     (NULL)\n");
448
          else
449
          {
2244.1.1 by Monty Taylor
Split libdrizzle into 1.0 and 2.0. Applied the C++ changes to 2.0 branch.
450
            printf("     (%" PRIu64 " %.*s\n", static_cast<uint64_t>(field_sizes[x]), (int32_t)field_sizes[x],
1712.1.1 by Monty Taylor
Merged libdrizzle directly into tree.
451
                   row[x]);
452
          }
453
        }
454
455
        drizzle_row_free(&(client_con->result), row);
456
        printf("\n");
457
      }
458
    }
459
460
    drizzle_result_free(&(client_con->result));
461
    break;
462
463
  default:
464
    /* This should be impossible. */
465
    return 1;
466
  }
467
468
  return 0;
469
}
470
471
void con_info(drizzle_con_st *con)
472
{
473
  printf("Connected: protocol_version=%u\n"
474
         "                    version=%s\n"
475
         "                  thread_id=%u\n"
476
         "               capabilities=%u\n"
477
         "                   language=%u\n"
478
         "                     status=%u\n\n",
479
         drizzle_con_protocol_version(con), drizzle_con_server_version(con),
480
         drizzle_con_thread_id(con), drizzle_con_capabilities(con),
481
         drizzle_con_charset(con), drizzle_con_status(con));
482
}
483
484
void result_info(drizzle_result_st *result)
485
{
486
  printf("Result:     row_count=%" PRId64 "\n"
487
         "            insert_id=%" PRId64 "\n"
488
         "        warning_count=%u\n"
489
         "         column_count=%u\n"
490
         "        affected_rows=%" PRId64 "\n\n",
491
         drizzle_result_row_count(result),
492
         drizzle_result_insert_id(result),
493
         drizzle_result_warning_count(result),
494
         drizzle_result_column_count(result),
495
         drizzle_result_affected_rows(result));
496
}
497
498
void column_info(drizzle_column_st *column)
499
{
500
  printf("Field:   catalog=%s\n"
501
         "              db=%s\n"
502
         "           table=%s\n"
503
         "       org_table=%s\n"
504
         "            name=%s\n"
505
         "        org_name=%s\n"
506
         "         charset=%u\n"
507
         "            size=%u\n"
2244.1.1 by Monty Taylor
Split libdrizzle into 1.0 and 2.0. Applied the C++ changes to 2.0 branch.
508
         "        max_size=%" PRIu64 "\n"
1712.1.1 by Monty Taylor
Merged libdrizzle directly into tree.
509
         "            type=%u\n"
510
         "           flags=%u\n\n",
511
         drizzle_column_catalog(column), drizzle_column_db(column),
512
         drizzle_column_table(column), drizzle_column_orig_table(column),
513
         drizzle_column_name(column), drizzle_column_orig_name(column),
514
         drizzle_column_charset(column), drizzle_column_size(column),
2244.1.1 by Monty Taylor
Split libdrizzle into 1.0 and 2.0. Applied the C++ changes to 2.0 branch.
515
         static_cast<uint64_t>(drizzle_column_max_size(column)), drizzle_column_type(column),
1712.1.1 by Monty Taylor
Merged libdrizzle directly into tree.
516
         drizzle_column_flags(column));
517
}