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 
00032 using namespace std;
00033 
00034 namespace drizzled
00035 {
00036 
00057 int sql_set_variables(Session *session, const SetVarVector &var_list)
00058 {
00059   int error;
00060   BOOST_FOREACH(SetVarVector::const_reference it, var_list)
00061   {
00062     if ((error= it->check(session)))
00063       goto err;
00064   }
00065   if (!(error= test(session->is_error())))
00066   {
00067     BOOST_FOREACH(SetVarVector::const_reference it, var_list)
00068     {
00069       error|= it->update(session);         // Returns 0, -1 or 1
00070     }
00071   }
00072 err:
00073   free_underlaid_joins(session, &session->lex().select_lex);
00074   return error;
00075 }
00076 
00077 
00078 /*****************************************************************************
00079   Functions to handle SET mysql_internal_variable=const_expr
00080 *****************************************************************************/
00081 set_var::set_var(sql_var_t type_arg, sys_var *var_arg,
00082                  const LEX_STRING *base_name_arg, Item *value_arg) :
00083   uint64_t_value(0),
00084   str_value(""),
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     if (!(value=new Item_string(item->field_name,
00097                                 (uint32_t) strlen(item->field_name),
00098                                 item->collation.collation)))
00099       value=value_arg;      /* Give error message later */
00100   }
00101   else
00102   {
00103     value= value_arg;
00104   }
00105 }
00106 
00107 int set_var::check(Session *session)
00108 {
00109   if (var->is_readonly())
00110   {
00111     my_error(ER_INCORRECT_GLOBAL_LOCAL_VAR, MYF(0), var->getName().c_str(), "read only");
00112     return -1;
00113   }
00114   if (var->check_type(type))
00115   {
00116     int err= type == OPT_GLOBAL ? ER_LOCAL_VARIABLE : ER_GLOBAL_VARIABLE;
00117     my_error(static_cast<drizzled::error_t>(err), MYF(0), var->getName().c_str());
00118     return -1;
00119   }
00120   /* value is a NULL pointer if we are using SET ... = DEFAULT */
00121   if (!value)
00122   {
00123     if (var->check_default(type))
00124     {
00125       my_error(ER_NO_DEFAULT, MYF(0), var->getName().c_str());
00126       return -1;
00127     }
00128     return 0;
00129   }
00130 
00131   if ((!value->fixed &&
00132        value->fix_fields(session, &value)) || value->check_cols(1))
00133     return -1;
00134   if (var->check_update_type(value->result_type()))
00135   {
00136     my_error(ER_WRONG_TYPE_FOR_VAR, MYF(0), var->getName().c_str());
00137     return -1;
00138   }
00139   return var->check(session, this) ? -1 : 0;
00140 }
00141 
00154 int set_var::update(Session *session)
00155 {
00156   try
00157   {
00158     if (! value)
00159       var->set_default(session, type);
00160     else if (var->update(session, this))
00161       return -1;        // should never happen
00162     if (var->getAfterUpdateTrigger())
00163       (*var->getAfterUpdateTrigger())(session, type);
00164   }
00165   catch (invalid_option_value &ex)
00166   {
00167     /* TODO: Fix this to be typesafe once we have properly typed set_var */
00168     string new_val= boost::lexical_cast<string>(uint64_t_value);
00169     if (boost::get_error_info<invalid_max_info>(ex) != NULL)
00170     { 
00171       const uint64_t max_val= *(boost::get_error_info<invalid_max_info>(ex));
00172       string explanation("(> ");
00173       explanation.append(boost::lexical_cast<std::string>(max_val));
00174       explanation.push_back(')');
00175       push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_ERROR,
00176                           ER_INVALID_OPTION_VALUE,
00177                           ER(ER_INVALID_OPTION_VALUE),
00178                           var->getName().c_str(),
00179                           new_val.c_str(),
00180                           explanation.c_str());
00181     }
00182     else if (boost::get_error_info<invalid_min_info>(ex) != NULL)
00183     { 
00184       const int64_t min_val= *(boost::get_error_info<invalid_min_info>(ex));
00185       string explanation("(< ");
00186       explanation.append(boost::lexical_cast<std::string>(min_val));
00187       explanation.push_back(')');
00188       push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_ERROR,
00189                           ER_INVALID_OPTION_VALUE,
00190                           ER(ER_INVALID_OPTION_VALUE),
00191                           var->getName().c_str(),
00192                           new_val.c_str(),
00193                           explanation.c_str());
00194     }
00195     else if (boost::get_error_info<invalid_value>(ex) != NULL)
00196     {
00197       const std::string str_val= *(boost::get_error_info<invalid_value>(ex));
00198       string explanation("(");
00199       explanation.append(str_val);
00200       explanation.push_back(')');
00201       push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_ERROR,
00202                           ER_INVALID_OPTION_VALUE,
00203                           ER(ER_INVALID_OPTION_VALUE),
00204                           var->getName().c_str(),
00205                           new_val.c_str(),
00206                           explanation.c_str());
00207     }
00208     else
00209     {
00210       push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_ERROR,
00211                           ER_INVALID_OPTION_VALUE,
00212                           ER(ER_INVALID_OPTION_VALUE),
00213                           var->getName().c_str(),
00214                           new_val.c_str(),
00215                           "");
00216     }
00217   }
00218   return 0;
00219 }
00220 
00221 /*****************************************************************************
00222   Functions to handle SET @user_variable=const_expr
00223 *****************************************************************************/
00224 
00225 int set_var_user::check(Session *session)
00226 {
00227   /*
00228     Item_func_set_user_var can't substitute something else on its place =>
00229     0 can be passed as last argument (reference on item)
00230   */
00231   return (user_var_item->fix_fields(session, (Item**) 0) ||
00232     user_var_item->check(0)) ? -1 : 0;
00233 }
00234 
00235 
00236 int set_var_user::update(Session *)
00237 {
00238   if (user_var_item->update())
00239   {
00240     /* Give an error if it's not given already */
00241     my_message(ER_SET_CONSTANTS_ONLY, ER(ER_SET_CONSTANTS_ONLY), MYF(0));
00242     return -1;
00243   }
00244   return 0;
00245 }
00246 
00247 void set_var::setValue(const std::string &new_value)
00248 {
00249   str_value= new_value;
00250 }
00251 
00252 void set_var::setValue(uint64_t new_value)
00253 {
00254   uint64_t_value= new_value;
00255 }
00256 
00257 void set_var::updateValue()
00258 {
00259   if (var->show_type() != SHOW_CHAR)
00260   {
00261     uint64_t_value= value->val_int();
00262   }
00263 }
00264 
00265 
00266 } /* namespace drizzled */