~drizzle-trunk/drizzle/development

2244.1.1 by Monty Taylor
Split libdrizzle into 1.0 and 2.0. Applied the C++ changes to 2.0 branch.
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
2449.1.2 by Brian Aker
Additional fixes for libdrizzle.
42
#include <libdrizzle-2.0/common.h>
2244.1.1 by Monty Taylor
Split libdrizzle into 1.0 and 2.0. Applied the C++ changes to 2.0 branch.
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
  }
98
99
  memcpy(result->field_buffer + offset, field, size);
100
101
  while ((offset + size) != (*total))
102
  {
103
    field= drizzle_field_read(result, &offset, &size, total, ret_ptr);
104
    if (*ret_ptr != DRIZZLE_RETURN_OK)
105
      return NULL;
106
107
    memcpy(result->field_buffer + offset, field, size);
108
  }
109
110
  field= result->field_buffer;
111
  result->field_buffer= NULL;
112
  field[*total]= 0;
113
114
  return field;
115
}
116
117
void drizzle_field_free(drizzle_field_t field)
118
{
2353.3.1 by Mark Atwood
fix cppcheck redundantIfDelete0 warnings. It is safe to deallocate a NULL pointer
119
  delete[] field;
2244.1.1 by Monty Taylor
Split libdrizzle into 1.0 and 2.0. Applied the C++ changes to 2.0 branch.
120
}
121
122
/*
123
 * Server definitions
124
 */
125
126
drizzle_return_t drizzle_field_write(drizzle_result_st *result,
127
                                     const drizzle_field_t field, size_t size,
128
                                     size_t total)
129
{
130
  drizzle_return_t ret;
131
132
  if (drizzle_state_none(result->con))
133
  {
134
    if (result->options & DRIZZLE_RESULT_ROW_BREAK)
135
    {
136
      result->options&= ~DRIZZLE_RESULT_ROW_BREAK;
137
      result->field= field;
138
      result->field_size= size;
139
    }
140
    else
141
    {
142
      result->field= field;
143
      result->field_size= size;
144
      result->field_offset= 0;
145
      result->field_total= total;
146
    }
147
148
    drizzle_state_push(result->con, drizzle_state_field_write);
149
  }
150
  else if (result->field == NULL)
151
  {
152
    result->field= field;
153
    result->field_size= size;
154
  }
155
156
  ret= drizzle_state_loop(result->con);
157
  if (ret == DRIZZLE_RETURN_PAUSE)
158
    ret= DRIZZLE_RETURN_OK;
159
160
  return ret;
161
}
162
163
/*
164
 * Internal state functions.
165
 */
