~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to libdrizzle-2.0/libdrizzle/field.cc

  • Committer: Monty Taylor
  • Date: 2011-03-22 18:39:54 UTC
  • mto: (2246.1.1 build)
  • mto: This revision was merged to the branch mainline in revision 2247.
  • Revision ID: mordred@inaugust.com-20110322183954-fz8ciuywjz2llbyo
Split libdrizzle into 1.0 and 2.0. Applied the C++ changes to 2.0 branch.

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
 * Redistribution and use in source and binary forms, with or without
 
8
 * modification, are permitted provided that the following conditions are
 
9
 * met:
 
10
 *
 
11
 *     * Redistributions of source code must retain the above copyright
 
12
 * notice, this list of conditions and the following disclaimer.
 
13
 *
 
14
 *     * Redistributions in binary form must reproduce the above
 
15
 * copyright notice, this list of conditions and the following disclaimer
 
16
 * in the documentation and/or other materials provided with the
 
17
 * distribution.
 
18
 *
 
19
 *     * The names of its contributors may not be used to endorse or
 
20
 * promote products derived from this software without specific prior
 
21
 * written permission.
 
22
 *
 
23
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 
24
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 
25
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 
26
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 
27
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 
28
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 
29
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 
30
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 
31
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 
32
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 
33
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
34
 *
 
35
 */
 
36
 
 
37
/**
 
38
 * @file
 
39
 * @brief Field definitions
 
40
 */
 
41
 
 
42
#include "common.h"
 
43
 
 
44
/*
 
45
 * Client definitions
 
46
 */
 
47
 
 
48
drizzle_field_t drizzle_field_read(drizzle_result_st *result, size_t *offset,
 
49
                                   size_t *size, size_t *total,
 
50
                                   drizzle_return_t *ret_ptr)
 
51
{
 
52
  if (drizzle_state_none(result->con))
 
53
  {
 
54
    if (result->field_current == result->column_count)
 
55
    {
 
56
      *ret_ptr= DRIZZLE_RETURN_ROW_END;
 
57
      return NULL;
 
58
    }
 
59
 
 
60
    drizzle_state_push(result->con, drizzle_state_field_read);
 
61
  }
 
62
 
 
63
  *ret_ptr= drizzle_state_loop(result->con);
 
64
  if (*ret_ptr == DRIZZLE_RETURN_OK &&
 
65
      result->options & DRIZZLE_RESULT_ROW_BREAK)
 
66
  {
 
67
    *ret_ptr= DRIZZLE_RETURN_ROW_BREAK;
 
68
  }
 
69
 
 
70
  *offset= result->field_offset;
 
71
  *size= result->field_size;
 
72
  *total= result->field_total;
 
73
 
 
74
  return result->field;
 
75
}
 
76
 
 
77
drizzle_field_t drizzle_field_buffer(drizzle_result_st *result, size_t *total,
 
78
                                     drizzle_return_t *ret_ptr)
 
79
{
 
80
  drizzle_field_t field;
 
81
  size_t offset= 0;
 
82
  size_t size= 0;
 
83
 
 
84
  field= drizzle_field_read(result, &offset, &size, total, ret_ptr);
 
85
  if (*ret_ptr != DRIZZLE_RETURN_OK)
 
86
    return NULL;
 
87
 
 
88
  if (field == NULL)
 
89
  {
 
90
    *total= 0;
 
91
    return NULL;
 
92
  }
 
93
 
 
94
  if (result->field_buffer == NULL)
 
95
  {
 
96
    result->field_buffer= new drizzle_field_t_type[(*total) + 1];
 
97
    if (result->field_buffer == NULL)
 
98
    {
 
99
      drizzle_set_error(result->con->drizzle, "drizzle_field_buffer", "malloc");
 
100
      *ret_ptr= DRIZZLE_RETURN_MEMORY;
 
101
      return NULL;
 
102
    }
 
103
  }
 
104
 
 
105
  memcpy(result->field_buffer + offset, field, size);
 
106
 
 
107
  while ((offset + size) != (*total))
 
108
  {
 
109
    field= drizzle_field_read(result, &offset, &size, total, ret_ptr);
 
110
    if (*ret_ptr != DRIZZLE_RETURN_OK)
 
111
      return NULL;
 
112
 
 
113
    memcpy(result->field_buffer + offset, field, size);
 
114
  }
 
115
 
 
116
  field= result->field_buffer;
 
117
  result->field_buffer= NULL;
 
118
  field[*total]= 0;
 
119
 
 
120
  return field;
 
121
}
 
122
 
 
123
void drizzle_field_free(drizzle_field_t field)
 
124
{
 
125
  if (field != NULL)
 
126
    delete[] field;
 
127
}
 
128
 
 
129
/*
 
130
 * Server definitions
 
131
 */
 
132
 
 
133
drizzle_return_t drizzle_field_write(drizzle_result_st *result,
 
134
                                     const drizzle_field_t field, size_t size,
 
135
                                     size_t total)
 
