~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to libdrizzle/field.c

  • Committer: Monty Taylor
  • Date: 2008-11-16 06:29:53 UTC
  • mto: (584.1.9 devel)
  • mto: This revision was merged to the branch mainline in revision 589.
  • Revision ID: monty@inaugust.com-20081116062953-ivdltjmfe009b5fr
Moved stuff into item/

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
 
}