~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/set_var.cc

  • Committer: Brian Aker
  • Date: 2010-10-20 20:26:18 UTC
  • mfrom: (1859.2.13 refactor)
  • Revision ID: brian@tangent.org-20101020202618-9222n39lm329urv5
Merge for Brian 

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* -*- mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; -*-
2
 
 *  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
3
 
 *
4
 
 *  Copyright (C) 2008 Sun Microsystems, Inc.
5
 
 *
6
 
 *  This program is free software; you can redistribute it and/or modify
7
 
 *  it under the terms of the GNU General Public License as published by
8
 
 *  the Free Software Foundation; version 2 of the License.
9
 
 *
10
 
 *  This program is distributed in the hope that it will be useful,
11
 
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 
 *  GNU General Public License for more details.
14
 
 *
15
 
 *  You should have received a copy of the GNU General Public License
16
 
 *  along with this program; if not, write to the Free Software
17
 
 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
18
 
 */
19
 
 
20
 
#include "config.h"
21
 
 
22
 
#include <boost/lexical_cast.hpp>
23
 
#include <boost/exception/get_error_info.hpp>
24
 
#include <string>
25
 
 
26
 
#include "drizzled/session.h"
27
 
#include "drizzled/item/string.h"
28
 
#include "drizzled/sql_list.h"
29
 
 
30
 
using namespace std;
31
 
 
32
 
namespace drizzled
33
 
{
34
 
 
35
 
/**
36
 
  Execute update of all variables.
37
 
 
38
 
  First run a check of all variables that all updates will go ok.
39
 
  If yes, then execute all updates, returning an error if any one failed.
40
 
 
41
 
  This should ensure that in all normal cases none all or variables are
42
 
  updated.
43
 
 
44
 
  @param Session                Thread id
45
 
  @param var_list       List of variables to update
46
 
 
47
 
  @retval
48
 
    0   ok
49
 
  @retval
50
 
    1   ERROR, message sent (normally no variables was updated)
51
 
  @retval
52
 
    -1  ERROR, message not sent
53
 
*/
54
 
 
55
 
int sql_set_variables(Session *session, const SetVarVector &var_list)
56
 
{
57
 
  int error;
58
 
 
59
 
  SetVarVector::const_iterator it(var_list.begin());
60
 
 
61
 
  while (it != var_list.end())
62
 
  {
63
 
    if ((error= (*it)->check(session)))
64
 
      goto err;
65
 
    ++it;
66
 
  }
67
 
  if (!(error= test(session->is_error())))
68
 
  {
69
 
    it= var_list.begin();
70
 
    while (it != var_list.end())
71
 
    {
72
 
      error|= (*it)->update(session);         // Returns 0, -1 or 1
73
 
      ++it;
74
 
    }
75
 
  }
76
 
 
77
 
err:
78
 
  free_underlaid_joins(session, &session->lex->select_lex);
79
 
  return(error);
80
 
}
81
 
 
82
 
 
83
 
/*****************************************************************************
84
 
  Functions to handle SET mysql_internal_variable=const_expr
85
 
*****************************************************************************/
86
 
set_var::set_var(sql_var_t type_arg, sys_var *var_arg,
87
 
                 const LEX_STRING *base_name_arg, Item *value_arg) :
88
 
  uint64_t_value(0),
89
 
  str_value(""),
90
 
  var(var_arg),
91
 
  type(type_arg),
92
 
  base(*base_name_arg)
93
 
{
94
 
  /*
95
 
    If the set value is a field, change it to a string to allow things like
96
 
    SET table_type=MYISAM;
97
 
  */
98
 
  if (value_arg && value_arg->type() == Item::FIELD_ITEM)
99
 
  {
100
 
    Item_field *item= (Item_field*) value_arg;
101
 
    if (!(value=new Item_string(item->field_name,
102
 
                                (uint32_t) strlen(item->field_name),
103
 
                                item->collation.collation)))
104
 
      value=value_arg;                  /* Give error message later */
105
 
  }
106
 
  else
107
 
  {
108
 
    value= value_arg;
109
 
  }
110
 
}
111
 
 
112
 
int set_var::check(Session *session)
113
 
{
114
 
  if (var->is_readonly())
115
 
  {
116
 
    my_error(ER_INCORRECT_GLOBAL_LOCAL_VAR, MYF(0), var->getName().c_str(), "read only");
117
 
    return -1;
118
 
  }
119
 
  if (var->check_type(type))
120
 
  {
121
 
    int err= type == OPT_GLOBAL ? ER_LOCAL_VARIABLE : ER_GLOBAL_VARIABLE;
122
 
    my_error(static_cast<drizzled::error_t>(err), MYF(0), var->getName().c_str());
123
 
    return -1;
124
 
  }
125
 
  /* value is a NULL pointer if we are using SET ... = DEFAULT */
126
 
  if (!value)
127
 
  {
128
 
    if (var->check_default(type))
129
 
    {
130
 
      my_error(ER_NO_DEFAULT, MYF(0), var->getName().c_str());
131
 
      return -1;
132
 
    }
133
 
    return 0;
134
 
  }
135
 
 
136
 
  if ((!value->fixed &&
137
 
       value->fix_fields(session, &value)) || value->check_cols(1))
138
 
    return -1;
139
 
  if (var->check_update_type(value->result_type()))
140
 
  {
141
 
    my_error(ER_WRONG_TYPE_FOR_VAR, MYF(0), var->getName().c_str());
142
 
    return -1;
143
 
  }
144
 
  return var->check(session, this) ? -1 : 0;
145
 
}
146
 
 
147
 
/**
148
 
  Update variable
149
 
 
150
 
  @param   session    thread handler
151
 
  @returns 0|1    ok or ERROR
152
 
 
153
 
  @note ERROR can be only due to abnormal operations involving
154
 
  the server's execution evironment such as
155
 
  out of memory, hard disk failure or the computer blows up.
156
 
  Consider set_var::check() method if there is a need to return
157
 
  an error due to logics.
158
 
*/
159
 
int set_var::update(Session *session)
160
 
{
161
 
  try
162
 
  {
163
 
    if (! value)
164
 
      var->set_default(session, type);
165
 
    else if (var->update(session, this))
166
 
      return -1;                                // should never happen
167
 
    if (var->getAfterUpdateTrigger())
168
 
      (*var->getAfterUpdateTrigger())(session, type);
169
 
  }
170
 
  catch (invalid_option_value &ex)
171
 
  {
172
 
    /* TODO: Fix this to be typesafe once we have properly typed set_var */
173
 
    string new_val= boost::lexical_cast<string>(uint64_t_value);
174
 
    if (boost::get_error_info<invalid_max_info>(ex) != NULL)
175
 
    { 
176
 
      const uint64_t max_val= *(boost::get_error_info<invalid_max_info>(ex));
177
 
      string explanation("(> ");
178
 
      explanation.append(boost::lexical_cast<std::string>(max_val));
179
 
      explanation.push_back(')');
180
 
      push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_ERROR,
181
 
                          ER_INVALID_OPTION_VALUE,
182
 
                          ER(ER_INVALID_OPTION_VALUE),
183
 
                          var->getName().c_str(),
184
 
                          new_val.c_str(),
185
 
                          explanation.c_str());
186
 
    }
187
 
    else if (boost::get_error_info<invalid_min_info>(ex) != NULL)
188
 
    { 
189
 
      const int64_t min_val= *(boost::get_error_info<invalid_min_info>(ex));
190
 
      string explanation("(< ");
191
 
      explanation.append(boost::lexical_cast<std::string>(min_val));
192
 
      explanation.push_back(')');
193
 
      push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_ERROR,
194
 
                          ER_INVALID_OPTION_VALUE,
195
 
                          ER(ER_INVALID_OPTION_VALUE),
196
 
                          var->getName().c_str(),
197
 
                          new_val.c_str(),
198
 
                          explanation.c_str());
199
 
    }
200
 
    else if (boost::get_error_info<invalid_value>(ex) != NULL)
201
 
    {
202
 
      const std::string str_val= *(boost::get_error_info<invalid_value>(ex));
203
 
      string explanation("(");
204
 
      explanation.append(str_val);
205
 
      explanation.push_back(')');
206
 
      push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_ERROR,
207
 
                          ER_INVALID_OPTION_VALUE,
208
 
                          ER(ER_INVALID_OPTION_VALUE),
209
 
                          var->getName().c_str(),
210
 
                          new_val.c_str(),
211
 
                          explanation.c_str());
212
 
    }
