1 /* Copyright (c) 2002, 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, version 2.0,
5 as published by the Free Software Foundation.
6
7 This program is also distributed with certain software (including
8 but not limited to OpenSSL) that is licensed under separate terms,
9 as designated in a particular file or component or in included license
10 documentation. The authors of MySQL hereby grant you an additional
11 permission to link the program and your derivative works with the
12 separately licensed software that they have included with MySQL.
13
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License, version 2.0, for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software Foundation,
21 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA */
22
23 #include "sql_priv.h"
24 #include "unireg.h"
25 #include "mysql.h"
26 #include "sp.h" // sp_eval_expr
27 #include "sql_cursor.h"
28 #include "sp_rcontext.h"
29 #include "sp_pcontext.h"
30 #include "sql_tmp_table.h" // create_virtual_tmp_table
31 #include "sp_instr.h"
32
33 extern "C" void sql_alloc_error_handler(void);
34
35 ///////////////////////////////////////////////////////////////////////////
36 // sp_rcontext implementation.
37 ///////////////////////////////////////////////////////////////////////////
38
39
sp_rcontext(const sp_pcontext * root_parsing_ctx,Field * return_value_fld,bool in_sub_stmt)40 sp_rcontext::sp_rcontext(const sp_pcontext *root_parsing_ctx,
41 Field *return_value_fld,
42 bool in_sub_stmt)
43 :end_partial_result_set(false),
44 m_root_parsing_ctx(root_parsing_ctx),
45 m_var_table(NULL),
46 m_return_value_fld(return_value_fld),
47 m_return_value_set(false),
48 m_in_sub_stmt(in_sub_stmt),
49 m_ccount(0)
50 {
51 }
52
53
~sp_rcontext()54 sp_rcontext::~sp_rcontext()
55 {
56 if (m_var_table)
57 free_blobs(m_var_table);
58
59 while (m_activated_handlers.elements())
60 delete m_activated_handlers.pop();
61
62 while (m_visible_handlers.elements())
63 delete m_visible_handlers.pop();
64
65 pop_all_cursors();
66
67 // Leave m_var_items and m_case_expr_holders untouched.
68 // They are allocated in mem roots and will be freed accordingly.
69 }
70
71
create(THD * thd,const sp_pcontext * root_parsing_ctx,Field * return_value_fld)72 sp_rcontext *sp_rcontext::create(THD *thd,
73 const sp_pcontext *root_parsing_ctx,
74 Field *return_value_fld)
75 {
76 sp_rcontext *ctx= new (thd->mem_root) sp_rcontext(root_parsing_ctx,
77 return_value_fld,
78 thd->in_sub_stmt);
79
80 if (!ctx)
81 return NULL;
82
83 if (ctx->alloc_arrays(thd) ||
84 ctx->init_var_table(thd) ||
85 ctx->init_var_items(thd))
86 {
87 delete ctx;
88 return NULL;
89 }
90
91 return ctx;
92 }
93
94
alloc_arrays(THD * thd)95 bool sp_rcontext::alloc_arrays(THD *thd)
96 {
97 {
98 size_t n= m_root_parsing_ctx->max_cursor_index();
99 m_cstack.reset(
100 static_cast<sp_cursor **> (
101 thd->alloc(n * sizeof (sp_cursor*))),
102 n);
103 }
104
105 {
106 size_t n= m_root_parsing_ctx->get_num_case_exprs();
107 m_case_expr_holders.reset(
108 static_cast<Item_cache **> (
109 thd->calloc(n * sizeof (Item_cache*))),
110 n);
111 }
112
113 return !m_cstack.array() || !m_case_expr_holders.array();
114 }
115
116
init_var_table(THD * thd)117 bool sp_rcontext::init_var_table(THD *thd)
118 {
119 List<Create_field> field_def_lst;
120
121 if (!m_root_parsing_ctx->max_var_index())
122 return false;
123
124 m_root_parsing_ctx->retrieve_field_definitions(&field_def_lst);
125
126 DBUG_ASSERT(field_def_lst.elements == m_root_parsing_ctx->max_var_index());
127
128 if (!(m_var_table= create_virtual_tmp_table(thd, field_def_lst)))
129 return true;
130
131 m_var_table->copy_blobs= true;
132 m_var_table->alias= "";
133
134 return false;
135 }
136
137
init_var_items(THD * thd)138 bool sp_rcontext::init_var_items(THD *thd)
139 {
140 uint num_vars= m_root_parsing_ctx->max_var_index();
141
142 m_var_items.reset(
143 static_cast<Item **> (
144 thd->alloc(num_vars * sizeof (Item *))),
145 num_vars);
146
147 if (!m_var_items.array())
148 return true;
149
150 for (uint idx = 0; idx < num_vars; ++idx)
151 {
152 if (!(m_var_items[idx]= new Item_field(m_var_table->field[idx])))
153 return true;
154 }
155
156 return false;
157 }
158
159
set_return_value(THD * thd,Item ** return_value_item)160 bool sp_rcontext::set_return_value(THD *thd, Item **return_value_item)
161 {
162 DBUG_ASSERT(m_return_value_fld);
163
164 m_return_value_set = true;
165
166 return sp_eval_expr(thd, m_return_value_fld, return_value_item);
167 }
168
169
push_cursor(sp_instr_cpush * i)170 bool sp_rcontext::push_cursor(sp_instr_cpush *i)
171 {
172 /*
173 We should create cursors on the system heap because:
174 - they could be (and usually are) used in several instructions,
175 thus they can not be stored on an execution mem-root;
176 - a cursor can be pushed/popped many times in a loop, having these objects
177 on callers' mem-root would lead to a memory leak in every iteration.
178 */
179 sp_cursor *c= new (std::nothrow) sp_cursor(i);
180
181 if (!c)
182 {
183 sql_alloc_error_handler();
184 return true;
185 }
186
187 m_cstack[m_ccount++]= c;
188 return false;
189 }
190
191
pop_cursors(uint count)192 void sp_rcontext::pop_cursors(uint count)
193 {
194 DBUG_ASSERT(m_ccount >= count);
195
196 while (count--)
197 delete m_cstack[--m_ccount];
198 }
199
200
push_handler(sp_handler * handler,uint first_ip)201 bool sp_rcontext::push_handler(sp_handler *handler, uint first_ip)
202 {
203 /*
204 We should create handler entries on the system heap because:
205 - they could be (and usually are) used in several instructions,
206 thus they can not be stored on an execution mem-root;
207 - a handler can be pushed/popped many times in a loop, having these
208 objects on callers' mem-root would lead to a memory leak in every
209 iteration.
210 */
211
212 sp_handler_entry *he=
213 new (std::nothrow) sp_handler_entry(handler, first_ip);
214
215 if (!he)
216 {
217 sql_alloc_error_handler();
218 return true;
219 }
220
221 return m_visible_handlers.append(he);
222 }
223
224
pop_handlers(sp_pcontext * current_scope)225 void sp_rcontext::pop_handlers(sp_pcontext *current_scope)
226 {
227 for (int i= m_visible_handlers.elements() - 1; i >= 0; --i)
228 {
229 int handler_level= m_visible_handlers.at(i)->handler->scope->get_level();
230
231 if (handler_level >= current_scope->get_level())
232 delete m_visible_handlers.pop();
233 }
234 }
235
236
exit_handler(sp_pcontext * target_scope)237 void sp_rcontext::exit_handler(sp_pcontext *target_scope)
238 {
239 // Pop the current handler frame.
240
241 delete m_activated_handlers.pop();
242
243 // Pop frames below the target scope level.
244
245 for (int i= m_activated_handlers.elements() - 1; i >= 0; --i)
246 {
247 int handler_level= m_activated_handlers.at(i)->handler->scope->get_level();
248
249 /*
250 Only pop until we hit the first handler with appropriate scope level.
251 Otherwise we can end up popping handlers from separate scopes.
252 */
253 if (handler_level > target_scope->get_level())
254 delete m_activated_handlers.pop();
255 else
256 break;
257 }
258 }
259
260
handle_sql_condition(THD * thd,uint * ip,const sp_instr * cur_spi)261 bool sp_rcontext::handle_sql_condition(THD *thd,
262 uint *ip,
263 const sp_instr *cur_spi)
264 {
265 DBUG_ENTER("sp_rcontext::handle_sql_condition");
266
267 /*
268 If this is a fatal sub-statement error, and this runtime
269 context corresponds to a sub-statement, no CONTINUE/EXIT
270 handlers from this context are applicable: try to locate one
271 in the outer scope.
272 */
273 if (thd->is_fatal_sub_stmt_error && m_in_sub_stmt)
274 DBUG_RETURN(false);
275
276 Diagnostics_area *da= thd->get_stmt_da();
277 const sp_handler *found_handler= NULL;
278
279 uint condition_sql_errno= 0;
280 Sql_condition::enum_warning_level condition_level=
281 Sql_condition::WARN_LEVEL_NOTE;
282 const char *condition_sqlstate= NULL;
283 const char *condition_message= NULL;
284
285 if (thd->is_error())
286 {
287 sp_pcontext *cur_pctx= cur_spi->get_parsing_ctx();
288
289 found_handler= cur_pctx->find_handler(da->get_sqlstate(),
290 da->sql_errno(),
291 Sql_condition::WARN_LEVEL_ERROR);
292
293 if (!found_handler)
294 DBUG_RETURN(false);
295
296 if (da->get_error_condition())
297 {
298 const Sql_condition *c= da->get_error_condition();
299 condition_sql_errno= c->get_sql_errno();
300 condition_level= c->get_level();
301 condition_sqlstate= c->get_sqlstate();
302 condition_message= c->get_message_text();
303 }
304 else
305 {
306 /*
307 SQL condition can be NULL if the diagnostics area was full
308 when the error was raised. It can also be NULL if
309 Diagnostics_area::set_error_status(uint sql_error) was used.
310 */
311
312 condition_sql_errno= da->sql_errno();
313 condition_level= Sql_condition::WARN_LEVEL_ERROR;
314 condition_sqlstate= da->get_sqlstate();
315 condition_message= da->message();
316 }
317 }
318 else if (da->current_statement_warn_count())
319 {
320 Diagnostics_area::Sql_condition_iterator it= da->sql_conditions();
321 const Sql_condition *c;
322
323 // Here we need to find the last warning/note from the stack.
324 // In MySQL most substantial warning is the last one.
325 // (We could have used a reverse iterator here if one existed)
326
327 while ((c= it++))
328 {
329 if (c->get_level() == Sql_condition::WARN_LEVEL_WARN ||
330 c->get_level() == Sql_condition::WARN_LEVEL_NOTE)
331 {
332 sp_pcontext *cur_pctx= cur_spi->get_parsing_ctx();
333
334 const sp_handler *handler= cur_pctx->find_handler(c->get_sqlstate(),
335 c->get_sql_errno(),
336 c->get_level());
337 if (handler)
338 {
339 found_handler= handler;
340
341 condition_sql_errno= c->get_sql_errno();
342 condition_level= c->get_level();
343 condition_sqlstate= c->get_sqlstate();
344 condition_message= c->get_message_text();
345 }
346 }
347 }
348 }
349
350 if (!found_handler)
351 DBUG_RETURN(false);
352
353 // At this point, we know that:
354 // - there is a pending SQL-condition (error or warning);
355 // - there is an SQL-handler for it.
356
357 DBUG_ASSERT(condition_sql_errno != 0);
358
359 sp_handler_entry *handler_entry= NULL;
360 for (int i= 0; i < m_visible_handlers.elements(); ++i)
361 {
362 sp_handler_entry *h= m_visible_handlers.at(i);
363
364 if (h->handler == found_handler)
365 {
366 handler_entry= h;
367 break;
368 }
369 }
370
371 /*
372 handler_entry usually should not be NULL here, as that indicates
373 that the parser context thinks a HANDLER should be activated,
374 but the runtime context cannot find it.
375
376 However, this can happen (and this is in line with the Standard)
377 if SQL-condition has been raised before DECLARE HANDLER instruction
378 is processed.
379
380 For example:
381 CREATE PROCEDURE p()
382 BEGIN
383 DECLARE v INT DEFAULT 'get'; -- raises SQL-warning here
384 DECLARE EXIT HANDLER ... -- this handler does not catch the warning
385 END
386 */
387 if (!handler_entry)
388 DBUG_RETURN(false);
389
390 // Mark active conditions so that they can be deleted when the handler exits.
391 da->mark_sql_conditions_for_removal();
392
393 uint continue_ip= handler_entry->handler->type == sp_handler::CONTINUE ?
394 cur_spi->get_cont_dest() : 0;
395
396 /* End aborted result set. */
397 if (end_partial_result_set)
398 thd->protocol->end_partial_result_set(thd);
399
400 /* Add a frame to handler-call-stack. */
401 Handler_call_frame *frame=
402 new (std::nothrow) Handler_call_frame(found_handler,
403 condition_sql_errno,
404 condition_sqlstate,
405 condition_level,
406 condition_message,
407 continue_ip);
408
409 /* Reset error state. */
410 thd->clear_error();
411 thd->killed= THD::NOT_KILLED; // Some errors set thd->killed
412 // (e.g. "bad data").
413
414 if (!frame)
415 {
416 sql_alloc_error_handler();
417 DBUG_RETURN(false);
418 }
419
420 m_activated_handlers.append(frame);
421
422 *ip= handler_entry->first_ip;
423
424 DBUG_RETURN(true);
425 }
426
427
set_variable(THD * thd,Field * field,Item ** value)428 bool sp_rcontext::set_variable(THD *thd, Field *field, Item **value)
429 {
430 if (!value)
431 {
432 field->set_null();
433 return false;
434 }
435
436 return sp_eval_expr(thd, field, value);
437 }
438
439
create_case_expr_holder(THD * thd,const Item * item) const440 Item_cache *sp_rcontext::create_case_expr_holder(THD *thd,
441 const Item *item) const
442 {
443 Item_cache *holder;
444 Query_arena current_arena;
445
446 thd->set_n_backup_active_arena(thd->sp_runtime_ctx->callers_arena,
447 ¤t_arena);
448
449 holder= Item_cache::get_cache(item);
450
451 thd->restore_active_arena(thd->sp_runtime_ctx->callers_arena, ¤t_arena);
452
453 return holder;
454 }
455
456
set_case_expr(THD * thd,int case_expr_id,Item ** case_expr_item_ptr)457 bool sp_rcontext::set_case_expr(THD *thd, int case_expr_id,
458 Item **case_expr_item_ptr)
459 {
460 Item *case_expr_item= sp_prepare_func_item(thd, case_expr_item_ptr);
461 if (!case_expr_item)
462 return true;
463
464 if (!m_case_expr_holders[case_expr_id] ||
465 m_case_expr_holders[case_expr_id]->result_type() !=
466 case_expr_item->result_type())
467 {
468 m_case_expr_holders[case_expr_id]=
469 create_case_expr_holder(thd, case_expr_item);
470 }
471
472 m_case_expr_holders[case_expr_id]->store(case_expr_item);
473 m_case_expr_holders[case_expr_id]->cache_value();
474 return false;
475 }
476
477
478 ///////////////////////////////////////////////////////////////////////////
479 // sp_cursor implementation.
480 ///////////////////////////////////////////////////////////////////////////
481
482
483 /**
484 Open an SP cursor
485
486 @param thd Thread context
487
488 @return Error status
489 */
490
open(THD * thd)491 bool sp_cursor::open(THD *thd)
492 {
493 if (m_server_side_cursor)
494 {
495 my_message(ER_SP_CURSOR_ALREADY_OPEN, ER(ER_SP_CURSOR_ALREADY_OPEN),
496 MYF(0));
497 return true;
498 }
499
500 return mysql_open_cursor(thd, &m_result, &m_server_side_cursor);
501 }
502
503
close(THD * thd)504 bool sp_cursor::close(THD *thd)
505 {
506 if (! m_server_side_cursor)
507 {
508 my_message(ER_SP_CURSOR_NOT_OPEN, ER(ER_SP_CURSOR_NOT_OPEN), MYF(0));
509 return true;
510 }
511
512 destroy();
513 return false;
514 }
515
516
destroy()517 void sp_cursor::destroy()
518 {
519 delete m_server_side_cursor;
520 m_server_side_cursor= NULL;
521 }
522
523
fetch(THD * thd,List<sp_variable> * vars)524 bool sp_cursor::fetch(THD *thd, List<sp_variable> *vars)
525 {
526 if (! m_server_side_cursor)
527 {
528 my_message(ER_SP_CURSOR_NOT_OPEN, ER(ER_SP_CURSOR_NOT_OPEN), MYF(0));
529 return true;
530 }
531
532 if (vars->elements != m_result.get_field_count())
533 {
534 my_message(ER_SP_WRONG_NO_OF_FETCH_ARGS,
535 ER(ER_SP_WRONG_NO_OF_FETCH_ARGS), MYF(0));
536 return true;
537 }
538
539 DBUG_EXECUTE_IF("bug23032_emit_warning",
540 push_warning(thd, Sql_condition::WARN_LEVEL_WARN,
541 ER_UNKNOWN_ERROR,
542 ER(ER_UNKNOWN_ERROR)););
543
544 m_result.set_spvar_list(vars);
545
546 /* Attempt to fetch one row */
547 if (m_server_side_cursor->is_open())
548 m_server_side_cursor->fetch(1);
549
550 /*
551 If the cursor was pointing after the last row, the fetch will
552 close it instead of sending any rows.
553 */
554 if (! m_server_side_cursor->is_open())
555 {
556 my_message(ER_SP_FETCH_NO_DATA, ER(ER_SP_FETCH_NO_DATA), MYF(0));
557 return true;
558 }
559
560 return false;
561 }
562
563
564 ///////////////////////////////////////////////////////////////////////////
565 // sp_cursor::Select_fetch_into_spvars implementation.
566 ///////////////////////////////////////////////////////////////////////////
567
568
prepare(List<Item> & fields,SELECT_LEX_UNIT * u)569 int sp_cursor::Select_fetch_into_spvars::prepare(List<Item> &fields,
570 SELECT_LEX_UNIT *u)
571 {
572 /*
573 Cache the number of columns in the result set in order to easily
574 return an error if column count does not match value count.
575 */
576 field_count= fields.elements;
577 return select_result_interceptor::prepare(fields, u);
578 }
579
580
send_data(List<Item> & items)581 bool sp_cursor::Select_fetch_into_spvars::send_data(List<Item> &items)
582 {
583 List_iterator_fast<sp_variable> spvar_iter(*spvar_list);
584 List_iterator_fast<Item> item_iter(items);
585 sp_variable *spvar;
586 Item *item;
587
588 /* Must be ensured by the caller */
589 DBUG_ASSERT(spvar_list->elements == items.elements);
590
591 /*
592 Assign the row fetched from a server side cursor to stored
593 procedure variables.
594 */
595 for (; spvar= spvar_iter++, item= item_iter++; )
596 {
597 if (thd->sp_runtime_ctx->set_variable(thd, spvar->offset, &item))
598 return true;
599 }
600 return false;
601 }
602