~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to libdrizzle/field.c

Added libdrizzle to the tree.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
 
 
11
/**
 
12
 * @file
 
13
 * @brief Field definitions
 
14
 */
 
15
 
 
16
#include "common.h"
 
17
 
 
18
/*
 
19
 * Client definitions
 
20
 */
 
21
 
 
22
drizzle_field_t drizzle_field_read(drizzle_result_st *result, size_t *offset,
 
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
 
 
34
    drizzle_state_push(result->con, drizzle_state_field_read);
 
35
  }
 
36
 
 
37
  *ret_ptr= drizzle_state_loop(result->con);
 
38
  if (*ret_ptr == DRIZZLE_RETURN_OK &&
 
39
      result->options & DRIZZLE_RESULT_ROW_BREAK)
 
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
 
 
51
drizzle_field_t drizzle_field_buffer(drizzle_result_st *result, size_t *total,
 
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
 
 
97
void drizzle_field_free(drizzle_field_t field)
 
98
{
 
99
  if (field != NULL)
 
100
    free(field);
 
101
}
 
102
 
 
103
/*
 
104
 * Server definitions
 
105
 */
 
106
 
 
107
drizzle_return_t drizzle_field_write(drizzle_result_st *result,
 
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
    {
 
117
      result->options&= (drizzle_result_options_t)~DRIZZLE_RESULT_ROW_BREAK;
 
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
 
 
129
    drizzle_state_push(result->con, drizzle_state_field_write);
 
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
 
 
148
drizzle_return_t drizzle_state_field_read(drizzle_con_st *con)
 
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
  {
 
156
    drizzle_state_push(con, drizzle_state_read);
 
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
      {
 
178
        drizzle_state_push(con, drizzle_state_read);
 
179
        return DRIZZLE_RETURN_OK;
 
180
      }
 
181
 
 
182
      return ret;
 
183
    }
 
184
 
 
185
    drizzle_log_debug(con->drizzle,
 
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)
 
213
      con->result->options|= DRIZZLE_RESULT_ROW_BREAK;
 
214
    else
 
215
    {
 
216
      drizzle_state_pop(con);
 
217
      drizzle_state_push(con, drizzle_state_packet_read);
 
218
      drizzle_state_push(con, drizzle_state_field_read);
 
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
 
 
227
  drizzle_log_debug(con->drizzle,
 
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 &&
 
236
        con->result->column_buffer[con->result->field_current].max_size <
 
237
        con->result->field_total)
 
238
    {
 
239
      con->result->column_buffer[con->result->field_current].max_size=
 
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
 
 
255
drizzle_return_t drizzle_state_field_write(drizzle_con_st *con)
 
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
    {
 
275
      drizzle_state_push(con, drizzle_state_write);
 
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
    {
 
301
      drizzle_state_push(con, drizzle_state_write);
 
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
    {
 
316
      con->result->options|= DRIZZLE_RESULT_ROW_BREAK;
 
317
      drizzle_state_pop(con);
 
318
    }
 
319
 
 
320
    drizzle_state_push(con, drizzle_state_write);
 
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
      {
 
345
        con->result->options|= DRIZZLE_RESULT_ROW_BREAK;
 
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;
 
355
        drizzle_state_push(con, drizzle_state_write);
 
356
      }
 
357
    }
 
358
  }
 
359
 
 
360
  return DRIZZLE_RETURN_OK;
 
361
}