~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/sql_error.cc

Moved sql_common.h and my_time.h to libdrizzle.

Show diffs side-by-side

added added

removed removed

Lines of Context:
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., 59 Temple Place, Suite 330, Boston, MA  02111-1307 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 <drizzled/server_includes.h>
45
 
 
46
 
/*
47
 
  Store a new message in an error object
48
 
 
49
 
  This is used to in group_concat() to register how many warnings we actually
50
 
  got after the query has been executed.
51
 
*/
52
 
void DRIZZLE_ERROR::set_msg(Session *session, const char *msg_arg)
53
 
{
54
 
  msg= strdup_root(&session->warn_root, msg_arg);
55
 
}
56
 
 
57
 
/*
58
 
  Reset all warnings for the thread
59
 
 
60
 
  SYNOPSIS
61
 
    drizzle_reset_errors()
62
 
    session                     Thread handle
63
 
    force               Reset warnings even if it has been done before
64
 
 
65
 
  IMPLEMENTATION
66
 
    Don't reset warnings if this has already been called for this query.
67
 
    This may happen if one gets a warning during the parsing stage,
68
 
    in which case push_warnings() has already called this function.
69
 
*/  
70
 
 
71
 
void drizzle_reset_errors(Session *session, bool force)
72
 
{
73
 
  if (session->query_id != session->warn_id || force)
74
 
  {
75
 
    session->warn_id= session->query_id;
76
 
    free_root(&session->warn_root,MYF(0));
77
 
    memset(session->warn_count, 0, sizeof(session->warn_count));
78
 
    if (force)
79
 
      session->total_warn_count= 0;
80
 
    session->warn_list.empty();
81
 
    session->row_count= 1; // by default point to row 1
82
 
  }
83
 
  return;
84
 
}
85
 
 
86
 
 
87
 
/* 
88
 
  Push the warning/error to error list if there is still room in the list
89
 
 
90
 
  SYNOPSIS
91
 
    push_warning()
92
 
    session                     Thread handle
93
 
    level               Severity of warning (note, warning, error ...)
94
 
    code                Error number
95
 
    msg                 Clear error message
96
 
    
97
 
  RETURN
98
 
    pointer on DRIZZLE_ERROR object
99
 
*/
100
 
 
101
 
DRIZZLE_ERROR *push_warning(Session *session, DRIZZLE_ERROR::enum_warning_level level, 
102
 
                          uint32_t code, const char *msg)
103
 
{
104
 
  DRIZZLE_ERROR *err= 0;
105
 
 
106
 
  if (level == DRIZZLE_ERROR::WARN_LEVEL_NOTE &&
107
 
      !(session->options & OPTION_SQL_NOTES))
108
 
    return(0);
109
 
 
110
 
  if (session->query_id != session->warn_id)
111
 
    drizzle_reset_errors(session, 0);
112
 
  session->got_warning= 1;
113
 
 
114
 
  /* Abort if we are using strict mode and we are not using IGNORE */
115
 
  if ((int) level >= (int) DRIZZLE_ERROR::WARN_LEVEL_WARN &&
116
 
      session->really_abort_on_warning())
117
 
  {
118
 
    /* Avoid my_message() calling push_warning */
119
 
    bool no_warnings_for_error= session->no_warnings_for_error;
120
 
 
121
 
    session->no_warnings_for_error= 1;
122
 
 
123
 
    session->killed= Session::KILL_BAD_DATA;
124
 
    my_message(code, msg, MYF(0));
125
 
 
126
 
    session->no_warnings_for_error= no_warnings_for_error;
127
 
    /* Store error in error list (as my_message() didn't do it) */
128
 
    level= DRIZZLE_ERROR::WARN_LEVEL_ERROR;
129
 
  }
130
 
 
131
 
  if (session->handle_error(code, msg, level))
132
 
    return(NULL);
133
 
 
134
 
  if (session->warn_list.elements < session->variables.max_error_count)
135
 
  {
136
 
    /* We have to use warn_root, as mem_root is freed after each query */
137
 
    if ((err= new (&session->warn_root) DRIZZLE_ERROR(session, code, level, msg)))
138
 
      session->warn_list.push_back(err, &session->warn_root);
139
 
  }
140
 
  session->warn_count[(uint) level]++;
141
 
  session->total_warn_count++;
142
 
  return(err);
143
 
}
144
 
 
145
 