166
167
drizzle_return_t drizzle_state_field_read(drizzle_con_st *con)
168
{
169
  drizzle_return_t ret;
170
171
  drizzle_log_debug(con->drizzle, "drizzle_state_field_read");
172
173
  if (con->buffer_size == 0)
174
  {
175
    drizzle_state_push(con, drizzle_state_read);
176
    return DRIZZLE_RETURN_OK;
177
  }
178
179
  con->result->field_offset+= con->result->field_size;
180
  if (con->result->field_offset == con->result->field_total)
181
  {
182
    con->result->field_offset= 0;
183
    con->result->field_size= 0;
184
185
    con->result->field_total= (size_t)drizzle_unpack_length(con, &ret);
186
    if (ret == DRIZZLE_RETURN_NULL_SIZE)
187
    {
188
      con->result->field= NULL;
189
      con->result->field_current++;
190
      drizzle_state_pop(con);
191
      return DRIZZLE_RETURN_OK;
192
    }
193
    else if (ret != DRIZZLE_RETURN_OK)
194
    {
195
      if (ret == DRIZZLE_RETURN_IO_WAIT)
196
      {
197
        drizzle_state_push(con, drizzle_state_read);
198
        return DRIZZLE_RETURN_OK;
199
      }
200
201
      return ret;
202
    }
203
204
    drizzle_log_debug(con->drizzle,
205
                      "field_offset= %zu, field_size= %zu, field_total= %zu",
206
                      con->result->field_offset, con->result->field_size,
207
                      con->result->field_total);
208
209
    if ((size_t)(con->buffer_size) >= con->result->field_total)
210
      con->result->field_size= con->result->field_total;
211
    else
212
      con->result->field_size= con->buffer_size;
213
  }
214
  else
215
  {
216
    if ((con->result->field_offset + con->buffer_size) >=
217
        con->result->field_total)
218
    {
219
      con->result->field_size= (con->result->field_total -
220
                                con->result->field_offset);
221
    }
222
    else
223
      con->result->field_size= con->buffer_size;
224
  }
225
226
  /* This is a special case when a row is larger than the packet size. */
227
  if (con->result->field_size > (size_t)con->packet_size)
228
  {
229
    con->result->field_size= con->packet_size;
230
231
    if (con->options & DRIZZLE_CON_RAW_PACKET)
232
      con->result->options|= DRIZZLE_RESULT_ROW_BREAK;
233
    else
234
    {
235
      drizzle_state_pop(con);
236
      drizzle_state_push(con, drizzle_state_packet_read);
237
      drizzle_state_push(con, drizzle_state_field_read);
238
    }
239
  }
240
241
  con->result->field= (char *)con->buffer_ptr;
242
  con->buffer_ptr+= con->result->field_size;
243
  con->buffer_size-= con->result->field_size;
244
  con->packet_size-= con->result->field_size;
245
246
  drizzle_log_debug(con->drizzle,
247
                    "field_offset= %zu, field_size= %zu, field_total= %zu",
248
                    con->result->field_offset, con->result->field_size,
249
                    con->result->field_total);
250
251
  if ((con->result->field_offset + con->result->field_size) ==
252
      con->result->field_total)
253
  {
254
    if (con->result->column_buffer != NULL &&
255
        con->result->column_buffer[con->result->field_current].max_size <
256
        con->result->field_total)
257
    {
258
      con->result->column_buffer[con->result->field_current].max_size=
259
                                                       con->result->field_total;
260
    }
261
262
    con->result->field_current++;
263
  }
264
265
  if (con->result->field_total == 0 || con->result->field_size > 0 ||
266
      con->packet_size == 0)
267
  {
268
    drizzle_state_pop(con);
269
  }
270
271
  return DRIZZLE_RETURN_OK;
272
}
273
274
drizzle_return_t drizzle_state_field_write(drizzle_con_st *con)
275
{
276
  uint8_t *start= con->buffer_ptr + con->buffer_size;
277
  uint8_t *ptr;
278
  size_t free_size;
279
  drizzle_result_st *result= con->result;
280
281
  drizzle_log_debug(con->drizzle, "drizzle_state_field_write");
282
283
  if (result->field == NULL && result->field_total != 0)
284
    return DRIZZLE_RETURN_PAUSE;
285
286
  free_size= (size_t)DRIZZLE_MAX_BUFFER_SIZE - (size_t)(start - con->buffer);
287
  ptr= start;
288
289
  if (result->field_offset == 0)
290
  {
291
    /* Make sure we can fit the max length and 1 byte of data in (9 + 1). */
292
    if (free_size < 10)
293
    {
294
      drizzle_state_push(con, drizzle_state_write);
295
      return DRIZZLE_RETURN_OK;
296
    }
297
298
    if (result->field == NULL)
299
    {
300
      ptr[0]= 251;
301
      ptr++;
302
    }
303
    else if (result->field_total == 0)
304
    {
305
      ptr[0]= 0;
306
      ptr++;
307
    }
308
    else
309
      ptr= drizzle_pack_length(result->field_total, ptr);
310
311
    free_size-= (size_t)(ptr - start);
312
    con->buffer_size+= (size_t)(ptr - start);
313
    con->packet_size-= (size_t)(ptr - start);
314
  }
315
  else if (result->field_size > DRIZZLE_BUFFER_COPY_THRESHOLD)
316
  {
317
    /* Flush the internal buffer first. */
318
    if (con->buffer_size != 0)
319
    {
320
      drizzle_state_push(con, drizzle_state_write);
321
      return DRIZZLE_RETURN_OK;
322
    }
323
324
    /* We do this to write directly from the field buffer to avoid memcpy(). */
325
    con->buffer_ptr= (uint8_t *)result->field;
326
    con->buffer_size= result->field_size;
327
    con->packet_size-= result->field_size;
328
    result->field_offset+= result->field_size;
329
    result->field= NULL;
330
331
    if (result->field_offset == result->field_total)
332
      drizzle_state_pop(con);
333
    else if (con->packet_size == 0)
334
    {
335
      con->result->options|= DRIZZLE_RESULT_ROW_BREAK;
336
      drizzle_state_pop(con);
337
    }
338
339
    drizzle_state_push(con, drizzle_state_write);
340
    return DRIZZLE_RETURN_OK;
341
  }
342
343
  if (result->field_size == 0)
344
    drizzle_state_pop(con);
345
  else
346
  {
347
    if (result->field_size < free_size)
348
      free_size= result->field_size;
349
350
    memcpy(ptr, result->field, free_size);
351
    result->field_offset+= free_size;
352
    con->buffer_size+= free_size;
353
    con->packet_size-= free_size;
354
355
    if (result->field_offset == result->field_total)
356
    {
357
      result->field= NULL;
358
      drizzle_state_pop(con);
359
    }
360
    else
361
    {
362
      if (con->packet_size == 0)
363
      {
364
        con->result->options|= DRIZZLE_RESULT_ROW_BREAK;
365
        drizzle_state_pop(con);
366
      }
367
368
      if (result->field_size == free_size)
369
        result->field= NULL;
370
      else
371
      {
372
        result->field+= free_size;
373
        result->field_size-= free_size;
374
        drizzle_state_push(con, drizzle_state_write);
375
      }
376
    }
377
  }
378
379
  return DRIZZLE_RETURN_OK;
380
}