Drizzled Public API Documentation

set_var.cc
00001 /* -*- mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; -*-
00002  *  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
00003  *
00004  *  Copyright (C) 2008 Sun Microsystems, Inc.
00005  *
00006  *  This program is free software; you can redistribute it and/or modify
00007  *  it under the terms of the GNU General Public License as published by
00008  *  the Free Software Foundation; version 2 of the License.
00009  *
00010  *  This program is distributed in the hope that it will be useful,
00011  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013  *  GNU General Public License for more details.
00014  *
00015  *  You should have received a copy of the GNU General Public License
00016  *  along with this program; if not, write to the Free Software
00017  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
00018  */
00019 
00020 #include <config.h>
00021 
00022 #include <boost/foreach.hpp>
00023 #include <boost/lexical_cast.hpp>
00024 #include <boost/exception/get_error_info.hpp>
00025 #include <string>
00026 
00027 #include <drizzled/session.h>
00028 #include <drizzled/item/string.h>
00029 #include <drizzled/function/set_user_var.h>
00030 #include <drizzled/sql_lex.h>
00031 #include <drizzled/util/test.h>
00032 
00033 using namespace std;
00034 
00035 namespace drizzled
00036 {
00037 
00058 int sql_set_variables(Session *session, const SetVarVector &var_list)
00059 {
00060   int error;
00061   BOOST_FOREACH(SetVarVector::const_reference it, var_list)
00062   {
00063     if ((error= it->check(session)))
00064       goto err;
00065   }
00066   if (!(error= test(session->is_error())))
00067   {
00068     BOOST_FOREACH(SetVarVector::const_reference it, var_list)
00069     {
00070       error|= it->update(session);         // Returns 0, -1 or 1
00071     }
00072   }
00073 
00074 err:
00075   free_underlaid_joins(session, &session->lex().select_lex);
00076   return error;
00077 }
00078 
00079 
00080 /*****************************************************************************
00081   Functions to handle SET mysql_internal_variable=const_expr
00082 *****************************************************************************/
00083 set_var::set_var(sql_var_t type_arg, sys_var *var_arg, str_ref base_name_arg, Item *value_arg) :
00084   uint64_t_value(0),
00085   var(var_arg),
00086   type(type_arg),
00087   base(base_name_arg)
00088 {
00089   /*
00090     If the set value is a field, change it to a string to allow things like
00091     SET table_type=MYISAM;
00092   */
00093   if (value_arg && value_arg->type() == Item::FIELD_ITEM)
00094   {
00095     Item_field *item= (Item_field*) value_arg;
00096     value= new Item_string(str_ref(item->field_name), item->collation.collation);
00097   }
00098   else
00099   {
00100     value= value_arg;
00101   }
00102 }
00103 
00104 int set_var::check(Session *session)
00105 {
00106   if (var->is_readonly())
00107   {
00108     my_error(ER_INCORRECT_GLOBAL_LOCAL_VAR, MYF(0), var->getName().c_str(), "read only");
00109     return -1;
00110   }
00111   if (var->check_type(type))
00112   {
00113     int err= type == OPT_GLOBAL ? ER_LOCAL_VARIABLE : ER_GLOBAL_VARIABLE;
00114     my_error(static_cast<drizzled::error_t>(err), MYF(0), var->getName().c_str());
00115     return -1;
00116   }
00117   /* value is a NULL pointer if we are using SET ... = DEFAULT */
00118   if (not value)
00119   {
00120     if (var->check_default(type))
00121     {
00122       my_error(ER_NO_DEFAULT, MYF(0), var->getName().c_str());
00123       return -1;
00124     }
00125     return 0;
00126   }
00127 
00128   if ((!value->fixed &&
00129        value->fix_fields(session, &value)) || value->check_cols(1))
00130     return -1;
00131   if (var->check_update_type(value->result_type()))
00132   {
00133     my_error(ER_WRONG_TYPE_FOR_VAR, MYF(0), var->getName().c_str());
00134     return -1;
00135   }
00136   return var->check(session, this) ? -1 : 0;
00137 }
00138 
00151 int set_var::update(Session *session)
00152 {
00153   try
00154   {
00155     if (not value)
00156       var->set_default(session, type);
00157     else if (var->update(session, this))
00158       return -1;        // should never happen
00159     if (var->getAfterUpdateTrigger())
00160       (*var->getAfterUpdateTrigger())(session, type);
00161   }
00162   catch (invalid_option_value &ex)
00163   {
00164     /* TODO: Fix this to be typesafe once we have properly typed set_var */
00165     string new_val= boost::lexical_cast<string>(uint64_t_value);
00166     if (boost::get_error_info<invalid_max_info>(ex) != NULL)
00167     { 
00168       const uint64_t max_val= *(boost::get_error_info<invalid_max_info>(ex));
00169       string explanation("(> ");
00170       explanation.append(boost::lexical_cast<std::string>(max_val));
00171       explanation.push_back(')');
00172       push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_ERROR,
00173                           ER_INVALID_OPTION_VALUE,
00174                           ER(ER_INVALID_OPTION_VALUE),
00175                           var->getName().c_str(),
00176                           new_val.c_str(),
00177                           explanation.c_str());
00178     }
00179     else if (boost::get_error_info<invalid_min_info>(ex) != NULL)
00180     { 
00181       const int64_t min_val= *(boost::get_error_info<invalid_min_info>(ex));
00182       string explanation("(< ");
00183       explanation.append(boost::lexical_cast<std::string>(min_val));
00184       explanation.push_back(')');
00185       push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_ERROR,
00186                           ER_INVALID_OPTION_VALUE,
00187                           ER(ER_INVALID_OPTION_VALUE),
00188                           var->getName().c_str(),
00189                           new_val.c_str(),
00190                           explanation.c_str());
00191     }
00192     else if (boost::get_error_info<invalid_value>(ex) != NULL)
00193     {
00194       const std::string str_val= *(boost::get_error_info<invalid_value>(ex));
00195       string explanation("(");
00196       explanation.append(str_val);
00197       explanation.push_back(')');
00198       push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_ERROR,
00199                           ER_INVALID_OPTION_VALUE,
00200                           ER(ER_INVALID_OPTION_VALUE),
00201                           var->getName().c_str(),
00202                           new_val.c_str(),
00203                           explanation.c_str());
00204     }
00205     else
00206     {
00207       push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_ERROR,
00208                           ER_INVALID_OPTION_VALUE,
00209                           ER(ER_INVALID_OPTION_VALUE),
00210                           var->getName().c_str(),
00211                           new_val.c_str(),
00212                           "");
00213     }
00214   }
00215   return 0;
00216 }
00217 
00218 /*****************************************************************************
00219   Functions to handle SET @user_variable=const_expr
00220 *****************************************************************************/
00221 
00222 int set_var_user::check(Session *session)
00223 {
00224   /*
00225     Item_func_set_user_var can't substitute something else on its place =>
00226     0 can be passed as last argument (reference on item)
00227   */
00228   return (user_var_item->fix_fields(session, (Item**) 0) ||
00229     user_var_item->check(0)) ? -1 : 0;
00230 }
00231 
00232 
00233 int set_var_user::update(Session *)
00234 {
00235   user_var_item->update();
00236   return 0;
00237 }
00238 
00239 void set_var::setValue(const std::string &new_value)
00240 {
00241   str_value= new_value;
00242 }
00243 
00244 void set_var::setValue(uint64_t new_value)
00245 {
00246   uint64_t_value= new_value;
00247 }
00248 
00249 void set_var::updateValue()
00250 {
00251   if (var->show_type() != SHOW_CHAR)
00252   {
00253     uint64_t_value= value->val_int();
00254   }
00255 }
00256 
00257 
00258 } /* namespace drizzled */