libdrizzle Developer Documentation

libdrizzle/query.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 drizzle_result_st *drizzle_query(drizzle_con_st *con, drizzle_result_st *result,
00019                                  const char *query, size_t size,
00020                                  drizzle_return_t *ret_ptr)
00021 {
00022   return drizzle_con_command_write(con, result, DRIZZLE_COMMAND_QUERY,
00023                                    (uint8_t *)query, size, size, ret_ptr);
00024 }
00025 
00026 drizzle_result_st *drizzle_query_str(drizzle_con_st *con,
00027                                      drizzle_result_st *result,
00028                                      const char *query, 
00029                                      drizzle_return_t *ret_ptr)
00030 {
00031   size_t size;
00032 
00033   size= strlen(query);
00034 
00035   return drizzle_con_command_write(con, result, DRIZZLE_COMMAND_QUERY,
00036                                    (uint8_t *)query, size, size, ret_ptr);
00037 }
00038 
00039 drizzle_result_st *drizzle_query_inc(drizzle_con_st *con,
00040                                      drizzle_result_st *result,
00041                                      const char *query, size_t size,
00042                                      size_t total, drizzle_return_t *ret_ptr)
00043 {
00044   return drizzle_con_command_write(con, result, DRIZZLE_COMMAND_QUERY,
00045                                    (uint8_t *)query, size, total, ret_ptr);
00046 }
00047 
00048 drizzle_query_st *drizzle_query_add(drizzle_st *drizzle,
00049                                     drizzle_query_st *query,
00050                                     drizzle_con_st *con,
00051                                     drizzle_result_st *result,
00052                                     const char *query_string, size_t size,
00053                                     drizzle_query_options_t options,
00054                                     void *context)
00055 {
00056   query= drizzle_query_create(drizzle, query);
00057   if (query == NULL)
00058     return NULL;
00059 
00060   drizzle_query_set_con(query, con);
00061   drizzle_query_set_result(query, result);
00062   drizzle_query_set_string(query, query_string, size);
00063   drizzle_query_add_options(query, options);
00064   drizzle_query_set_context(query, context);
00065 
00066   return query;
00067 }
00068 
00069 drizzle_query_st *drizzle_query_create(drizzle_st *drizzle,
00070                                        drizzle_query_st *query)
00071 {
00072   if (query == NULL)
00073   {
00074     query= malloc(sizeof(drizzle_query_st));
00075     if (query == NULL)
00076     {
00077       drizzle_set_error(drizzle, "drizzle_query_create", "malloc");
00078       return NULL;
00079     }
00080 
00081     memset(query, 0, sizeof(drizzle_query_st));
00082     query->options|= DRIZZLE_CON_ALLOCATED;
00083   }
00084   else
00085     memset(query, 0, sizeof(drizzle_query_st));
00086 
00087   query->drizzle= drizzle;
00088 
00089   if (drizzle->query_list)
00090     drizzle->query_list->prev= query;
00091   query->next= drizzle->query_list;
00092   drizzle->query_list= query;
00093   drizzle->query_count++;
00094   drizzle->query_new++;
00095 
00096   return query;
00097 }
00098 
00099 void drizzle_query_free(drizzle_query_st *query)
00100 {
00101   if (query->context != NULL && query->context_free_fn != NULL)
00102     query->context_free_fn(query, query->context);
00103 
00104   if (query->drizzle->query_list == query)
00105     query->drizzle->query_list= query->next;
00106   if (query->prev)
00107     query->prev->next= query->next;
00108   if (query->next)
00109     query->next->prev= query->prev;
00110   query->drizzle->query_count--;
00111 
00112   if (query->options & DRIZZLE_QUERY_ALLOCATED)
00113     free(query);
00114 }
00115 
00116 void drizzle_query_free_all(drizzle_st *drizzle)
00117 {
00118   while (drizzle->query_list != NULL)
00119     drizzle_query_free(drizzle->query_list);
00120 }
00121 
00122 drizzle_con_st *drizzle_query_con(drizzle_query_st *query)
00123 {
00124   return query->con;
00125 }
00126 
00127 void drizzle_query_set_con(drizzle_query_st *query, drizzle_con_st *con)
00128 {
00129   query->con= con;
00130 }
00131 
00132 drizzle_result_st *drizzle_query_result(drizzle_query_st *query)
00133 {
00134   return query->result;
00135 }
00136 
00137 void drizzle_query_set_result(drizzle_query_st *query,
00138                               drizzle_result_st *result)
00139 {
00140   query->result= result;
00141 }
00142 
00143 char *drizzle_query_string(drizzle_query_st *query, size_t *size)
00144 {
00145   *size= query->size;
00146   return (char *)(query->string);
00147 }
00148 
00149 void drizzle_query_set_string(drizzle_query_st *query, const char *string,
00150                               size_t size)
00151 {
00152   query->string= string;
00153   query->size= size;
00154 }
00155 
00156 drizzle_query_options_t drizzle_query_options(drizzle_query_st *query)
00157 {
00158   return query->options;
00159 }
00160 
00161 void drizzle_query_set_options(drizzle_query_st *query,
00162                                drizzle_query_options_t options)
00163 {
00164   query->options= options;
00165 }
00166 
00167 void drizzle_query_add_options(drizzle_query_st *query,
00168                                drizzle_query_options_t options)
00169 {
00170   query->options|= options;
00171 }
00172 
00173 void drizzle_query_remove_options(drizzle_query_st *query,
00174                                   drizzle_query_options_t options)
00175 {
00176   query->options&= ~options;
00177 }
00178 
00179 void *drizzle_query_context(drizzle_query_st *query)
00180 {
00181   return query->context;
00182 }
00183 
00184 void drizzle_query_set_context(drizzle_query_st *query, void *context)
00185 {
00186   query->context= context;
00187 }
00188 
00189 void drizzle_query_set_context_free_fn(drizzle_query_st *query,
00190                                        drizzle_query_context_free_fn *function)
00191 {
00192   query->context_free_fn= function;
00193 }
00194 
00195 static void drizzle_query_run_state(drizzle_query_st* query,
00196                                     drizzle_return_t* ret_ptr)
00197 {
00198   switch (query->state)
00199   {
00200   case DRIZZLE_QUERY_STATE_INIT:
00201     query->state= DRIZZLE_QUERY_STATE_QUERY;
00202   case DRIZZLE_QUERY_STATE_QUERY:
00203     query->result= drizzle_query(query->con, query->result, query->string,
00204                                  query->size, ret_ptr);
00205     if (*ret_ptr == DRIZZLE_RETURN_IO_WAIT)
00206     {
00207       return;
00208     }
00209     else if (*ret_ptr != DRIZZLE_RETURN_OK)
00210     {
00211       query->state= DRIZZLE_QUERY_STATE_DONE;
00212       return;
00213     }
00214 
00215     query->state= DRIZZLE_QUERY_STATE_RESULT;
00216 
00217   case DRIZZLE_QUERY_STATE_RESULT:
00218     *ret_ptr= drizzle_result_buffer(query->result);
00219     if (*ret_ptr == DRIZZLE_RETURN_IO_WAIT)
00220     {
00221       return;
00222     }
00223 
00224     query->state= DRIZZLE_QUERY_STATE_DONE;
00225     return;
00226 
00227   default:
00228   case DRIZZLE_QUERY_STATE_DONE:
00229     return;
00230   }
00231 }
00232 
00233 drizzle_query_st *drizzle_query_run(drizzle_st *drizzle,
00234                                     drizzle_return_t *ret_ptr)
00235 {
00236   drizzle_options_t options;
00237   drizzle_query_st *query;
00238   drizzle_con_st *con;
00239 
00240   if (drizzle->query_new == 0 && drizzle->query_running == 0)
00241   {
00242     *ret_ptr= DRIZZLE_RETURN_OK;
00243     return NULL;
00244   }
00245 
00246   options= drizzle->options;
00247   drizzle->options|= DRIZZLE_NON_BLOCKING;
00248 
00249   /* Check to see if any queries need to be started. */
00250   if (drizzle->query_new > 0)
00251   {
00252     for (query= drizzle->query_list; query != NULL; query= query->next)
00253     {
00254       if (query->state != DRIZZLE_QUERY_STATE_INIT)
00255         continue;
00256 
00257       drizzle->query_new--;
00258       drizzle->query_running++;
00259       assert(query->con->query == NULL);
00260       query->con->query= query;
00261 
00262       drizzle_query_run_state(query, ret_ptr);
00263       if (*ret_ptr != DRIZZLE_RETURN_IO_WAIT)
00264       {
00265         assert(query->state == DRIZZLE_QUERY_STATE_DONE);
00266         drizzle->query_running--;
00267         drizzle->options= options;
00268         query->con->query= NULL;
00269         if (*ret_ptr == DRIZZLE_RETURN_ERROR_CODE || *ret_ptr == DRIZZLE_RETURN_OK)
00270         {
00271           return query;
00272         }
00273         return NULL;
00274       }
00275     }
00276     assert(drizzle->query_new == 0);
00277   }
00278 
00279   while (1)
00280   {
00281     /* Loop through each active connection. */
00282     while ((con= drizzle_con_ready(drizzle)) != NULL)
00283     {
00284       query= con->query;
00285       drizzle_query_run_state(query, ret_ptr);
00286       if (query->state == DRIZZLE_QUERY_STATE_DONE)
00287       {
00288         drizzle->query_running--;
00289         drizzle->options= options;
00290         con->query= NULL;
00291         return query;
00292       }
00293       assert(*ret_ptr == DRIZZLE_RETURN_IO_WAIT);
00294     }
00295 
00296     if (options & DRIZZLE_NON_BLOCKING)
00297     {
00298       *ret_ptr= DRIZZLE_RETURN_IO_WAIT;
00299       return NULL;
00300     }
00301 
00302     *ret_ptr= drizzle_con_wait(drizzle);
00303     if (*ret_ptr != DRIZZLE_RETURN_OK)
00304     {
00305       drizzle->options= options;
00306       return NULL;
00307     }
00308   }
00309 }
00310 
00311 drizzle_return_t drizzle_query_run_all(drizzle_st *drizzle)
00312 {
00313   drizzle_return_t ret;
00314 
00315   while (drizzle->query_new > 0 || drizzle->query_running > 0)
00316   {
00317     (void)drizzle_query_run(drizzle, &ret);
00318     if (ret != DRIZZLE_RETURN_OK && ret != DRIZZLE_RETURN_ERROR_CODE)
00319       return ret;
00320   }
00321 
00322   return DRIZZLE_RETURN_OK;
00323 }
00324 
00325 size_t drizzle_escape_string(char *to, const char *from, size_t from_size)
00326 {
00327   size_t to_size= 0;
00328 
00329   while (from_size > 0)
00330   {
00331     /* All multi-byte UTF8 characters have the high bit set for all bytes. */
00332     if (!(*from & 0x80))
00333     {
00334       switch (*from)
00335       {
00336       case 0:
00337       case '\n':
00338       case '\r':
00339       case '\\':
00340       case '\'':
00341       case '"':
00342       case '\032':
00343         *to++= '\\';
00344         to_size++;
00345       default:
00346         break;
00347       }
00348     }
00349 
00350     *to++= *from++;
00351     from_size--;
00352     to_size++;
00353   }
00354 
00355   *to= 0;
00356 
00357   return to_size;
00358 }
00359 
00360 size_t drizzle_hex_string(char *to, const char *from, size_t from_size)
00361 {
00362   static const char hex_map[]= "0123456789ABCDEF";
00363   const char *from_end;
00364 
00365   for (from_end= from + from_size; from != from_end; from++)
00366   {
00367     *to++= hex_map[((unsigned char) *from) >> 4];
00368     *to++= hex_map[((unsigned char) *from) & 0xF];
00369   }
00370 
00371   *to= 0;
00372 
00373   return from_size * 2;
00374 }