~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to libdrizzle/result.c

  • Committer: Brian Aker
  • Date: 2008-07-05 17:02:05 UTC
  • Revision ID: brian@tangent.org-20080705170205-ezff9is4e7hpa3x2
Conversion of handler type.

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