Drizzled Public API Documentation

field.cc
Go to the documentation of this file.
00001 /* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
00002  *
00003  * Drizzle Client & Protocol Library
00004  *
00005  * Copyright (C) 2008 Eric Day (eday@oddments.org)
00006  * All rights reserved.
00007  *
00008  * Redistribution and use in source and binary forms, with or without
00009  * modification, are permitted provided that the following conditions are
00010  * met:
00011  *
00012  *     * Redistributions of source code must retain the above copyright
00013  * notice, this list of conditions and the following disclaimer.
00014  *
00015  *     * Redistributions in binary form must reproduce the above
00016  * copyright notice, this list of conditions and the following disclaimer
00017  * in the documentation and/or other materials provided with the
00018  * distribution.
00019  *
00020  *     * The names of its contributors may not be used to endorse or
00021  * promote products derived from this software without specific prior
00022  * written permission.
00023  *
00024  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00025  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00026  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
00027  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
00028  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
00029  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
00030  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
00031  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
00032  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00033  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
00034  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00035  *
00036  */
00037 
00043 #include <libdrizzle/common.h>
00044 
00045 /*
00046  * Client definitions
00047  */
00048 
00049 drizzle_field_t drizzle_field_read(drizzle_result_st *result, size_t *offset,
00050                                    size_t *size, size_t *total,
00051                                    drizzle_return_t *ret_ptr)
00052 {
00053   drizzle_return_t unused_ret;
00054   if (ret_ptr == NULL)
00055   {
00056     ret_ptr= &unused_ret;
00057   }
00058 
00059   if (result == NULL)
00060   {
00061     *ret_ptr= DRIZZLE_RETURN_INVALID_ARGUMENT;
00062     return drizzle_field_t();
00063   }
00064 
00065   if (drizzle_state_none(result->con))
00066   {
00067     if (result->field_current == result->column_count)
00068     {
00069       *ret_ptr= DRIZZLE_RETURN_ROW_END;
00070       return NULL;
00071     }
00072 
00073     drizzle_state_push(result->con, drizzle_state_field_read);
00074   }
00075 
00076   *ret_ptr= drizzle_state_loop(result->con);
00077   if (*ret_ptr == DRIZZLE_RETURN_OK and
00078       result->options & DRIZZLE_RESULT_ROW_BREAK)
00079   {
00080     *ret_ptr= DRIZZLE_RETURN_ROW_BREAK;
00081   }
00082 
00083   if (offset)
00084   {
00085     *offset= result->field_offset;
00086   }
00087 
00088   if (size)
00089   {
00090     *size= result->field_size;
00091   }
00092 
00093   if (total)
00094   {
00095     *total= result->field_total;
00096   }
00097 
00098   return result->field;
00099 }
00100 
00101 drizzle_field_t drizzle_field_buffer(drizzle_result_st *result, size_t *total,
00102                                      drizzle_return_t *ret_ptr)
00103 {
00104   size_t offset= 0;
00105   size_t size= 0;
00106 
00107   drizzle_return_t unused_ret;
00108   if (ret_ptr == NULL)
00109   {
00110     ret_ptr= &unused_ret;
00111   }
00112 
00113   if (result == NULL)
00114   {
00115     *ret_ptr= DRIZZLE_RETURN_INVALID_ARGUMENT;
00116     return drizzle_field_t();
00117   }
00118 
00119   drizzle_field_t field= drizzle_field_read(result, &offset, &size, total, ret_ptr);
00120 
00121   if (*ret_ptr != DRIZZLE_RETURN_OK)
00122   {
00123     return NULL;
00124   }
00125 
00126   if (field == NULL)
00127   {
00128     *total= 0;
00129     return NULL;
00130   }
00131 
00132   if (result->field_buffer == NULL)
00133   {
00134     result->field_buffer= (drizzle_field_t)realloc(NULL, (*total) +1);
00135     if (result->field_buffer == NULL)
00136     {
00137       drizzle_set_error(result->con->drizzle, __func__, "Failed to allocate.");
00138       *ret_ptr= DRIZZLE_RETURN_MEMORY;
00139       return NULL;
00140     }
00141   }
00142 
00143   memcpy(result->field_buffer + offset, field, size);
00144 
00145   while ((offset + size) != (*total))
00146   {
00147     field= drizzle_field_read(result, &offset, &size, total, ret_ptr);
00148     if (*ret_ptr != DRIZZLE_RETURN_OK)
00149     {
00150       return NULL;
00151     }
00152 
00153     memcpy(result->field_buffer + offset, field, size);
00154   }
00155 
00156   field= result->field_buffer;
00157   result->field_buffer= NULL;
00158   field[*total]= 0;
00159 
00160   return field;
00161 }
00162 
00163 void drizzle_field_free(drizzle_field_t field)
00164 {
00165   if (field)
00166   {
00167     free(field);
00168   }
00169 }
00170 
00171 /*
00172  * Server definitions
00173  */
00174 
00175 drizzle_return_t drizzle_field_write(drizzle_result_st *result,
00176                                      const drizzle_field_t field, size_t size,
00177                                      size_t total)
00178 {
00179   if (result == NULL)
00180   {
00181     return  DRIZZLE_RETURN_INVALID_ARGUMENT;
00182   }
00183 
00184   drizzle_return_t ret;
00185 
00186   if (drizzle_state_none(result->con))
00187   {
00188     if (result->options & DRIZZLE_RESULT_ROW_BREAK)
00189     {
00190       result->options&= int(~DRIZZLE_RESULT_ROW_BREAK);
00191       result->field= field;
00192       result->field_size= size;
00193     }
00194     else
00195     {
00196       result->field= field;
00197       result->field_size= size;
00198       result->field_offset= 0;
00199       result->field_total= total;
00200     }
00201 
00202     drizzle_state_push(result->con, drizzle_state_field_write);
00203   }
00204   else if (result->field == NULL)
00205   {
00206     result->field= field;
00207     result->field_size= size;
00208   }
00209 
00210   ret= drizzle_state_loop(result->con);
00211   if (ret == DRIZZLE_RETURN_PAUSE)
00212     ret= DRIZZLE_RETURN_OK;
00213 
00214   return ret;
00215 }
00216 
00217 /*
00218  * Internal state functions.
00219  */
00220 
00221 drizzle_return_t drizzle_state_field_read(drizzle_con_st *con)
00222 {
00223   if (con == NULL)
00224   {
00225     return DRIZZLE_RETURN_INVALID_ARGUMENT;
00226   }
00227   drizzle_log_debug(con->drizzle, "drizzle_state_field_read");
00228 
00229   if (con->buffer_size == 0)
00230   {
00231     drizzle_state_push(con, drizzle_state_read);
00232     return DRIZZLE_RETURN_OK;
00233   }
00234 
00235   con->result->field_offset+= con->result->field_size;
00236   if (con->result->field_offset == con->result->field_total)
00237   {
00238     con->result->field_offset= 0;
00239     con->result->field_size= 0;
00240 
00241     drizzle_return_t ret;
00242     con->result->field_total= (size_t)drizzle_unpack_length(con, &ret);
00243     if (ret == DRIZZLE_RETURN_NULL_SIZE)
00244     {
00245       con->result->field= NULL;
00246       con->result->field_current++;
00247       drizzle_state_pop(con);
00248       return DRIZZLE_RETURN_OK;
00249     }
00250     else if (ret != DRIZZLE_RETURN_OK)
00251     {
00252       if (ret == DRIZZLE_RETURN_IO_WAIT)
00253       {
00254         drizzle_state_push(con, drizzle_state_read);
00255         return DRIZZLE_RETURN_OK;
00256       }
00257 
00258       return ret;
00259     }
00260 
00261     drizzle_log_debug(con->drizzle,
00262                       "field_offset= %zu, field_size= %zu, field_total= %zu",
00263                       con->result->field_offset, con->result->field_size,
00264                       con->result->field_total);
00265 
00266     if ((size_t)(con->buffer_size) >= con->result->field_total)
00267     {
00268       con->result->field_size= con->result->field_total;
00269     }
00270     else
00271     {
00272       con->result->field_size= con->buffer_size;
00273     }
00274   }
00275   else
00276   {
00277     if ((con->result->field_offset + con->buffer_size) >=
00278         con->result->field_total)
00279     {
00280       con->result->field_size= (con->result->field_total -
00281                                 con->result->field_offset);
00282     }
00283     else
00284     {
00285       con->result->field_size= con->buffer_size;
00286     }
00287   }
00288 
00289   /* This is a special case when a row is larger than the packet size. */
00290   if (con->result->field_size > (size_t)con->packet_size)
00291   {
00292     con->result->field_size= con->packet_size;
00293 
00294     if (con->options & DRIZZLE_CON_RAW_PACKET)
00295     {
00296       con->result->options|= DRIZZLE_RESULT_ROW_BREAK;
00297     }
00298     else
00299     {
00300       drizzle_state_pop(con);
00301       drizzle_state_push(con, drizzle_state_packet_read);
00302       drizzle_state_push(con, drizzle_state_field_read);
00303     }
00304   }
00305 
00306   con->result->field= (char *)con->buffer_ptr;
00307   con->buffer_ptr+= con->result->field_size;
00308   con->buffer_size-= con->result->field_size;
00309   con->packet_size-= con->result->field_size;
00310 
00311   drizzle_log_debug(con->drizzle,
00312                     "field_offset= %zu, field_size= %zu, field_total= %zu",
00313                     con->result->field_offset, con->result->field_size,
00314                     con->result->field_total);
00315 
00316   if ((con->result->field_offset + con->result->field_size) ==
00317       con->result->field_total)
00318   {
00319     if (con->result->column_buffer != NULL &&
00320         con->result->column_buffer[con->result->field_current].max_size <
00321         con->result->field_total)
00322     {
00323       con->result->column_buffer[con->result->field_current].max_size=
00324                                                        con->result->field_total;
00325     }
00326 
00327     con->result->field_current++;
00328   }
00329 
00330   if (con->result->field_total == 0 || con->result->field_size > 0 ||
00331       con->packet_size == 0)
00332   {
00333     drizzle_state_pop(con);
00334   }
00335 
00336   return DRIZZLE_RETURN_OK;
00337 }
00338 
00339 drizzle_return_t drizzle_state_field_write(drizzle_con_st *con)
00340 {
00341   if (con == NULL)
00342   {
00343     return DRIZZLE_RETURN_INVALID_ARGUMENT;
00344   }
00345 
00346   uint8_t *start= con->buffer_ptr + con->buffer_size;
00347   uint8_t *ptr;
00348   size_t free_size;
00349   drizzle_result_st *result= con->result;
00350 
00351   drizzle_log_debug(con->drizzle, "drizzle_state_field_write");
00352 
00353   if (result->field == NULL && result->field_total != 0)
00354   {
00355     return DRIZZLE_RETURN_PAUSE;
00356   }
00357 
00358   free_size= (size_t)DRIZZLE_MAX_BUFFER_SIZE - (size_t)(start - con->buffer);
00359   ptr= start;
00360 
00361   if (result->field_offset == 0)
00362   {
00363     /* Make sure we can fit the max length and 1 byte of data in (9 + 1). */
00364     if (free_size < 10)
00365     {
00366       drizzle_state_push(con, drizzle_state_write);
00367       return DRIZZLE_RETURN_OK;
00368     }
00369 
00370     if (result->field == NULL)
00371     {
00372       ptr[0]= 251;
00373       ptr++;
00374     }
00375     else if (result->field_total == 0)
00376     {
00377       ptr[0]= 0;
00378       ptr++;
00379     }
00380     else
00381       ptr= drizzle_pack_length(result->field_total, ptr);
00382 
00383     free_size-= (size_t)(ptr - start);
00384     con->buffer_size+= (size_t)(ptr - start);
00385     con->packet_size-= (size_t)(ptr - start);
00386   }
00387   else if (result->field_size > DRIZZLE_BUFFER_COPY_THRESHOLD)
00388   {
00389     /* Flush the internal buffer first. */
00390     if (con->buffer_size != 0)
00391     {
00392       drizzle_state_push(con, drizzle_state_write);
00393       return DRIZZLE_RETURN_OK;
00394     }
00395 
00396     /* We do this to write directly from the field buffer to avoid memcpy(). */
00397     con->buffer_ptr= (uint8_t *)result->field;
00398     con->buffer_size= result->field_size;
00399     con->packet_size-= result->field_size;
00400     result->field_offset+= result->field_size;
00401     result->field= NULL;
00402 
00403     if (result->field_offset == result->field_total)
00404     {
00405       drizzle_state_pop(con);
00406     }
00407     else if (con->packet_size == 0)
00408     {
00409       con->result->options|= DRIZZLE_RESULT_ROW_BREAK;
00410       drizzle_state_pop(con);
00411     }
00412 
00413     drizzle_state_push(con, drizzle_state_write);
00414 
00415     return DRIZZLE_RETURN_OK;
00416   }
00417 
00418   if (result->field_size == 0)
00419   {
00420     drizzle_state_pop(con);
00421   }
00422   else
00423   {
00424     if (result->field_size < free_size)
00425       free_size= result->field_size;
00426 
00427     memcpy(ptr, result->field, free_size);
00428     result->field_offset+= free_size;
00429     con->buffer_size+= free_size;
00430     con->packet_size-= free_size;
00431 
00432     if (result->field_offset == result->field_total)
00433     {
00434       result->field= NULL;
00435       drizzle_state_pop(con);
00436     }
00437     else
00438     {
00439       if (con->packet_size == 0)
00440       {
00441         con->result->options|= DRIZZLE_RESULT_ROW_BREAK;
00442         drizzle_state_pop(con);
00443       }
00444 
00445       if (result->field_size == free_size)
00446       {
00447         result->field= NULL;
00448       }
00449       else
00450       {
00451         result->field+= free_size;
00452         result->field_size-= free_size;
00453         drizzle_state_push(con, drizzle_state_write);
00454       }
00455     }
00456   }
00457 
00458   return DRIZZLE_RETURN_OK;
00459 }