Drizzled Public API Documentation

sql_error.cc
1 /* Copyright (C) 1995-2002 MySQL AB
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 /**********************************************************************
17 This file contains the implementation of error and warnings related
18 
19  - Whenever an error or warning occurred, it pushes it to a warning list
20  that the user can retrieve with SHOW WARNINGS or SHOW ERRORS.
21 
22  - For each statement, we return the number of warnings generated from this
23  command. Note that this can be different from @@warning_count as
24  we reset the warning list only for questions that uses a table.
25  This is done to allow on to do:
26  INSERT ...;
27  SELECT @@warning_count;
28  SHOW WARNINGS;
29  (If we would reset after each command, we could not retrieve the number
30  of warnings)
31 
32  - When client requests the information using SHOW command, then
33  server processes from this list and returns back in the form of
34  resultset.
35 
36  Supported syntaxes:
37 
38  SHOW [COUNT(*)] ERRORS [LIMIT [offset,] rows]
39  SHOW [COUNT(*)] WARNINGS [LIMIT [offset,] rows]
40  SELECT @@warning_count, @@error_count;
41 
42 ***********************************************************************/
43 
44 #include <config.h>
45 
46 #include <cstdio>
47 #include <stdarg.h>
48 
49 #include <drizzled/session.h>
50 #include <drizzled/sql_base.h>
51 #include <drizzled/item/empty_string.h>
52 #include <drizzled/item/return_int.h>
53 #include <drizzled/plugin/client.h>
54 #include <drizzled/sql_lex.h>
55 #include <drizzled/system_variables.h>
56 #include <drizzled/diagnostics_area.h>
57 
58 using namespace std;
59 
60 namespace drizzled {
61 
62 /*
63  Store a new message in an error object
64 
65  This is used to in group_concat() to register how many warnings we actually
66  got after the query has been executed.
67 */
68 void DRIZZLE_ERROR::set_msg(Session *session, const char *msg_arg)
69 {
70  msg= session->warn_root.strdup(msg_arg);
71 }
72 
73 /*
74  Reset all warnings for the thread
75 
76  SYNOPSIS
77  drizzle_reset_errors()
78  session Thread handle
79  force Reset warnings even if it has been done before
80 
81  IMPLEMENTATION
82  Don't reset warnings if this has already been called for this query.
83  This may happen if one gets a warning during the parsing stage,
84  in which case push_warnings() has already called this function.
85 */
86 
87 void drizzle_reset_errors(Session& session, bool force)
88 {
89  if (session.getQueryId() != session.getWarningQueryId() || force)
90  {
91  session.setWarningQueryId(session.getQueryId());
92  session.warn_root.free_root(MYF(0));
93  memset(session.warn_count, 0, sizeof(session.warn_count));
94  if (force)
95  session.total_warn_count= 0;
96  session.main_da().m_warn_list.clear();
97  session.row_count= 1; // by default point to row 1
98  }
99 }
100 
101 
102 /*
103  Push the warning/error to error list if there is still room in the list
104 
105  SYNOPSIS
106  push_warning()
107  session Thread handle
108  level Severity of warning (note, warning, error ...)
109  code Error number
110  msg Clear error message
111 
112  RETURN
113  pointer on DRIZZLE_ERROR object
114 */
115 
116 DRIZZLE_ERROR *push_warning(Session *session, DRIZZLE_ERROR::enum_warning_level level,
117  drizzled::error_t code, const char *msg)
118 {
119  if (level == DRIZZLE_ERROR::WARN_LEVEL_NOTE && !(session->options & OPTION_SQL_NOTES))
120  {
121  return NULL;
122  }
123 
124  if (session->getQueryId() != session->getWarningQueryId())
125  drizzle_reset_errors(*session, false);
126  session->got_warning= 1;
127 
128  /* Abort if we are using strict mode and we are not using IGNORE */
129  if ((int) level >= (int) DRIZZLE_ERROR::WARN_LEVEL_WARN &&
130  session->abortOnWarning())
131  {
132  /* Avoid my_message() calling push_warning */
133  bool no_warnings_for_error= session->no_warnings_for_error;
134 
135  session->no_warnings_for_error= 1;
136 
137  session->setKilled(Session::KILL_BAD_DATA);
138  my_message(code, msg, MYF(0));
139 
140  session->no_warnings_for_error= no_warnings_for_error;
141  /* Store error in error list (as my_message() didn't do it) */
142  level= DRIZZLE_ERROR::WARN_LEVEL_ERROR;
143  }
144 
145  DRIZZLE_ERROR *err= NULL;
146  if (session->main_da().m_warn_list.size() < session->variables.max_error_count)
147  {
148  /* We have to use warn_root, as mem_root is freed after each query */
149  err= new (session->warn_root) DRIZZLE_ERROR(session, code, level, msg);
150  session->main_da().m_warn_list.push_back(err);
151  }
152  session->warn_count[level]++;
153  session->total_warn_count++;
154 
155  return err;
156 }
157 
158 /*
159  Push the warning/error to error list if there is still room in the list
160 
161  SYNOPSIS
162  push_warning_printf()
163  session Thread handle
164  level Severity of warning (note, warning, error ...)
165  code Error number
166  msg Clear error message
167 */
168 
169 void push_warning_printf(Session *session, DRIZZLE_ERROR::enum_warning_level level,
170  drizzled::error_t code, const char *format, ...)
171 {
172  va_list args;
173  char warning[ERRMSGSIZE+20];
174 
175  va_start(args,format);
176  vsnprintf(warning, sizeof(warning), format, args);
177  va_end(args);
178  push_warning(session, level, code, warning);
179 }
180 
181 
182 /*
183  Send all notes, errors or warnings to the client in a result set
184 
185  SYNOPSIS
186  show_warnings()
187  session Thread handler
188  levels_to_show Bitmap for which levels to show
189 
190  DESCRIPTION
191  Takes into account the current LIMIT
192 
193  RETURN VALUES
194  false ok
195  true Error sending data to client
196 */
197 
198 const lex_string_t warning_level_names[]=
199 {
200  { C_STRING_WITH_LEN("Note") },
201  { C_STRING_WITH_LEN("Warning") },
202  { C_STRING_WITH_LEN("Error") },
203  { C_STRING_WITH_LEN("?") }
204 };
205 
206 bool show_warnings(Session *session, bitset<DRIZZLE_ERROR::NUM_ERRORS> &levels_to_show)
207 {
208  List<Item> field_list;
209 
210  field_list.push_back(new Item_empty_string("Level", 7));
211  field_list.push_back(new Item_return_int("Code",4, DRIZZLE_TYPE_LONG));
212  field_list.push_back(new Item_empty_string("Message",DRIZZLE_ERRMSG_SIZE));
213 
214  session->getClient()->sendFields(field_list);
215 
216  Select_Lex *sel= &session->lex().select_lex;
217  Select_Lex_Unit *unit= &session->lex().unit;
218  ha_rows idx= 0;
219 
220  unit->set_limit(sel);
221 
222  BOOST_FOREACH(DRIZZLE_ERROR* err, session->main_da().m_warn_list)
223  {
224  /* Skip levels that the user is not interested in */
225  if (! levels_to_show.test(err->level))
226  continue;
227  if (++idx <= unit->offset_limit_cnt)
228  continue;
229  if (idx > unit->select_limit_cnt)
230  break;
231  session->getClient()->store(warning_level_names[err->level]);
232  session->getClient()->store((uint32_t) err->code);
233  session->getClient()->store(err->msg, strlen(err->msg));
234  if (session->getClient()->flush())
235  return true;
236  }
237  session->my_eof();
238  return false;
239 }
240 
241 } /* namespace drizzled */
TODO: Rename this file - func.h is stupid.