/*
146
 
  Push the warning/error to error list if there is still room in the list
147
 
 
148
 
  SYNOPSIS
149
 
    push_warning_printf()
150
 
    session                     Thread handle
151
 
    level               Severity of warning (note, warning, error ...)
152
 
    code                Error number
153
 
    msg                 Clear error message
154
 
*/
155
 
 
156
 
void push_warning_printf(Session *session, DRIZZLE_ERROR::enum_warning_level level,
157
 
                         uint32_t code, const char *format, ...)
158
 
{
159
 
  va_list args;
160
 
  char    warning[ERRMSGSIZE+20];
161
 
  
162
 
  va_start(args,format);
163
 
  vsnprintf(warning, sizeof(warning), format, args);
164
 
  va_end(args);
165
 
  push_warning(session, level, code, warning);
166
 
  return;
167
 
}
168
 
 
169
 
 
170
 
/*
171
 
  Send all notes, errors or warnings to the client in a result set
172
 
 
173
 
  SYNOPSIS
174
 
    mysqld_show_warnings()
175
 
    session                     Thread handler
176
 
    levels_to_show      Bitmap for which levels to show
177
 
 
178
 
  DESCRIPTION
179
 
    Takes into account the current LIMIT
180
 
 
181
 
  RETURN VALUES
182
 
    false ok
183
 
    true  Error sending data to client
184
 
*/
185
 
 
186
 
const LEX_STRING warning_level_names[]=
187
 
{
188
 
  { C_STRING_WITH_LEN("Note") },
189
 
  { C_STRING_WITH_LEN("Warning") },
190
 
  { C_STRING_WITH_LEN("Error") },
191
 
  { C_STRING_WITH_LEN("?") }
192
 
};
193
 
 
194
 
bool mysqld_show_warnings(Session *session, uint32_t levels_to_show)
195
 
{  
196
 
  List<Item> field_list;
197
 
 
198
 
  field_list.push_back(new Item_empty_string("Level", 7));
199
 
  field_list.push_back(new Item_return_int("Code",4, DRIZZLE_TYPE_LONG));
200
 
  field_list.push_back(new Item_empty_string("Message",DRIZZLE_ERRMSG_SIZE));
201
 
 
202
 
  if (session->protocol->send_fields(&field_list,
203
 
                                 Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
204
 
    return(true);
205
 
 
206
 
  DRIZZLE_ERROR *err;
207
 
  SELECT_LEX *sel= &session->lex->select_lex;
208
 
  SELECT_LEX_UNIT *unit= &session->lex->unit;
209
 
  ha_rows idx= 0;
210
 
  Protocol *protocol=session->protocol;
211
 
 
212
 
  unit->set_limit(sel);
213
 
 
214
 
  List_iterator_fast<DRIZZLE_ERROR> it(session->warn_list);
215
 
  while ((err= it++))
216
 
  {
217
 
    /* Skip levels that the user is not interested in */
218
 
    if (!(levels_to_show & ((ulong) 1 << err->level)))
219
 
      continue;
220
 
    if (++idx <= unit->offset_limit_cnt)
221
 
      continue;
222
 
    if (idx > unit->select_limit_cnt)
223
 
      break;
224
 
    protocol->prepare_for_resend();
225
 
    protocol->store(warning_level_names[err->level].str,
226
 
                    warning_level_names[err->level].length, system_charset_info);
227
 
    protocol->store((uint32_t) err->code);
228
 
    protocol->store(err->msg, strlen(err->msg), system_charset_info);
229
 
    if (protocol->write())
230
 
      return(true);
231
 
  }
232
 
  my_eof(session);
233
 
  return(false);
234
 
}