libdrizzle Developer Documentation

field.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  * Client definitions
20  */
21 
23  size_t *size, size_t *total,
24  drizzle_return_t *ret_ptr)
25 {
26  if (drizzle_state_none(result->con))
27  {
28  if (result->field_current == result->column_count)
29  {
30  *ret_ptr= DRIZZLE_RETURN_ROW_END;
31  return NULL;
32  }
33 
35  }
36 
37  *ret_ptr= drizzle_state_loop(result->con);
38  if (*ret_ptr == DRIZZLE_RETURN_OK &&
40  {
41  *ret_ptr= DRIZZLE_RETURN_ROW_BREAK;
42  }
43 
44  *offset= result->field_offset;
45  *size= result->field_size;
46  *total= result->field_total;
47 
48  return result->field;
49 }
50 
52  drizzle_return_t *ret_ptr)
53 {
54  drizzle_field_t field;
55  size_t offset= 0;
56  size_t size= 0;
57 
58  field= drizzle_field_read(result, &offset, &size, total, ret_ptr);
59  if (*ret_ptr != DRIZZLE_RETURN_OK)
60  return NULL;
61 
62  if (field == NULL)
63  {
64  *total= 0;
65  return NULL;
66  }
67 
68  if (result->field_buffer == NULL)
69  {
70  result->field_buffer= malloc((*total) + 1);
71  if (result->field_buffer == NULL)
72  {
73  drizzle_set_error(result->con->drizzle, "drizzle_field_buffer", "malloc");
74  *ret_ptr= DRIZZLE_RETURN_MEMORY;
75  return NULL;
76  }
77  }
78 
79  memcpy(result->field_buffer + offset, field, size);
80 
81  while ((offset + size) != (*total))
82  {
83  field= drizzle_field_read(result, &offset, &size, total, ret_ptr);
84  if (*ret_ptr != DRIZZLE_RETURN_OK)
85  return NULL;
86 
87  memcpy(result->field_buffer + offset, field, size);
88  }
89 
90  field= result->field_buffer;
91  result->field_buffer= NULL;
92  field[*total]= 0;
93 
94  return field;
95 }
96 
98 {
99  if (field != NULL)
100  free(field);
101 }
102 
103 /*
104  * Server definitions
105  */
106 
108  const drizzle_field_t field, size_t size,
109  size_t total)
110 {
111  drizzle_return_t ret;
112 
113  if (drizzle_state_none(result->con))
114  {
115  if (result->options & DRIZZLE_RESULT_ROW_BREAK)
116  {
118  result->field= field;
119  result->field_size= size;
120  }
121  else
122  {
123  result->field= field;
124  result->field_size= size;
125  result->field_offset= 0;
126  result->field_total= total;
127  }
128 
130  }
131  else if (result->field == NULL)
132  {
133  result->field= field;
134  result->field_size= size;
135  }
136 
137  ret= drizzle_state_loop(result->con);
138  if (ret == DRIZZLE_RETURN_PAUSE)
139  ret= DRIZZLE_RETURN_OK;
140 
141  return ret;
142 }
143 
144 /*
145  * Internal state functions.
146  */
147 
149 {
150  drizzle_return_t ret;
151 
152  drizzle_log_debug(con->drizzle, "drizzle_state_field_read");
153 
154  if (con->buffer_size == 0)
155  {
157  return DRIZZLE_RETURN_OK;
158  }
159 
160  con->result->field_offset+= con->result->field_size;
161  if (con->result->field_offset == con->result->field_total)
162  {
163  con->result->field_offset= 0;
164  con->result->field_size= 0;
165 
166  con->result->field_total= (size_t)drizzle_unpack_length(con, &ret);
167  if (ret == DRIZZLE_RETURN_NULL_SIZE)
168  {
169  con->result->field= NULL;
170  con->result->field_current++;
171  drizzle_state_pop(con);
172  return DRIZZLE_RETURN_OK;
173  }
174  else if (ret != DRIZZLE_RETURN_OK)
175  {
176  if (ret == DRIZZLE_RETURN_IO_WAIT)
177  {
179  return DRIZZLE_RETURN_OK;
180  }
181 
182  return ret;
183  }
184 
186  "field_offset= %zu, field_size= %zu, field_total= %zu",
187  con->result->field_offset, con->result->field_size,
188  con->result->field_total);
189 
190  if ((size_t)(con->buffer_size) >= con->result->field_total)
191  con->result->field_size= con->result->field_total;
192  else
193  con->result->field_size= con->buffer_size;
194  }
195  else
196  {
197  if ((con->result->field_offset + con->buffer_size) >=
198  con->result->field_total)
199  {
200  con->result->field_size= (con->result->field_total -
201  con->result->field_offset);
202  }
203  else
204  con->result->field_size= con->buffer_size;
205  }
206 
207  /* This is a special case when a row is larger than the packet size. */
208  if (con->result->field_size > (size_t)con->packet_size)
209  {
210  con->result->field_size= con->packet_size;
211 
212  if (con->options & DRIZZLE_CON_RAW_PACKET)
214  else
215  {
216  drizzle_state_pop(con);
219  }
220  }
221 
222  con->result->field= (char *)con->buffer_ptr;
223  con->buffer_ptr+= con->result->field_size;
224  con->buffer_size-= con->result->field_size;
225  con->packet_size-= con->result->field_size;
226 
228  "field_offset= %zu, field_size= %zu, field_total= %zu",
229  con->result->field_offset, con->result->field_size,
230  con->result->field_total);
231 
232  if ((con->result->field_offset + con->result->field_size) ==
233  con->result->field_total)
234  {
235  if (con->result->column_buffer != NULL &&
237  con->result->field_total)
238  {
240  con->result->field_total;
241  }
242 
243  con->result->field_current++;
244  }
245 
246  if (con->result->field_total == 0 || con->result->field_size > 0 ||
247  con->packet_size == 0)
248  {
249  drizzle_state_pop(con);
250  }
251 
252  return DRIZZLE_RETURN_OK;
253 }
254 
256 {
257  uint8_t *start= con->buffer_ptr + con->buffer_size;
258  uint8_t *ptr;
259  size_t free_size;
260  drizzle_result_st *result= con->result;
261 
262  drizzle_log_debug(con->drizzle, "drizzle_state_field_write");
263 
264  if (result->field == NULL && result->field_total != 0)
265  return DRIZZLE_RETURN_PAUSE;
266 
267  free_size= (size_t)DRIZZLE_MAX_BUFFER_SIZE - (size_t)(start - con->buffer);
268  ptr= start;
269 
270  if (result->field_offset == 0)
271  {
272  /* Make sure we can fit the max length and 1 byte of data in (9 + 1). */
273  if (free_size < 10)
274  {
276  return DRIZZLE_RETURN_OK;
277  }
278 
279  if (result->field == NULL)
280  {
281  ptr[0]= 251;
282  ptr++;
283  }
284  else if (result->field_total == 0)
285  {
286  ptr[0]= 0;
287  ptr++;
288  }
289  else
290  ptr= drizzle_pack_length(result->field_total, ptr);
291 
292  free_size-= (size_t)(ptr - start);
293  con->buffer_size+= (size_t)(ptr - start);
294  con->packet_size-= (size_t)(ptr - start);
295  }
296  else if (result->field_size > DRIZZLE_BUFFER_COPY_THRESHOLD)
297  {
298  /* Flush the internal buffer first. */
299  if (con->buffer_size != 0)
300  {
302  return DRIZZLE_RETURN_OK;
303  }
304 
305  /* We do this to write directly from the field buffer to avoid memcpy(). */
306  con->buffer_ptr= (uint8_t *)result->field;
307  con->buffer_size= result->field_size;
308  con->packet_size-= result->field_size;
309  result->field_offset+= result->field_size;
310  result->field= NULL;
311 
312  if (result->field_offset == result->field_total)
313  drizzle_state_pop(con);
314  else if (con->packet_size == 0)
315  {
317  drizzle_state_pop(con);
318  }
319 
321  return DRIZZLE_RETURN_OK;
322  }
323 
324  if (result->field_size == 0)
325  drizzle_state_pop(con);
326  else
327  {
328  if (result->field_size < free_size)
329  free_size= result->field_size;
330 
331  memcpy(ptr, result->field, free_size);
332  result->field_offset+= free_size;
333  con->buffer_size+= free_size;
334  con->packet_size-= free_size;
335 
336  if (result->field_offset == result->field_total)
337  {
338  result->field= NULL;
339  drizzle_state_pop(con);
340  }
341  else
342  {
343  if (con->packet_size == 0)
344  {
346  drizzle_state_pop(con);
347  }
348 
349  if (result->field_size == free_size)
350  result->field= NULL;
351  else
352  {
353  result->field+= free_size;
354  result->field_size-= free_size;
356  }
357  }
358  }
359 
360  return DRIZZLE_RETURN_OK;
361 }