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