Drizzled Public API Documentation

field.cc
Go to the documentation of this file.
1 /* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
2  *
3  * Drizzle Client & Protocol Library
4  *
5  * Copyright (C) 2008 Eric Day (eday@oddments.org)
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions are
10  * met:
11  *
12  * * Redistributions of source code must retain the above copyright
13  * notice, this list of conditions and the following disclaimer.
14  *
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
18  * distribution.
19  *
20  * * The names of its contributors may not be used to endorse or
21  * promote products derived from this software without specific prior
22  * written permission.
23  *
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.
35  *
36  */
37 
43 #include <libdrizzle/common.h>
44 
45 /*
46  * Client definitions
47  */
48 
49 drizzle_field_t drizzle_field_read(drizzle_result_st *result, size_t *offset,
50  size_t *size, size_t *total,
51  drizzle_return_t *ret_ptr)
52 {
53  drizzle_return_t unused_ret;
54  if (ret_ptr == NULL)
55  {
56  ret_ptr= &unused_ret;
57  }
58 
59  if (result == NULL)
60  {
61  *ret_ptr= DRIZZLE_RETURN_INVALID_ARGUMENT;
62  return drizzle_field_t();
63  }
64 
65  if (drizzle_state_none(result->con))
66  {
67  if (result->field_current == result->column_count)
68  {
69  *ret_ptr= DRIZZLE_RETURN_ROW_END;
70  return NULL;
71  }
72 
73  drizzle_state_push(result->con, drizzle_state_field_read);
74  }
75 
76  *ret_ptr= drizzle_state_loop(result->con);
77  if (*ret_ptr == DRIZZLE_RETURN_OK and
78  result->options & DRIZZLE_RESULT_ROW_BREAK)
79  {
80  *ret_ptr= DRIZZLE_RETURN_ROW_BREAK;
81  }
82 
83  if (offset)
84  {
85  *offset= result->field_offset;
86  }
87 
88  if (size)
89  {
90  *size= result->field_size;
91  }
92 
93  if (total)
94  {
95  *total= result->field_total;
96  }
97 
98  return result->field;
99 }
100 
101 drizzle_field_t drizzle_field_buffer(drizzle_result_st *result, size_t *total,
102  drizzle_return_t *ret_ptr)
103 {
104  size_t offset= 0;
105  size_t size= 0;
106 
107  drizzle_return_t unused_ret;
108  if (ret_ptr == NULL)
109  {
110  ret_ptr= &unused_ret;
111  }
112 
113  if (result == NULL)
114  {
115  *ret_ptr= DRIZZLE_RETURN_INVALID_ARGUMENT;
116  return drizzle_field_t();
117  }
118 
119  drizzle_field_t field= drizzle_field_read(result, &offset, &size, total, ret_ptr);
120 
121  if (*ret_ptr != DRIZZLE_RETURN_OK)
122  {
123  return NULL;
124  }
125 
126  if (field == NULL)
127  {
128  *total= 0;
129  return NULL;
130  }
131 
132  if (result->field_buffer == NULL)
133  {
134  result->field_buffer= (drizzle_field_t)realloc(NULL, (*total) +1);
135  if (result->field_buffer == NULL)
136  {
137  drizzle_set_error(result->con->drizzle, __func__, "Failed to allocate.");
138  *ret_ptr= DRIZZLE_RETURN_MEMORY;
139  return NULL;
140  }
141  }
142 
143  memcpy(result->field_buffer + offset, field, size);
144 
145  while ((offset + size) != (*total))
146  {
147  field= drizzle_field_read(result, &offset, &size, total, ret_ptr);
148  if (*ret_ptr != DRIZZLE_RETURN_OK)
149  {
150  return NULL;
151  }
152 
153  memcpy(result->field_buffer + offset, field, size);
154  }
155 
156  field= result->field_buffer;
157  result->field_buffer= NULL;
158  field[*total]= 0;
159 
160  return field;
161 }
162 
163 void drizzle_field_free(drizzle_field_t field)
164 {
165  if (field)
166  {
167  free(field);
168  }
169 }
170 
171 /*
172  * Server definitions
173  */
174 
175 drizzle_return_t drizzle_field_write(drizzle_result_st *result,
176  const drizzle_field_t field, size_t size,
177  size_t total)
178 {
179  if (result == NULL)
180  {
181  return DRIZZLE_RETURN_INVALID_ARGUMENT;
182  }
183 
184  drizzle_return_t ret;
185 
186  if (drizzle_state_none(result->con))
187  {
188  if (result->options & DRIZZLE_RESULT_ROW_BREAK)
189  {
190  result->options&= int(~DRIZZLE_RESULT_ROW_BREAK);
191  result->field= field;
192  result->field_size= size;
193  }
194  else
195  {
196  result->field= field;
197  result->field_size= size;
198  result->field_offset= 0;
199  result->field_total= total;
200  }
201 
202  drizzle_state_push(result->con, drizzle_state_field_write);
203  }
204  else if (result->field == NULL)
205  {
206  result->field= field;
207  result->field_size= size;
208  }
209 
210  ret= drizzle_state_loop(result->con);
211  if (ret == DRIZZLE_RETURN_PAUSE)
212  ret= DRIZZLE_RETURN_OK;
213 
214  return ret;
215 }
216 
217 /*
218  * Internal state functions.
219  */
220 
221 drizzle_return_t drizzle_state_field_read(drizzle_con_st *con)
222 {
223  if (con == NULL)
224  {
225  return DRIZZLE_RETURN_INVALID_ARGUMENT;
226  }
227  drizzle_log_debug(con->drizzle, "drizzle_state_field_read");
228 
229  if (con->buffer_size == 0)
230  {
231  drizzle_state_push(con, drizzle_state_read);
232  return DRIZZLE_RETURN_OK;
233  }
234 
235  con->result->field_offset+= con->result->field_size;
236  if (con->result->field_offset == con->result->field_total)
237  {
238  con->result->field_offset= 0;
239  con->result->field_size= 0;
240 
241  drizzle_return_t ret;
242  con->result->field_total= (size_t)drizzle_unpack_length(con, &ret);
243  if (ret == DRIZZLE_RETURN_NULL_SIZE)
244  {
245  con->result->field= NULL;
246  con->result->field_current++;
247  drizzle_state_pop(con);
248  return DRIZZLE_RETURN_OK;
249  }
250  else if (ret != DRIZZLE_RETURN_OK)
251  {
252  if (ret == DRIZZLE_RETURN_IO_WAIT)
253  {
254  drizzle_state_push(con, drizzle_state_read);
255  return DRIZZLE_RETURN_OK;
256  }
257 
258  return ret;
259  }
260 
261  drizzle_log_debug(con->drizzle,
262  "field_offset= %zu, field_size= %zu, field_total= %zu",
263  con->result->field_offset, con->result->field_size,
264  con->result->field_total);
265 
266  if ((size_t)(con->buffer_size) >= con->result->field_total)
267  {
268  con->result->field_size= con->result->field_total;
269  }
270  else
271  {
272  con->result->field_size= con->buffer_size;
273  }
274  }
275  else
276  {
277  if ((con->result->field_offset + con->buffer_size) >=
278  con->result->field_total)
279  {
280  con->result->field_size= (con->result->field_total -
281  con->result->field_offset);
282  }
283  else
284  {
285  con->result->field_size= con->buffer_size;
286  }
287  }
288 
289  /* This is a special case when a row is larger than the packet size. */
290  if (con->result->field_size > (size_t)con->packet_size)
291  {
292  con->result->field_size= con->packet_size;
293 
294  if (con->options & DRIZZLE_CON_RAW_PACKET)
295  {
296  con->result->options|= DRIZZLE_RESULT_ROW_BREAK;
297  }
298  else
299  {
300  drizzle_state_pop(con);
301  drizzle_state_push(con, drizzle_state_packet_read);
302  drizzle_state_push(con, drizzle_state_field_read);
303  }
304  }
305 
306  con->result->field= (char *)con->buffer_ptr;
307  con->buffer_ptr+= con->result->field_size;
308  con->buffer_size-= con->result->field_size;
309  con->packet_size-= con->result->field_size;
310 
311  drizzle_log_debug(con->drizzle,
312  "field_offset= %zu, field_size= %zu, field_total= %zu",
313  con->result->field_offset, con->result->field_size,
314  con->result->field_total);
315 
316  if ((con->result->field_offset + con->result->field_size) ==
317  con->result->field_total)
318  {
319  if (con->result->column_buffer != NULL &&
320  con->result->column_buffer[con->result->field_current].max_size <
321  con->result->field_total)
322  {
323  con->result->column_buffer[con->result->field_current].max_size=
324  con->result->field_total;
325  }
326 
327  con->result->field_current++;
328  }
329 
330  if (con->result->field_total == 0 || con->result->field_size > 0 ||
331  con->packet_size == 0)
332  {
333  drizzle_state_pop(con);
334  }
335 
336  return DRIZZLE_RETURN_OK;
337 }
338 
339 drizzle_return_t drizzle_state_field_write(drizzle_con_st *con)
340 {
341  if (con == NULL)
342  {
343  return DRIZZLE_RETURN_INVALID_ARGUMENT;
344  }
345 
346  uint8_t *start= con->buffer_ptr + con->buffer_size;
347  uint8_t *ptr;
348  size_t free_size;
349  drizzle_result_st *result= con->result;
350 
351  drizzle_log_debug(con->drizzle, "drizzle_state_field_write");
352 
353  if (result->field == NULL && result->field_total != 0)
354  {
355  return DRIZZLE_RETURN_PAUSE;
356  }
357 
358  free_size= (size_t)DRIZZLE_MAX_BUFFER_SIZE - (size_t)(start - con->buffer);
359  ptr= start;
360 
361  if (result->field_offset == 0)
362  {
363  /* Make sure we can fit the max length and 1 byte of data in (9 + 1). */
364  if (free_size < 10)
365  {
366  drizzle_state_push(con, drizzle_state_write);
367  return DRIZZLE_RETURN_OK;
368  }
369 
370  if (result->field == NULL)
371  {
372  ptr[0]= 251;
373  ptr++;
374  }
375  else if (result->field_total == 0)
376  {
377  ptr[0]= 0;
378  ptr++;
379  }
380  else
381  ptr= drizzle_pack_length(result->field_total, ptr);
382 
383  free_size-= (size_t)(ptr - start);
384  con->buffer_size+= (size_t)(ptr - start);
385  con->packet_size-= (size_t)(ptr - start);
386  }
387  else if (result->field_size > DRIZZLE_BUFFER_COPY_THRESHOLD)
388  {
389  /* Flush the internal buffer first. */
390  if (con->buffer_size != 0)
391  {
392  drizzle_state_push(con, drizzle_state_write);
393  return DRIZZLE_RETURN_OK;
394  }
395 
396  /* We do this to write directly from the field buffer to avoid memcpy(). */
397  con->buffer_ptr= (uint8_t *)result->field;
398  con->buffer_size= result->field_size;
399  con->packet_size-= result->field_size;
400  result->field_offset+= result->field_size;
401  result->field= NULL;
402 
403  if (result->field_offset == result->field_total)
404  {
405  drizzle_state_pop(con);
406  }
407  else if (con->packet_size == 0)
408  {
409  con->result->options|= DRIZZLE_RESULT_ROW_BREAK;
410  drizzle_state_pop(con);
411  }
412 
413  drizzle_state_push(con, drizzle_state_write);
414 
415  return DRIZZLE_RETURN_OK;
416  }
417 
418  if (result->field_size == 0)
419  {
420  drizzle_state_pop(con);
421  }
422  else
423  {
424  if (result->field_size < free_size)
425  free_size= result->field_size;
426 
427  memcpy(ptr, result->field, free_size);
428  result->field_offset+= free_size;
429  con->buffer_size+= free_size;
430  con->packet_size-= free_size;
431 
432  if (result->field_offset == result->field_total)
433  {
434  result->field= NULL;
435  drizzle_state_pop(con);
436  }
437  else
438  {
439  if (con->packet_size == 0)
440  {
441  con->result->options|= DRIZZLE_RESULT_ROW_BREAK;
442  drizzle_state_pop(con);
443  }
444 
445  if (result->field_size == free_size)
446  {
447  result->field= NULL;
448  }
449  else
450  {
451  result->field+= free_size;
452  result->field_size-= free_size;
453  drizzle_state_push(con, drizzle_state_write);
454  }
455  }
456  }
457 
458  return DRIZZLE_RETURN_OK;
459 }