~ubuntu-branches/ubuntu/trusty/drizzle/trusty

« back to all changes in this revision

Viewing changes to libdrizzle/result.c

  • Committer: Package Import Robot
  • Author(s): Clint Byrum
  • Date: 2012-06-19 10:46:49 UTC
  • mfrom: (1.1.6)
  • mto: This revision was merged to the branch mainline in revision 29.
  • Revision ID: package-import@ubuntu.com-20120619104649-e2l0ggd4oz3um0f4
Tags: upstream-7.1.36-stable
ImportĀ upstreamĀ versionĀ 7.1.36-stable

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 Result definitions
40
 
 */
41
 
 
42
 
#include "common.h"
43
 
 
44
 
/*
45
 
 * Common definitions
46
 
 */
47
 
 
48
 
drizzle_result_st *drizzle_result_create(drizzle_con_st *con,
49
 
                                         drizzle_result_st *result)
50
 
{
51
 
  if (result == NULL)
52
 
  {
53
 
    result= malloc(sizeof(drizzle_result_st));
54
 
    if (result == NULL)
55
 
    {
56
 
      drizzle_set_error(con->drizzle, "drizzle_result_create", "malloc");
57
 
      return NULL;
58
 
    }
59
 
 
60
 
    memset(result, 0, sizeof(drizzle_result_st));
61
 
    result->options|= DRIZZLE_RESULT_ALLOCATED;
62
 
  }
63
 
  else
64
 
    memset(result, 0, sizeof(drizzle_result_st));
65
 
 
66
 
  result->con= con;
67
 
  con->result= result;
68
 
 
69
 
  if (con->result_list)
70
 
    con->result_list->prev= result;
71
 
  result->next= con->result_list;
72
 
  con->result_list= result;
73
 
  con->result_count++;
74
 
 
75
 
  return result;
76
 
}
77
 
 
78
 
drizzle_result_st *drizzle_result_clone(drizzle_con_st *con,
79
 
                                        drizzle_result_st *result,
80
 
                                        drizzle_result_st *from)
81
 
{
82
 
  result= drizzle_result_create(con, result);
83
 
  if (result == NULL)
84
 
    return NULL;
85
 
 
86
 
  result->options|= (from->options &
87
 
                     (drizzle_result_options_t)~DRIZZLE_RESULT_ALLOCATED);
88
 
 
89
 
  drizzle_result_set_info(result, from->info);
90
 
  result->error_code= from->error_code;
91
 
  drizzle_result_set_sqlstate(result, from->sqlstate);
92
 
  result->warning_count= from->warning_count;
93
 
  result->insert_id= from->insert_id;
94
 
  result->affected_rows= from->affected_rows;
95
 
  result->column_count= from->column_count;
96
 
  result->row_count= from->row_count;
97
 
 
98
 
  return result;
99
 
}
100
 
 
101
 
void drizzle_result_free(drizzle_result_st *result)
102
 
{
103
 
  drizzle_column_st *column;
104
 
  uint64_t x;
105
 
 
106
 
  for (column= result->column_list; column != NULL; column= result->column_list)
107
 
    drizzle_column_free(column);
108
 
 
109
 
  if (result->column_buffer != NULL)
110
 
    free(result->column_buffer);
111
 
 
112
 
  if (result->options & DRIZZLE_RESULT_BUFFER_ROW)
113
 
  {
114
 
    for (x= 0; x < result->row_count; x++)
115
 
      drizzle_row_free(result, result->row_list[x]);
116
 
 
117
 
    free(result->row_list);
118
 
    free(result->field_sizes_list);
119
 
  }
120
 
 
121
 
  if (result->con)
122
 
  {
123
 
    result->con->result_count--;
124
 
    if (result->con->result_list == result)
125
 
      result->con->result_list= result->next;
126
 
  }
127
 
  if (result->prev)
128
 
    result->prev->next= result->next;
129
 
  if (result->next)
130
 
    result->next->prev= result->prev;
131
 
 
132
 
  if (result->options & DRIZZLE_RESULT_ALLOCATED)
133
 
    free(result);
134
 
}
135
 
 
136
 
void drizzle_result_free_all(drizzle_con_st *con)
137
 
{
138
 
  while (con->result_list != NULL)
139
 
    drizzle_result_free(con->result_list);
140
 
}
141
 
 
142
 
drizzle_con_st *drizzle_result_drizzle_con(drizzle_result_st *result)
143
 
{
144
 
  return result->con;
145
 
}
146
 
 
147
 
bool drizzle_result_eof(drizzle_result_st *result)
148
 
