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