2
* Drizzle Client & Protocol Library
4
* Copyright (C) 2008 Eric Day (eday@oddments.org)
7
* Use and distribution licensed under the BSD license. See
8
* the COPYING file in this directory for full text.
13
* @brief Result definitions
22
drizzle_result_st *drizzle_result_create(drizzle_con_st *con,
23
drizzle_result_st *result)
27
result= malloc(sizeof(drizzle_result_st));
30
drizzle_set_error(con->drizzle, "drizzle_result_create", "malloc");
34
memset(result, 0, sizeof(drizzle_result_st));
35
result->options|= DRIZZLE_RESULT_ALLOCATED;
38
memset(result, 0, sizeof(drizzle_result_st));
44
con->result_list->prev= result;
45
result->next= con->result_list;
46
con->result_list= result;
52
drizzle_result_st *drizzle_result_clone(drizzle_con_st *con,
53
drizzle_result_st *result,
54
drizzle_result_st *from)
56
result= drizzle_result_create(con, result);
60
result->options|= (from->options &
61
(drizzle_result_options_t)~DRIZZLE_RESULT_ALLOCATED);
63
drizzle_result_set_info(result, from->info);
64
result->error_code= from->error_code;
65
drizzle_result_set_sqlstate(result, from->sqlstate);
66
result->warning_count= from->warning_count;
67
result->insert_id= from->insert_id;
68
result->affected_rows= from->affected_rows;
69
result->column_count= from->column_count;
70
result->row_count= from->row_count;
75
void drizzle_result_free(drizzle_result_st *result)
77
drizzle_column_st *column;
80
for (column= result->column_list; column != NULL; column= result->column_list)
81
drizzle_column_free(column);
83
if (result->column_buffer != NULL)
84
free(result->column_buffer);
86
if (result->options & DRIZZLE_RESULT_BUFFER_ROW)
88
for (x= 0; x < result->row_count; x++)
89
drizzle_row_free(result, result->row_list[x]);
91
free(result->row_list);
92
free(result->field_sizes_list);
95
if (result->con->result_list == result)
96
result->con->result_list= result->next;
98
result->prev->next= result->next;
100
result->next->prev= result->prev;
101
result->con->result_count--;
103
if (result->options & DRIZZLE_RESULT_ALLOCATED)
107
void drizzle_result_free_all(drizzle_con_st *con)
109
while (con->result_list != NULL)
110
drizzle_result_free(con->result_list);
113
drizzle_con_st *drizzle_result_drizzle_con(drizzle_result_st *result)
118
bool drizzle_result_eof(drizzle_result_st *result)
120
return result->options & DRIZZLE_RESULT_EOF_PACKET;
123
const char *drizzle_result_info(drizzle_result_st *result)
128
const char *drizzle_result_error(drizzle_result_st *result)
133
uint16_t drizzle_result_error_code(drizzle_result_st *result)
135
return result->error_code;
138
const char *drizzle_result_sqlstate(drizzle_result_st *result)
140
return result->sqlstate;
143
uint16_t drizzle_result_warning_count(drizzle_result_st *result)
145
return result->warning_count;
148
uint64_t drizzle_result_insert_id(drizzle_result_st *result)
150
return result->insert_id;
153
uint64_t drizzle_result_affected_rows(drizzle_result_st *result)
155
return result->affected_rows;
158
uint16_t drizzle_result_column_count(drizzle_result_st *result)
160
return result->column_count;
163
uint64_t drizzle_result_row_count(drizzle_result_st *result)
165
return result->row_count;
172
drizzle_result_st *drizzle_result_read(drizzle_con_st *con,
173
drizzle_result_st *result,
174
drizzle_return_t *ret_ptr)
176
if (drizzle_state_none(con))
178
con->result= drizzle_result_create(con, result);
179
if (con->result == NULL)
181
*ret_ptr= DRIZZLE_RETURN_MEMORY;
185
drizzle_state_push(con, drizzle_state_result_read);
186
drizzle_state_push(con, drizzle_state_packet_read);
189
*ret_ptr= drizzle_state_loop(con);
193
drizzle_return_t drizzle_result_buffer(drizzle_result_st *result)
195
drizzle_return_t ret;
197
drizzle_row_t *row_list;
198
size_t **field_sizes_list;
200
if (!(result->options & DRIZZLE_RESULT_BUFFER_COLUMN))
202
ret= drizzle_column_buffer(result);
203
if (ret != DRIZZLE_RETURN_OK)
207
if (result->column_count == 0)
209
result->options|= DRIZZLE_RESULT_BUFFER_ROW;
210
return DRIZZLE_RETURN_OK;
215
row= drizzle_row_buffer(result, &ret);
216
if (ret != DRIZZLE_RETURN_OK)
222
if (result->row_list_size < result->row_count)
224
row_list= realloc(result->row_list, sizeof(drizzle_row_t) *
225
((size_t)(result->row_list_size) +
226
DRIZZLE_ROW_GROW_SIZE));
227
if (row_list == NULL)
229
drizzle_row_free(result, row);
230
drizzle_set_error(result->con->drizzle, "drizzle_result_buffer",
232
return DRIZZLE_RETURN_MEMORY;
235
result->row_list= row_list;
237
field_sizes_list= realloc(result->field_sizes_list, sizeof(size_t *) *
238
((size_t)(result->row_list_size) +
239
DRIZZLE_ROW_GROW_SIZE));
240
if (field_sizes_list == NULL)
242
drizzle_row_free(result, row);
243
drizzle_set_error(result->con->drizzle, "drizzle_result_buffer",
245
return DRIZZLE_RETURN_MEMORY;
248
result->field_sizes_list= field_sizes_list;
250
result->row_list_size+= DRIZZLE_ROW_GROW_SIZE;
253
result->row_list[result->row_current - 1]= row;
254
result->field_sizes_list[result->row_current - 1]= result->field_sizes;
257
result->options|= DRIZZLE_RESULT_BUFFER_ROW;
258
return DRIZZLE_RETURN_OK;
261
size_t drizzle_result_row_size(drizzle_result_st *result)
263
return result->con->packet_size;
270
drizzle_return_t drizzle_result_write(drizzle_con_st *con,
271
drizzle_result_st *result, bool flush)
273
if (drizzle_state_none(con))
278
drizzle_state_push(con, drizzle_state_write);
280
drizzle_state_push(con, drizzle_state_result_write);
283
return drizzle_state_loop(con);
286
void drizzle_result_set_row_size(drizzle_result_st *result, size_t size)
288
result->con->packet_size= size;
291
void drizzle_result_calc_row_size(drizzle_result_st *result,
292
const drizzle_field_t *field,
297
result->con->packet_size= 0;
299
for (x= 0; x < result->column_count; x++)
301
if (field[x] == NULL)
302
result->con->packet_size++;
303
else if (size[x] < 251)
304
result->con->packet_size+= (1 + size[x]);
305
else if (size[x] < 65536)
306
result->con->packet_size+= (3 + size[x]);
307
else if (size[x] < 16777216)
308
result->con->packet_size+= (4 + size[x]);
310
result->con->packet_size+= (9 + size[x]);
314
void drizzle_result_set_eof(drizzle_result_st *result, bool is_eof)
317
result->options|= DRIZZLE_RESULT_EOF_PACKET;
319
result->options&= (drizzle_result_options_t)~DRIZZLE_RESULT_EOF_PACKET;
322
void drizzle_result_set_info(drizzle_result_st *result, const char *info)
328
strncpy(result->info, info, DRIZZLE_MAX_INFO_SIZE);
329
result->info[DRIZZLE_MAX_INFO_SIZE - 1]= 0;
333
void drizzle_result_set_error(drizzle_result_st *result, const char *error)
335
drizzle_result_set_info(result, error);
338
void drizzle_result_set_error_code(drizzle_result_st *result,
341
result->error_code= error_code;
344
void drizzle_result_set_sqlstate(drizzle_result_st *result,
345
const char *sqlstate)
347
if (sqlstate == NULL)
348
result->sqlstate[0]= 0;
351
strncpy(result->sqlstate, sqlstate, DRIZZLE_MAX_SQLSTATE_SIZE + 1);
352
result->sqlstate[DRIZZLE_MAX_SQLSTATE_SIZE]= 0;
356
void drizzle_result_set_warning_count(drizzle_result_st *result,
357
uint16_t warning_count)
359
result->warning_count= warning_count;
362
void drizzle_result_set_insert_id(drizzle_result_st *result,
365
result->insert_id= insert_id;
368
void drizzle_result_set_affected_rows(drizzle_result_st *result,
369
uint64_t affected_rows)
371
result->affected_rows= affected_rows;
374
void drizzle_result_set_column_count(drizzle_result_st *result,
375
uint16_t column_count)
377
result->column_count= column_count;
381
* Internal state functions.
384
drizzle_return_t drizzle_state_result_read(drizzle_con_st *con)
386
drizzle_return_t ret;
388
drizzle_log_debug(con->drizzle, "drizzle_state_result_read");
390
/* Assume the entire result packet will fit in the buffer. */
391
if (con->buffer_size < con->packet_size)
393
drizzle_state_push(con, drizzle_state_read);
394
return DRIZZLE_RETURN_OK;
397
if (con->buffer_ptr[0] == 0)
400
/* We can ignore the returns since we've buffered the entire packet. */
401
con->result->affected_rows= drizzle_unpack_length(con, &ret);
402
con->result->insert_id= drizzle_unpack_length(con, &ret);
403
con->status= drizzle_get_byte2(con->buffer_ptr);
404
con->result->warning_count= drizzle_get_byte2(con->buffer_ptr + 2);
406
con->buffer_size-= 5;
407
con->packet_size-= 5;
408
if (con->packet_size > 0)
410
/* Skip one byte for message size. */
412
con->buffer_size-= 1;
413
con->packet_size-= 1;
415
ret= DRIZZLE_RETURN_OK;
417
else if (con->buffer_ptr[0] == 254)
419
con->result->options= DRIZZLE_RESULT_EOF_PACKET;
420
con->result->warning_count= drizzle_get_byte2(con->buffer_ptr + 1);
421
con->status= drizzle_get_byte2(con->buffer_ptr + 3);
423
con->buffer_size-= 5;
424
con->packet_size-= 5;
425
ret= DRIZZLE_RETURN_OK;
427
else if (con->buffer_ptr[0] == 255)
429
con->result->error_code= drizzle_get_byte2(con->buffer_ptr + 1);
430
con->drizzle->error_code= con->result->error_code;
431
/* Byte 3 is always a '#' character, skip it. */
432
memcpy(con->result->sqlstate, con->buffer_ptr + 4,
433
DRIZZLE_MAX_SQLSTATE_SIZE);
434
con->result->sqlstate[DRIZZLE_MAX_SQLSTATE_SIZE]= 0;
435
memcpy(con->drizzle->sqlstate, con->result->sqlstate,
436
DRIZZLE_MAX_SQLSTATE_SIZE + 1);
438
con->buffer_size-= 9;
439
con->packet_size-= 9;
440
ret= DRIZZLE_RETURN_ERROR_CODE;
444
/* We can ignore the return since we've buffered the entire packet. */
445
con->result->column_count= (uint16_t)drizzle_unpack_length(con, &ret);
446
ret= DRIZZLE_RETURN_OK;
449
if (con->packet_size > 0)
451
snprintf(con->drizzle->last_error, DRIZZLE_MAX_ERROR_SIZE, "%.*s",
452
(int32_t)con->packet_size, con->buffer_ptr);
453
snprintf(con->result->info, DRIZZLE_MAX_INFO_SIZE, "%.*s",
454
(int32_t)con->packet_size, con->buffer_ptr);
455
con->buffer_ptr+= con->packet_size;
456
con->buffer_size-= con->packet_size;
460
drizzle_state_pop(con);
464
drizzle_return_t drizzle_state_result_write(drizzle_con_st *con)
466
uint8_t *start= con->buffer_ptr + con->buffer_size;
468
drizzle_result_st *result= con->result;
470
drizzle_log_debug(con->drizzle, "drizzle_state_result_write");
472
/* Calculate max packet size. */
473
con->packet_size= 1 /* OK/Field Count/EOF/Error */
474
+ 9 /* Affected rows */
477
+ 2 /* Warning count */
478
+ strlen(result->info); /* Info/error message */
480
/* Assume the entire result packet will fit in the buffer. */
481
if ((con->packet_size + 4) > DRIZZLE_MAX_BUFFER_SIZE)
483
drizzle_set_error(con->drizzle, "drizzle_state_result_write",
484
"buffer too small:%zu", con->packet_size + 4);
485
return DRIZZLE_RETURN_INTERNAL_ERROR;
488
/* Flush buffer if there is not enough room. */
489
if (((size_t)DRIZZLE_MAX_BUFFER_SIZE - (size_t)(start - con->buffer)) <
492
drizzle_state_push(con, drizzle_state_write);
493
return DRIZZLE_RETURN_OK;
496
/* Store packet size at the end since it may change. */
498
ptr[3]= con->packet_number;
499
con->packet_number++;
502
if (result->options & DRIZZLE_RESULT_EOF_PACKET)
507
drizzle_set_byte2(ptr, result->warning_count);
510
drizzle_set_byte2(ptr, con->status);
513
else if (result->error_code != 0)
518
drizzle_set_byte2(ptr, result->error_code);
524
memcpy(ptr, result->sqlstate, DRIZZLE_MAX_SQLSTATE_SIZE);
525
ptr+= DRIZZLE_MAX_SQLSTATE_SIZE;
527
memcpy(ptr, result->info, strlen(result->info));
528
ptr+= strlen(result->info);
530
else if (result->column_count == 0)
535
ptr= drizzle_pack_length(result->affected_rows, ptr);
536
ptr= drizzle_pack_length(result->insert_id, ptr);
538
drizzle_set_byte2(ptr, con->status);
541
drizzle_set_byte2(ptr, result->warning_count);
544
memcpy(ptr, result->info, strlen(result->info));
545
ptr+= strlen(result->info);
548
ptr= drizzle_pack_length(result->column_count, ptr);
550
con->packet_size= ((size_t)(ptr - start) - 4);
551
con->buffer_size+= (4 + con->packet_size);
553
/* Store packet size now. */
554
drizzle_set_byte3(start, con->packet_size);
556
drizzle_state_pop(con);
557
return DRIZZLE_RETURN_OK;