{
149
 
  return result->options & DRIZZLE_RESULT_EOF_PACKET;
150
 
}
151
 
 
152
 
const char *drizzle_result_info(drizzle_result_st *result)
153
 
{
154
 
  return result->info;
155
 
}
156
 
 
157
 
const char *drizzle_result_error(drizzle_result_st *result)
158
 
{
159
 
  return result->info;
160
 
}
161
 
 
162
 
uint16_t drizzle_result_error_code(drizzle_result_st *result)
163
 
{
164
 
  return result->error_code;
165
 
}
166
 
 
167
 
const char *drizzle_result_sqlstate(drizzle_result_st *result)
168
 
{
169
 
  return result->sqlstate;
170
 
}
171
 
 
172
 
uint16_t drizzle_result_warning_count(drizzle_result_st *result)
173
 
{
174
 
  return result->warning_count;
175
 
}
176
 
 
177
 
uint64_t drizzle_result_insert_id(drizzle_result_st *result)
178
 
{
179
 
  return result->insert_id;
180
 
}
181
 
 
182
 
uint64_t drizzle_result_affected_rows(drizzle_result_st *result)
183
 
{
184
 
  return result->affected_rows;
185
 
}
186
 
 
187
 
uint16_t drizzle_result_column_count(drizzle_result_st *result)
188
 
{
189
 
  return result->column_count;
190
 
}
191
 
 
192
 
uint64_t drizzle_result_row_count(drizzle_result_st *result)
193
 
{
194
 
  return result->row_count;
195
 
}
196
 
 
197
 
/*
198
 
 * Client definitions
199
 
 */
200
 
 
201
 
drizzle_result_st *drizzle_result_read(drizzle_con_st *con,
202
 
                                       drizzle_result_st *result,
203
 
                                       drizzle_return_t *ret_ptr)
204
 
{
205
 
  if (drizzle_state_none(con))
206
 
  {
207
 
    con->result= drizzle_result_create(con, result);
208
 
    if (con->result == NULL)
209
 
    {
210
 
      *ret_ptr= DRIZZLE_RETURN_MEMORY;
211
 
      return NULL;
212
 
    }
213
 
 
214
 
    drizzle_state_push(con, drizzle_state_result_read);
215
 
    drizzle_state_push(con, drizzle_state_packet_read);
216
 
  }
217
 
 
218
 
  *ret_ptr= drizzle_state_loop(con);
219
 
  return con->result;
220
 
}
221
 
 
222
 
drizzle_return_t drizzle_result_buffer(drizzle_result_st *result)
223
 
{
224
 
  drizzle_return_t ret;
225
 
  drizzle_row_t row;
226
 
  drizzle_row_t *row_list;
227
 
  size_t **field_sizes_list;
228
 
 
229
 
  if (!(result->options & DRIZZLE_RESULT_BUFFER_COLUMN))
230
 
  {
231
 
    ret= drizzle_column_buffer(result);
232
 
    if (ret != DRIZZLE_RETURN_OK)
233
 
      return ret;
234
 
  }
235
 
 
236
 
  if (result->column_count == 0)
237
 
  {
238
 
    result->options|= DRIZZLE_RESULT_BUFFER_ROW;
239
 
    return DRIZZLE_RETURN_OK;
240
 
  }
241
 
 
242
 
  while (1)
243
 
  {
244
 
    row= drizzle_row_buffer(result, &ret);
245
 
    if (ret != DRIZZLE_RETURN_OK)
246
 
      return ret;
247
 
 
248
 
    if (row == NULL)
249
 
      break;
250
 
 
251
 
    if (result->row_list_size < result->row_count)
252
 
    {
253
 
      row_list= realloc(result->row_list, sizeof(drizzle_row_t) *
254
 
                        ((size_t)(result->row_list_size) +
255
 
                         DRIZZLE_ROW_GROW_SIZE));
256
 
      if (row_list == NULL)
257
 
      {
258
 
        drizzle_row_free(result, row);
259
 
        drizzle_set_error(result->con->drizzle, "drizzle_result_buffer",
260
 
                          "realloc");
261
 
        return DRIZZLE_RETURN_MEMORY;
262
 
      }
263
 
 
264
 
      result->row_list= row_list;
265
 
 
266
 
      field_sizes_list= realloc(result->field_sizes_list, sizeof(size_t *) *
267
 
                                ((size_t)(result->row_list_size) +
268
 
                                 DRIZZLE_ROW_GROW_SIZE));
269
 
      if (field_sizes_list == NULL)
270
 
      {
271
 
        drizzle_row_free(result, row);
272
 
        drizzle_set_error(result->con->drizzle, "drizzle_result_buffer",
273
 
                          "realloc");
274
 
        return DRIZZLE_RETURN_MEMORY;
275
 
      }
276
 
 
277
 
      result->field_sizes_list= field_sizes_list;
278
 
 
279
 
      result->row_list_size+= DRIZZLE_ROW_GROW_SIZE;
280
 
    }
281
 
 
282
 
    result->row_list[result->row_current - 1]= row;
283
 
    result->field_sizes_list[result->row_current - 1]= result->field_sizes;
284
 
  }
285
 
 
286
 
  result->options|= DRIZZLE_RESULT_BUFFER_ROW;
287
 
  return DRIZZLE_RETURN_OK;
288
 
}
289
 
 
290
 