136
{
 
137
  drizzle_return_t ret;
 
138
 
 
139
  if (drizzle_state_none(result->con))
 
140
  {
 
141
    if (result->options & DRIZZLE_RESULT_ROW_BREAK)
 
142
    {
 
143
      result->options&= ~DRIZZLE_RESULT_ROW_BREAK;
 
144
      result->field= field;
 
145
      result->field_size= size;
 
146
    }
 
147
    else
 
148
    {
 
149
      result->field= field;
 
150
      result->field_size= size;
 
151
      result->field_offset= 0;
 
152
      result->field_total= total;
 
153
    }
 
154
 
 
155
    drizzle_state_push(result->con, drizzle_state_field_write);
 
156
  }
 
157
  else if (result->field == NULL)
 
158
  {
 
159
    result->field= field;
 
160
    result->field_size= size;
 
161
  }
 
162
 
 
163
  ret= drizzle_state_loop(result->con);
 
164
  if (ret == DRIZZLE_RETURN_PAUSE)
 
165
    ret= DRIZZLE_RETURN_OK;
 
166
 
 
167
  return ret;
 
168
}
 
169
 
 
170
/*
 
171
 * Internal state functions.
 
172
 */
 
173
 
 
174
drizzle_return_t drizzle_state_field_read(drizzle_con_st *con)
 
175
{
 
176
  drizzle_return_t ret;
 
177
 
 
178
  drizzle_log_debug(con->drizzle, "drizzle_state_field_read");
 
179
 
 
180
  if (con->buffer_size == 0)
 
181
  {
 
182
    drizzle_state_push(con, drizzle_state_read);
 
183
    return DRIZZLE_RETURN_OK;
 
184
  }
 
185
 
 
186
  con->result->field_offset+= con->result->field_size;
 
187
  if (con->result->field_offset == con->result->field_total)
 
188
  {
 
189
    con->result->field_offset= 0;
 
190
    con->result->field_size= 0;
 
191
 
 
192
    con->result->field_total= (size_t)drizzle_unpack_length(con, &ret);
 
193
    if (ret == DRIZZLE_RETURN_NULL_SIZE)
 
194
    {
 
195
      con->result->field= NULL;
 
196
      con->result->field_current++;
 
197
      drizzle_state_pop(con);
 
198
      return DRIZZLE_RETURN_OK;
 
199
    }
 
200
    else if (ret != DRIZZLE_RETURN_OK)
 
201
    {
 
202
      if (ret == DRIZZLE_RETURN_IO_WAIT)
 
203
      {
 
204
        drizzle_state_push(con, drizzle_state_read);
 
205
        return DRIZZLE_RETURN_OK;
 
206
      }
 
207
 
 
208
      return ret;
 
209
    }
 
210
 
 
211
    drizzle_log_debug(con->drizzle,
 
212
                      "field_offset= %zu, field_size= %zu, field_total= %zu",
 
213
                      con->result->field_offset, con->result->field_size,
 
214
                      con->result->field_total);
 
215
 
 
216
    if ((size_t)(con->buffer_size) >= con->result->field_total)
 
217
      con->result->field_size= con->result->field_total;
 
218
    else
 
219
      con->result->field_size= con->buffer_size;
 
220
  }
 
221
  else
 
222
  {
 
223
    if ((con->result->field_offset + con->buffer_size) >=
 
224
        con->result->field_total)
 
225
    {
 
226
      con->result->field_size= (con->result->field_total -
 
227
                                con->result->field_offset);
 
228
    }
 
229
    else
 
230
      con->result->field_size= con->buffer_size;
 
231
  }
 
232
 
 
233
  /* This is a special case when a row is larger than the packet size. */
 
234
  if (con->result->field_size > (size_t)con->packet_size)
 
235
  {
 
236
    con->result->field_size= con->packet_size;
 
237
 
 
238
    if (con->options & DRIZZLE_CON_RAW_PACKET)
 
239
      con->result->options|= DRIZZLE_RESULT_ROW_BREAK;
 
240
    else
 
241
    {
 
242
      drizzle_state_pop(con);
 
243
      drizzle_state_push(con, drizzle_state_packet_read);
 
244
      drizzle_state_push(con, drizzle_state_field_read);
 
245
    }
 
246
  }
 
247
 
 
248
  con->result->field= (char *)con->buffer_ptr;
 
249
  con->buffer_ptr+= con->result->field_size;
 
250
  con->buffer_size-= con->result->field_size;
 
251
  con->packet_size-= con->result->field_size;
 
252
 
 
253
  drizzle_log_debug(con->drizzle,
 
254
                    "field_offset= %zu, field_size= %zu, field_total= %zu",
 
255
                    con->result->field_offset, con->result->field_size,
 
256
                    con->result->field_total);
 
257
 
 
258
  if ((con->result->field_offset + con->result->field_size) ==
 
259
      con->result->field_total)
 
260
  {
 
261
    if (con->result->column_buffer != NULL &&
 
262
        con->result->column_buffer[con->result->field_current].max_size <
 
263
        con->result->field_total)
 
264
    {
 
265
      con->result->column_buffer[con->result->field_current].max_size=
 
266
                                                       con->result->field_total;
 
267
    }
 
268
 
 
269
    con->result->field_current++;
 
270
  }
 
271
 
 
272
  if (con->result->field_total == 0 || con->result->field_size > 0 ||
 
273
      con->packet_size == 0)
 
274
  {
 
275
    drizzle_state_pop(con);
 
276
  }
 
277
 
 
278
  return DRIZZLE_RETURN_OK;
 
279
}
 
