~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
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
  {
1992.6.7 by Monty Taylor
Revert -Wc++-compat change.
96
    result->field_buffer= 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
{
125
  if (field != NULL)
126
    free(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_options_t)~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
}