size_t drizzle_result_row_size(drizzle_result_st *result)
291
 
{
292
 
  return result->con->packet_size;
293
 
}
294
 
 
295
 
/*
296
 
 * Server definitions
297
 
 */
298
 
 
299
 
drizzle_return_t drizzle_result_write(drizzle_con_st *con,
300
 
                                      drizzle_result_st *result, bool flush)
301
 
{
302
 
  if (drizzle_state_none(con))
303
 
  {
304
 
    con->result= result;
305
 
 
306
 
    if (flush)
307
 
      drizzle_state_push(con, drizzle_state_write);
308
 
 
309
 
    drizzle_state_push(con, drizzle_state_result_write);
310
 
  }
311
 
 
312
 
  return drizzle_state_loop(con);
313
 
}
314
 
 
315
 
void drizzle_result_set_row_size(drizzle_result_st *result, size_t size)
316
 
{
317
 
  result->con->packet_size= size;
318
 
}
319
 
 
320
 
void drizzle_result_calc_row_size(drizzle_result_st *result,
321
 
                                  const drizzle_field_t *field,
322
 
                                  const size_t *size)
323
 
{
324
 
  uint16_t x;
325
 
 
326
 
  result->con->packet_size= 0;
327
 
 
328
 
  for (x= 0; x < result->column_count; x++)
329
 
  {
330
 
    if (field[x] == NULL)
331
 
      result->con->packet_size++;
332
 
    else if (size[x] < 251)
333
 
      result->con->packet_size+= (1 + size[x]);
334
 
    else if (size[x] < 65536)
335
 
      result->con->packet_size+= (3 + size[x]);
336
 
    else if (size[x] < 16777216)
337
 
      result->con->packet_size+= (4 + size[x]);
338
 
    else
339
 
      result->con->packet_size+= (9 + size[x]);
340
 
  }
341
 
}
342
 
 
343
 
void drizzle_result_set_eof(drizzle_result_st *result, bool is_eof)
344
 
{
345
 
  if (is_eof)
346
 
    result->options|= DRIZZLE_RESULT_EOF_PACKET;
347
 
  else
348
 
    result->options&= (drizzle_result_options_t)~DRIZZLE_RESULT_EOF_PACKET;
349
 
}
350
 
 
351
 
void drizzle_result_set_info(drizzle_result_st *result, const char *info)
352
 
{
353
 
  if (info == NULL)
354
 
    result->info[0]= 0;
355
 
  else
356
 
  {
357
 
    strncpy(result->info, info, DRIZZLE_MAX_INFO_SIZE);
358
 
    result->info[DRIZZLE_MAX_INFO_SIZE - 1]= 0;
359
 
  }
360
 
}
361
 
 
362
 
void drizzle_result_set_error(drizzle_result_st *result, const char *error)
363
 
{
364
 
  drizzle_result_set_info(result, error);
365
 
}
366
 
 
367
 
void drizzle_result_set_error_code(drizzle_result_st *result,
368
 
                                   uint16_t error_code)
369
 
{
370
 
  result->error_code= error_code;
371
 
}
372
 
 
373
 
void drizzle_result_set_sqlstate(drizzle_result_st *result,
374
 
                                 const char *sqlstate)
375
 
{
376
 
  if (sqlstate == NULL)
377
 
    result->sqlstate[0]= 0;
378
 
  else
379
 
  {
380
 
    strncpy(result->sqlstate, sqlstate, DRIZZLE_MAX_SQLSTATE_SIZE + 1);
381
 
    result->sqlstate[DRIZZLE_MAX_SQLSTATE_SIZE]= 0;
382
 
  }
383
 
}
384
 
 
385
 
void drizzle_result_set_warning_count(drizzle_result_st *result,
386
 
                                      uint16_t warning_count)
387
 
