Drizzled Public API Documentation

query.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 drizzle_result_st *drizzle_query(drizzle_con_st *con, drizzle_result_st *result,
00046                                  const char *query, size_t size,
00047                                  drizzle_return_t *ret_ptr)
00048 {
00049   return drizzle_con_command_write(con, result, DRIZZLE_COMMAND_QUERY,
00050                                    (uint8_t *)query, size, size, ret_ptr);
00051 }
00052 
00053 drizzle_result_st *drizzle_query_str(drizzle_con_st *con,
00054                                      drizzle_result_st *result,
00055                                      const char *query, 
00056                                      drizzle_return_t *ret_ptr)
00057 {
00058   if (query == NULL)
00059   {
00060     return NULL;
00061   }
00062 
00063   size_t size= strlen(query);
00064 
00065   return drizzle_con_command_write(con, result, DRIZZLE_COMMAND_QUERY,
00066                                    (uint8_t *)query, size, size, ret_ptr);
00067 }
00068 
00069 drizzle_result_st *drizzle_query_inc(drizzle_con_st *con,
00070                                      drizzle_result_st *result,
00071                                      const char *query, size_t size,
00072                                      size_t total, drizzle_return_t *ret_ptr)
00073 {
00074   return drizzle_con_command_write(con, result, DRIZZLE_COMMAND_QUERY,
00075                                    (uint8_t *)query, size, total, ret_ptr);
00076 }
00077 
00078 drizzle_query_st *drizzle_query_add(drizzle_st *drizzle,
00079                                     drizzle_query_st *query,
00080                                     drizzle_con_st *con,
00081                                     drizzle_result_st *result,
00082                                     const char *query_string, size_t size,
00083                                     drizzle_query_options_t options,
00084                                     void *context)
00085 {
00086   if (drizzle == NULL)
00087   {
00088     return NULL;
00089   }
00090 
00091   query= drizzle_query_create(drizzle, query);
00092   if (query == NULL)
00093   {
00094     return NULL;
00095   }
00096 
00097   drizzle_query_set_con(query, con);
00098   drizzle_query_set_result(query, result);
00099   drizzle_query_set_string(query, query_string, size);
00100   drizzle_query_add_options(query, options);
00101   drizzle_query_set_context(query, context);
00102 
00103   return query;
00104 }
00105 
00106 drizzle_query_st *drizzle_query_create(drizzle_st *drizzle,
00107                                        drizzle_query_st *query)
00108 {
00109   if (drizzle == NULL)
00110   {
00111     return NULL;
00112   }
00113 
00114   if (query == NULL)
00115   {
00116     query= new (std::nothrow) drizzle_query_st;
00117     if (query == NULL)
00118     {
00119       drizzle_set_error(drizzle, __func__, "Failed to allocate.");
00120       return NULL;
00121     }
00122 
00123     query->options|= DRIZZLE_CON_ALLOCATED;
00124   }
00125   else
00126   {
00127     memset(query, 0, sizeof(drizzle_query_st));
00128   }
00129 
00130   query->drizzle= drizzle;
00131 
00132   if (drizzle->query_list)
00133     drizzle->query_list->prev= query;
00134   query->next= drizzle->query_list;
00135   drizzle->query_list= query;
00136   drizzle->query_count++;
00137   drizzle->query_new++;
00138 
00139   return query;
00140 }
00141 
00142 void drizzle_query_free(drizzle_query_st *query)
00143 {
00144   if (query == NULL)
00145   {
00146     return;
00147   }
00148 
00149   if (query->context != NULL && query->context_free_fn != NULL)
00150     query->context_free_fn(query, query->context);
00151 
00152   if (query->drizzle->query_list == query)
00153     query->drizzle->query_list= query->next;
00154 
00155   if (query->prev)
00156     query->prev->next= query->next;
00157 
00158   if (query->next)
00159     query->next->prev= query->prev;
00160   query->drizzle->query_count--;
00161 
00162   if (query->options & DRIZZLE_QUERY_ALLOCATED)
00163   {
00164     delete query;
00165   }
00166 }
00167 
00168 void drizzle_query_free_all(drizzle_st *drizzle)
00169 {
00170   if (drizzle == NULL)
00171   {
00172     return;
00173   }
00174 
00175   while (drizzle->query_list != NULL)
00176   {
00177     drizzle_query_free(drizzle->query_list);
00178   }
00179 }
00180 
00181 drizzle_con_st *drizzle_query_con(drizzle_query_st *query)
00182 {
00183   if (query == NULL)
00184   {
00185     return NULL;
00186   }
00187 
00188   return query->con;
00189 }
00190 
00191 void drizzle_query_set_con(drizzle_query_st *query, drizzle_con_st *con)
00192 {
00193   if (query == NULL)
00194   {
00195     return;
00196   }
00197 
00198   query->con= con;
00199 }
00200 
00201 drizzle_result_st *drizzle_query_result(drizzle_query_st *query)
00202 {
00203   if (query == NULL)
00204   {
00205     return NULL;
00206   }
00207 
00208   return query->result;
00209 }
00210 
00211 void drizzle_query_set_result(drizzle_query_st *query,
00212                               drizzle_result_st *result)
00213 {
00214   if (query == NULL)
00215   {
00216     return;
00217   }
00218 
00219   query->result= result;
00220 }
00221 
00222 char *drizzle_query_string(drizzle_query_st *query, size_t *size)
00223 {
00224   if (query == NULL)
00225   {
00226     return NULL;
00227   }
00228 
00229   if (size)
00230   {
00231     *size= query->size;
00232   }
00233 
00234   return (char *)(query->string);
00235 }
00236 
00237 void drizzle_query_set_string(drizzle_query_st *query, const char *string,
00238                               size_t size)
00239 {
00240   if (query == NULL)
00241   {
00242     return;
00243   }
00244 
00245   query->string= string;
00246   query->size= size;
00247 }
00248 
00249 drizzle_query_options_t drizzle_query_options(drizzle_query_st *query)
00250 {
00251   if (query == NULL)
00252   {
00253     return drizzle_query_options_t();
00254   }
00255 
00256   return drizzle_query_options_t(query->options);
00257 }
00258 
00259 void drizzle_query_set_options(drizzle_query_st *query,
00260                                drizzle_query_options_t options)
00261 {
00262   if (query == NULL)
00263   {
00264     return;
00265   }
00266 
00267   query->options= options;
00268 }
00269 
00270 void drizzle_query_add_options(drizzle_query_st *query,
00271                                drizzle_query_options_t options)
00272 {
00273   if (query == NULL)
00274   {
00275     return;
00276   }
00277 
00278   query->options|= options;
00279 }
00280 
00281 void drizzle_query_remove_options(drizzle_query_st *query,
00282                                   drizzle_query_options_t options)
00283 {
00284   if (query == NULL)
00285   {
00286     return;
00287   }
00288 
00289   query->options&= ~options;
00290 }
00291 
00292 void *drizzle_query_context(drizzle_query_st *query)
00293 {
00294   if (query == NULL)
00295   {
00296     return NULL;
00297   }
00298 
00299   return query->context;
00300 }
00301 
00302 void drizzle_query_set_context(drizzle_query_st *query, void *context)
00303 {
00304   if (query == NULL)
00305   {
00306     return;
00307   }
00308 
00309   query->context= context;
00310 }
00311 
00312 void drizzle_query_set_context_free_fn(drizzle_query_st *query,
00313                                        drizzle_query_context_free_fn *function)
00314 {
00315   if (query == NULL)
00316   {
00317     return;
00318   }
00319 
00320   query->context_free_fn= function;
00321 }
00322 
00323 static void drizzle_query_run_state(drizzle_query_st* query,
00324                                     drizzle_return_t* ret_ptr)
00325 {
00326   drizzle_return_t unused_ret;
00327   if (ret_ptr == NULL)
00328   {
00329     ret_ptr= &unused_ret;
00330   }
00331 
00332   if (query == NULL)
00333   {
00334     *ret_ptr= DRIZZLE_RETURN_INVALID_ARGUMENT;
00335     return;
00336   }
00337 
00338   switch (query->state)
00339   {
00340   case DRIZZLE_QUERY_STATE_INIT:
00341     query->state= DRIZZLE_QUERY_STATE_QUERY;
00342   case DRIZZLE_QUERY_STATE_QUERY:
00343     query->result= drizzle_query(query->con, query->result, query->string,
00344                                  query->size, ret_ptr);
00345     if (*ret_ptr == DRIZZLE_RETURN_IO_WAIT)
00346     {
00347       return;
00348     }
00349     else if (*ret_ptr != DRIZZLE_RETURN_OK)
00350     {
00351       query->state= DRIZZLE_QUERY_STATE_DONE;
00352       return;
00353     }
00354 
00355     query->state= DRIZZLE_QUERY_STATE_RESULT;
00356 
00357   case DRIZZLE_QUERY_STATE_RESULT:
00358     *ret_ptr= drizzle_result_buffer(query->result);
00359     if (*ret_ptr == DRIZZLE_RETURN_IO_WAIT)
00360     {
00361       return;
00362     }
00363 
00364     query->state= DRIZZLE_QUERY_STATE_DONE;
00365     return;
00366 
00367   default:
00368   case DRIZZLE_QUERY_STATE_DONE:
00369     return;
00370   }
00371 }
00372 
00373 drizzle_query_st *drizzle_query_run(drizzle_st *drizzle,
00374                                     drizzle_return_t *ret_ptr)
00375 {
00376   drizzle_return_t unused_ret;
00377   if (ret_ptr == NULL)
00378   {
00379     ret_ptr= &unused_ret;
00380   }
00381 
00382   if (drizzle == NULL)
00383   {
00384     *ret_ptr= DRIZZLE_RETURN_INVALID_ARGUMENT;
00385     return NULL;
00386   }
00387 
00388   int options;
00389   drizzle_query_st *query;
00390   drizzle_con_st *con;
00391 
00392   if (drizzle->query_new == 0 && drizzle->query_running == 0)
00393   {
00394     *ret_ptr= DRIZZLE_RETURN_OK;
00395     return NULL;
00396   }
00397 
00398   options= int(drizzle->options);
00399   drizzle->options|= int(DRIZZLE_NON_BLOCKING);
00400 
00401   /* Check to see if any queries need to be started. */
00402   if (drizzle->query_new > 0)
00403   {
00404     for (query= drizzle->query_list; query != NULL; query= query->next)
00405     {
00406       if (query->state != DRIZZLE_QUERY_STATE_INIT)
00407         continue;
00408 
00409       drizzle->query_new--;
00410       drizzle->query_running++;
00411       assert(query->con->query == NULL);
00412       query->con->query= query;
00413 
00414       drizzle_query_run_state(query, ret_ptr);
00415       if (*ret_ptr != DRIZZLE_RETURN_IO_WAIT)
00416       {
00417         assert(query->state == DRIZZLE_QUERY_STATE_DONE);
00418         drizzle->query_running--;
00419         drizzle->options= int(options);
00420         query->con->query= NULL;
00421         if (*ret_ptr == DRIZZLE_RETURN_ERROR_CODE || *ret_ptr == DRIZZLE_RETURN_OK)
00422         {
00423           return query;
00424         }
00425         return NULL;
00426       }
00427     }
00428     assert(drizzle->query_new == 0);
00429   }
00430 
00431   while (1)
00432   {
00433     /* Loop through each active connection. */
00434     while ((con= drizzle_con_ready(drizzle)) != NULL)
00435     {
00436       query= con->query;
00437       drizzle_query_run_state(query, ret_ptr);
00438       if (query->state == DRIZZLE_QUERY_STATE_DONE)
00439       {
00440         drizzle->query_running--;
00441         drizzle->options= options;
00442         con->query= NULL;
00443         return query;
00444       }
00445       assert(*ret_ptr == DRIZZLE_RETURN_IO_WAIT);
00446     }
00447 
00448     if (options & DRIZZLE_NON_BLOCKING)
00449     {
00450       *ret_ptr= DRIZZLE_RETURN_IO_WAIT;
00451       return NULL;
00452     }
00453 
00454     *ret_ptr= drizzle_con_wait(drizzle);
00455     if (*ret_ptr != DRIZZLE_RETURN_OK)
00456     {
00457       drizzle->options= options;
00458       return NULL;
00459     }
00460   }
00461 }
00462 
00463 drizzle_return_t drizzle_query_run_all(drizzle_st *drizzle)
00464 {
00465   if (drizzle == NULL)
00466   {
00467     return DRIZZLE_RETURN_INVALID_ARGUMENT;
00468   }
00469 
00470   while (drizzle->query_new > 0 || drizzle->query_running > 0)
00471   {
00472     drizzle_return_t ret;
00473 
00474     (void)drizzle_query_run(drizzle, &ret);
00475     if (ret != DRIZZLE_RETURN_OK && ret != DRIZZLE_RETURN_ERROR_CODE)
00476       return ret;
00477   }
00478 
00479   return DRIZZLE_RETURN_OK;
00480 }
00481 
00482 ssize_t drizzle_safe_escape_string(char *to, const size_t max_to_size, const char *from, const size_t from_size)
00483 {
00484   if (to == NULL or max_to_size == 0 or from == NULL or from_size == 0)
00485   {
00486     return -1;
00487   }
00488 
00489   ssize_t to_size= 0;
00490   char newchar;
00491 
00492   for (const char *end= from +from_size; from < end; from++)
00493   {
00494     newchar= 0;
00495     /* All multi-byte UTF8 characters have the high bit set for all bytes. */
00496     if (!(*from & 0x80))
00497     {
00498       switch (*from)
00499       {
00500       case 0:
00501         newchar= '0';
00502         break;
00503       case '\n':
00504         newchar= 'n';
00505         break;
00506       case '\r':
00507         newchar= 'r';
00508         break;
00509       case '\032':
00510         newchar= 'Z';
00511         break;
00512       case '\\':
00513         newchar= '\\';
00514         break;
00515       case '\'':
00516         newchar= '\'';
00517         break;
00518       case '"':
00519         newchar= '"';
00520         break;
00521       default:
00522         break;
00523       }
00524     }
00525     if (newchar != '\0')
00526     {
00527       if ((size_t)to_size + 2 > max_to_size)
00528         return -1;
00529 
00530       *to++= '\\';
00531       *to++= newchar;
00532       to_size++;
00533     }
00534     else
00535     {
00536       if ((size_t)to_size + 1 > max_to_size)
00537         return -1;
00538 
00539       *to++= *from;
00540     }
00541     to_size++;
00542   }
00543 
00544   *to= 0;
00545 
00546   return to_size;
00547 }
00548 
00549 size_t drizzle_escape_string(char *to, const char *from, const size_t from_size)
00550 {
00551   return size_t(drizzle_safe_escape_string(to, (from_size * 2), from, from_size));
00552 }
00553 
00554 size_t drizzle_hex_string(char *to, const char *from, const size_t from_size)
00555 {
00556   if (to == NULL or from == NULL or from_size == 0)
00557   {
00558     return size_t(-1);
00559   }
00560 
00561   static const char hex_map[]= "0123456789ABCDEF";
00562   const char *from_end;
00563 
00564   for (from_end= from + from_size; from != from_end; from++)
00565   {
00566     *to++= hex_map[((unsigned char) *from) >> 4];
00567     *to++= hex_map[((unsigned char) *from) & 0xF];
00568   }
00569 
00570   *to= 0;
00571 
00572   return from_size * 2;
00573 }
00574 
00575 void drizzle_mysql_password_hash(char *to, const char *from, const size_t from_size)
00576 {
00577   SHA1_CTX ctx;
00578   uint8_t hash_tmp1[SHA1_DIGEST_LENGTH];
00579   uint8_t hash_tmp2[SHA1_DIGEST_LENGTH];
00580 
00581   SHA1Init(&ctx);
00582   SHA1Update(&ctx, (const uint8_t*)from, from_size);
00583   SHA1Final(hash_tmp1, &ctx);
00584 
00585   SHA1Init(&ctx);
00586   SHA1Update(&ctx, hash_tmp1, SHA1_DIGEST_LENGTH);
00587   SHA1Final(hash_tmp2, &ctx);
00588 
00589   (void)drizzle_hex_string(to, (char*)hash_tmp2, SHA1_DIGEST_LENGTH);
00590 }