1 /* Copyright (c) 2002, 2021, Oracle and/or its affiliates.
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 "my_global.h"
24 #include "mysql.h"
25 #include "sp.h"                                // sp_eval_expr
26 #include "sql_cursor.h"
27 #include "sp_rcontext.h"
28 #include "sp_pcontext.h"
29 #include "sql_tmp_table.h"                     // create_virtual_tmp_table
30 #include "sp_instr.h"
31 #include "template_utils.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_visible_handlers(PSI_INSTRUMENT_ME),
50    m_activated_handlers(PSI_INSTRUMENT_ME),
51    m_ccount(0)
52 {
53 }
54 
55 
~sp_rcontext()56 sp_rcontext::~sp_rcontext()
57 {
58   if (m_var_table)
59     free_blobs(m_var_table);
60 
61   delete_container_pointers(m_activated_handlers);
62   delete_container_pointers(m_visible_handlers);
63   pop_all_cursors();
64 
65   // Leave m_var_items and m_case_expr_holders untouched.
66   // They are allocated in mem roots and will be freed accordingly.
67 }
68 
69 
create(THD * thd,const sp_pcontext * root_parsing_ctx,Field * return_value_fld)70 sp_rcontext *sp_rcontext::create(THD *thd,
71                                  const sp_pcontext *root_parsing_ctx,
72                                  Field *return_value_fld)
73 {
74   sp_rcontext *ctx= new (thd->mem_root) sp_rcontext(root_parsing_ctx,
75                                                     return_value_fld,
76                                                     thd->in_sub_stmt);
77 
78   if (!ctx)
79     return NULL;
80 
81   if (ctx->alloc_arrays(thd) ||
82       ctx->init_var_table(thd) ||
83       ctx->init_var_items(thd))
84   {
85     delete ctx;
86     return NULL;
87   }
88 
89   return ctx;
90 }
91 
92 
alloc_arrays(THD * thd)93 bool sp_rcontext::alloc_arrays(THD *thd)
94 {
95   {
96     size_t n= m_root_parsing_ctx->max_cursor_index();
97     m_cstack.reset(
98       static_cast<sp_cursor **> (
99         thd->alloc(n * sizeof (sp_cursor*))),
100       n);
101   }
102 
103   {
104     size_t n= m_root_parsing_ctx->get_num_case_exprs();
105     m_case_expr_holders.reset(
106       static_cast<Item_cache **> (
107         thd->mem_calloc(n * sizeof (Item_cache*))),
108       n);
109   }
110 
111   return !m_cstack.array() || !m_case_expr_holders.array();
112 }
113 
114 
init_var_table(THD * thd)115 bool sp_rcontext::init_var_table(THD *thd)
116 {
117   List<Create_field> field_def_lst;
118 
119   if (!m_root_parsing_ctx->max_var_index())
120     return false;
121 
122   m_root_parsing_ctx->retrieve_field_definitions(&field_def_lst);
123 
124   assert(field_def_lst.elements == m_root_parsing_ctx->max_var_index());
125 
126   if (!(m_var_table= create_virtual_tmp_table(thd, field_def_lst)))
127     return true;
128 
129   m_var_table->copy_blobs= true;
130   m_var_table->alias= "";
131 
132   return false;
133 }
134 
135 
init_var_items(THD * thd)136 bool sp_rcontext::init_var_items(THD *thd)
137 {
138   uint num_vars= m_root_parsing_ctx->max_var_index();
139 
140   m_var_items.reset(
141     static_cast<Item **> (
142       thd->alloc(num_vars * sizeof (Item *))),
143     num_vars);
144 
145   if (!m_var_items.array())
146     return true;
147 
148   for (uint idx = 0; idx < num_vars; ++idx)
149   {
150     if (!(m_var_items[idx]= new Item_field(m_var_table->field[idx])))
151       return true;
152   }
153 
154   return false;
155 }
156 
157 
set_return_value(THD * thd,Item ** return_value_item)158 bool sp_rcontext::set_return_value(THD *thd, Item **return_value_item)
159 {
160   assert(m_return_value_fld);
161 
162   m_return_value_set = true;
163 
164   return sp_eval_expr(thd, m_return_value_fld, return_value_item);
165 }
166 
167 
push_cursor(sp_instr_cpush * i)168 bool sp_rcontext::push_cursor(sp_instr_cpush *i)
169 {
170   /*
171     We should create cursors on the system heap because:
172      - they could be (and usually are) used in several instructions,
173        thus they can not be stored on an execution mem-root;
174      - a cursor can be pushed/popped many times in a loop, having these objects
175        on callers' mem-root would lead to a memory leak in every iteration.
176   */
177   sp_cursor *c= new (std::nothrow) sp_cursor(i);
178 
179   if (!c)
180   {
181     sql_alloc_error_handler();
182     return true;
183   }
184 
185   m_cstack[m_ccount++]= c;
186   return false;
187 }
188 
189 
pop_cursors(uint count)190 void sp_rcontext::pop_cursors(uint count)
191 {
192   assert(m_ccount >= count);
193 
194   while (count--)
195     delete m_cstack[--m_ccount];
196 }
197 
198 
push_handler(sp_handler * handler,uint first_ip)199 bool sp_rcontext::push_handler(sp_handler *handler, uint first_ip)
200 {
201   /*
202     We should create handler entries on the system heap because:
203      - they could be (and usually are) used in several instructions,
204        thus they can not be stored on an execution mem-root;
205      - a handler can be pushed/popped many times in a loop, having these
206        objects on callers' mem-root would lead to a memory leak in every
207        iteration.
208   */
209   sp_handler_entry *he=
210     new (std::nothrow) sp_handler_entry(handler, first_ip);
211 
212   if (!he)
213   {
214     sql_alloc_error_handler();
215     return true;
216   }
217 
218   return m_visible_handlers.push_back(he);
219 }
220 
221 
pop_handlers(sp_pcontext * current_scope)222 void sp_rcontext::pop_handlers(sp_pcontext *current_scope)
223 {
224   for (int i= static_cast<int>(m_visible_handlers.size()) - 1; i >= 0; --i)
225   {
226     int handler_level= m_visible_handlers.at(i)->handler->scope->get_level();
227 
228     if (handler_level >= current_scope->get_level())
229     {
230       delete m_visible_handlers.back();
231       m_visible_handlers.pop_back();
232     }
233   }
234 }
235 
236 
pop_handler_frame(THD * thd)237 void sp_rcontext::pop_handler_frame(THD *thd)
238 {
239   Handler_call_frame *frame= m_activated_handlers.back();
240   m_activated_handlers.pop_back();
241 
242   // Also pop matching DA and copy new conditions.
243   assert(thd->get_stmt_da() == &frame->handler_da);
244   thd->pop_diagnostics_area();
245   // Out with the old, in with the new!
246   thd->get_stmt_da()->reset_condition_info(thd);
247   thd->get_stmt_da()->copy_new_sql_conditions(thd, &frame->handler_da);
248 
249   delete frame;
250 }
251 
252 
exit_handler(THD * thd,sp_pcontext * target_scope)253 void sp_rcontext::exit_handler(THD *thd, sp_pcontext *target_scope)
254 {
255   /*
256     The handler has successfully completed. We should now pop the current
257     handler frame and pop the diagnostics area which was pushed when the
258     handler was activated.
259 
260     The diagnostics area of the caller should then contain only any
261     conditions pushed during handler execution. The conditions present
262     when the handler was activated should be removed since they have
263     been successfully handled.
264   */
265   pop_handler_frame(thd);
266 
267   // Pop frames below the target scope level.
268   for (int i= static_cast<int>(m_activated_handlers.size()) - 1; i >= 0; --i)
269   {
270     int handler_level= m_activated_handlers.at(i)->handler->scope->get_level();
271 
272     if (handler_level <= target_scope->get_level())
273       break;
274 
275     pop_handler_frame(thd);
276   }
277 
278   /*
279     Condition was successfully handled, reset condition count
280     so we don't trigger the handler again for the same warning.
281   */
282   thd->get_stmt_da()->reset_statement_cond_count();
283 }
284 
285 
handle_sql_condition(THD * thd,uint * ip,const sp_instr * cur_spi)286 bool sp_rcontext::handle_sql_condition(THD *thd,
287                                        uint *ip,
288                                        const sp_instr *cur_spi)
289 {
290   DBUG_ENTER("sp_rcontext::handle_sql_condition");
291 
292   /*
293     If this is a fatal sub-statement error, and this runtime
294     context corresponds to a sub-statement, no CONTINUE/EXIT
295     handlers from this context are applicable: try to locate one
296     in the outer scope.
297   */
298   if (thd->is_fatal_sub_stmt_error && m_in_sub_stmt)
299     DBUG_RETURN(false);
300 
301   Diagnostics_area *da= thd->get_stmt_da();
302   const sp_handler *found_handler= NULL;
303   Sql_condition *found_condition= NULL;
304 
305   if (thd->is_error())
306   {
307     sp_pcontext *cur_pctx= cur_spi->get_parsing_ctx();
308 
309     found_handler= cur_pctx->find_handler(da->returned_sqlstate(),
310                                           da->mysql_errno(),
311                                           Sql_condition::SL_ERROR);
312 
313     if (found_handler)
314     {
315       found_condition= da->error_condition();
316 
317       /*
318         error_condition can be NULL if the Diagnostics Area was full
319         when the error was raised. It can also be NULL if
320         Diagnostics_area::set_error_status(uint sql_error) was used.
321         In these cases, make a temporary Sql_condition here so the
322         error can be handled.
323       */
324       if (!found_condition)
325       {
326         found_condition= new (callers_arena->mem_root)
327           Sql_condition(callers_arena->mem_root,
328                         da->mysql_errno(),
329                         da->returned_sqlstate(),
330                         Sql_condition::SL_ERROR,
331                         da->message_text());
332       }
333     }
334   }
335   else if (da->current_statement_cond_count())
336   {
337     Diagnostics_area::Sql_condition_iterator it= da->sql_conditions();
338     const Sql_condition *c;
339 
340     /*
341       Here we need to find the last warning/note from the stack.
342       In MySQL most substantial warning is the last one.
343       (We could have used a reverse iterator here if one existed.)
344       We ignore preexisting conditions so we don't throw for them
345       again if the next statement isn't one that pre-clears the
346       DA. (Critically, that includes hpush_jump, i.e. any handlers
347       declared within the one we're calling. At that point, the
348       catcher for our throw would become very hard to predict!)
349       One benefit of not simply clearing the DA as we enter a handler
350       (instead of resetting the condition cound further down in this
351       exact function as we do now) and forcing the user to utilize
352       GET STACKED DIAGNOSTICS is that this way, we can make
353       SHOW WARNINGS|ERRORS work.
354     */
355 
356     while ((c= it++))
357     {
358       if (c->severity() == Sql_condition::SL_WARNING ||
359           c->severity() == Sql_condition::SL_NOTE)
360       {
361         sp_pcontext *cur_pctx= cur_spi->get_parsing_ctx();
362 
363         const sp_handler *handler=
364           cur_pctx->find_handler(c->returned_sqlstate(),
365                                  c->mysql_errno(),
366                                  c->severity());
367         if (handler)
368         {
369           found_handler= handler;
370           found_condition= const_cast<Sql_condition*>(c);
371         }
372       }
373     }
374   }
375 
376   if (!found_handler)
377     DBUG_RETURN(false);
378 
379   // At this point, we know that:
380   //  - there is a pending SQL-condition (error or warning);
381   //  - there is an SQL-handler for it.
382 
383   assert(found_condition);
384 
385   sp_handler_entry *handler_entry= NULL;
386   for (size_t i= 0; i < m_visible_handlers.size(); ++i)
387   {
388     sp_handler_entry *h= m_visible_handlers.at(i);
389 
390     if (h->handler == found_handler)
391     {
392       handler_entry= h;
393       break;
394     }
395   }
396 
397   /*
398     handler_entry usually should not be NULL here, as that indicates
399     that the parser context thinks a HANDLER should be activated,
400     but the runtime context cannot find it.
401 
402     However, this can happen (and this is in line with the Standard)
403     if SQL-condition has been raised before DECLARE HANDLER instruction
404     is processed.
405 
406     For example:
407     CREATE PROCEDURE p()
408     BEGIN
409       DECLARE v INT DEFAULT 'get'; -- raises SQL-warning here
410       DECLARE EXIT HANDLER ...     -- this handler does not catch the warning
411     END
412   */
413   if (!handler_entry)
414     DBUG_RETURN(false);
415 
416   uint continue_ip= handler_entry->handler->type == sp_handler::CONTINUE ?
417     cur_spi->get_cont_dest() : 0;
418 
419   /* Add a frame to handler-call-stack. */
420   Handler_call_frame *frame=
421     new (std::nothrow) Handler_call_frame(found_handler,
422                                           found_condition,
423                                           continue_ip);
424   if (!frame)
425   {
426     sql_alloc_error_handler();
427     DBUG_RETURN(false);
428   }
429 
430   m_activated_handlers.push_back(frame);
431 
432   /* End aborted result set. */
433   if (end_partial_result_set)
434     thd->get_protocol()->end_partial_result_set();
435 
436   /* Reset error state. */
437   thd->clear_error();
438   thd->killed= THD::NOT_KILLED; // Some errors set thd->killed
439                                 // (e.g. "bad data").
440 
441   thd->push_diagnostics_area(&frame->handler_da);
442 
443   /*
444     Mark current conditions so we later will know which conditions
445     were added during handler execution (if any).
446   */
447   frame->handler_da.mark_preexisting_sql_conditions();
448 
449   frame->handler_da.reset_statement_cond_count();
450 
451   *ip= handler_entry->first_ip;
452 
453   DBUG_RETURN(true);
454 }
455 
456 
set_variable(THD * thd,Field * field,Item ** value)457 bool sp_rcontext::set_variable(THD *thd, Field *field, Item **value)
458 {
459   if (!value)
460   {
461     field->set_null();
462     return false;
463   }
464 
465   return sp_eval_expr(thd, field, value);
466 }
467 
468 
create_case_expr_holder(THD * thd,const Item * item) const469 Item_cache *sp_rcontext::create_case_expr_holder(THD *thd,
470                                                  const Item *item) const
471 {
472   Item_cache *holder;
473   Query_arena current_arena;
474 
475   thd->set_n_backup_active_arena(thd->sp_runtime_ctx->callers_arena,
476                                  &current_arena);
477 
478   holder= Item_cache::get_cache(item);
479 
480   thd->restore_active_arena(thd->sp_runtime_ctx->callers_arena, &current_arena);
481 
482   return holder;
483 }
484 
485 
set_case_expr(THD * thd,int case_expr_id,Item ** case_expr_item_ptr)486 bool sp_rcontext::set_case_expr(THD *thd, int case_expr_id,
487                                 Item **case_expr_item_ptr)
488 {
489   Item *case_expr_item= sp_prepare_func_item(thd, case_expr_item_ptr);
490   if (!case_expr_item)
491     return true;
492 
493   if (!m_case_expr_holders[case_expr_id] ||
494       m_case_expr_holders[case_expr_id]->result_type() !=
495         case_expr_item->result_type())
496   {
497     m_case_expr_holders[case_expr_id]=
498       create_case_expr_holder(thd, case_expr_item);
499   }
500 
501   m_case_expr_holders[case_expr_id]->store(case_expr_item);
502   m_case_expr_holders[case_expr_id]->cache_value();
503   return false;
504 }
505 
506 
507 ///////////////////////////////////////////////////////////////////////////
508 // sp_cursor implementation.
509 ///////////////////////////////////////////////////////////////////////////
510 
511 
512 /**
513   Open an SP cursor
514 
515   @param thd  Thread context
516 
517   @return Error status
518 */
519 
open(THD * thd)520 bool sp_cursor::open(THD *thd)
521 {
522   if (m_server_side_cursor)
523   {
524     my_message(ER_SP_CURSOR_ALREADY_OPEN, ER(ER_SP_CURSOR_ALREADY_OPEN),
525                MYF(0));
526     return true;
527   }
528 
529   return mysql_open_cursor(thd, &m_result, &m_server_side_cursor);
530 }
531 
532 
close(THD * thd)533 bool sp_cursor::close(THD *thd)
534 {
535   if (! m_server_side_cursor)
536   {
537     my_message(ER_SP_CURSOR_NOT_OPEN, ER(ER_SP_CURSOR_NOT_OPEN), MYF(0));
538     return true;
539   }
540 
541   destroy();
542   return false;
543 }
544 
545 
destroy()546 void sp_cursor::destroy()
547 {
548   delete m_server_side_cursor;
549   m_server_side_cursor= NULL;
550 }
551 
552 
fetch(THD * thd,List<sp_variable> * vars)553 bool sp_cursor::fetch(THD *thd, List<sp_variable> *vars)
554 {
555   if (! m_server_side_cursor)
556   {
557     my_message(ER_SP_CURSOR_NOT_OPEN, ER(ER_SP_CURSOR_NOT_OPEN), MYF(0));
558     return true;
559   }
560 
561   if (vars->elements != m_result.get_field_count())
562   {
563     my_message(ER_SP_WRONG_NO_OF_FETCH_ARGS,
564                ER(ER_SP_WRONG_NO_OF_FETCH_ARGS), MYF(0));
565     return true;
566   }
567 
568   DBUG_EXECUTE_IF("bug23032_emit_warning",
569                   push_warning(thd, Sql_condition::SL_WARNING,
570                                ER_UNKNOWN_ERROR,
571                                ER(ER_UNKNOWN_ERROR)););
572 
573   m_result.set_spvar_list(vars);
574 
575   /* Attempt to fetch one row */
576   if (m_server_side_cursor->is_open())
577   {
578     if (m_server_side_cursor->fetch(1))
579       return true;
580   }
581 
582   /*
583     If the cursor was pointing after the last row, the fetch will
584     close it instead of sending any rows.
585   */
586   if (! m_server_side_cursor->is_open())
587   {
588     my_message(ER_SP_FETCH_NO_DATA, ER(ER_SP_FETCH_NO_DATA), MYF(0));
589     return true;
590   }
591 
592   return false;
593 }
594 
595 
596 ///////////////////////////////////////////////////////////////////////////
597 // sp_cursor::Query_fetch_into_spvars implementation.
598 ///////////////////////////////////////////////////////////////////////////
599 
600 
prepare(List<Item> & fields,SELECT_LEX_UNIT * u)601 int sp_cursor::Query_fetch_into_spvars::prepare(List<Item> &fields,
602                                                 SELECT_LEX_UNIT *u)
603 {
604   /*
605     Cache the number of columns in the result set in order to easily
606     return an error if column count does not match value count.
607   */
608   field_count= fields.elements;
609   return Query_result_interceptor::prepare(fields, u);
610 }
611 
612 
send_data(List<Item> & items)613 bool sp_cursor::Query_fetch_into_spvars::send_data(List<Item> &items)
614 {
615   List_iterator_fast<sp_variable> spvar_iter(*spvar_list);
616   List_iterator_fast<Item> item_iter(items);
617   sp_variable *spvar;
618   Item *item;
619 
620   /* Must be ensured by the caller */
621   assert(spvar_list->elements == items.elements);
622 
623   /*
624     Assign the row fetched from a server side cursor to stored
625     procedure variables.
626   */
627   for (; spvar= spvar_iter++, item= item_iter++; )
628   {
629     if (thd->sp_runtime_ctx->set_variable(thd, spvar->offset, &item))
630       return true;
631   }
632   return false;
633 }
634