~drizzle-trunk/drizzle/development

1878.3.1 by Monty Taylor
Split set_var.* into sys_var.* and set_var.*
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
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"
1897.4.14 by Monty Taylor
Update to support default values and properly throw warnings on value
21
22
#include <boost/lexical_cast.hpp>
23
#include <string>
24
1878.3.1 by Monty Taylor
Split set_var.* into sys_var.* and set_var.*
25
#include "drizzled/session.h"
1878.3.2 by Monty Taylor
Split out show_type into its own header and made sys_var work through
26
#include "drizzled/item/string.h"
1878.3.1 by Monty Taylor
Split set_var.* into sys_var.* and set_var.*
27
#include "drizzled/sql_list.h"
28
29
using namespace std;
30
31
namespace drizzled
32
{
33
34
/**
35
  Execute update of all variables.
36
37
  First run a check of all variables that all updates will go ok.
38
  If yes, then execute all updates, returning an error if any one failed.
39
40
  This should ensure that in all normal cases none all or variables are
41
  updated.
42
43
  @param Session		Thread id
44
  @param var_list       List of variables to update
45
46
  @retval
47
    0	ok
48
  @retval
49
    1	ERROR, message sent (normally no variables was updated)
50
  @retval
51
    -1  ERROR, message not sent
52
*/
53
54
int sql_set_variables(Session *session, List<set_var_base> *var_list)
55
{
56
  int error;
57
  List_iterator_fast<set_var_base> it(*var_list);
58
59
  set_var_base *var;
60
  while ((var=it++))
61
  {
62
    if ((error= var->check(session)))
63
      goto err;
64
  }
65
  if (!(error= test(session->is_error())))
66
  {
67
    it.rewind();
68
    while ((var= it++))
69
      error|= var->update(session);         // Returns 0, -1 or 1
70
  }
71
72
err:
73
  free_underlaid_joins(session, &session->lex->select_lex);
74
  return(error);
75
}
76
77
78
/*****************************************************************************
79
  Functions to handle SET mysql_internal_variable=const_expr
80
*****************************************************************************/
1878.3.2 by Monty Taylor
Split out show_type into its own header and made sys_var work through
81
set_var::set_var(sql_var_t type_arg, sys_var *var_arg,
82
                 const LEX_STRING *base_name_arg, Item *value_arg) :
83
  var(var_arg), type(type_arg), base(*base_name_arg)
84
{
85
  /*
86
    If the set value is a field, change it to a string to allow things like
87
    SET table_type=MYISAM;
88
  */
89
  if (value_arg && value_arg->type() == Item::FIELD_ITEM)
90
  {
91
    Item_field *item= (Item_field*) value_arg;
92
    if (!(value=new Item_string(item->field_name,
93
                                (uint32_t) strlen(item->field_name),
94
                                item->collation.collation)))
95
      value=value_arg;			/* Give error message later */
96
  }
97
  else
98
    value=value_arg;
99
}
1878.3.1 by Monty Taylor
Split set_var.* into sys_var.* and set_var.*
100
101
int set_var::check(Session *session)
102
{
103
  if (var->is_readonly())
104
  {
105
    my_error(ER_INCORRECT_GLOBAL_LOCAL_VAR, MYF(0), var->getName().c_str(), "read only");
106
    return -1;
107
  }
108
  if (var->check_type(type))
109
  {
110
    int err= type == OPT_GLOBAL ? ER_LOCAL_VARIABLE : ER_GLOBAL_VARIABLE;
111
    my_error(err, MYF(0), var->getName().c_str());
112
    return -1;
113
  }
114
  /* value is a NULL pointer if we are using SET ... = DEFAULT */
115
  if (!value)
116
  {
117
    if (var->check_default(type))
118
    {
119
      my_error(ER_NO_DEFAULT, MYF(0), var->getName().c_str());
120
      return -1;
121
    }
122
    return 0;
123
  }
124
125
  if ((!value->fixed &&
126
       value->fix_fields(session, &value)) || value->check_cols(1))
127
    return -1;
128
  if (var->check_update_type(value->result_type()))
129
  {
130
    my_error(ER_WRONG_TYPE_FOR_VAR, MYF(0), var->getName().c_str());
131
    return -1;
132
  }
133
  return var->check(session, this) ? -1 : 0;
134
}
135
136
/**
137
  Update variable
138
139
  @param   session    thread handler
140
  @returns 0|1    ok or	ERROR
141
142
  @note ERROR can be only due to abnormal operations involving
143
  the server's execution evironment such as
144
  out of memory, hard disk failure or the computer blows up.
145
  Consider set_var::check() method if there is a need to return
146
  an error due to logics.
147
*/
148
int set_var::update(Session *session)
149
{
1897.4.14 by Monty Taylor
Update to support default values and properly throw warnings on value
150
  try
151
  {
152
    if (! value)
153
      var->set_default(session, type);
154
    else if (var->update(session, this))
155
      return -1;				// should never happen
156
    if (var->getAfterUpdateTrigger())
157
      (*var->getAfterUpdateTrigger())(session, type);
158
  }
159
  catch (boost::exception &)
160
  {
1897.4.18 by Monty Taylor
Cleaned up another debugging leftover.
161
    /* TODO: Fix this to be typesafe once we have properly typed set_var */
1897.4.14 by Monty Taylor
Update to support default values and properly throw warnings on value
162
    string new_val= boost::lexical_cast<string>(save_result.uint32_t_value);
163
    push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_ERROR,
164
                        ER_TRUNCATED_WRONG_VALUE,
165
                        ER(ER_TRUNCATED_WRONG_VALUE), var->getName().c_str(),
166
                        new_val.c_str());
167
  }
1878.3.1 by Monty Taylor
Split set_var.* into sys_var.* and set_var.*
168
  return 0;
169
}
170
171
/*****************************************************************************
172
  Functions to handle SET @user_variable=const_expr
173
*****************************************************************************/
174
175
int set_var_user::check(Session *session)
176
{
177
  /*
178
    Item_func_set_user_var can't substitute something else on its place =>
179
    0 can be passed as last argument (reference on item)
180
  */
181
  return (user_var_item->fix_fields(session, (Item**) 0) ||
182
	  user_var_item->check(0)) ? -1 : 0;
183
}
184
185
186
int set_var_user::update(Session *)
187
{
188
  if (user_var_item->update())
189
  {
190
    /* Give an error if it's not given already */
191
    my_message(ER_SET_CONSTANTS_ONLY, ER(ER_SET_CONSTANTS_ONLY), MYF(0));
192
    return -1;
193
  }
194
  return 0;
195
}
196
197
} /* namespace drizzled */