libdrizzle Developer Documentation

libdrizzle/row.c
Go to the documentation of this file.
00001 /*
00002  * Drizzle Client & Protocol Library
00003  *
00004  * Copyright (C) 2008 Eric Day (eday@oddments.org)
00005  * All rights reserved.
00006  *
00007  * Use and distribution licensed under the BSD license.  See
00008  * the COPYING file in this directory for full text.
00009  */
00010 
00016 #include "common.h"
00017 
00018 /*
00019  * Client definitions
00020  */
00021 
00022 uint64_t drizzle_row_read(drizzle_result_st *result, drizzle_return_t *ret_ptr)
00023 {
00024   if (drizzle_state_none(result->con))
00025   {
00026     drizzle_state_push(result->con, drizzle_state_row_read);
00027     drizzle_state_push(result->con, drizzle_state_packet_read);
00028   }
00029 
00030   *ret_ptr= drizzle_state_loop(result->con);
00031 
00032   return result->row_current;
00033 }
00034 
00035 drizzle_row_t drizzle_row_buffer(drizzle_result_st *result,
00036                                  drizzle_return_t *ret_ptr)
00037 {
00038   size_t total;
00039   drizzle_field_t field;
00040   drizzle_row_t row;
00041 
00042   if (result->row == NULL)
00043   {
00044     if (drizzle_row_read(result, ret_ptr) == 0 || *ret_ptr != DRIZZLE_RETURN_OK)
00045       return NULL;
00046 
00047     result->row= malloc((sizeof(drizzle_field_t) + sizeof(size_t)) *
00048                         result->column_count);
00049     if (result->row == NULL)
00050     {
00051       drizzle_set_error(result->con->drizzle, "drizzle_row_buffer", "malloc");
00052       *ret_ptr= DRIZZLE_RETURN_MEMORY;
00053       return NULL;
00054     }
00055 
00056     result->field_sizes= (size_t *)(result->row + result->column_count);
00057   }
00058 
00059   while (1)
00060   {
00061     field= drizzle_field_buffer(result, &total, ret_ptr);
00062     if (*ret_ptr == DRIZZLE_RETURN_ROW_END)
00063       break;
00064     if (*ret_ptr != DRIZZLE_RETURN_OK)
00065     {
00066       if (*ret_ptr != DRIZZLE_RETURN_IO_WAIT)
00067       {
00068         free(result->row);
00069         result->row= NULL;
00070         free(result->field_sizes);
00071         result->field_sizes= NULL;
00072       }
00073 
00074       return NULL;
00075     }
00076 
00077     result->row[result->field_current - 1]= field;
00078     result->field_sizes[result->field_current - 1]= total;
00079   }
00080 
00081   *ret_ptr= DRIZZLE_RETURN_OK;
00082   row= result->row;
00083   result->row= NULL;
00084 
00085   return row;
00086 }
00087 
00088 void drizzle_row_free(drizzle_result_st *result, drizzle_row_t row)
00089 {
00090   uint16_t x;
00091 
00092   for (x= 0; x < result->column_count; x++)
00093       drizzle_field_free(row[x]);
00094 
00095   free(row);
00096 }
00097 
00098 size_t *drizzle_row_field_sizes(drizzle_result_st *result)
00099 {
00100   return result->field_sizes;
00101 }
00102 
00103 drizzle_row_t drizzle_row_next(drizzle_result_st *result)
00104 {
00105   if (result->row_current == result->row_count)
00106     return NULL;
00107 
00108   result->field_sizes= result->field_sizes_list[result->row_current];
00109   result->row_current++;
00110   return result->row_list[result->row_current - 1];
00111 }
00112 
00113 drizzle_row_t drizzle_row_prev(drizzle_result_st *result)
00114 {
00115   if (result->row_current == 0)
00116     return NULL;
00117 
00118   result->row_current--;
00119   result->field_sizes= result->field_sizes_list[result->row_current];
00120   return result->row_list[result->row_current];
00121 }
00122 
00123 void drizzle_row_seek(drizzle_result_st *result, uint64_t row)
00124 {
00125   if (row <= result->row_count)
00126     result->row_current= row;
00127 }
00128 
00129 drizzle_row_t drizzle_row_index(drizzle_result_st *result, uint64_t row)
00130 {
00131   if (row >= result->row_count)
00132     return NULL;
00133 
00134   return result->row_list[row];
00135 }
00136 
00137 uint64_t drizzle_row_current(drizzle_result_st *result)
00138 {
00139   return result->row_current;
00140 }
00141 
00142 /*
00143  * Server definitions
00144  */
00145 
00146 drizzle_return_t drizzle_row_write(drizzle_result_st *result)
00147 {
00148   if (drizzle_state_none(result->con))
00149     drizzle_state_push(result->con, drizzle_state_row_write);
00150 
00151   return drizzle_state_loop(result->con);
00152 }
00153 
00154 /*
00155  * Internal state functions.
00156  */
00157 
00158 drizzle_return_t drizzle_state_row_read(drizzle_con_st *con)
00159 {
00160   drizzle_log_debug(con->drizzle, "drizzle_state_row_read");
00161 
00162   if (con->packet_size == 5 && con->buffer_ptr[0] == 254)
00163   {
00164     if (con->buffer_size < 5)
00165     {
00166       drizzle_state_push(con, drizzle_state_read);
00167       return DRIZZLE_RETURN_OK;
00168     }
00169 
00170     /* Got EOF packet, no more rows. */
00171     con->result->row_current= 0;
00172     con->result->warning_count= drizzle_get_byte2(con->buffer_ptr + 1);
00173     con->status= drizzle_get_byte2(con->buffer_ptr + 3);
00174     con->buffer_ptr+= 5;
00175     con->buffer_size-= 5;
00176   }
00177   else if (con->buffer_ptr[0] == 255)
00178   {
00179     drizzle_state_pop(con);
00180     drizzle_state_push(con, drizzle_state_result_read);
00181     return DRIZZLE_RETURN_OK;
00182   }
00183   else if (con->result->options & DRIZZLE_RESULT_ROW_BREAK)
00184     con->result->options&= (drizzle_result_options_t)~DRIZZLE_RESULT_ROW_BREAK;
00185   else
00186   {
00187     con->result->row_count++;
00188     con->result->row_current++;
00189     con->result->field_current= 0;
00190   }
00191 
00192   drizzle_state_pop(con);
00193   return DRIZZLE_RETURN_OK;
00194 }
00195 
00196 drizzle_return_t drizzle_state_row_write(drizzle_con_st *con)
00197 {
00198   uint8_t *start= con->buffer_ptr + con->buffer_size;
00199 
00200   drizzle_log_debug(con->drizzle, "drizzle_state_row_write");
00201 
00202   /* Flush buffer if there is not enough room. */
00203   if (((size_t)DRIZZLE_MAX_BUFFER_SIZE - (size_t)(start - con->buffer)) < 4)
00204   {
00205     drizzle_state_push(con, drizzle_state_write);
00206     return DRIZZLE_RETURN_OK;
00207   }
00208 
00209   drizzle_set_byte3(start, con->packet_size);
00210   start[3]= con->packet_number;
00211   con->packet_number++;
00212 
00213   con->buffer_size+= 4;
00214 
00215   drizzle_state_pop(con);
00216   return DRIZZLE_RETURN_OK;
00217 }