libdrizzle Developer Documentation

libdrizzle/field.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 drizzle_field_t drizzle_field_read(drizzle_result_st *result, size_t *offset,
00023                                    size_t *size, size_t *total,
00024                                    drizzle_return_t *ret_ptr)
00025 {
00026   if (drizzle_state_none(result->con))
00027   {
00028     if (result->field_current == result->column_count)
00029     {
00030       *ret_ptr= DRIZZLE_RETURN_ROW_END;
00031       return NULL;
00032     }
00033 
00034     drizzle_state_push(result->con, drizzle_state_field_read);
00035   }
00036 
00037   *ret_ptr= drizzle_state_loop(result->con);
00038   if (*ret_ptr == DRIZZLE_RETURN_OK &&
00039       result->options & DRIZZLE_RESULT_ROW_BREAK)
00040   {
00041     *ret_ptr= DRIZZLE_RETURN_ROW_BREAK;
00042   }
00043 
00044   *offset= result->field_offset;
00045   *size= result->field_size;
00046   *total= result->field_total;
00047 
00048   return result->field;
00049 }
00050 
00051 drizzle_field_t drizzle_field_buffer(drizzle_result_st *result, size_t *total,
00052                                      drizzle_return_t *ret_ptr)
00053 {
00054   drizzle_field_t field;
00055   size_t offset= 0;
00056   size_t size= 0;
00057 
00058   field= drizzle_field_read(result, &offset, &size, total, ret_ptr);
00059   if (*ret_ptr != DRIZZLE_RETURN_OK)
00060     return NULL;
00061 
00062   if (field == NULL)
00063   {
00064     *total= 0;
00065     return NULL;
00066   }
00067 
00068   if (result->field_buffer == NULL)
00069   {
00070     result->field_buffer= malloc((*total) + 1);
00071     if (result->field_buffer == NULL)
00072     {
00073       drizzle_set_error(result->con->drizzle, "drizzle_field_buffer", "malloc");
00074       *ret_ptr= DRIZZLE_RETURN_MEMORY;
00075       return NULL;
00076     }
00077   }
00078 
00079   memcpy(result->field_buffer + offset, field, size);
00080 
00081   while ((offset + size) != (*total))
00082   {
00083     field= drizzle_field_read(result, &offset, &size, total, ret_ptr);
00084     if (*ret_ptr != DRIZZLE_RETURN_OK)
00085       return NULL;
00086 
00087     memcpy(result->field_buffer + offset, field, size);
00088   }
00089 
00090   field= result->field_buffer;
00091   result->field_buffer= NULL;
00092   field[*total]= 0;
00093 
00094   return field;
00095 }
00096 
00097 void drizzle_field_free(drizzle_field_t field)
00098 {
00099   if (field != NULL)
00100     free(field);
00101 }
00102 
00103 /*
00104  * Server definitions
00105  */
00106 
00107 drizzle_return_t drizzle_field_write(drizzle_result_st *result,
00108                                      const drizzle_field_t field, size_t size,
00109                                      size_t total)
00110 {
00111   drizzle_return_t ret;
00112 
00113   if (drizzle_state_none(result->con))
00114   {
00115     if (result->options & DRIZZLE_RESULT_ROW_BREAK)
00116     {
00117       result->options&= (drizzle_result_options_t)~DRIZZLE_RESULT_ROW_BREAK;
00118       result->field= field;
00119       result->field_size= size;
00120     }
00121     else
00122     {
00123       result->field= field;
00124       result->field_size= size;
00125       result->field_offset= 0;
00126       result->field_total= total;
00127     }
00128 
00129     drizzle_state_push(result->con, drizzle_state_field_write);
00130   }
00131   else if (result->field == NULL)
00132   {
00133     result->field= field;
00134     result->field_size= size;
00135   }
00136 
00137   ret= drizzle_state_loop(result->con);
00138   if (ret == DRIZZLE_RETURN_PAUSE)
00139     ret= DRIZZLE_RETURN_OK;
00140 
00141   return ret;
00142 }
00143 
00144 /*
00145  * Internal state functions.
00146  */
00147 
00148 drizzle_return_t drizzle_state_field_read(drizzle_con_st *con)
00149 {
00150   drizzle_return_t ret;
00151 
00152   drizzle_log_debug(con->drizzle, "drizzle_state_field_read");
00153 
00154   if (con->buffer_size == 0)
00155   {
00156     drizzle_state_push(con, drizzle_state_read);
00157     return DRIZZLE_RETURN_OK;
00158   }
00159 
00160   con->result->field_offset+= con->result->field_size;
00161   if (con->result->field_offset == con->result->field_total)
00162   {
00163     con->result->field_offset= 0;
00164     con->result->field_size= 0;
00165 
00166     con->result->field_total= (size_t)drizzle_unpack_length(con, &ret);
00167     if (ret == DRIZZLE_RETURN_NULL_SIZE)
00168     {
00169       con->result->field= NULL;
00170       con->result->field_current++;
00171       drizzle_state_pop(con);
00172       return DRIZZLE_RETURN_OK;
00173     }
00174     else if (ret != DRIZZLE_RETURN_OK)
00175     {
00176       if (ret == DRIZZLE_RETURN_IO_WAIT)
00177       {
00178         drizzle_state_push(con, drizzle_state_read);
00179         return DRIZZLE_RETURN_OK;
00180       }
00181 
00182       return ret;
00183     }
00184 
00185     drizzle_log_debug(con->drizzle,
00186                       "field_offset= %zu, field_size= %zu, field_total= %zu",
00187                       con->result->field_offset, con->result->field_size,
00188                       con->result->field_total);
00189 
00190     if ((size_t)(con->buffer_size) >= con->result->field_total)
00191       con->result->field_size= con->result->field_total;
00192     else
00193       con->result->field_size= con->buffer_size;
00194   }
00195   else
00196   {
00197     if ((con->result->field_offset + con->buffer_size) >=
00198         con->result->field_total)
00199     {
00200       con->result->field_size= (con->result->field_total -
00201                                 con->result->field_offset);
00202     }
00203     else
00204       con->result->field_size= con->buffer_size;
00205   }
00206 
00207   /* This is a special case when a row is larger than the packet size. */
00208   if (con->result->field_size > (size_t)con->packet_size)
00209   {
00210     con->result->field_size= con->packet_size;
00211 
00212     if (con->options & DRIZZLE_CON_RAW_PACKET)
00213       con->result->options|= DRIZZLE_RESULT_ROW_BREAK;
00214     else
00215     {
00216       drizzle_state_pop(con);
00217       drizzle_state_push(con, drizzle_state_packet_read);
00218       drizzle_state_push(con, drizzle_state_field_read);
00219     }
00220   }
00221 
00222   con->result->field= (char *)con->buffer_ptr;
00223   con->buffer_ptr+= con->result->field_size;
00224   con->buffer_size-= con->result->field_size;
00225   con->packet_size-= con->result->field_size;
00226 
00227   drizzle_log_debug(con->drizzle,
00228                     "field_offset= %zu, field_size= %zu, field_total= %zu",
00229                     con->result->field_offset, con->result->field_size,
00230                     con->result->field_total);
00231 
00232   if ((con->result->field_offset + con->result->field_size) ==
00233       con->result->field_total)
00234   {
00235     if (con->result->column_buffer != NULL &&
00236         con->result->column_buffer[con->result->field_current].max_size <
00237         con->result->field_total)
00238     {
00239       con->result->column_buffer[con->result->field_current].max_size=
00240                                                        con->result->field_total;
00241     }
00242 
00243     con->result->field_current++;
00244   }
00245 
00246   if (con->result->field_total == 0 || con->result->field_size > 0 ||
00247       con->packet_size == 0)
00248   {
00249     drizzle_state_pop(con);
00250   }
00251 
00252   return DRIZZLE_RETURN_OK;
00253 }
00254 
00255 drizzle_return_t drizzle_state_field_write(drizzle_con_st *con)
00256 {
00257   uint8_t *start= con->buffer_ptr + con->buffer_size;
00258   uint8_t *ptr;
00259   size_t free_size;
00260   drizzle_result_st *result= con->result;
00261 
00262   drizzle_log_debug(con->drizzle, "drizzle_state_field_write");
00263 
00264   if (result->field == NULL && result->field_total != 0)
00265     return DRIZZLE_RETURN_PAUSE;
00266 
00267   free_size= (size_t)DRIZZLE_MAX_BUFFER_SIZE - (size_t)(start - con->buffer);
00268   ptr= start;
00269 
00270   if (result->field_offset == 0)
00271   {
00272     /* Make sure we can fit the max length and 1 byte of data in (9 + 1). */
00273     if (free_size < 10)
00274     {
00275       drizzle_state_push(con, drizzle_state_write);
00276       return DRIZZLE_RETURN_OK;
00277     }
00278 
00279     if (result->field == NULL)
00280     {
00281       ptr[0]= 251;
00282       ptr++;
00283     }
00284     else if (result->field_total == 0)
00285     {
00286       ptr[0]= 0;
00287       ptr++;
00288     }
00289     else
00290       ptr= drizzle_pack_length(result->field_total, ptr);
00291 
00292     free_size-= (size_t)(ptr - start);
00293     con->buffer_size+= (size_t)(ptr - start);
00294     con->packet_size-= (size_t)(ptr - start);
00295   }
00296   else if (result->field_size > DRIZZLE_BUFFER_COPY_THRESHOLD)
00297   {
00298     /* Flush the internal buffer first. */
00299     if (con->buffer_size != 0)
00300     {
00301       drizzle_state_push(con, drizzle_state_write);
00302       return DRIZZLE_RETURN_OK;
00303     }
00304 
00305     /* We do this to write directly from the field buffer to avoid memcpy(). */
00306     con->buffer_ptr= (uint8_t *)result->field;
00307     con->buffer_size= result->field_size;
00308     con->packet_size-= result->field_size;
00309     result->field_offset+= result->field_size;
00310     result->field= NULL;
00311 
00312     if (result->field_offset == result->field_total)
00313       drizzle_state_pop(con);
00314     else if (con->packet_size == 0)
00315     {
00316       con->result->options|= DRIZZLE_RESULT_ROW_BREAK;
00317       drizzle_state_pop(con);
00318     }
00319 
00320     drizzle_state_push(con, drizzle_state_write);
00321     return DRIZZLE_RETURN_OK;
00322   }
00323 
00324   if (result->field_size == 0)
00325     drizzle_state_pop(con);
00326   else
00327   {
00328     if (result->field_size < free_size)
00329       free_size= result->field_size;
00330 
00331     memcpy(ptr, result->field, free_size);
00332     result->field_offset+= free_size;
00333     con->buffer_size+= free_size;
00334     con->packet_size-= free_size;
00335 
00336     if (result->field_offset == result->field_total)
00337     {
00338       result->field= NULL;
00339       drizzle_state_pop(con);
00340     }
00341     else
00342     {
00343       if (con->packet_size == 0)
00344       {
00345         con->result->options|= DRIZZLE_RESULT_ROW_BREAK;
00346         drizzle_state_pop(con);
00347       }
00348 
00349       if (result->field_size == free_size)
00350         result->field= NULL;
00351       else
00352       {
00353         result->field+= free_size;
00354         result->field_size-= free_size;
00355         drizzle_state_push(con, drizzle_state_write);
00356       }
00357     }
00358   }
00359 
00360   return DRIZZLE_RETURN_OK;
00361 }