Drizzled Public API Documentation

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