MySQL 5.6.14 Source Code Document
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
sql_get_diagnostics.cc
1 /* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
2 
3  This program is free software; you can redistribute it and/or modify
4  it under the terms of the GNU General Public License as published by
5  the Free Software Foundation; version 2 of the License.
6 
7  This program is distributed in the hope that it will be useful,
8  but WITHOUT ANY WARRANTY; without even the implied warranty of
9  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  GNU General Public License for more details.
11 
12  You should have received a copy of the GNU General Public License
13  along with this program; if not, write to the Free Software
14  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
15 
16 #include "sql_list.h" // Sql_alloc, List, List_iterator
17 #include "sql_cmd.h" // Sql_cmd
18 #include "sql_class.h" // Diagnostics_area
19 #include "sql_get_diagnostics.h" // Sql_cmd_get_diagnostics
20 
42 bool
44 {
45  bool rv;
46  Diagnostics_area new_stmt_da(thd->query_id, false);
47  Diagnostics_area *save_stmt_da= thd->get_stmt_da();
48  DBUG_ENTER("Sql_cmd_get_diagnostics::execute");
49 
50  /* Disable the unneeded read-only mode of the original DA. */
51  save_stmt_da->set_warning_info_read_only(false);
52 
53  /* Set new diagnostics area, execute statement and restore. */
54  thd->set_stmt_da(&new_stmt_da);
55  rv= m_info->aggregate(thd, save_stmt_da);
56  thd->set_stmt_da(save_stmt_da);
57 
58  /* Bail out early if statement succeeded. */
59  if (! rv)
60  {
61  thd->get_stmt_da()->set_ok_status(0, 0, NULL);
62  DBUG_RETURN(false);
63  }
64 
65  /* Statement failed, retrieve the error information for propagation. */
66  uint sql_errno= new_stmt_da.sql_errno();
67  const char *message= new_stmt_da.message();
68  const char *sqlstate= new_stmt_da.get_sqlstate();
69 
70  /* In case of a fatal error, set it into the original DA.*/
71  if (thd->is_fatal_error)
72  {
73  save_stmt_da->set_error_status(sql_errno, message, sqlstate, NULL);
74  DBUG_RETURN(true);
75  }
76 
77  /* Otherwise, just append the new error as a exception condition. */
78  save_stmt_da->push_warning(thd, sql_errno, sqlstate,
79  Sql_condition::WARN_LEVEL_ERROR,
80  message);
81 
82  /* Appending might have failed. */
83  if (! (rv= thd->is_error()))
84  thd->get_stmt_da()->set_ok_status(0, 0, NULL);
85 
86  DBUG_RETURN(rv);
87 }
88 
89 
100 bool
102 {
103  bool rv;
105  DBUG_ENTER("Diagnostics_information_item::set_value");
106 
107  /* Get a settable reference to the target. */
108  srp= m_target->get_settable_routine_parameter();
109 
110  DBUG_ASSERT(srp);
111 
112  /* Set variable/parameter value. */
113  rv= srp->set_value(thd, thd->sp_runtime_ctx, value);
114 
115  DBUG_RETURN(rv);
116 }
117 
118 
129 bool
131 {
132  bool rv= false;
133  Statement_information_item *stmt_info_item;
135  DBUG_ENTER("Statement_information::aggregate");
136 
137  /*
138  Each specified target gets the value of each given
139  information item obtained from the diagnostics area.
140  */
141  while ((stmt_info_item= it++))
142  {
143  if ((rv= evaluate(thd, stmt_info_item, da)))
144  break;
145  }
146 
147  DBUG_RETURN(rv);
148 }
149 
150 
162 Item *
164 {
165  Item *value= NULL;
166  DBUG_ENTER("Statement_information_item::get_value");
167 
168  switch (m_name)
169  {
170  /*
171  The number of condition areas that have information. That is,
172  the number of errors and warnings within the diagnostics area.
173  */
174  case NUMBER:
175  {
176  ulong count= da->cond_count();
177  value= new (thd->mem_root) Item_uint(count);
178  break;
179  }
180  /*
181  Number that shows how many rows were directly affected by
182  a data-change statement (INSERT, UPDATE, DELETE, MERGE,
183  REPLACE, LOAD).
184  */
185  case ROW_COUNT:
186  value= new (thd->mem_root) Item_int(thd->get_row_count_func());
187  break;
188  }
189 
190  DBUG_RETURN(value);
191 }
192 
193 
204 bool
206 {
207  bool rv= false;
208  longlong cond_number;
209  const Sql_condition *cond= NULL;
210  Condition_information_item *cond_info_item;
211  Diagnostics_area::Sql_condition_iterator it_conds= da->sql_conditions();
213  DBUG_ENTER("Condition_information::aggregate");
214 
215  /* Prepare the expression for evaluation. */
216  if (!m_cond_number_expr->fixed &&
217  m_cond_number_expr->fix_fields(thd, &m_cond_number_expr))
218  DBUG_RETURN(true);
219 
220  cond_number= m_cond_number_expr->val_int();
221 
222  /*
223  Limit to the number of available conditions. Warning_info::warn_count()
224  is not used because it indicates the number of condition regardless of
225  @@max_error_count, which prevents conditions from being pushed, but not
226  counted.
227  */
228  if (cond_number < 1 || (ulonglong) cond_number > da->cond_count())
229  {
230  my_error(ER_DA_INVALID_CONDITION_NUMBER, MYF(0));
231  DBUG_RETURN(true);
232  }
233 
234  /* Advance to the requested condition. */
235  while (cond_number--)
236  cond= it_conds++;
237 
238  DBUG_ASSERT(cond);
239 
240  /* Evaluate the requested information in the context of the condition. */
241  while ((cond_info_item= it_items++))
242  {
243  if ((rv= evaluate(thd, cond_info_item, cond)))
244  break;
245  }
246 
247  DBUG_RETURN(rv);
248 }
249 
250 
263 Item *
264 Condition_information_item::make_utf8_string_item(THD *thd, const String *str)
265 {
266  /* Default is utf8 character set and utf8_general_ci collation. */
267  const CHARSET_INFO *to_cs= &my_charset_utf8_general_ci;
268  /* If a charset was not set, assume that no conversion is needed. */
269  const CHARSET_INFO *from_cs= str->charset() ? str->charset() : to_cs;
270  Item_string *item= new Item_string(str->ptr(), str->length(), from_cs);
271  /* If necessary, convert the string (ignoring errors), then copy it over. */
272  return item ? item->charset_converter(to_cs, false) : NULL;
273 }
274 
275 
287 Item *
289 {
290  String str;
291  Item *value= NULL;
292  DBUG_ENTER("Condition_information_item::get_value");
293 
294  switch (m_name)
295  {
296  case CLASS_ORIGIN:
297  value= make_utf8_string_item(thd, &(cond->m_class_origin));
298  break;
299  case SUBCLASS_ORIGIN:
300  value= make_utf8_string_item(thd, &(cond->m_subclass_origin));
301  break;
302  case CONSTRAINT_CATALOG:
303  value= make_utf8_string_item(thd, &(cond->m_constraint_catalog));
304  break;
305  case CONSTRAINT_SCHEMA:
306  value= make_utf8_string_item(thd, &(cond->m_constraint_schema));
307  break;
308  case CONSTRAINT_NAME:
309  value= make_utf8_string_item(thd, &(cond->m_constraint_name));
310  break;
311  case CATALOG_NAME:
312  value= make_utf8_string_item(thd, &(cond->m_catalog_name));
313  break;
314  case SCHEMA_NAME:
315  value= make_utf8_string_item(thd, &(cond->m_schema_name));
316  break;
317  case TABLE_NAME:
318  value= make_utf8_string_item(thd, &(cond->m_table_name));
319  break;
320  case COLUMN_NAME:
321  value= make_utf8_string_item(thd, &(cond->m_column_name));
322  break;
323  case CURSOR_NAME:
324  value= make_utf8_string_item(thd, &(cond->m_cursor_name));
325  break;
326  case MESSAGE_TEXT:
327  value= make_utf8_string_item(thd, &(cond->m_message_text));
328  break;
329  case MYSQL_ERRNO:
330  value= new (thd->mem_root) Item_uint(cond->m_sql_errno);
331  break;
332  case RETURNED_SQLSTATE:
333  str.set_ascii(cond->get_sqlstate(), strlen(cond->get_sqlstate()));
334  value= make_utf8_string_item(thd, &str);
335  break;
336  }
337 
338  DBUG_RETURN(value);
339 }
340