2
* Drizzle Client & Protocol Library
4
* Copyright (C) 2008 Eric Day (eday@oddments.org)
7
* Redistribution and use in source and binary forms, with or without
8
* modification, are permitted provided that the following conditions are
11
* * Redistributions of source code must retain the above copyright
12
* notice, this list of conditions and the following disclaimer.
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
19
* * The names of its contributors may not be used to endorse or
20
* promote products derived from this software without specific prior
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.
48
#include <libdrizzle-2.0/drizzle_client.h>
68
drizzle_result_st result;
69
drizzle_column_st column;
78
client_con_st *client_con_list;
79
uint32_t client_con_count;
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);
90
#define CLIENT_ERROR(__function, __ret, __client) { \
91
fprintf(stderr, __function ":%d:%s\n", __ret, \
92
drizzle_error(((__client)->drizzle))); \
95
int main(int argc, char *argv[])
100
drizzle_return_t ret;
102
int wait_for_connections= 0;
103
client_con_st *client_con;
107
char *password= NULL;
110
memset(&client, 0, sizeof(client_st));
112
/* Use one connection by default. */
113
client.client_con_count= 1;
115
while ((c = getopt(argc, argv, "bB:c:d:h:Hmp:P:u:")) != -1)
124
if (!strcasecmp(optarg, "none"))
125
client.level= BUFFER_NONE;
126
else if (!strcasecmp(optarg, "field"))
127
client.level= BUFFER_FIELD;
128
else if (!strcasecmp(optarg, "row"))
129
client.level= BUFFER_ROW;
130
else if (!strcasecmp(optarg, "all"))
131
client.level= BUFFER_ALL;
134
fprintf(stderr, "Invalid buffer level: %s\n", optarg);
140
client.client_con_count= (uint32_t)atoi(optarg);
152
client.mysql_protocol= true;
160
port= (in_port_t)atoi(optarg);
169
printf("\nUsage: %s [options] [query]\n", argv[0]);
170
printf("\t-b - Use blocking sockets\n");
171
printf("\t-B <level> - Use buffer <level>, options are:\n");
172
printf("\t none - Don't buffer anything (default)\n");
173
printf("\t field - Only buffer individual fields\n");
174
printf("\t row - Only buffer individual rows\n");
175
printf("\t all - Buffer entire result\n");
176
printf("\t-c <cons> - Create <cons> connections\n");
177
printf("\t-d <db> - Use <db> for the connection\n");
178
printf("\t-h <host> - Connect to <host>\n");
179
printf("\t-H - Print this help menu\n");
180
printf("\t-m - Use MySQL protocol\n");
181
printf("\t-p <password> - Use <password> for authentication\n");
182
printf("\t-P <port> - Connect to <port>\n");
183
printf("\t-u <user> - Use <user> for authentication\n");
190
client.query= argv[optind];
191
client.query_len= strlen(client.query);
194
if (client.client_con_count > 0)
196
client.client_con_list= (client_con_st *)calloc(client.client_con_count,
197
sizeof(client_con_st));
198
if (client.client_con_list == NULL)
200
fprintf(stderr, "calloc:%d\n", errno);
205
/* This may fail if there is other initialization that fails. See docs. */
206
if ((client.drizzle= drizzle_create()) == NULL)
208
fprintf(stderr, "drizzle_create failed\n");
214
drizzle_set_option(client.drizzle, DRIZZLE_NON_BLOCKING, true);
217
/* Start all connections, and if in non-blocking mode, return as soon as the
218
connection would block. In blocking mode, this completes the entire
219
connection/query/result. */
220
for (x= 0; x < client.client_con_count; x++)
222
/* This may fail if there is other initialization that fails. See docs. */
223
drizzle_con_st *con= drizzle_con_add_tcp(client.drizzle,
224
host, port, user, password, db,
225
client.mysql_protocol
230
CLIENT_ERROR("drizzle_con_add_tcp", 0, &client);
232
drizzle_con_set_context(&(client.client_con_list[x].con),
233
&(client.client_con_list[x]));
235
if (client_process(&client, &(client.client_con_list[x])) == 1)
236
wait_for_connections++;
239
/* If in non-blocking mode, continue to process connections as they become
240
ready. Loop exits when all connections have completed. */
241
while (wait_for_connections != 0)
243
ret= drizzle_con_wait(client.drizzle);
244
if (ret != DRIZZLE_RETURN_OK)
246
CLIENT_ERROR("drizzle_con_wait", ret, &client);
250
while ((con= drizzle_con_ready(client.drizzle)) != NULL)
252
client_con= (client_con_st *)drizzle_con_context(con);
254
if (client_process(&client, client_con) == 0)
256
wait_for_connections--;
261
for (x= 0; x < client.client_con_count; x++)
263
drizzle_con_free(&(client.client_con_list[x].con));
266
drizzle_free(client.drizzle);
268
free(client.client_con_list);
273
char client_process(client_st *client, client_con_st *client_con)
275
drizzle_return_t ret;
276
drizzle_column_st *column;
280
drizzle_field_t field;
285
switch (client_con->state)
288
if (client->query == NULL)
291
/* This may fail if some allocation fails, but it will set ret. */
292
(void)drizzle_query(&(client_con->con), &(client_con->result),
293
client->query, client->query_len, &ret);
294
if (ret == DRIZZLE_RETURN_IO_WAIT)
298
else if (ret != DRIZZLE_RETURN_OK)
300
CLIENT_ERROR("drizzle_query", ret, client);
303
result_info(&(client_con->result));
305
if (drizzle_result_column_count(&(client_con->result)) == 0)
310
client_con->state= CLIENT_FIELDS;
313
if (client->level == BUFFER_ALL)
315
ret= drizzle_result_buffer(&(client_con->result));
316
if (ret == DRIZZLE_RETURN_IO_WAIT)
320
else if (ret != DRIZZLE_RETURN_OK)
322
CLIENT_ERROR("drizzle_result_buffer", ret, client);
325
while ((column= drizzle_column_next(&(client_con->result))) != NULL)
332
column= drizzle_column_read(&(client_con->result),
333
&(client_con->column), &ret);
334
if (ret == DRIZZLE_RETURN_IO_WAIT)
338
else if (ret != DRIZZLE_RETURN_OK)
340
CLIENT_ERROR("drizzle_column_read", ret, client);
347
drizzle_column_free(column);
351
client_con->state= CLIENT_ROWS;
354
if (client->level == BUFFER_ALL)
356
/* Everything has been buffered, just loop through and print. */
357
while ((row= drizzle_row_next(&(client_con->result))) != NULL)
359
field_sizes= drizzle_row_field_sizes(&(client_con->result));
361
printf("Row: %" PRId64 "\n", drizzle_row_current(&(client_con->result)));
363
for (x= 0; x < drizzle_result_column_count(&(client_con->result)); x++)
371
printf(" (%"PRIu64") %.*s\n", static_cast<uint64_t>(field_sizes[x]), (int32_t)field_sizes[x], row[x]);
378
drizzle_result_free(&(client_con->result));
384
if (client->level == BUFFER_NONE || client->level == BUFFER_FIELD)
386
/* Still need to read a row at a time, and then each field. */
387
if (client_con->row == 0)
389
client_con->row= drizzle_row_read(&(client_con->result), &ret);
390
if (ret == DRIZZLE_RETURN_IO_WAIT)
395
else if (ret != DRIZZLE_RETURN_OK)
396
CLIENT_ERROR("drizzle_row", ret, client);
398
if (client_con->row == 0)
400
drizzle_result_free(&(client_con->result));
404
printf("Row: %" PRId64 "\n", client_con->row);
409
if (client->level == BUFFER_FIELD)
411
/* Since an entire field is buffered, we don't need to worry about
413
field= drizzle_field_buffer(&(client_con->result), &total, &ret);
418
field= drizzle_field_read(&(client_con->result), &offset, &length,
422
if (ret == DRIZZLE_RETURN_IO_WAIT)
424
else if (ret == DRIZZLE_RETURN_ROW_END)
426
else if (ret != DRIZZLE_RETURN_OK)
427
CLIENT_ERROR("drizzle_field_read", ret, client);
435
printf("%.*s", (int32_t)length, field);
439
printf(" (%" PRIu64 " %.*s", (uint64_t)total, (int32_t)length, field);
442
if (offset + length == total)
447
/* If we buffered the entire field, be sure to free it. */
448
if (client->level == BUFFER_FIELD)
449
drizzle_field_free(field);
455
else if (client->level == BUFFER_ROW)
457
/* The entire row will be buffered here, so no need to worry about
459
row = drizzle_row_buffer(&(client_con->result), &ret);
460
if (ret == DRIZZLE_RETURN_IO_WAIT)
462
else if (ret != DRIZZLE_RETURN_OK)
463
CLIENT_ERROR("drizzle_row", ret, client);
465
/* This marks the end of rows. */
469
field_sizes= drizzle_row_field_sizes(&(client_con->result));
471
printf("Row: %" PRId64 "\n",
472
static_cast<uint64_t>(drizzle_row_current(&(client_con->result))));
474
for (x= 0; x < drizzle_result_column_count(&(client_con->result)); x++)
480
printf(" (%" PRIu64 " %.*s\n", static_cast<uint64_t>(field_sizes[x]), (int32_t)field_sizes[x],
485
drizzle_row_free(&(client_con->result), row);
490
drizzle_result_free(&(client_con->result));
494
/* This should be impossible. */
501
void con_info(drizzle_con_st *con)
503
printf("Connected: protocol_version=%u\n"
509
drizzle_con_protocol_version(con), drizzle_con_server_version(con),
510
drizzle_con_thread_id(con), drizzle_con_capabilities(con),
511
drizzle_con_charset(con), drizzle_con_status(con));
514
void result_info(drizzle_result_st *result)
516
printf("Result: row_count=%" PRId64 "\n"
517
" insert_id=%" PRId64 "\n"
518
" warning_count=%u\n"
520
" affected_rows=%" PRId64 "\n\n",
521
drizzle_result_row_count(result),
522
drizzle_result_insert_id(result),
523
drizzle_result_warning_count(result),
524
drizzle_result_column_count(result),
525
drizzle_result_affected_rows(result));
528
void column_info(drizzle_column_st *column)
530
printf("Field: catalog=%s\n"
538
" max_size=%" PRIu64 "\n"
541
drizzle_column_catalog(column), drizzle_column_db(column),
542
drizzle_column_table(column), drizzle_column_orig_table(column),
543
drizzle_column_name(column), drizzle_column_orig_name(column),
544
drizzle_column_charset(column), drizzle_column_size(column),
545
static_cast<uint64_t>(drizzle_column_max_size(column)), drizzle_column_type(column),
546
drizzle_column_flags(column));