{
388
 
  result->warning_count= warning_count;
389
 
}
390
 
 
391
 
void drizzle_result_set_insert_id(drizzle_result_st *result,
392
 
                                  uint64_t insert_id)
393
 
{
394
 
  result->insert_id= insert_id;
395
 
}
396
 
 
397
 
void drizzle_result_set_affected_rows(drizzle_result_st *result,
398
 
                                      uint64_t affected_rows)
399
 
{
400
 
  result->affected_rows= affected_rows;
401
 
}
402
 
 
403
 
void drizzle_result_set_column_count(drizzle_result_st *result,
404
 
                                     uint16_t column_count)
405
 
{
406
 
  result->column_count= column_count;
407
 
}
408
 
 
409
 
/*
410
 
 * Internal state functions.
411
 
 */
412
 
 
413
 
drizzle_return_t drizzle_state_result_read(drizzle_con_st *con)
414
 
{
415
 
  drizzle_return_t ret;
416
 
 
417
 
  drizzle_log_debug(con->drizzle, "drizzle_state_result_read");
418
 
 
419
 
  /* Assume the entire result packet will fit in the buffer. */
420
 
  if (con->buffer_size < con->packet_size)
421
 
  {
422
 
    drizzle_state_push(con, drizzle_state_read);
423
 
    return DRIZZLE_RETURN_OK;
424
 
  }
425
 
 
426
 
  if (con->buffer_ptr[0] == 0)
427
 
  {
428
 
    con->buffer_ptr++;
429
 
    /* We can ignore the returns since we've buffered the entire packet. */
430
 
    con->result->affected_rows= drizzle_unpack_length(con, &ret);
431
 
    con->result->insert_id= drizzle_unpack_length(con, &ret);
432
 
    con->status= drizzle_get_byte2(con->buffer_ptr);
433
 
    con->result->warning_count= drizzle_get_byte2(con->buffer_ptr + 2);
434
 
    con->buffer_ptr+= 4;
435
 
    con->buffer_size-= 5;
436
 
    con->packet_size-= 5;
437
 
    if (con->packet_size > 0)
438
 
    {
439
 
      /* Skip one byte for message size. */
440
 
      con->buffer_ptr+= 1;
441
 
      con->buffer_size-= 1;
442
 
      con->packet_size-= 1;
443
 
    }
444
 
    ret= DRIZZLE_RETURN_OK;
445
 
  }
446
 
  else if (con->buffer_ptr[0] == 254)
447
 
  {
448
 
    con->result->options= DRIZZLE_RESULT_EOF_PACKET;
449
 
    con->result->warning_count= drizzle_get_byte2(con->buffer_ptr + 1);
450
 
    con->status= drizzle_get_byte2(con->buffer_ptr + 3);
451
 
    con->buffer_ptr+= 5;
452
 
    con->buffer_size-= 5;
453
 
    con->packet_size-= 5;
454
 
    ret= DRIZZLE_RETURN_OK;
455
 
  }
456
 
  else if (con->buffer_ptr[0] == 255)
457
 
  {
458
 
    con->result->error_code= drizzle_get_byte2(con->buffer_ptr + 1);
459
 
    con->drizzle->error_code= con->result->error_code;
460
 
    /* Byte 3 is always a '#' character, skip it. */
461
 
    memcpy(con->result->sqlstate, con->buffer_ptr + 4,
462
 
           DRIZZLE_MAX_SQLSTATE_SIZE);
463
 
    con->result->sqlstate[DRIZZLE_MAX_SQLSTATE_SIZE]= 0;
464
 
    memcpy(con->drizzle->sqlstate, con->result->sqlstate,
465
 
           DRIZZLE_MAX_SQLSTATE_SIZE + 1);
466
 
    con->buffer_ptr+= 9;
467
 
    con->buffer_size-= 9;
468
 
    con->packet_size-= 9;
469
 
    ret= DRIZZLE_RETURN_ERROR_CODE;
470
 
  }
471
 
  else
472
 
  {
473
 
    /* We can ignore the return since we've buffered the entire packet. */
474
 
    con->result->column_count= (uint16_t)drizzle_unpack_length(con, &ret);
475
 
    ret= DRIZZLE_RETURN_OK;
476
 
  }
477
 
 
478
 
  if (con->packet_size > 0)
479
 
  {
480
 
    snprintf(con->drizzle->last_error, DRIZZLE_MAX_ERROR_SIZE, "%.*s",
481
 
             (int32_t)con->packet_size, con->buffer_ptr);
482
 
    snprintf(con->result->info, DRIZZLE_MAX_INFO_SIZE, "%.*s",
483
 
             (int32_t)con->packet_size, con->buffer_ptr);
484
 
    con->buffer_ptr+= con->packet_size;
485
 
    con->buffer_size-= con->packet_size;
486
 
    con->packet_size= 0;
487
 
  }
488
 
 
489
 
  drizzle_state_pop(con);
490
 
  return ret;
491
 
}
492
 
 
493
 
