libdrizzle Developer Documentation

result.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 
16 #include "common.h"
17 
18 /*
19  * Common definitions
20  */
21 
23  drizzle_result_st *result)
24 {
25  if (result == NULL)
26  {
27  result= malloc(sizeof(drizzle_result_st));
28  if (result == NULL)
29  {
30  drizzle_set_error(con->drizzle, "drizzle_result_create", "malloc");
31  return NULL;
32  }
33 
34  memset(result, 0, sizeof(drizzle_result_st));
36  }
37  else
38  memset(result, 0, sizeof(drizzle_result_st));
39 
40  result->con= con;
41  con->result= result;
42 
43  if (con->result_list)
44  con->result_list->prev= result;
45  result->next= con->result_list;
46  con->result_list= result;
47  con->result_count++;
48 
49  return result;
50 }
51 
53  drizzle_result_st *result,
54  drizzle_result_st *from)
55 {
56  result= drizzle_result_create(con, result);
57  if (result == NULL)
58  return NULL;
59 
60  result->options|= (from->options &
62 
63  drizzle_result_set_info(result, from->info);
64  result->error_code= from->error_code;
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;
71 
72  return result;
73 }
74 
76 {
77  drizzle_column_st *column;
78  uint64_t x;
79 
80  for (column= result->column_list; column != NULL; column= result->column_list)
81  drizzle_column_free(column);
82 
83  if (result->column_buffer != NULL)
84  free(result->column_buffer);
85 
86  if (result->options & DRIZZLE_RESULT_BUFFER_ROW)
87  {
88  for (x= 0; x < result->row_count; x++)
89  drizzle_row_free(result, result->row_list[x]);
90 
91  free(result->row_list);
92  free(result->field_sizes_list);
93  }
94 
95  if (result->con->result_list == result)
96  result->con->result_list= result->next;
97  if (result->prev)
98  result->prev->next= result->next;
99  if (result->next)
100  result->next->prev= result->prev;
101  result->con->result_count--;
102 
103  if (result->options & DRIZZLE_RESULT_ALLOCATED)
104  free(result);
105 }
106 
108 {
109  while (con->result_list != NULL)
111 }
112 
114 {
115  return result->con;
116 }
117 
119 {
120  return result->options & DRIZZLE_RESULT_EOF_PACKET;
121 }
122 
124 {
125  return result->info;
126 }
127 
129 {
130  return result->info;
131 }
132 
134 {
135  return result->error_code;
136 }
137 
139 {
140  return result->sqlstate;
141 }
142 
144 {
145  return result->warning_count;
146 }
147 
149 {
150  return result->insert_id;
151 }
152 
154 {
155  return result->affected_rows;
156 }
157 
159 {
160  return result->column_count;
161 }
162 
164 {
165  return result->row_count;
166 }
167 
168 /*
169  * Client definitions
170  */
171 
173  drizzle_result_st *result,
174  drizzle_return_t *ret_ptr)
175 {
176  if (drizzle_state_none(con))
177  {
178  con->result= drizzle_result_create(con, result);
179  if (con->result == NULL)
180  {
181  *ret_ptr= DRIZZLE_RETURN_MEMORY;
182  return NULL;
183  }
184 
187  }
188 
189  *ret_ptr= drizzle_state_loop(con);
190  return con->result;
191 }
192 
194 {
195  drizzle_return_t ret;
196  drizzle_row_t row;
197  drizzle_row_t *row_list;
198  size_t **field_sizes_list;
199 
200  if (!(result->options & DRIZZLE_RESULT_BUFFER_COLUMN))
201  {
202  ret= drizzle_column_buffer(result);
203  if (ret != DRIZZLE_RETURN_OK)
204  return ret;
205  }
206 
207  if (result->column_count == 0)
208  {
210  return DRIZZLE_RETURN_OK;
211  }
212 
213  while (1)
214  {
215  row= drizzle_row_buffer(result, &ret);
216  if (ret != DRIZZLE_RETURN_OK)
217  return ret;
218 
219  if (row == NULL)
220  break;
221 
222  if (result->row_list_size < result->row_count)
223  {
224  row_list= realloc(result->row_list, sizeof(drizzle_row_t) *
225  ((size_t)(result->row_list_size) +
227  if (row_list == NULL)
228  {
229  drizzle_row_free(result, row);
230  drizzle_set_error(result->con->drizzle, "drizzle_result_buffer",
231  "realloc");
232  return DRIZZLE_RETURN_MEMORY;
233  }
234 
235  result->row_list= row_list;
236 
237  field_sizes_list= realloc(result->field_sizes_list, sizeof(size_t *) *
238  ((size_t)(result->row_list_size) +
240  if (field_sizes_list == NULL)
241  {
242  drizzle_row_free(result, row);
243  drizzle_set_error(result->con->drizzle, "drizzle_result_buffer",
244  "realloc");
245  return DRIZZLE_RETURN_MEMORY;
246  }
247 
248  result->field_sizes_list= field_sizes_list;
249 
251  }
252 
253  result->row_list[result->row_current - 1]= row;
254  result->field_sizes_list[result->row_current - 1]= result->field_sizes;
255  }
256 
258  return DRIZZLE_RETURN_OK;
259 }
260 
262 {
263  return result->con->packet_size;
264 }
265 
266 /*
267  * Server definitions
268  */
269 
271  drizzle_result_st *result, bool flush)
272 {
273  if (drizzle_state_none(con))
274  {
275  con->result= result;
276 
277  if (flush)
279 
281  }
282 
283  return drizzle_state_loop(con);
284 }
285 
287 {
288  result->con->packet_size= size;
289 }
290 
292  const drizzle_field_t *field,
293  const size_t *size)
294 {
295  uint16_t x;
296 
297  result->con->packet_size= 0;
298 
299  for (x= 0; x < result->column_count; x++)
300  {
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]);
309  else
310  result->con->packet_size+= (9 + size[x]);
311  }
312 }
313 
315 {
316  if (eof)
318  else
320 }
321 
322 void drizzle_result_set_info(drizzle_result_st *result, const char *info)
323 {
324  if (info == NULL)
325  result->info[0]= 0;
326  else
327  {
328  strncpy(result->info, info, DRIZZLE_MAX_INFO_SIZE);
329  result->info[DRIZZLE_MAX_INFO_SIZE - 1]= 0;
330  }
331 }
332 
333 void drizzle_result_set_error(drizzle_result_st *result, const char *error)
334 {
335  drizzle_result_set_info(result, error);
336 }
337 
339  uint16_t error_code)
340 {
341  result->error_code= error_code;
342 }
343 
345  const char *sqlstate)
346 {
347  if (sqlstate == NULL)
348  result->sqlstate[0]= 0;
349  else
350  {
351  strncpy(result->sqlstate, sqlstate, DRIZZLE_MAX_SQLSTATE_SIZE + 1);
353  }
354 }
355 
357  uint16_t warning_count)
358 {
359  result->warning_count= warning_count;
360 }
361 
363  uint64_t insert_id)
364 {
365  result->insert_id= insert_id;
366 }
367 
369  uint64_t affected_rows)
370 {
371  result->affected_rows= affected_rows;
372 }
373 
375  uint16_t column_count)
376 {
377  result->column_count= column_count;
378 }
379 
380 /*
381  * Internal state functions.
382  */
383 
385 {
386  drizzle_return_t ret;
387 
388  drizzle_log_debug(con->drizzle, "drizzle_state_result_read");
389 
390  /* Assume the entire result packet will fit in the buffer. */
391  if (con->buffer_size < con->packet_size)
392  {
394  return DRIZZLE_RETURN_OK;
395  }
396 
397  if (con->buffer_ptr[0] == 0)
398  {
399  con->buffer_ptr++;
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);
405  con->buffer_ptr+= 4;
406  con->buffer_size-= 5;
407  con->packet_size-= 5;
408  if (con->packet_size > 0)
409  {
410  /* Skip one byte for message size. */
411  con->buffer_ptr+= 1;
412  con->buffer_size-= 1;
413  con->packet_size-= 1;
414  }
415  ret= DRIZZLE_RETURN_OK;
416  }
417  else if (con->buffer_ptr[0] == 254)
418  {
421  con->status= drizzle_get_byte2(con->buffer_ptr + 3);
422  con->buffer_ptr+= 5;
423  con->buffer_size-= 5;
424  con->packet_size-= 5;
425  ret= DRIZZLE_RETURN_OK;
426  }
427  else if (con->buffer_ptr[0] == 255)
428  {
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,
435  memcpy(con->drizzle->sqlstate, con->result->sqlstate,
437  con->buffer_ptr+= 9;
438  con->buffer_size-= 9;
439  con->packet_size-= 9;
441  }
442  else
443  {
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;
447  }
448 
449  if (con->packet_size > 0)
450  {
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;
457  con->packet_size= 0;
458  }
459 
460  drizzle_state_pop(con);
461  return ret;
462 }
463 
465 {
466  uint8_t *start= con->buffer_ptr + con->buffer_size;
467  uint8_t *ptr;
468  drizzle_result_st *result= con->result;
469 
470  drizzle_log_debug(con->drizzle, "drizzle_state_result_write");
471 
472  /* Calculate max packet size. */
473  con->packet_size= 1 /* OK/Field Count/EOF/Error */
474  + 9 /* Affected rows */
475  + 9 /* Insert ID */
476  + 2 /* Status */
477  + 2 /* Warning count */
478  + strlen(result->info); /* Info/error message */
479 
480  /* Assume the entire result packet will fit in the buffer. */
481  if ((con->packet_size + 4) > DRIZZLE_MAX_BUFFER_SIZE)
482  {
483  drizzle_set_error(con->drizzle, "drizzle_state_result_write",
484  "buffer too small:%zu", con->packet_size + 4);
486  }
487 
488  /* Flush buffer if there is not enough room. */
489  if (((size_t)DRIZZLE_MAX_BUFFER_SIZE - (size_t)(start - con->buffer)) <
490  con->packet_size)
491  {
493  return DRIZZLE_RETURN_OK;
494  }
495 
496  /* Store packet size at the end since it may change. */
497  ptr= start;
498  ptr[3]= con->packet_number;
499  con->packet_number++;
500  ptr+= 4;
501 
502  if (result->options & DRIZZLE_RESULT_EOF_PACKET)
503  {
504  ptr[0]= 254;
505  ptr++;
506 
507  drizzle_set_byte2(ptr, result->warning_count);
508  ptr+= 2;
509 
510  drizzle_set_byte2(ptr, con->status);
511  ptr+= 2;
512  }
513  else if (result->error_code != 0)
514  {
515  ptr[0]= 255;
516  ptr++;
517 
518  drizzle_set_byte2(ptr, result->error_code);
519  ptr+= 2;
520 
521  ptr[0]= '#';
522  ptr++;
523 
524  memcpy(ptr, result->sqlstate, DRIZZLE_MAX_SQLSTATE_SIZE);
526 
527  memcpy(ptr, result->info, strlen(result->info));
528  ptr+= strlen(result->info);
529  }
530  else if (result->column_count == 0)
531  {
532  ptr[0]= 0;
533  ptr++;
534 
535  ptr= drizzle_pack_length(result->affected_rows, ptr);
536  ptr= drizzle_pack_length(result->insert_id, ptr);
537 
538  drizzle_set_byte2(ptr, con->status);
539  ptr+= 2;
540 
541  drizzle_set_byte2(ptr, result->warning_count);
542  ptr+= 2;
543 
544  memcpy(ptr, result->info, strlen(result->info));
545  ptr+= strlen(result->info);
546  }
547  else
548  ptr= drizzle_pack_length(result->column_count, ptr);
549 
550  con->packet_size= ((size_t)(ptr - start) - 4);
551  con->buffer_size+= (4 + con->packet_size);
552 
553  /* Store packet size now. */
554  drizzle_set_byte3(start, con->packet_size);
555 
556  drizzle_state_pop(con);
557  return DRIZZLE_RETURN_OK;
558 }