213
 
    else
214
 
    {
215
 
      push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_ERROR,
216
 
                          ER_INVALID_OPTION_VALUE,
217
 
                          ER(ER_INVALID_OPTION_VALUE),
218
 
                          var->getName().c_str(),
219
 
                          new_val.c_str(),
220
 
                          "");
221
 
    }
222
 
  }
223
 
  return 0;
224
 
}
225
 
 
226
 
/*****************************************************************************
227
 
  Functions to handle SET @user_variable=const_expr
228
 
*****************************************************************************/
229
 
 
230
 
int set_var_user::check(Session *session)
231
 
{
232
 
  /*
233
 
    Item_func_set_user_var can't substitute something else on its place =>
234
 
    0 can be passed as last argument (reference on item)
235
 
  */
236
 
  return (user_var_item->fix_fields(session, (Item**) 0) ||
237
 
          user_var_item->check(0)) ? -1 : 0;
238
 
}
239
 
 
240
 
 
241
 
int set_var_user::update(Session *)
242
 
{
243
 
  if (user_var_item->update())
244
 
  {
245
 
    /* Give an error if it's not given already */
246
 
    my_message(ER_SET_CONSTANTS_ONLY, ER(ER_SET_CONSTANTS_ONLY), MYF(0));
247
 
    return -1;
248
 
  }
249
 
  return 0;
250
 
}
251
 
 
252
 
void set_var::setValue(const std::string &new_value)
253
 
{
254
 
  str_value= new_value;
255
 
}
256
 
 
257
 
void set_var::setValue(uint64_t new_value)
258
 
{
259
 
  uint64_t_value= new_value;
260
 
}
261
 
 
262
 
void set_var::updateValue()
263
 
{
264
 
  if (var->show_type() != SHOW_CHAR)
265
 
  {
266
 
    uint64_t_value= value->val_int();
267
 
  }
268
 
}
269
 
 
270
 
 
271
 
} /* namespace drizzled */