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.
39
* @brief Result definitions
48
drizzle_result_st *drizzle_result_create(drizzle_con_st *con,
49
drizzle_result_st *result)
53
result= malloc(sizeof(drizzle_result_st));
56
drizzle_set_error(con->drizzle, "drizzle_result_create", "malloc");
60
memset(result, 0, sizeof(drizzle_result_st));
61
result->options|= DRIZZLE_RESULT_ALLOCATED;
64
memset(result, 0, sizeof(drizzle_result_st));
70
con->result_list->prev= result;
71
result->next= con->result_list;
72
con->result_list= result;
78
drizzle_result_st *drizzle_result_clone(drizzle_con_st *con,
79
drizzle_result_st *result,
80
drizzle_result_st *from)
82
result= drizzle_result_create(con, result);
86
result->options|= (from->options &
87
(drizzle_result_options_t)~DRIZZLE_RESULT_ALLOCATED);
89
drizzle_result_set_info(result, from->info);
90
result->error_code= from->error_code;
91
drizzle_result_set_sqlstate(result, from->sqlstate);
92
result->warning_count= from->warning_count;
93
result->insert_id= from->insert_id;
94
result->affected_rows= from->affected_rows;
95
result->column_count= from->column_count;
96
result->row_count= from->row_count;
101
void drizzle_result_free(drizzle_result_st *result)
103
drizzle_column_st *column;
106
for (column= result->column_list; column != NULL; column= result->column_list)
107
drizzle_column_free(column);
109
if (result->column_buffer != NULL)
110
free(result->column_buffer);
112
if (result->options & DRIZZLE_RESULT_BUFFER_ROW)
114
for (x= 0; x < result->row_count; x++)
115
drizzle_row_free(result, result->row_list[x]);
117
free(result->row_list);
118
free(result->field_sizes_list);
121
if (result->con->result_list == result)
122
result->con->result_list= result->next;
124
result->prev->next= result->next;
126
result->next->prev= result->prev;
127
result->con->result_count--;
129
if (result->options & DRIZZLE_RESULT_ALLOCATED)
133
void drizzle_result_free_all(drizzle_con_st *con)
135
while (con->result_list != NULL)
136
drizzle_result_free(con->result_list);
139
drizzle_con_st *drizzle_result_drizzle_con(drizzle_result_st *result)
144
bool drizzle_result_eof(drizzle_result_st *result)
146
return result->options & DRIZZLE_RESULT_EOF_PACKET;
149
const char *drizzle_result_info(drizzle_result_st *result)
154
const char *drizzle_result_error(drizzle_result_st *result)
159
uint16_t drizzle_result_error_code(drizzle_result_st *result)
161
return result->error_code;
164
const char *drizzle_result_sqlstate(drizzle_result_st *result)
166
return result->sqlstate;
169
uint16_t drizzle_result_warning_count(drizzle_result_st *result)
171
return result->warning_count;
174
uint64_t drizzle_result_insert_id(drizzle_result_st *result)
176
return result->insert_id;
179
uint64_t drizzle_result_affected_rows(drizzle_result_st *result)
181
return result->affected_rows;
184
uint16_t drizzle_result_column_count(drizzle_result_st *result)
186
return result->column_count;
189
uint64_t drizzle_result_row_count(drizzle_result_st *result)
191
return result->row_count;
198
drizzle_result_st *drizzle_result_read(drizzle_con_st *con,
199
drizzle_result_st *result,
200
drizzle_return_t *ret_ptr)
202
if (drizzle_state_none(con))
204
con->result= drizzle_result_create(con, result);
205
if (con->result == NULL)
207
*ret_ptr= DRIZZLE_RETURN_MEMORY;
211
drizzle_state_push(con, drizzle_state_result_read);
212
drizzle_state_push(con, drizzle_state_packet_read);
215
*ret_ptr= drizzle_state_loop(con);
219
drizzle_return_t drizzle_result_buffer(drizzle_result_st *result)
221
drizzle_return_t ret;
223
drizzle_row_t *row_list;
224
size_t **field_sizes_list;
226
if (!(result->options & DRIZZLE_RESULT_BUFFER_COLUMN))
228
ret= drizzle_column_buffer(result);
229
if (ret != DRIZZLE_RETURN_OK)
233
if (result->column_count == 0)
235
result->options|= DRIZZLE_RESULT_BUFFER_ROW;
236
return DRIZZLE_RETURN_OK;
241
row= drizzle_row_buffer(result, &ret);
242
if (ret != DRIZZLE_RETURN_OK)
248
if (result->row_list_size < result->row_count)
250
row_list= realloc(result->row_list, sizeof(drizzle_row_t) *
251
((size_t)(result->row_list_size) +
252
DRIZZLE_ROW_GROW_SIZE));
253
if (row_list == NULL)
255
drizzle_row_free(result, row);
256
drizzle_set_error(result->con->drizzle, "drizzle_result_buffer",
258
return DRIZZLE_RETURN_MEMORY;
261
result->row_list= row_list;
263
field_sizes_list= realloc(result->field_sizes_list, sizeof(size_t *) *
264
((size_t)(result->row_list_size) +
265
DRIZZLE_ROW_GROW_SIZE));
266
if (field_sizes_list == NULL)
268
drizzle_row_free(result, row);
269
drizzle_set_error(result->con->drizzle, "drizzle_result_buffer",
271
return DRIZZLE_RETURN_MEMORY;
274
result->field_sizes_list= field_sizes_list;
276
result->row_list_size+= DRIZZLE_ROW_GROW_SIZE;
279
result->row_list[result->row_current - 1]= row;
280
result->field_sizes_list[result->row_current - 1]= result->field_sizes;
283
result->options|= DRIZZLE_RESULT_BUFFER_ROW;
284
return DRIZZLE_RETURN_OK;
287
size_t drizzle_result_row_size(drizzle_result_st *result)
289
return result->con->packet_size;
296
drizzle_return_t drizzle_result_write(drizzle_con_st *con,
297
drizzle_result_st *result, bool flush)
299
if (drizzle_state_none(con))
304
drizzle_state_push(con, drizzle_state_write);
306
drizzle_state_push(con, drizzle_state_result_write);
309
return drizzle_state_loop(con);
312
void drizzle_result_set_row_size(drizzle_result_st *result, size_t size)
314
result->con->packet_size= size;
317
void drizzle_result_calc_row_size(drizzle_result_st *result,
318
const drizzle_field_t *field,
323
result->con->packet_size= 0;
325
for (x= 0; x < result->column_count; x++)
327
if (field[x] == NULL)
328
result->con->packet_size++;
329
else if (size[x] < 251)
330
result->con->packet_size+= (1 + size[x]);
331
else if (size[x] < 65536)
332
result->con->packet_size+= (3 + size[x]);
333
else if (size[x] < 16777216)
334
result->con->packet_size+= (4 + size[x]);
336
result->con->packet_size+= (9 + size[x]);
340
void drizzle_result_set_eof(drizzle_result_st *result, bool is_eof)
343
result->options|= DRIZZLE_RESULT_EOF_PACKET;
345
result->options&= (drizzle_result_options_t)~DRIZZLE_RESULT_EOF_PACKET;
348
void drizzle_result_set_info(drizzle_result_st *result, const char *info)
354
strncpy(result->info, info, DRIZZLE_MAX_INFO_SIZE);
355
result->info[DRIZZLE_MAX_INFO_SIZE - 1]= 0;
359
void drizzle_result_set_error(drizzle_result_st *result, const char *error)
361
drizzle_result_set_info(result, error);
364
void drizzle_result_set_error_code(drizzle_result_st *result,
367
result->error_code= error_code;
370
void drizzle_result_set_sqlstate(drizzle_result_st *result,
371
const char *sqlstate)
373
if (sqlstate == NULL)
374
result->sqlstate[0]= 0;
377
strncpy(result->sqlstate, sqlstate, DRIZZLE_MAX_SQLSTATE_SIZE + 1);
378
result->sqlstate[DRIZZLE_MAX_SQLSTATE_SIZE]= 0;
382
void drizzle_result_set_warning_count(drizzle_result_st *result,
383
uint16_t warning_count)
385
result->warning_count= warning_count;
388
void drizzle_result_set_insert_id(drizzle_result_st *result,
391
result->insert_id= insert_id;
394
void drizzle_result_set_affected_rows(drizzle_result_st *result,
395
uint64_t affected_rows)
397
result->affected_rows= affected_rows;
400
void drizzle_result_set_column_count(drizzle_result_st *result,
401
uint16_t column_count)
403
result->column_count= column_count;
407
* Internal state functions.
410
drizzle_return_t drizzle_state_result_read(drizzle_con_st *con)
412
drizzle_return_t ret;
414
drizzle_log_debug(con->drizzle, "drizzle_state_result_read");
416
/* Assume the entire result packet will fit in the buffer. */
417
if (con->buffer_size < con->packet_size)
419
drizzle_state_push(con, drizzle_state_read);
420
return DRIZZLE_RETURN_OK;
423
if (con->buffer_ptr[0] == 0)
426
/* We can ignore the returns since we've buffered the entire packet. */
427
con->result->affected_rows= drizzle_unpack_length(con, &ret);
428
con->result->insert_id= drizzle_unpack_length(con, &ret);
429
con->status= drizzle_get_byte2(con->buffer_ptr);
430
con->result->warning_count= drizzle_get_byte2(con->buffer_ptr + 2);
432
con->buffer_size-= 5;
433
con->packet_size-= 5;
434
if (con->packet_size > 0)
436
/* Skip one byte for message size. */
438
con->buffer_size-= 1;
439
con->packet_size-= 1;
441
ret= DRIZZLE_RETURN_OK;
443
else if (con->buffer_ptr[0] == 254)
445
con->result->options= DRIZZLE_RESULT_EOF_PACKET;
446
con->result->warning_count= drizzle_get_byte2(con->buffer_ptr + 1);
447
con->status= drizzle_get_byte2(con->buffer_ptr + 3);
449
con->buffer_size-= 5;
450
con->packet_size-= 5;
451
ret= DRIZZLE_RETURN_OK;
453
else if (con->buffer_ptr[0] == 255)
455
con->result->error_code= drizzle_get_byte2(con->buffer_ptr + 1);
456
con->drizzle->error_code= con->result->error_code;
457
/* Byte 3 is always a '#' character, skip it. */
458
memcpy(con->result->sqlstate, con->buffer_ptr + 4,
459
DRIZZLE_MAX_SQLSTATE_SIZE);
460
con->result->sqlstate[DRIZZLE_MAX_SQLSTATE_SIZE]= 0;
461
memcpy(con->drizzle->sqlstate, con->result->sqlstate,
462
DRIZZLE_MAX_SQLSTATE_SIZE + 1);
464
con->buffer_size-= 9;
465
con->packet_size-= 9;
466
ret= DRIZZLE_RETURN_ERROR_CODE;
470
/* We can ignore the return since we've buffered the entire packet. */
471
con->result->column_count= (uint16_t)drizzle_unpack_length(con, &ret);
472
ret= DRIZZLE_RETURN_OK;
475
if (con->packet_size > 0)
477
snprintf(con->drizzle->last_error, DRIZZLE_MAX_ERROR_SIZE, "%.*s",
478
(int32_t)con->packet_size, con->buffer_ptr);
479
snprintf(con->result->info, DRIZZLE_MAX_INFO_SIZE, "%.*s",
480
(int32_t)con->packet_size, con->buffer_ptr);
481
con->buffer_ptr+= con->packet_size;
482
con->buffer_size-= con->packet_size;
486
drizzle_state_pop(con);
490
drizzle_return_t drizzle_state_result_write(drizzle_con_st *con)
492
uint8_t *start= con->buffer_ptr + con->buffer_size;
494
drizzle_result_st *result= con->result;
496
drizzle_log_debug(con->drizzle, "drizzle_state_result_write");
498
/* Calculate max packet size. */
499
con->packet_size= 1 /* OK/Field Count/EOF/Error */
500
+ 9 /* Affected rows */
503
+ 2 /* Warning count */
504
+ strlen(result->info); /* Info/error message */
506
/* Assume the entire result packet will fit in the buffer. */
507
if ((con->packet_size + 4) > DRIZZLE_MAX_BUFFER_SIZE)
509
drizzle_set_error(con->drizzle, "drizzle_state_result_write",
510
"buffer too small:%zu", con->packet_size + 4);
511
return DRIZZLE_RETURN_INTERNAL_ERROR;
514
/* Flush buffer if there is not enough room. */
515
if (((size_t)DRIZZLE_MAX_BUFFER_SIZE - (size_t)(start - con->buffer)) <
518
drizzle_state_push(con, drizzle_state_write);
519
return DRIZZLE_RETURN_OK;
522
/* Store packet size at the end since it may change. */
524
ptr[3]= con->packet_number;
525
con->packet_number++;
528
if (result->options & DRIZZLE_RESULT_EOF_PACKET)
533
drizzle_set_byte2(ptr, result->warning_count);
536
drizzle_set_byte2(ptr, con->status);
539
else if (result->error_code != 0)
544
drizzle_set_byte2(ptr, result->error_code);
550
memcpy(ptr, result->sqlstate, DRIZZLE_MAX_SQLSTATE_SIZE);
551
ptr+= DRIZZLE_MAX_SQLSTATE_SIZE;
553
memcpy(ptr, result->info, strlen(result->info));
554
ptr+= strlen(result->info);
556
else if (result->column_count == 0)
561
ptr= drizzle_pack_length(result->affected_rows, ptr);
562
ptr= drizzle_pack_length(result->insert_id, ptr);
564
drizzle_set_byte2(ptr, con->status);
567
drizzle_set_byte2(ptr, result->warning_count);
570
memcpy(ptr, result->info, strlen(result->info));
571
ptr+= strlen(result->info);
574
ptr= drizzle_pack_length(result->column_count, ptr);
576
con->packet_size= ((size_t)(ptr - start) - 4);
577
con->buffer_size+= (4 + con->packet_size);
579
/* Store packet size now. */
580
drizzle_set_byte3(start, con->packet_size);
582
drizzle_state_pop(con);
583
return DRIZZLE_RETURN_OK;