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/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
printf(__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;
104
client_con_st *client_con;
108
char *password= NULL;
111
memset(&client, 0, sizeof(client_st));
113
/* Use one connection by default. */
114
client.client_con_count= 1;
116
while ((c = getopt(argc, argv, "bB:c:d:h:Hmp:P:u:")) != -1)
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;
135
printf("Invalid buffer level: %s\n", optarg);
141
client.client_con_count= (uint32_t)atoi(optarg);
153
client.mysql_protocol= true;
161
port= (in_port_t)atoi(optarg);
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");
191
client.query= argv[optind];
192
client.query_len= strlen(client.query);
195
if (client.client_con_count > 0)
197
client.client_con_list= (client_con_st *)calloc(client.client_con_count,
198
sizeof(client_con_st));
199
if (client.client_con_list == NULL)
201
printf("calloc:%d\n", errno);
206
/* This may fail if there is other initialization that fails. See docs. */
207
if (drizzle_create(&(client.drizzle)) == NULL)
209
printf("drizzle_create failed\n");
214
drizzle_add_options(&(client.drizzle), DRIZZLE_NON_BLOCKING);
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++)
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
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]));
233
if (client_process(&client, &(client.client_con_list[x])) == 1)
234
wait_for_connections++;
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)
241
ret= drizzle_con_wait(&(client.drizzle));
242
if (ret != DRIZZLE_RETURN_OK)
243
CLIENT_ERROR("drizzle_con_wait", ret, &client);
245
while ((con= drizzle_con_ready(&(client.drizzle))) != NULL)
247
client_con= (client_con_st *)drizzle_con_context(con);
249
if (client_process(&client, client_con) == 0)
250
wait_for_connections--;
254
for (x= 0; x < client.client_con_count; x++)
255
drizzle_con_free(&(client.client_con_list[x].con));
257
drizzle_free(&(client.drizzle));
259
if (client.client_con_list != NULL)
260
free(client.client_con_list);
265
char client_process(client_st *client, client_con_st *client_con)
267
drizzle_return_t ret;
268
drizzle_column_st *column;
272
drizzle_field_t field;
277
switch (client_con->state)
280
if (client->query == NULL)
283
/* This may fail if some allocation fails, but it will set ret. */
284
(void)drizzle_query(&(client_con->con), &(client_con->result),
285
client->query, client->query_len, &ret);
286
if (ret == DRIZZLE_RETURN_IO_WAIT)
288
else if (ret != DRIZZLE_RETURN_OK)
289
CLIENT_ERROR("drizzle_query", ret, client);
291
result_info(&(client_con->result));
293
if (drizzle_result_column_count(&(client_con->result)) == 0)
296
client_con->state= CLIENT_FIELDS;
299
if (client->level == BUFFER_ALL)
301
ret= drizzle_result_buffer(&(client_con->result));
302
if (ret == DRIZZLE_RETURN_IO_WAIT)
304
else if (ret != DRIZZLE_RETURN_OK)
305
CLIENT_ERROR("drizzle_result_buffer", ret, client);
307
while ((column= drizzle_column_next(&(client_con->result))) != NULL)
314
column= drizzle_column_read(&(client_con->result),
315
&(client_con->column), &ret);
316
if (ret == DRIZZLE_RETURN_IO_WAIT)
318
else if (ret != DRIZZLE_RETURN_OK)
319
CLIENT_ERROR("drizzle_column_read", ret, client);
325
drizzle_column_free(column);
329
client_con->state= CLIENT_ROWS;
332
if (client->level == BUFFER_ALL)
334
/* Everything has been buffered, just loop through and print. */
335
while ((row= drizzle_row_next(&(client_con->result))) != NULL)
337
field_sizes= drizzle_row_field_sizes(&(client_con->result));
339
printf("Row: %" PRId64 "\n",
340
drizzle_row_current(&(client_con->result)));
342
for (x= 0; x < drizzle_result_column_count(&(client_con->result)); x++)
348
printf(" (%zd) %.*s\n", field_sizes[x], (int32_t)field_sizes[x],
356
drizzle_result_free(&(client_con->result));
362
if (client->level == BUFFER_NONE || client->level == BUFFER_FIELD)
364
/* Still need to read a row at a time, and then each field. */
365
if (client_con->row == 0)
367
client_con->row= drizzle_row_read(&(client_con->result), &ret);
368
if (ret == DRIZZLE_RETURN_IO_WAIT)
373
else if (ret != DRIZZLE_RETURN_OK)
374
CLIENT_ERROR("drizzle_row", ret, client);
376
if (client_con->row == 0)
378
drizzle_result_free(&(client_con->result));
382
printf("Row: %" PRId64 "\n", client_con->row);
387
if (client->level == BUFFER_FIELD)
389
/* Since an entire field is buffered, we don't need to worry about
391
field= drizzle_field_buffer(&(client_con->result), &total, &ret);
396
field= drizzle_field_read(&(client_con->result), &offset, &length,
400
if (ret == DRIZZLE_RETURN_IO_WAIT)
402
else if (ret == DRIZZLE_RETURN_ROW_END)
404
else if (ret != DRIZZLE_RETURN_OK)
405
CLIENT_ERROR("drizzle_field_read", ret, client);
410
printf("%.*s", (int32_t)length, field);
412
printf(" (%zd) %.*s", total, (int32_t)length, field);
414
if (offset + length == total)
417
/* If we buffered the entire field, be sure to free it. */
418
if (client->level == BUFFER_FIELD)
419
drizzle_field_free(field);
425
else if (client->level == BUFFER_ROW)
427
/* The entire row will be buffered here, so no need to worry about
429
row = drizzle_row_buffer(&(client_con->result), &ret);
430
if (ret == DRIZZLE_RETURN_IO_WAIT)
432
else if (ret != DRIZZLE_RETURN_OK)
433
CLIENT_ERROR("drizzle_row", ret, client);
435
/* This marks the end of rows. */
439
field_sizes= drizzle_row_field_sizes(&(client_con->result));
441
printf("Row: %" PRId64 "\n",
442
drizzle_row_current(&(client_con->result)));
444
for (x= 0; x < drizzle_result_column_count(&(client_con->result)); x++)
450
printf(" (%zd) %.*s\n", field_sizes[x], (int32_t)field_sizes[x],
455
drizzle_row_free(&(client_con->result), row);
460
drizzle_result_free(&(client_con->result));
464
/* This should be impossible. */
471
void con_info(drizzle_con_st *con)
473
printf("Connected: protocol_version=%u\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));
484
void result_info(drizzle_result_st *result)
486
printf("Result: row_count=%" PRId64 "\n"
487
" insert_id=%" PRId64 "\n"
488
" warning_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));
498
void column_info(drizzle_column_st *column)
500
printf("Field: catalog=%s\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),
515
drizzle_column_max_size(column), drizzle_column_type(column),
516
drizzle_column_flags(column));