Drizzled Public API Documentation

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