00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #include "config.h"
00012
00013 #include <errno.h>
00014 #include <stdbool.h>
00015 #include <stdint.h>
00016 #include <stdio.h>
00017 #include <stdlib.h>
00018 #include <string.h>
00019 #include <unistd.h>
00020
00021 #include <libdrizzle/drizzle_client.h>
00022
00023 typedef enum
00024 {
00025 CLIENT_QUERY,
00026 CLIENT_FIELDS,
00027 CLIENT_ROWS
00028 } client_state;
00029
00030 typedef enum
00031 {
00032 BUFFER_NONE,
00033 BUFFER_FIELD,
00034 BUFFER_ROW,
00035 BUFFER_ALL
00036 } buffer_level;
00037
00038 typedef struct
00039 {
00040 drizzle_con_st con;
00041 drizzle_result_st result;
00042 drizzle_column_st column;
00043 client_state state;
00044 uint64_t row;
00045 } client_con_st;
00046
00047 typedef struct
00048 {
00049 drizzle_st drizzle;
00050 bool mysql_protocol;
00051 client_con_st *client_con_list;
00052 uint32_t client_con_count;
00053 buffer_level level;
00054 char *query;
00055 size_t query_len;
00056 } client_st;
00057
00058 char client_process(client_st *client, client_con_st *client_con);
00059 void con_info(drizzle_con_st *con);
00060 void result_info(drizzle_result_st *result);
00061 void column_info(drizzle_column_st *column);
00062
00063 #define CLIENT_ERROR(__function, __ret, __client) { \
00064 printf(__function ":%d:%s\n", __ret, \
00065 drizzle_error(&((__client)->drizzle))); \
00066 exit(1); }
00067
00068 int main(int argc, char *argv[])
00069 {
00070 client_st client;
00071 int c;
00072 char blocking= 0;
00073 drizzle_return_t ret;
00074 uint32_t x;
00075 int wait_for_connections= 0;
00076 drizzle_con_st *con;
00077 client_con_st *client_con;
00078 char *host= NULL;
00079 in_port_t port= 0;
00080 char *user= NULL;
00081 char *password= NULL;
00082 char *db= NULL;
00083
00084 memset(&client, 0, sizeof(client_st));
00085
00086
00087 client.client_con_count= 1;
00088
00089 while ((c = getopt(argc, argv, "bB:c:d:h:Hmp:P:u:")) != -1)
00090 {
00091 switch(c)
00092 {
00093 case 'b':
00094 blocking= 1;
00095 break;
00096
00097 case 'B':
00098 if (!strcasecmp(optarg, "none"))
00099 client.level= BUFFER_NONE;
00100 else if (!strcasecmp(optarg, "field"))
00101 client.level= BUFFER_FIELD;
00102 else if (!strcasecmp(optarg, "row"))
00103 client.level= BUFFER_ROW;
00104 else if (!strcasecmp(optarg, "all"))
00105 client.level= BUFFER_ALL;
00106 else
00107 {
00108 printf("Invalid buffer level: %s\n", optarg);
00109 exit(0);
00110 }
00111 break;
00112
00113 case 'c':
00114 client.client_con_count= (uint32_t)atoi(optarg);
00115 break;
00116
00117 case 'd':
00118 db= optarg;
00119 break;
00120
00121 case 'h':
00122 host= optarg;
00123 break;
00124
00125 case 'm':
00126 client.mysql_protocol= true;
00127 break;
00128
00129 case 'p':
00130 password= optarg;
00131 break;
00132
00133 case 'P':
00134 port= (in_port_t)atoi(optarg);
00135 break;
00136
00137 case 'u':
00138 user= optarg;
00139 break;
00140
00141 case 'H':
00142 default:
00143 printf("\nUsage: %s [options] [query]\n", argv[0]);
00144 printf("\t-b - Use blocking sockets\n");
00145 printf("\t-B <level> - Use buffer <level>, options are:\n");
00146 printf("\t none - Don't buffer anything (default)\n");
00147 printf("\t field - Only buffer individual fields\n");
00148 printf("\t row - Only buffer individual rows\n");
00149 printf("\t all - Buffer entire result\n");
00150 printf("\t-c <cons> - Create <cons> connections\n");
00151 printf("\t-d <db> - Use <db> for the connection\n");
00152 printf("\t-h <host> - Connect to <host>\n");
00153 printf("\t-H - Print this help menu\n");
00154 printf("\t-m - Use MySQL protocol\n");
00155 printf("\t-p <password> - Use <password> for authentication\n");
00156 printf("\t-P <port> - Connect to <port>\n");
00157 printf("\t-u <user> - Use <user> for authentication\n");
00158 exit(0);
00159 }
00160 }
00161
00162 if (argc != optind)
00163 {
00164 client.query= argv[optind];
00165 client.query_len= strlen(client.query);
00166 }
00167
00168 if (client.client_con_count > 0)
00169 {
00170 client.client_con_list= calloc(client.client_con_count,
00171 sizeof(client_con_st));
00172 if (client.client_con_list == NULL)
00173 {
00174 printf("calloc:%d\n", errno);
00175 exit(1);
00176 }
00177 }
00178
00179
00180 if (drizzle_create(&(client.drizzle)) == NULL)
00181 {
00182 printf("drizzle_create failed\n");
00183 exit(1);
00184 }
00185
00186 if (blocking == 0)
00187 drizzle_add_options(&(client.drizzle), DRIZZLE_NON_BLOCKING);
00188
00189
00190
00191
00192 for (x= 0; x < client.client_con_count; x++)
00193 {
00194
00195 con= drizzle_con_add_tcp(&(client.drizzle),
00196 &(client.client_con_list[x].con),
00197 host, port, user, password, db,
00198 client.mysql_protocol ? DRIZZLE_CON_MYSQL : 0);
00199 if (con == NULL)
00200 CLIENT_ERROR("drizzle_con_add_tcp", 0, &client);
00201 drizzle_con_set_context(&(client.client_con_list[x].con),
00202 &(client.client_con_list[x]));
00203
00204 if (client_process(&client, &(client.client_con_list[x])) == 1)
00205 wait_for_connections++;
00206 }
00207
00208
00209
00210 while (wait_for_connections != 0)
00211 {
00212 ret= drizzle_con_wait(&(client.drizzle));
00213 if (ret != DRIZZLE_RETURN_OK)
00214 CLIENT_ERROR("drizzle_con_wait", ret, &client);
00215
00216 while ((con= drizzle_con_ready(&(client.drizzle))) != NULL)
00217 {
00218 client_con= (client_con_st *)drizzle_con_context(con);
00219
00220 if (client_process(&client, client_con) == 0)
00221 wait_for_connections--;
00222 }
00223 }
00224
00225 for (x= 0; x < client.client_con_count; x++)
00226 drizzle_con_free(&(client.client_con_list[x].con));
00227
00228 drizzle_free(&(client.drizzle));
00229
00230 if (client.client_con_list != NULL)
00231 free(client.client_con_list);
00232
00233 return 0;
00234 }
00235
00236 char client_process(client_st *client, client_con_st *client_con)
00237 {
00238 drizzle_return_t ret;
00239 drizzle_column_st *column;
00240 size_t offset= 0;
00241 size_t length;
00242 size_t total;
00243 drizzle_field_t field;
00244 drizzle_row_t row;
00245 size_t *field_sizes;
00246 uint16_t x;
00247
00248 switch (client_con->state)
00249 {
00250 case CLIENT_QUERY:
00251 if (client->query == NULL)
00252 break;
00253
00254
00255 (void)drizzle_query(&(client_con->con), &(client_con->result),
00256 client->query, client->query_len, &ret);
00257 if (ret == DRIZZLE_RETURN_IO_WAIT)
00258 return 1;
00259 else if (ret != DRIZZLE_RETURN_OK)
00260 CLIENT_ERROR("drizzle_query", ret, client);
00261
00262 result_info(&(client_con->result));
00263
00264 if (drizzle_result_column_count(&(client_con->result)) == 0)
00265 break;
00266
00267 client_con->state= CLIENT_FIELDS;
00268
00269 case CLIENT_FIELDS:
00270 if (client->level == BUFFER_ALL)
00271 {
00272 ret= drizzle_result_buffer(&(client_con->result));
00273 if (ret == DRIZZLE_RETURN_IO_WAIT)
00274 return 1;
00275 else if (ret != DRIZZLE_RETURN_OK)
00276 CLIENT_ERROR("drizzle_result_buffer", ret, client);
00277
00278 while ((column= drizzle_column_next(&(client_con->result))) != NULL)
00279 column_info(column);
00280 }
00281 else
00282 {
00283 while (1)
00284 {
00285 column= drizzle_column_read(&(client_con->result),
00286 &(client_con->column), &ret);
00287 if (ret == DRIZZLE_RETURN_IO_WAIT)
00288 return 1;
00289 else if (ret != DRIZZLE_RETURN_OK)
00290 CLIENT_ERROR("drizzle_column_read", ret, client);
00291
00292 if (column == NULL)
00293 break;
00294
00295 column_info(column);
00296 drizzle_column_free(column);
00297 }
00298 }
00299
00300 client_con->state= CLIENT_ROWS;
00301
00302 case CLIENT_ROWS:
00303 if (client->level == BUFFER_ALL)
00304 {
00305
00306 while ((row= drizzle_row_next(&(client_con->result))) != NULL)
00307 {
00308 field_sizes= drizzle_row_field_sizes(&(client_con->result));
00309
00310 printf("Row: %" PRId64 "\n",
00311 drizzle_row_current(&(client_con->result)));
00312
00313 for (x= 0; x < drizzle_result_column_count(&(client_con->result)); x++)
00314 {
00315 if (row[x] == NULL)
00316 printf(" (NULL)\n");
00317 else
00318 {
00319 printf(" (%zd) %.*s\n", field_sizes[x], (int32_t)field_sizes[x],
00320 row[x]);
00321 }
00322 }
00323
00324 printf("\n");
00325 }
00326
00327 drizzle_result_free(&(client_con->result));
00328 break;
00329 }
00330
00331 while (1)
00332 {
00333 if (client->level == BUFFER_NONE || client->level == BUFFER_FIELD)
00334 {
00335
00336 if (client_con->row == 0)
00337 {
00338 client_con->row= drizzle_row_read(&(client_con->result), &ret);
00339 if (ret == DRIZZLE_RETURN_IO_WAIT)
00340 {
00341 client_con->row= 0;
00342 return 1;
00343 }
00344 else if (ret != DRIZZLE_RETURN_OK)
00345 CLIENT_ERROR("drizzle_row", ret, client);
00346
00347 if (client_con->row == 0)
00348 {
00349 drizzle_result_free(&(client_con->result));
00350 break;
00351 }
00352
00353 printf("Row: %" PRId64 "\n", client_con->row);
00354 }
00355
00356 while (1)
00357 {
00358 if (client->level == BUFFER_FIELD)
00359 {
00360
00361
00362 field= drizzle_field_buffer(&(client_con->result), &total, &ret);
00363 length= total;
00364 }
00365 else
00366 {
00367 field= drizzle_field_read(&(client_con->result), &offset, &length,
00368 &total, &ret);
00369 }
00370
00371 if (ret == DRIZZLE_RETURN_IO_WAIT)
00372 return 1;
00373 else if (ret == DRIZZLE_RETURN_ROW_END)
00374 break;
00375 else if (ret != DRIZZLE_RETURN_OK)
00376 CLIENT_ERROR("drizzle_field_read", ret, client);
00377
00378 if (field == NULL)
00379 printf(" (NULL)");
00380 else if (offset > 0)
00381 printf("%.*s", (int32_t)length, field);
00382 else
00383 printf(" (%zd) %.*s", total, (int32_t)length, field);
00384
00385 if (offset + length == total)
00386 printf("\n");
00387
00388
00389 if (client->level == BUFFER_FIELD)
00390 drizzle_field_free(field);
00391 }
00392
00393 client_con->row= 0;
00394 printf("\n");
00395 }
00396 else if (client->level == BUFFER_ROW)
00397 {
00398
00399
00400 row = drizzle_row_buffer(&(client_con->result), &ret);
00401 if (ret == DRIZZLE_RETURN_IO_WAIT)
00402 return 1;
00403 else if (ret != DRIZZLE_RETURN_OK)
00404 CLIENT_ERROR("drizzle_row", ret, client);
00405
00406
00407 if (row == NULL)
00408 break;
00409
00410 field_sizes= drizzle_row_field_sizes(&(client_con->result));
00411
00412 printf("Row: %" PRId64 "\n",
00413 drizzle_row_current(&(client_con->result)));
00414
00415 for (x= 0; x < drizzle_result_column_count(&(client_con->result)); x++)
00416 {
00417 if (row[x] == NULL)
00418 printf(" (NULL)\n");
00419 else
00420 {
00421 printf(" (%zd) %.*s\n", field_sizes[x], (int32_t)field_sizes[x],
00422 row[x]);
00423 }
00424 }
00425
00426 drizzle_row_free(&(client_con->result), row);
00427 printf("\n");
00428 }
00429 }
00430
00431 drizzle_result_free(&(client_con->result));
00432 break;
00433
00434 default:
00435
00436 return 1;
00437 }
00438
00439 return 0;
00440 }
00441
00442 void con_info(drizzle_con_st *con)
00443 {
00444 printf("Connected: protocol_version=%u\n"
00445 " version=%s\n"
00446 " thread_id=%u\n"
00447 " capabilities=%u\n"
00448 " language=%u\n"
00449 " status=%u\n\n",
00450 drizzle_con_protocol_version(con), drizzle_con_server_version(con),
00451 drizzle_con_thread_id(con), drizzle_con_capabilities(con),
00452 drizzle_con_charset(con), drizzle_con_status(con));
00453 }
00454
00455 void result_info(drizzle_result_st *result)
00456 {
00457 printf("Result: row_count=%" PRId64 "\n"
00458 " insert_id=%" PRId64 "\n"
00459 " warning_count=%u\n"
00460 " column_count=%u\n\n",
00461 drizzle_result_row_count(result),
00462 drizzle_result_insert_id(result),
00463 drizzle_result_warning_count(result),
00464 drizzle_result_column_count(result));
00465 }
00466
00467 void column_info(drizzle_column_st *column)
00468 {
00469 printf("Field: catalog=%s\n"
00470 " db=%s\n"
00471 " table=%s\n"
00472 " org_table=%s\n"
00473 " name=%s\n"
00474 " org_name=%s\n"
00475 " charset=%u\n"
00476 " size=%u\n"
00477 " max_size=%zu\n"
00478 " type=%u\n"
00479 " flags=%u\n\n",
00480 drizzle_column_catalog(column), drizzle_column_db(column),
00481 drizzle_column_table(column), drizzle_column_orig_table(column),
00482 drizzle_column_name(column), drizzle_column_orig_name(column),
00483 drizzle_column_charset(column), drizzle_column_size(column),
00484 drizzle_column_max_size(column), drizzle_column_type(column),
00485 drizzle_column_flags(column));
00486 }