drizzle_return_t drizzle_state_result_write(drizzle_con_st *con)
494
 
{
495
 
  uint8_t *start= con->buffer_ptr + con->buffer_size;
496
 
  uint8_t *ptr;
497
 
  drizzle_result_st *result= con->result;
498
 
 
499
 
  drizzle_log_debug(con->drizzle, "drizzle_state_result_write");
500
 
 
501
 
  /* Calculate max packet size. */
502
 
  con->packet_size= 1 /* OK/Field Count/EOF/Error */
503
 
                  + 9 /* Affected rows */
504
 
                  + 9 /* Insert ID */
505
 
                  + 2 /* Status */
506
 
                  + 2 /* Warning count */
507
 
                  + strlen(result->info); /* Info/error message */
508
 
 
509
 
  /* Assume the entire result packet will fit in the buffer. */
510
 
  if ((con->packet_size + 4) > DRIZZLE_MAX_BUFFER_SIZE)
511
 
  {
512
 
    drizzle_set_error(con->drizzle, "drizzle_state_result_write",
513
 
                      "buffer too small:%zu", con->packet_size + 4);
514
 
    return DRIZZLE_RETURN_INTERNAL_ERROR;
515
 
  }
516
 
 
517
 
  /* Flush buffer if there is not enough room. */
518
 
  if (((size_t)DRIZZLE_MAX_BUFFER_SIZE - (size_t)(start - con->buffer)) <
519
 
      con->packet_size)
520
 
  {
521
 
    drizzle_state_push(con, drizzle_state_write);
522
 
    return DRIZZLE_RETURN_OK;
523
 
  }
524
 
 
525
 
  /* Store packet size at the end since it may change. */
526
 
  ptr= start;
527
 
  ptr[3]= con->packet_number;
528
 
  con->packet_number++;
529
 
  ptr+= 4;
530
 
 
531
 
  if (result->options & DRIZZLE_RESULT_EOF_PACKET)
532
 
  {
533
 
    ptr[0]= 254;
534
 
    ptr++;
535
 
 
536
 
    drizzle_set_byte2(ptr, result->warning_count);
537
 
    ptr+= 2;
538
 
 
539
 
    drizzle_set_byte2(ptr, con->status);
540
 
    ptr+= 2;
541
 
  }
542
 
  else if (result->error_code != 0)
543
 
  {
544
 
    ptr[0]= 255;
545
 
    ptr++;
546
 
 
547
 
    drizzle_set_byte2(ptr, result->error_code);
548
 
    ptr+= 2;
549
 
 
550
 
    ptr[0]= '#';
551
 
    ptr++;
552
 
 
553
 
    memcpy(ptr, result->sqlstate, DRIZZLE_MAX_SQLSTATE_SIZE);
554
 
    ptr+= DRIZZLE_MAX_SQLSTATE_SIZE;
555
 
 
556
 
    memcpy(ptr, result->info, strlen(result->info));
557
 
    ptr+= strlen(result->info);
558
 
  }
559
 
  else if (result->column_count == 0)
560
 
  {
561
 
    ptr[0]= 0;
562
 
    ptr++;
563
 
 
564
 
    ptr= drizzle_pack_length(result->affected_rows, ptr);
565
 
    ptr= drizzle_pack_length(result->insert_id, ptr);
566
 
 
567
 
    drizzle_set_byte2(ptr, con->status);
568
 
    ptr+= 2;
569
 
 
570
 
    drizzle_set_byte2(ptr, result->warning_count);
571
 
    ptr+= 2;
572
 
 
573
 
    memcpy(ptr, result->info, strlen(result->info));
574
 
    ptr+= strlen(result->info);
575
 
  }
576
 
  else
577
 
    ptr= drizzle_pack_length(result->column_count, ptr);
578
 
 
579
 
  con->packet_size= ((size_t)(ptr - start) - 4);
580
 
  con->buffer_size+= (4 + con->packet_size);
581
 
 
582
 
  /* Store packet size now. */
583
 
  drizzle_set_byte3(start, con->packet_size);
584
 
 
585
 
  drizzle_state_pop(con);
586
 
  return DRIZZLE_RETURN_OK;
587
 
}