~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/set_var.cc

  • Committer: Monty Taylor
  • Date: 2010-09-26 21:24:15 UTC
  • mto: (1796.1.2 build)
  • mto: This revision was merged to the branch mainline in revision 1797.
  • Revision ID: mordred@inaugust.com-20100926212415-5fn3p3q75pgiei7r
Moved protocol doc into the docs.

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, List<set_var_base> *var_list)
56
 
{
57
 
  int error;
58
 
  List_iterator_fast<set_var_base> it(*var_list);
59
 
 
60
 
  set_var_base *var;
61
 
  while ((var=it++))
62
 
  {
63
 
    if ((error= var->check(session)))
64
 
      goto err;
65
 
  }
66
 
  if (!(error= test(session->is_error())))
67
 
  {
68
 
    it.rewind();
69
 
    while ((var= it++))
70
 
      error|= var->update(session);         // Returns 0, -1 or 1
71
 
  }
72
 
 
73
 
err:
74
 
  free_underlaid_joins(session, &session->lex->select_lex);
75
 
  return(error);
76
 
}
77
 
 
78
 
 
79
 
/*****************************************************************************
80
 
  Functions to handle SET mysql_internal_variable=const_expr
81
 
*****************************************************************************/
82
 
set_var::set_var(sql_var_t type_arg, sys_var *var_arg,
83
 
                 const LEX_STRING *base_name_arg, Item *value_arg) :
84
 
  var(var_arg), type(type_arg), base(*base_name_arg)
85
 
{
86
 
  /*
87
 
    If the set value is a field, change it to a string to allow things like
88
 
    SET table_type=MYISAM;
89
 
  */
90
 
  if (value_arg && value_arg->type() == Item::FIELD_ITEM)
91
 
  {
92
 
    Item_field *item= (Item_field*) value_arg;
93
 
    if (!(value=new Item_string(item->field_name,
94
 
                                (uint32_t) strlen(item->field_name),
95
 
                                item->collation.collation)))
96
 
      value=value_arg;                  /* Give error message later */
97
 
  }
98
 
  else
99
 
    value=value_arg;
100
 
}
101
 
 
102
 
int set_var::check(Session *session)
103
 
{
104
 
  if (var->is_readonly())
105
 
  {
106
 
    my_error(ER_INCORRECT_GLOBAL_LOCAL_VAR, MYF(0), var->getName().c_str(), "read only");
107
 
    return -1;
108
 
  }
109
 
  if (var->check_type(type))
110
 
  {
111
 
    int err= type == OPT_GLOBAL ? ER_LOCAL_VARIABLE : ER_GLOBAL_VARIABLE;
112
 
    my_error(err, MYF(0), var->getName().c_str());
113
 
    return -1;
114
 
  }
115
 
  /* value is a NULL pointer if we are using SET ... = DEFAULT */
116
 
  if (!value)
117
 
  {
118
 
    if (var->check_default(type))
119
 
    {
120
 
      my_error(ER_NO_DEFAULT, MYF(0), var->getName().c_str());
121
 
      return -1;
122
 
    }
123
 
    return 0;
124
 
  }
125
 
 
126
 
  if ((!value->fixed &&
127
 
       value->fix_fields(session, &value)) || value->check_cols(1))
128
 
    return -1;
129
 
  if (var->check_update_type(value->result_type()))
130
 
  {
131
 
    my_error(ER_WRONG_TYPE_FOR_VAR, MYF(0), var->getName().c_str());
132
 
    return -1;
133
 
  }
134
 
  return var->check(session, this) ? -1 : 0;
135
 
}
136
 
 
137
 
/**
138
 
  Update variable
139
 
 
140
 
  @param   session    thread handler
141
 
  @returns 0|1    ok or ERROR
142
 
 
143
 
  @note ERROR can be only due to abnormal operations involving
144
 
  the server's execution evironment such as
145
 
  out of memory, hard disk failure or the computer blows up.
146
 
  Consider set_var::check() method if there is a need to return
147
 
  an error due to logics.
148
 
*/
149
 
int set_var::update(Session *session)
150
 
{
151
 
  try
152
 
  {
153
 
    if (! value)
154
 
      var->set_default(session, type);
155
 
    else if (var->update(session, this))
156
 
      return -1;                                // should never happen
157
 
    if (var->getAfterUpdateTrigger())
158
 
      (*var->getAfterUpdateTrigger())(session, type);
159
 
  }
160
 
  catch (invalid_option_value &ex)
161
 
  {
162
 
    /* TODO: Fix this to be typesafe once we have properly typed set_var */
163
 
    string new_val= boost::lexical_cast<string>(save_result.uint32_t_value);
164
 
    if (boost::get_error_info<invalid_max_info>(ex) != NULL)
165
 
    { 
166
 
      const uint64_t max_val= *(boost::get_error_info<invalid_max_info>(ex));
167
 
      string explanation("(> ");
168
 
      explanation.append(boost::lexical_cast<std::string>(max_val));
169
 
      explanation.push_back(')');
170
 
      push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_ERROR,
171
 
                          ER_INVALID_OPTION_VALUE,
172
 
                          ER(ER_INVALID_OPTION_VALUE),
173
 
                          var->getName().c_str(),
174
 
                          new_val.c_str(),
175
 
                          explanation.c_str());
176
 
    }
177
 
    else if (boost::get_error_info<invalid_min_info>(ex) != NULL)
178
 
    { 
179
 
      const int64_t min_val= *(boost::get_error_info<invalid_min_info>(ex));
180
 
      string explanation("(< ");
181
 
      explanation.append(boost::lexical_cast<std::string>(min_val));
182
 
      explanation.push_back(')');
183
 
      push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_ERROR,
184
 
                          ER_INVALID_OPTION_VALUE,
185
 
                          ER(ER_INVALID_OPTION_VALUE),
186
 
                          var->getName().c_str(),
187
 
                          new_val.c_str(),
188
 
                          explanation.c_str());
189
 
    }
190
 
    else
191
 
    {
192
 
      push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_ERROR,
193
 
                          ER_INVALID_OPTION_VALUE,
194
 
                          ER(ER_INVALID_OPTION_VALUE),
195
 
                          var->getName().c_str(),
196
 
                          new_val.c_str(),
197
 
                          "");
198
 
    }
199
 
  }
200
 
  return 0;
201
 
}
202
 
 
203
 
/*****************************************************************************
204
 
  Functions to handle SET @user_variable=const_expr
205
 
*****************************************************************************/
206
 
 
207
 
int set_var_user::check(Session *session)
208
 
{
209
 
  /*
210
 
    Item_func_set_user_var can't substitute something else on its place =>
211
 
    0 can be passed as last argument (reference on item)
212
 
  */
213
 
  return (user_var_item->fix_fields(session, (Item**) 0) ||
214
 
          user_var_item->check(0)) ? -1 : 0;
215
 
}
216
 
 
217
 
 
218
 
int set_var_user::update(Session *)
219
 
{
220
 
  if (user_var_item->update())
221
 
  {
222
 
    /* Give an error if it's not given already */
223
 
    my_message(ER_SET_CONSTANTS_ONLY, ER(ER_SET_CONSTANTS_ONLY), MYF(0));
224
 
    return -1;
225
 
  }
226
 
  return 0;
227
 
}
228
 
 
229
 
} /* namespace drizzled */