~drizzle-trunk/drizzle/development

1712.1.1 by Monty Taylor
Merged libdrizzle directly into tree.
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
}