1
/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
3
* Drizzle Client & Protocol Library
5
* Copyright (C) 2008 Eric Day (eday@oddments.org)
8
* Redistribution and use in source and binary forms, with or without
9
* modification, are permitted provided that the following conditions are
12
* * Redistributions of source code must retain the above copyright
13
* notice, this list of conditions and the following disclaimer.
15
* * Redistributions in binary form must reproduce the above
16
* copyright notice, this list of conditions and the following disclaimer
17
* in the documentation and/or other materials provided with the
20
* * The names of its contributors may not be used to endorse or
21
* promote products derived from this software without specific prior
24
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
25
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
26
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
27
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
28
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
29
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
30
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
31
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
32
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
33
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
34
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
40
* @brief Result definitions
43
#include <libdrizzle/common.h>
49
drizzle_result_st *drizzle_result_create(drizzle_con_st *con,
50
drizzle_result_st *result)
59
result= malloc(sizeof(drizzle_result_st));
62
drizzle_set_error(con->drizzle, __func__, "Failed to allocate.");
66
result->options|= DRIZZLE_RESULT_ALLOCATED;
70
memset(result, 0, sizeof(drizzle_result_st));
77
con->result_list->prev= result;
78
result->next= con->result_list;
79
con->result_list= result;
85
drizzle_result_st *drizzle_result_clone(drizzle_con_st *con,
86
drizzle_result_st *result,
87
drizzle_result_st *from)
89
// A NULL con will return a NULL result
90
result= drizzle_result_create(con, result);
96
result->options|= from->options & ~DRIZZLE_RESULT_ALLOCATED;
98
drizzle_result_set_info(result, from->info);
99
result->error_code= from->error_code;
100
drizzle_result_set_sqlstate(result, from->sqlstate);
101
result->warning_count= from->warning_count;
102
result->insert_id= from->insert_id;
103
result->affected_rows= from->affected_rows;
104
result->column_count= from->column_count;
105
result->row_count= from->row_count;
110
void drizzle_result_free(drizzle_result_st *result)
112
drizzle_column_st* column;
119
for (column= result->column_list; column != NULL; column= result->column_list)
121
drizzle_column_free(column);
124
free(result->column_buffer);
126
if (result->options & DRIZZLE_RESULT_BUFFER_ROW)
129
for (x= 0; x < result->row_count; x++)
131
drizzle_row_free(result, result->row_list[x]);
134
free(result->row_list);
135
free(result->field_sizes_list);
140
result->con->result_count--;
141
if (result->con->result_list == result)
142
result->con->result_list= result->next;
147
result->prev->next= result->next;
151
result->next->prev= result->prev;
154
if (result->options & DRIZZLE_RESULT_ALLOCATED)
160
void drizzle_result_free_all(drizzle_con_st *con)
167
while (con->result_list != NULL)
169
drizzle_result_free(con->result_list);
173
drizzle_con_st *drizzle_result_drizzle_con(drizzle_result_st *result)
183
bool drizzle_result_eof(drizzle_result_st *result)
190
return result->options & DRIZZLE_RESULT_EOF_PACKET;
193
const char *drizzle_result_info(drizzle_result_st *result)
203
const char *drizzle_result_error(drizzle_result_st *result)
213
uint16_t drizzle_result_error_code(drizzle_result_st *result)
220
return result->error_code;
223
const char *drizzle_result_sqlstate(drizzle_result_st *result)
230
return result->sqlstate;
233
uint16_t drizzle_result_warning_count(drizzle_result_st *result)
240
return result->warning_count;
243
uint64_t drizzle_result_insert_id(drizzle_result_st *result)
250
return result->insert_id;
253
uint64_t drizzle_result_affected_rows(drizzle_result_st *result)
260
return result->affected_rows;
263
uint16_t drizzle_result_column_count(drizzle_result_st *result)
270
return result->column_count;
273
uint64_t drizzle_result_row_count(drizzle_result_st *result)
280
return result->row_count;
287
drizzle_result_st *drizzle_result_read(drizzle_con_st *con,
288
drizzle_result_st *result,
289
drizzle_return_t *ret_ptr)
291
drizzle_return_t unused;
299
*ret_ptr= DRIZZLE_RETURN_INVALID_ARGUMENT;
303
if (drizzle_state_none(con))
305
con->result= drizzle_result_create(con, result);
306
if (con->result == NULL)
308
*ret_ptr= DRIZZLE_RETURN_MEMORY;
312
drizzle_state_push(con, drizzle_state_result_read);
313
drizzle_state_push(con, drizzle_state_packet_read);
316
*ret_ptr= drizzle_state_loop(con);
320
drizzle_return_t drizzle_result_buffer(drizzle_result_st *result)
324
return DRIZZLE_RETURN_INVALID_ARGUMENT;
327
drizzle_return_t ret;
329
drizzle_row_t *row_list;
330
size_t **field_sizes_list;
332
if (!(result->options & DRIZZLE_RESULT_BUFFER_COLUMN))
334
ret= drizzle_column_buffer(result);
335
if (ret != DRIZZLE_RETURN_OK)
339
if (result->column_count == 0)
341
result->options|= DRIZZLE_RESULT_BUFFER_ROW;
342
return DRIZZLE_RETURN_OK;
347
row= drizzle_row_buffer(result, &ret);
348
if (ret != DRIZZLE_RETURN_OK)
354
if (result->row_list_size < result->row_count)
356
row_list= (drizzle_row_t *)realloc(result->row_list, sizeof(drizzle_row_t) * ((size_t)(result->row_list_size) + DRIZZLE_ROW_GROW_SIZE));
357
if (row_list == NULL)
359
drizzle_row_free(result, row);
360
drizzle_set_error(result->con->drizzle, __func__, "Failed to realloc row_list.");
361
return DRIZZLE_RETURN_MEMORY;
364
result->row_list= row_list;
366
field_sizes_list= (size_t **)realloc(result->field_sizes_list, sizeof(size_t *) * ((size_t)(result->row_list_size) + DRIZZLE_ROW_GROW_SIZE));
367
if (field_sizes_list == NULL)
369
drizzle_row_free(result, row);
370
drizzle_set_error(result->con->drizzle, "drizzle_result_buffer", "Failed to realloc field list.");
371
return DRIZZLE_RETURN_MEMORY;
374
result->field_sizes_list= field_sizes_list;
376
result->row_list_size+= DRIZZLE_ROW_GROW_SIZE;
379
result->row_list[result->row_current - 1]= row;
380
result->field_sizes_list[result->row_current - 1]= result->field_sizes;
383
result->options|= DRIZZLE_RESULT_BUFFER_ROW;
384
return DRIZZLE_RETURN_OK;
387
size_t drizzle_result_row_size(drizzle_result_st *result)
394
return result->con->packet_size;
401
drizzle_return_t drizzle_result_write(drizzle_con_st *con,
402
drizzle_result_st *result, bool flush)
406
return DRIZZLE_RETURN_INVALID_ARGUMENT;
409
if (drizzle_state_none(con))
414
drizzle_state_push(con, drizzle_state_write);
416
drizzle_state_push(con, drizzle_state_result_write);
419
return drizzle_state_loop(con);
422
void drizzle_result_set_row_size(drizzle_result_st *result, size_t size)
429
result->con->packet_size= size;
432
void drizzle_result_calc_row_size(drizzle_result_st *result,
433
const drizzle_field_t *field,
442
result->con->packet_size= 0;
444
for (x= 0; x < result->column_count; x++)
446
if (field[x] == NULL)
448
result->con->packet_size++;
450
else if (size[x] < 251)
452
result->con->packet_size+= (1 + size[x]);
454
else if (size[x] < 65536)
456
result->con->packet_size+= (3 + size[x]);
458
else if (size[x] < 16777216)
460
result->con->packet_size+= (4 + size[x]);
464
result->con->packet_size+= (9 + size[x]);
469
void drizzle_result_set_eof(drizzle_result_st *result, bool is_eof)
477
result->options|= DRIZZLE_RESULT_EOF_PACKET;
479
result->options&= ~DRIZZLE_RESULT_EOF_PACKET;
482
void drizzle_result_set_info(drizzle_result_st *result, const char *info)
495
strncpy(result->info, info, DRIZZLE_MAX_INFO_SIZE);
496
result->info[DRIZZLE_MAX_INFO_SIZE - 1]= 0;
500
void drizzle_result_set_error(drizzle_result_st *result, const char *error)
507
drizzle_result_set_info(result, error);
510
void drizzle_result_set_error_code(drizzle_result_st *result,
518
result->error_code= error_code;
521
void drizzle_result_set_sqlstate(drizzle_result_st *result,
522
const char *sqlstate)
529
if (sqlstate == NULL)
531
result->sqlstate[0]= 0;
535
strncpy(result->sqlstate, sqlstate, DRIZZLE_MAX_SQLSTATE_SIZE + 1);
536
result->sqlstate[DRIZZLE_MAX_SQLSTATE_SIZE]= 0;
540
void drizzle_result_set_warning_count(drizzle_result_st *result,
541
uint16_t warning_count)
548
result->warning_count= warning_count;
551
void drizzle_result_set_insert_id(drizzle_result_st *result,
559
result->insert_id= insert_id;
562
void drizzle_result_set_affected_rows(drizzle_result_st *result,
563
uint64_t affected_rows)
570
result->affected_rows= affected_rows;
573
void drizzle_result_set_column_count(drizzle_result_st *result,
574
uint16_t column_count)
581
result->column_count= column_count;
585
* Internal state functions.
588
drizzle_return_t drizzle_state_result_read(drizzle_con_st *con)
590
drizzle_return_t ret;
594
return DRIZZLE_RETURN_INVALID_ARGUMENT;
597
drizzle_log_debug(con->drizzle, "drizzle_state_result_read");
599
/* Assume the entire result packet will fit in the buffer. */
600
if (con->buffer_size < con->packet_size)
602
drizzle_state_push(con, drizzle_state_read);
603
return DRIZZLE_RETURN_OK;
606
if (con->buffer_ptr[0] == 0)
609
/* We can ignore the returns since we've buffered the entire packet. */
610
con->result->affected_rows= drizzle_unpack_length(con, &ret);
611
con->result->insert_id= drizzle_unpack_length(con, &ret);
612
con->status= drizzle_get_byte2(con->buffer_ptr);
613
con->result->warning_count= drizzle_get_byte2(con->buffer_ptr + 2);
615
con->buffer_size-= 5;
616
con->packet_size-= 5;
617
if (con->packet_size > 0)
619
/* Skip one byte for message size. */
621
con->buffer_size-= 1;
622
con->packet_size-= 1;
624
ret= DRIZZLE_RETURN_OK;
626
else if (con->buffer_ptr[0] == 254)
628
con->result->options= DRIZZLE_RESULT_EOF_PACKET;
629
con->result->warning_count= drizzle_get_byte2(con->buffer_ptr + 1);
630
con->status= drizzle_get_byte2(con->buffer_ptr + 3);
632
con->buffer_size-= 5;
633
con->packet_size-= 5;
634
ret= DRIZZLE_RETURN_OK;
636
else if (con->buffer_ptr[0] == 255)
638
con->result->error_code= drizzle_get_byte2(con->buffer_ptr + 1);
639
con->drizzle->error_code= con->result->error_code;
640
/* Byte 3 is always a '#' character, skip it. */
641
memcpy(con->result->sqlstate, con->buffer_ptr + 4,
642
DRIZZLE_MAX_SQLSTATE_SIZE);
643
con->result->sqlstate[DRIZZLE_MAX_SQLSTATE_SIZE]= 0;
644
memcpy(con->drizzle->sqlstate, con->result->sqlstate,
645
DRIZZLE_MAX_SQLSTATE_SIZE + 1);
647
con->buffer_size-= 9;
648
con->packet_size-= 9;
649
ret= DRIZZLE_RETURN_ERROR_CODE;
653
/* We can ignore the return since we've buffered the entire packet. */
654
con->result->column_count= (uint16_t)drizzle_unpack_length(con, &ret);
655
ret= DRIZZLE_RETURN_OK;
658
if (con->packet_size > 0)
660
snprintf(con->drizzle->last_error, DRIZZLE_MAX_ERROR_SIZE, "%.*s",
661
(int32_t)con->packet_size, con->buffer_ptr);
662
con->drizzle->last_error[DRIZZLE_MAX_ERROR_SIZE-1]= 0;
663
snprintf(con->result->info, DRIZZLE_MAX_INFO_SIZE, "%.*s",
664
(int32_t)con->packet_size, con->buffer_ptr);
665
con->result->info[DRIZZLE_MAX_INFO_SIZE-1]= 0;
666
con->buffer_ptr+= con->packet_size;
667
con->buffer_size-= con->packet_size;
671
drizzle_state_pop(con);
675
drizzle_return_t drizzle_state_result_write(drizzle_con_st *con)
679
return DRIZZLE_RETURN_INVALID_ARGUMENT;
682
uint8_t *start= con->buffer_ptr + con->buffer_size;
684
drizzle_result_st *result= con->result;
686
drizzle_log_debug(con->drizzle, "drizzle_state_result_write");
688
/* Calculate max packet size. */
689
con->packet_size= 1 /* OK/Field Count/EOF/Error */
690
+ 9 /* Affected rows */
693
+ 2 /* Warning count */
694
+ strlen(result->info); /* Info/error message */
696
/* Assume the entire result packet will fit in the buffer. */
697
if ((con->packet_size + 4) > DRIZZLE_MAX_BUFFER_SIZE)
699
drizzle_set_error(con->drizzle, "drizzle_state_result_write",
700
"buffer too small:%zu", con->packet_size + 4);
701
return DRIZZLE_RETURN_INTERNAL_ERROR;
704
/* Flush buffer if there is not enough room. */
705
if (((size_t)DRIZZLE_MAX_BUFFER_SIZE - (size_t)(start - con->buffer)) <
708
drizzle_state_push(con, drizzle_state_write);
709
return DRIZZLE_RETURN_OK;
712
/* Store packet size at the end since it may change. */
714
ptr[3]= con->packet_number;
715
con->packet_number++;
718
if (result->options & DRIZZLE_RESULT_EOF_PACKET)
723
drizzle_set_byte2(ptr, result->warning_count);
726
drizzle_set_byte2(ptr, con->status);
729
else if (result->error_code != 0)
734
drizzle_set_byte2(ptr, result->error_code);
740
memcpy(ptr, result->sqlstate, DRIZZLE_MAX_SQLSTATE_SIZE);
741
ptr+= DRIZZLE_MAX_SQLSTATE_SIZE;
743
memcpy(ptr, result->info, strlen(result->info));
744
ptr+= strlen(result->info);
746
else if (result->column_count == 0)
751
ptr= drizzle_pack_length(result->affected_rows, ptr);
752
ptr= drizzle_pack_length(result->insert_id, ptr);
754
drizzle_set_byte2(ptr, con->status);
757
drizzle_set_byte2(ptr, result->warning_count);
760
memcpy(ptr, result->info, strlen(result->info));
761
ptr+= strlen(result->info);
764
ptr= drizzle_pack_length(result->column_count, ptr);
766
con->packet_size= ((size_t)(ptr - start) - 4);
767
con->buffer_size+= (4 + con->packet_size);
769
/* Store packet size now. */
770
drizzle_set_byte3(start, con->packet_size);
772
drizzle_state_pop(con);
773
return DRIZZLE_RETURN_OK;