280
 
 
281
drizzle_return_t drizzle_state_field_write(drizzle_con_st *con)
 
282
{
 
283
  uint8_t *start= con->buffer_ptr + con->buffer_size;
 
284
  uint8_t *ptr;
 
285
  size_t free_size;
 
286
  drizzle_result_st *result= con->result;
 
287
 
 
288
  drizzle_log_debug(con->drizzle, "drizzle_state_field_write");
 
289
 
 
290
  if (result->field == NULL && result->field_total != 0)
 
291
    return DRIZZLE_RETURN_PAUSE;
 
292
 
 
293
  free_size= (size_t)DRIZZLE_MAX_BUFFER_SIZE - (size_t)(start - con->buffer);
 
294
  ptr= start;
 
295
 
 
296
  if (result->field_offset == 0)
 
297
  {
 
298
    /* Make sure we can fit the max length and 1 byte of data in (9 + 1). */
 
299
    if (free_size < 10)
 
300
    {
 
301
      drizzle_state_push(con, drizzle_state_write);
 
302
      return DRIZZLE_RETURN_OK;
 
303
    }
 
304
 
 
305
    if (result->field == NULL)
 
306
    {
 
307
      ptr[0]= 251;
 
308
      ptr++;
 
309
    }
 
310
    else if (result->field_total == 0)
 
311
    {
 
312
      ptr[0]= 0;
 
313
      ptr++;
 
314
    }
 
315
    else
 
316
      ptr= drizzle_pack_length(result->field_total, ptr);
 
317
 
 
318
    free_size-= (size_t)(ptr - start);
 
319
    con->buffer_size+= (size_t)(ptr - start);
 
320
    con->packet_size-= (size_t)(ptr - start);
 
321
  }
 
322
  else if (result->field_size > DRIZZLE_BUFFER_COPY_THRESHOLD)
 
323
  {
 
324
    /* Flush the internal buffer first. */
 
325
    if (con->buffer_size != 0)
 
326
    {
 
327
      drizzle_state_push(con, drizzle_state_write);
 
328
      return DRIZZLE_RETURN_OK;
 
329
    }
 
330
 
 
331
    /* We do this to write directly from the field buffer to avoid memcpy(). */
 
332
    con->buffer_ptr= (uint8_t *)result->field;
 
333
    con->buffer_size= result->field_size;
 
334
    con->packet_size-= result->field_size;
 
335
    result->field_offset+= result->field_size;
 
336
    result->field= NULL;
 
337
 
 
338
    if (result->field_offset == result->field_total)
 
339
      drizzle_state_pop(con);
 
340
    else if (con->packet_size == 0)
 
341
    {
 
342
      con->result->options|= DRIZZLE_RESULT_ROW_BREAK;
 
343
      drizzle_state_pop(con);
 
344
    }
 
345
 
 
346
    drizzle_state_push(con, drizzle_state_write);
 
347
    return DRIZZLE_RETURN_OK;
 
348
  }
 
349
 
 
350
  if (result->field_size == 0)
 
351
    drizzle_state_pop(con);
 
352
  else
 
353
  {
 
354
    if (result->field_size < free_size)
 
355
      free_size= result->field_size;
 
356
 
 
357
    memcpy(ptr, result->field, free_size);
 
358
    result->field_offset+= free_size;
 
359
    con->buffer_size+= free_size;
 
360
    con->packet_size-= free_size;
 
361
 
 
362
    if (result->field_offset == result->field_total)
 
363
    {
 
364
      result->field= NULL;
 
365
      drizzle_state_pop(con);
 
366
    }
 
367
    else
 
368
    {
 
369
      if (con->packet_size == 0)
 
370
      {
 
371
        con->result->options|= DRIZZLE_RESULT_ROW_BREAK;
 
372
        drizzle_state_pop(con);
 
373
      }
 
374
 
 
375
      if (result->field_size == free_size)
 
376
        result->field= NULL;
 
377
      else
 
378
      {
 
379
        result->field+= free_size;
 
380
        result->field_size-= free_size;
 
381
        drizzle_state_push(con, drizzle_state_write);
 
382
      }
 
383
    }
 
384
  }
 
385
 
 
386
  return DRIZZLE_RETURN_OK;
 
387
}