libdrizzle Public API Documentation

client.c
Go to the documentation of this file.
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
22
29
37
46
57
58char client_process(client_st *client, client_con_st *client_con);
59void con_info(drizzle_con_st *con);
60void result_info(drizzle_result_st *result);
61void 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
68int main(int argc, char *argv[])
69{
70 client_st client;
71 int c;
72 char blocking= 0;
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)
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);
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++)
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
236char client_process(client_st *client, client_con_st *client_con)
237{
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
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",
453}
454
456{
457 printf("Result: row_count=%" PRId64 "\n"
458 " insert_id=%" PRId64 "\n"
459 " warning_count=%u\n"
460 " column_count=%u\n\n",
465}
466
468{
469 printf("Field: catalog=%s\n"
470 " db=%s\n"
471 " table=%s\n"
472 " org_table=%s\n"
473 " name=%s\n"
474 " org_name=%s\n"
475 " charset=%u\n"
476 " size=%u\n"
477 " max_size=%zu\n"
478 " type=%u\n"
479 " flags=%u\n\n",
485 drizzle_column_flags(column));
486}
void result_info(drizzle_result_st *result)
Definition client.c:455
buffer_level
Definition client.c:31
@ BUFFER_NONE
Definition client.c:32
@ BUFFER_FIELD
Definition client.c:33
@ BUFFER_ROW
Definition client.c:34
@ BUFFER_ALL
Definition client.c:35
int main(int argc, char *argv[])
Definition client.c:68
char client_process(client_st *client, client_con_st *client_con)
Definition client.c:236
client_state
Definition client.c:24
@ CLIENT_ROWS
Definition client.c:27
@ CLIENT_QUERY
Definition client.c:25
@ CLIENT_FIELDS
Definition client.c:26
void con_info(drizzle_con_st *con)
Definition client.c:442
void column_info(drizzle_column_st *column)
Definition client.c:467
#define CLIENT_ERROR(__function, __ret, __client)
Definition client.c:63
Drizzle Declarations for Clients.
drizzle_con_st * drizzle_con_add_tcp(drizzle_st *drizzle, drizzle_con_st *con, const char *host, in_port_t port, const char *user, const char *password, const char *db, drizzle_con_options_t options)
drizzle_column_st * drizzle_column_next(drizzle_result_st *result)
drizzle_column_st * drizzle_column_read(drizzle_result_st *result, drizzle_column_st *column, drizzle_return_t *ret_ptr)
const char * drizzle_column_catalog(drizzle_column_st *column)
const char * drizzle_column_orig_name(drizzle_column_st *column)
const char * drizzle_column_name(drizzle_column_st *column)
void drizzle_column_free(drizzle_column_st *column)
drizzle_column_flags_t drizzle_column_flags(drizzle_column_st *column)
const char * drizzle_column_table(drizzle_column_st *column)
drizzle_charset_t drizzle_column_charset(drizzle_column_st *column)
const char * drizzle_column_db(drizzle_column_st *column)
drizzle_column_type_t drizzle_column_type(drizzle_column_st *column)
uint32_t drizzle_column_size(drizzle_column_st *column)
const char * drizzle_column_orig_table(drizzle_column_st *column)
size_t drizzle_column_max_size(drizzle_column_st *column)
uint8_t drizzle_con_protocol_version(const drizzle_con_st *con)
void drizzle_con_set_context(drizzle_con_st *con, void *context)
uint32_t drizzle_con_thread_id(const drizzle_con_st *con)
drizzle_capabilities_t drizzle_con_capabilities(const drizzle_con_st *con)
void * drizzle_con_context(const drizzle_con_st *con)
drizzle_charset_t drizzle_con_charset(const drizzle_con_st *con)
drizzle_con_status_t drizzle_con_status(const drizzle_con_st *con)
const char * drizzle_con_server_version(const drizzle_con_st *con)
@ DRIZZLE_CON_MYSQL
Definition constants.h:135
drizzle_return_t
Definition constants.h:69
@ DRIZZLE_RETURN_OK
Definition constants.h:70
@ DRIZZLE_RETURN_IO_WAIT
Definition constants.h:71
@ DRIZZLE_RETURN_ROW_END
Definition constants.h:89
drizzle_field_t drizzle_field_read(drizzle_result_st *result, size_t *offset, size_t *size, size_t *total, drizzle_return_t *ret_ptr)
drizzle_field_t drizzle_field_buffer(drizzle_result_st *result, size_t *total, drizzle_return_t *ret_ptr)
void drizzle_field_free(drizzle_field_t field)
drizzle_result_st * drizzle_query(drizzle_con_st *con, drizzle_result_st *result, const char *query, size_t size, drizzle_return_t *ret_ptr)
drizzle_return_t drizzle_result_buffer(drizzle_result_st *result)
uint16_t drizzle_result_column_count(drizzle_result_st *result)
uint64_t drizzle_result_insert_id(drizzle_result_st *result)
void drizzle_result_free(drizzle_result_st *result)
uint16_t drizzle_result_warning_count(drizzle_result_st *result)
uint64_t drizzle_result_row_count(drizzle_result_st *result)
uint64_t drizzle_row_current(drizzle_result_st *result)
size_t * drizzle_row_field_sizes(drizzle_result_st *result)
uint64_t drizzle_row_read(drizzle_result_st *result, drizzle_return_t *ret_ptr)
drizzle_row_t drizzle_row_next(drizzle_result_st *result)
drizzle_row_t drizzle_row_buffer(drizzle_result_st *result, drizzle_return_t *ret_ptr)
void drizzle_row_free(drizzle_result_st *result, drizzle_row_t row)
drizzle_field_t * drizzle_row_t
Definition constants.h:413
struct drizzle_result_st drizzle_result_st
Definition constants.h:410
char * drizzle_field_t
Definition constants.h:412
struct drizzle_con_st drizzle_con_st
Definition constants.h:408
struct drizzle_st drizzle_st
Definition constants.h:405
struct drizzle_column_st drizzle_column_st
Definition constants.h:411
drizzle_con_st * drizzle_con_ready(drizzle_st *drizzle)
void drizzle_free(drizzle_st *drizzle)
void drizzle_add_options(drizzle_st *drizzle, drizzle_options_t options)
drizzle_st * drizzle_create(drizzle_st *drizzle)
drizzle_return_t drizzle_con_wait(drizzle_st *drizzle)
void drizzle_con_free(drizzle_con_st *con)
@ DRIZZLE_NON_BLOCKING
Definition constants.h:122
uint64_t row
Definition client.c:44
drizzle_result_st result
Definition client.c:41
drizzle_column_st column
Definition client.c:42
drizzle_con_st con
Definition client.c:40
client_state state
Definition client.c:43
client_con_st * client_con_list
Definition client.c:51
drizzle_st drizzle
Definition client.c:49
char * query
Definition client.c:54
buffer_level level
Definition client.c:53
bool mysql_protocol
Definition client.c:50
size_t query_len
Definition client.c:55
uint32_t client_con_count
Definition client.c:52